From 3c56c2ecf53b8bbaa863c32c9e93ef2d3b102e28 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Thu, 3 Jul 2025 23:39:31 +0800 Subject: [PATCH 01/19] stabilize `const_slice_reverse` --- library/core/src/slice/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 3a3f44c6b8546..35bebdbe522a6 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -967,7 +967,7 @@ impl [T] { /// assert!(v == [3, 2, 1]); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_slice_reverse", issue = "135120")] + #[rustc_const_stable(feature = "const_slice_reverse", since = "CURRENT_RUSTC_VERSION")] #[inline] pub const fn reverse(&mut self) { let half_len = self.len() / 2; @@ -1000,6 +1000,7 @@ impl [T] { // this check tells LLVM that the indexing below is // in-bounds. Then after inlining -- once the actual // lengths of the slices are known -- it's removed. + // FIXME(const_trait_impl) replace with let (a, b) = (&mut a[..n], &mut b[..n]); let (a, _) = a.split_at_mut(n); let (b, _) = b.split_at_mut(n); From 229be21d0d5297a66e7fe6b56606d0549bfccd5f Mon Sep 17 00:00:00 2001 From: xizheyin Date: Tue, 24 Jun 2025 16:09:42 +0800 Subject: [PATCH 02/19] Add ui test unnessary-error-issue-138401.rs Signed-off-by: xizheyin --- .../issues/unnessary-error-issue-138401.rs | 7 +++++++ .../unnessary-error-issue-138401.stderr | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/ui/parser/issues/unnessary-error-issue-138401.rs create mode 100644 tests/ui/parser/issues/unnessary-error-issue-138401.stderr diff --git a/tests/ui/parser/issues/unnessary-error-issue-138401.rs b/tests/ui/parser/issues/unnessary-error-issue-138401.rs new file mode 100644 index 0000000000000..e5e5f1ee4e9ce --- /dev/null +++ b/tests/ui/parser/issues/unnessary-error-issue-138401.rs @@ -0,0 +1,7 @@ +pub fn foo(x: i64) -> i64 { + x.abs) + //~^ ERROR mismatched closing delimiter +} +//~^ ERROR unexpected closing delimiter: `}` + +fn main() {} diff --git a/tests/ui/parser/issues/unnessary-error-issue-138401.stderr b/tests/ui/parser/issues/unnessary-error-issue-138401.stderr new file mode 100644 index 0000000000000..b50f77f1247cd --- /dev/null +++ b/tests/ui/parser/issues/unnessary-error-issue-138401.stderr @@ -0,0 +1,19 @@ +error: mismatched closing delimiter: `)` + --> $DIR/unnessary-error-issue-138401.rs:1:27 + | +LL | pub fn foo(x: i64) -> i64 { + | ^ unclosed delimiter +LL | x.abs) + | ^ mismatched closing delimiter + +error: unexpected closing delimiter: `}` + --> $DIR/unnessary-error-issue-138401.rs:4:1 + | +LL | x.abs) + | - missing open `(` for this delimiter +LL | +LL | } + | ^ unexpected closing delimiter + +error: aborting due to 2 previous errors + From 132a47e72316b60e99c3e5fefb9c3a06641138e4 Mon Sep 17 00:00:00 2001 From: Bastian Kersting Date: Tue, 15 Jul 2025 12:28:15 +0000 Subject: [PATCH 03/19] Correct which exploit mitigations are enabled by default --- src/doc/rustc/src/exploit-mitigations.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/doc/rustc/src/exploit-mitigations.md b/src/doc/rustc/src/exploit-mitigations.md index f8bafe032140c..c80d7d8743cd9 100644 --- a/src/doc/rustc/src/exploit-mitigations.md +++ b/src/doc/rustc/src/exploit-mitigations.md @@ -54,17 +54,17 @@ Summary of exploit mitigations supported by the Rust compiler when building programs for the Linux operating system on the AMD64 architecture and equivalent. -| Exploit mitigation | Supported and enabled by default | Since | -| - | - | - | -| Position-independent executable | Yes | 0.12.0 (2014-10-09) | -| Integer overflow checks | Yes (enabled when debug assertions are enabled, and disabled when debug assertions are disabled) | 1.1.0 (2015-06-25) | -| Non-executable memory regions | Yes | 1.8.0 (2016-04-14) | -| Stack clashing protection | Yes | 1.20.0 (2017-08-31) | -| Read-only relocations and immediate binding | Yes | 1.21.0 (2017-10-12) | -| Heap corruption protection | Yes | 1.32.0 (2019-01-17) (via operating system default or specified allocator) | -| Stack smashing protection | Yes | Nightly | -| Forward-edge control flow protection | Yes | Nightly | -| Backward-edge control flow protection (e.g., shadow and safe stack) | Yes | Nightly | +| Exploit mitigation | Supported | Enabled by default | Since | +| - | - | - | - | +| Position-independent executable | Yes | Yes | 0.12.0 (2014-10-09) | +| Integer overflow checks | Yes | (enabled when debug assertions are enabled, and disabled when debug assertions are disabled) | 1.1.0 (2015-06-25) | +| Non-executable memory regions | Yes | Yes | 1.8.0 (2016-04-14) | +| Stack clashing protection | Yes | Yes | 1.20.0 (2017-08-31) | +| Read-only relocations and immediate binding | Yes | Yes | 1.21.0 (2017-10-12) | +| Heap corruption protection | Yes | Yes | 1.32.0 (2019-01-17) (via operating system default or specified allocator) | +| Stack smashing protection | Yes | No, `-Z stack-protector` | Nightly | +| Forward-edge control flow protection | Yes | No, `-Z sanitizer=cfi` | Nightly | +| Backward-edge control flow protection (e.g., shadow and safe stack) | Yes | No, `-Z sanitizer=shadow-call-stack,safestack` | Nightly | [^all-targets]: See for a list of targets and their default options. From 49ae52e3ffeb3d98f19845eba5eb9fa1408fa432 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Thu, 17 Jul 2025 08:02:26 +0200 Subject: [PATCH 04/19] Fix encoding of `link_section` and `no_mangle` cross crate --- .../rustc_attr_data_structures/src/encode_cross_crate.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs index 3e2dc0a15b2f3..c24b45e83f907 100644 --- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs @@ -40,9 +40,9 @@ impl AttributeKind { Fundamental { .. } => Yes, Ignore { .. } => No, Inline(..) => No, - LinkName { .. } => Yes, + LinkName { .. } => Yes, // Needed for rustdoc LinkOrdinal { .. } => No, - LinkSection { .. } => No, + LinkSection { .. } => Yes, // Needed for rustdoc LoopMatch(..) => No, MacroTransparency(..) => Yes, Marker(..) => No, @@ -50,8 +50,8 @@ impl AttributeKind { MustUse { .. } => Yes, Naked(..) => No, NoImplicitPrelude(..) => No, - NoMangle(..) => No, - NonExhaustive(..) => Yes, + NoMangle(..) => Yes, // Needed for rustdoc + NonExhaustive(..) => Yes, // Needed for rustdoc OmitGdbPrettyPrinterSection => No, Optimize(..) => No, ParenSugar(..) => No, From 9f16db6611b0fb35f4a16dcbf326fb9aee3d87f3 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Thu, 17 Jul 2025 08:03:17 +0200 Subject: [PATCH 05/19] Regression test --- .../reexport/auxiliary/reexports-attrs.rs | 14 +++++++++++++ tests/rustdoc/reexport/reexport-attrs.rs | 20 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 tests/rustdoc/reexport/auxiliary/reexports-attrs.rs create mode 100644 tests/rustdoc/reexport/reexport-attrs.rs diff --git a/tests/rustdoc/reexport/auxiliary/reexports-attrs.rs b/tests/rustdoc/reexport/auxiliary/reexports-attrs.rs new file mode 100644 index 0000000000000..96fa8209cde84 --- /dev/null +++ b/tests/rustdoc/reexport/auxiliary/reexports-attrs.rs @@ -0,0 +1,14 @@ +#[unsafe(no_mangle)] +pub fn f0() {} + +#[unsafe(link_section = ".here")] +pub fn f1() {} + +#[unsafe(export_name = "f2export")] +pub fn f2() {} + +#[repr(u8)] +pub enum T0 { V1 } + +#[non_exhaustive] +pub enum T1 {} diff --git a/tests/rustdoc/reexport/reexport-attrs.rs b/tests/rustdoc/reexport/reexport-attrs.rs new file mode 100644 index 0000000000000..0ec645841f0b8 --- /dev/null +++ b/tests/rustdoc/reexport/reexport-attrs.rs @@ -0,0 +1,20 @@ +//@ aux-build: reexports-attrs.rs + +#![crate_name = "foo"] + +extern crate reexports_attrs; + +//@ has 'foo/fn.f0.html' '//pre[@class="rust item-decl"]' '#[no_mangle]' +pub use reexports_attrs::f0; + +//@ has 'foo/fn.f1.html' '//pre[@class="rust item-decl"]' '#[link_section = ".here"]' +pub use reexports_attrs::f1; + +//@ has 'foo/fn.f2.html' '//pre[@class="rust item-decl"]' '#[export_name = "f2export"]' +pub use reexports_attrs::f2; + +//@ has 'foo/enum.T0.html' '//pre[@class="rust item-decl"]' '#[repr(u8)]' +pub use reexports_attrs::T0; + +//@ has 'foo/enum.T1.html' '//pre[@class="rust item-decl"]' '#[non_exhaustive]' +pub use reexports_attrs::T1; From 12eedafc38b1d3af02c9c15333d0ba2f1aee1253 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 18 Jun 2025 12:51:47 +0000 Subject: [PATCH 06/19] Report the range of uninit bytes in CTFE errors --- .../rustc_const_eval/src/interpret/validity.rs | 2 +- .../rustc_middle/src/mir/interpret/allocation.rs | 7 +++++-- .../libc_pthread_cond_double_destroy.rs | 2 +- .../libc_pthread_cond_double_destroy.stderr | 9 ++++++++- .../libc_pthread_condattr_double_destroy.rs | 2 +- .../libc_pthread_condattr_double_destroy.stderr | 7 ++++++- .../libc_pthread_mutex_double_destroy.rs | 2 +- .../libc_pthread_mutex_double_destroy.stderr | 9 ++++++++- .../libc_pthread_mutexattr_double_destroy.rs | 2 +- .../libc_pthread_mutexattr_double_destroy.stderr | 7 ++++++- .../libc_pthread_rwlock_double_destroy.rs | 2 +- .../libc_pthread_rwlock_double_destroy.stderr | 10 +++++++++- .../arg_inplace_observe_after.stderr | 7 ++++++- .../arg_inplace_observe_during.none.stderr | 7 ++++++- .../return_pointer_aliasing_read.none.stderr | 7 ++++++- .../return_pointer_on_unwind.stderr | 15 ++++++++++++++- .../intrinsics/ptr_metadata_uninit_slice_data.rs | 2 +- .../ptr_metadata_uninit_slice_data.stderr | 7 ++++++- .../intrinsics/ptr_metadata_uninit_slice_len.rs | 2 +- .../ptr_metadata_uninit_slice_len.stderr | 7 ++++++- .../fail/intrinsics/ptr_metadata_uninit_thin.rs | 2 +- .../intrinsics/ptr_metadata_uninit_thin.stderr | 7 ++++++- .../miri/tests/fail/read_from_trivial_switch.rs | 2 +- .../tests/fail/read_from_trivial_switch.stderr | 7 ++++++- .../miri/tests/fail/uninit/padding-enum.stderr | 8 +++++++- .../miri/tests/fail/uninit/padding-pair.stderr | 7 ++++++- .../miri/tests/fail/uninit/padding-struct.stderr | 7 ++++++- .../tests/fail/uninit/padding-wide-ptr.stderr | 7 ++++++- .../fail/uninit/transmute-pair-uninit.stderr | 7 ++++++- .../tests/fail/uninit/uninit_byte_read.stderr | 7 ++++++- .../tests/fail/validity/invalid_int_op.stderr | 7 ++++++- .../invalid-patterns.32bit.stderr | 4 ++-- .../invalid-patterns.64bit.stderr | 4 ++-- .../ui/consts/const-err-enum-discriminant.stderr | 2 +- ...t-pointer-values-in-various-types.64bit.stderr | 4 ++-- .../ui/consts/const-eval/ub-enum-overwrite.stderr | 2 +- tests/ui/consts/const-eval/ub-enum.stderr | 2 +- tests/ui/consts/const-eval/ub-nonnull.stderr | 2 +- tests/ui/consts/const-eval/ub-ref-ptr.stderr | 4 ++-- tests/ui/consts/const-eval/ub-wide-ptr.stderr | 4 ++-- .../const-eval/union-const-eval-field.stderr | 2 +- tests/ui/consts/const-eval/union-ice.stderr | 6 +++--- tests/ui/consts/const-eval/union-ub.32bit.stderr | 2 +- tests/ui/consts/const-eval/union-ub.64bit.stderr | 2 +- tests/ui/type/pattern_types/validity.rs | 4 ++-- tests/ui/type/pattern_types/validity.stderr | 4 ++-- 46 files changed, 175 insertions(+), 56 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 62f591ceaa910..693b378296004 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -394,7 +394,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { interp_ok(try_validation!( self.ecx.read_immediate(val), self.path, - Ub(InvalidUninitBytes(None)) => + Ub(InvalidUninitBytes(_)) => Uninit { expected }, // The `Unsup` cases can only occur during CTFE Unsup(ReadPointerAsInt(_)) => diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 133111ff15de8..27ead51453195 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -702,8 +702,11 @@ impl Allocation read_provenance: bool, ) -> AllocResult> { // First and foremost, if anything is uninit, bail. - if self.init_mask.is_range_initialized(range).is_err() { - return Err(AllocError::InvalidUninitBytes(None)); + if let Err(bad) = self.init_mask.is_range_initialized(range) { + return Err(AllocError::InvalidUninitBytes(Some(BadBytesAccess { + access: range, + bad, + }))); } // Get the integer part of the result. We HAVE TO check provenance before returning this! diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs index 047fe07df14b4..8624e4d28fbeb 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs @@ -15,6 +15,6 @@ fn main() { libc::pthread_cond_destroy(cond.as_mut_ptr()); libc::pthread_cond_destroy(cond.as_mut_ptr()); - //~^ ERROR: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + //~^ ERROR: /Undefined Behavior: reading memory .*, but memory is uninitialized/ } } diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.stderr index 7abdfa87f75d4..3318ac7fca592 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory --> tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs:LL:CC | LL | libc::pthread_cond_destroy(cond.as_mut_ptr()); @@ -9,6 +9,13 @@ LL | libc::pthread_cond_destroy(cond.as_mut_ptr()); = note: BACKTRACE: = note: inside `main` at tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs:LL:CC +Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation: +ALLOC (stack variable, size: 48, align: 8) { + 0x00 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ + 0x10 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ + 0x20 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.rs index 90e33d58673a2..a510ee77cfb2e 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.rs @@ -13,6 +13,6 @@ fn main() { libc::pthread_condattr_destroy(attr.as_mut_ptr()); libc::pthread_condattr_destroy(attr.as_mut_ptr()); - //~^ ERROR: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + //~^ ERROR: /Undefined Behavior: reading memory .*, but memory is uninitialized/ } } diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.stderr index 28a66253ae809..1971bbc721031 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory --> tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.rs:LL:CC | LL | libc::pthread_condattr_destroy(attr.as_mut_ptr()); @@ -9,6 +9,11 @@ LL | libc::pthread_condattr_destroy(attr.as_mut_ptr()); = note: BACKTRACE: = note: inside `main` at tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.rs:LL:CC +Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation: +ALLOC (stack variable, size: 4, align: 4) { + __ __ __ __ │ ░░░░ +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs index 1792c227e132d..71a8029203299 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs @@ -16,6 +16,6 @@ fn main() { libc::pthread_mutex_destroy(mutex.as_mut_ptr()); libc::pthread_mutex_destroy(mutex.as_mut_ptr()); - //~^ ERROR: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + //~^ ERROR: /Undefined Behavior: reading memory .*, but memory is uninitialized/ } } diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.stderr index e7a6dee020335..251f8036e383b 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory --> tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs:LL:CC | LL | libc::pthread_mutex_destroy(mutex.as_mut_ptr()); @@ -9,6 +9,13 @@ LL | libc::pthread_mutex_destroy(mutex.as_mut_ptr()); = note: BACKTRACE: = note: inside `main` at tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs:LL:CC +Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation: +ALLOC (stack variable, size: 40, align: 8) { + 0x00 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ + 0x10 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ + 0x20 │ __ __ __ __ __ __ __ __ │ ░░░░░░░░ +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.rs index 3711c1f8dc10c..28dacc9931a42 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.rs @@ -12,6 +12,6 @@ fn main() { libc::pthread_mutexattr_destroy(attr.as_mut_ptr()); libc::pthread_mutexattr_destroy(attr.as_mut_ptr()); - //~^ ERROR: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + //~^ ERROR: /Undefined Behavior: reading memory .*, but memory is uninitialized/ } } diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.stderr index 0c9ee71de452c..b341efb7770c6 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory --> tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.rs:LL:CC | LL | libc::pthread_mutexattr_destroy(attr.as_mut_ptr()); @@ -9,6 +9,11 @@ LL | libc::pthread_mutexattr_destroy(attr.as_mut_ptr()); = note: BACKTRACE: = note: inside `main` at tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.rs:LL:CC +Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation: +ALLOC (stack variable, size: 4, align: 4) { + __ __ __ __ │ ░░░░ +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs index 6a31e972e68b8..a46a124bf2ecc 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs @@ -9,6 +9,6 @@ fn main() { libc::pthread_rwlock_destroy(&mut lock); libc::pthread_rwlock_destroy(&mut lock); - //~^ ERROR: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + //~^ ERROR: /Undefined Behavior: reading memory .*, but memory is uninitialized/ } } diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.stderr index 836f0d060bd0a..8f388577a27d4 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory --> tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs:LL:CC | LL | libc::pthread_rwlock_destroy(&mut lock); @@ -9,6 +9,14 @@ LL | libc::pthread_rwlock_destroy(&mut lock); = note: BACKTRACE: = note: inside `main` at tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs:LL:CC +Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation: +ALLOC (stack variable, size: 56, align: 8) { + 0x00 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ + 0x10 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ + 0x20 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ + 0x30 │ __ __ __ __ __ __ __ __ │ ░░░░░░░░ +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.stderr index 6a7d9a495f978..3252368ea6de7 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory --> tests/fail/function_calls/arg_inplace_observe_after.rs:LL:CC | LL | _observe = non_copy.0; @@ -9,6 +9,11 @@ LL | _observe = non_copy.0; = note: BACKTRACE: = note: inside `main` at tests/fail/function_calls/arg_inplace_observe_after.rs:LL:CC +Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation: +ALLOC (stack variable, size: 4, align: 4) { + __ __ __ __ │ ░░░░ +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr index 0fc634bb7fcec..09a5b9a649619 100644 --- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr +++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory --> tests/fail/function_calls/arg_inplace_observe_during.rs:LL:CC | LL | unsafe { ptr.read() }; @@ -14,6 +14,11 @@ note: inside `main` LL | Call(_unit = change_arg(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation: +ALLOC (stack variable, size: 4, align: 4) { + __ __ __ __ │ ░░░░ +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.none.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.none.stderr index 746ab2e59ca03..2409154725846 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.none.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing_read.none.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory --> tests/fail/function_calls/return_pointer_aliasing_read.rs:LL:CC | LL | unsafe { ptr.read() }; @@ -14,6 +14,11 @@ note: inside `main` LL | Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation: +ALLOC (stack variable, size: 4, align: 4) { + __ __ __ __ │ ░░░░ +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr index 7747a75d1cfe4..93720ca7d2771 100644 --- a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr +++ b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.stderr @@ -3,7 +3,7 @@ thread 'main' panicked at tests/fail/function_calls/return_pointer_on_unwind.rs: explicit panic note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory --> tests/fail/function_calls/return_pointer_on_unwind.rs:LL:CC | LL | dbg!(x.0); @@ -15,6 +15,19 @@ LL | dbg!(x.0); = note: inside `main` at RUSTLIB/std/src/macros.rs:LL:CC = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info) +Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation: +ALLOC (stack variable, size: 132, align: 4) { + 0x00 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ + 0x10 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ + 0x20 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ + 0x30 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ + 0x40 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ + 0x50 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ + 0x60 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ + 0x70 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ + 0x80 │ __ __ __ __ │ ░░░░ +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs index 0c305eed6e187..16f07c7ee9943 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs @@ -9,7 +9,7 @@ use std::intrinsics::mir::*; pub unsafe fn deref_meta(p: *const *const [i32]) -> usize { mir! { { - RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data + RET = PtrMetadata(*p); //~ ERROR: /Undefined Behavior: .*, but memory is uninitialized/ Return() } } diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr index 1c22876ba4350..9bacd80f7d524 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x0..0x8], but memory is uninitialized at [0x0..0x8], and this operation requires initialized memory --> tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs:LL:CC | LL | RET = PtrMetadata(*p); @@ -14,6 +14,11 @@ note: inside `main` LL | let _meta = deref_meta(p.as_ptr().cast()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Uninitialized memory occurred at ALLOC[0x0..0x8], in this allocation: +ALLOC (stack variable, size: 16, align: 8) { + __ __ __ __ __ __ __ __ 04 00 00 00 00 00 00 00 │ ░░░░░░░░........ +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs index a2ffdc92c4e22..38db894537b78 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs @@ -9,7 +9,7 @@ use std::intrinsics::mir::*; pub unsafe fn deref_meta(p: *const *const [i32]) -> usize { mir! { { - RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data + RET = PtrMetadata(*p); //~ ERROR: /Undefined Behavior: .*, but memory is uninitialized/ Return() } } diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr index 00e63b1275f76..621325d72ff7a 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr @@ -12,7 +12,7 @@ LL | (*p.as_mut_ptr().cast::<[*const i32; 2]>())[0] = 4 as *const i32; = note: BACKTRACE: = note: inside `main` at tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs:LL:CC -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x8..0x10], but memory is uninitialized at [0x8..0x10], and this operation requires initialized memory --> tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs:LL:CC | LL | RET = PtrMetadata(*p); @@ -28,6 +28,11 @@ note: inside `main` LL | let _meta = deref_meta(p.as_ptr().cast()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Uninitialized memory occurred at ALLOC[0x8..0x10], in this allocation: +ALLOC (stack variable, size: 16, align: 8) { + ╾────0x4[wildcard]────╼ __ __ __ __ __ __ __ __ │ ╾──────╼░░░░░░░░ +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error; 1 warning emitted diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs index e5a51289a8ae6..179fd33ed7c4f 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs @@ -9,7 +9,7 @@ use std::intrinsics::mir::*; pub unsafe fn deref_meta(p: *const *const i32) -> () { mir! { { - RET = PtrMetadata(*p); //~ ERROR: Undefined Behavior: using uninitialized data + RET = PtrMetadata(*p); //~ ERROR: /Undefined Behavior: .*, but memory is uninitialized/ Return() } } diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr index 24066953d79f7..b0e452420570d 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x0..0x8], but memory is uninitialized at [0x0..0x8], and this operation requires initialized memory --> tests/fail/intrinsics/ptr_metadata_uninit_thin.rs:LL:CC | LL | RET = PtrMetadata(*p); @@ -14,6 +14,11 @@ note: inside `main` LL | let _meta = deref_meta(p.as_ptr()); | ^^^^^^^^^^^^^^^^^^^^^^ +Uninitialized memory occurred at ALLOC[0x0..0x8], in this allocation: +ALLOC (stack variable, size: 8, align: 8) { + __ __ __ __ __ __ __ __ │ ░░░░░░░░ +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/read_from_trivial_switch.rs b/src/tools/miri/tests/fail/read_from_trivial_switch.rs index d34b1cd582009..35117c80b7380 100644 --- a/src/tools/miri/tests/fail/read_from_trivial_switch.rs +++ b/src/tools/miri/tests/fail/read_from_trivial_switch.rs @@ -10,5 +10,5 @@ fn main() { let uninit: MaybeUninit = MaybeUninit::uninit(); let bad_ref: &i32 = unsafe { uninit.assume_init_ref() }; let &(0 | _) = bad_ref; - //~^ ERROR: Undefined Behavior: using uninitialized data, but this operation requires initialized memory + //~^ ERROR: /Undefined Behavior: .*, but memory is uninitialized .* requires initialized memory/ } diff --git a/src/tools/miri/tests/fail/read_from_trivial_switch.stderr b/src/tools/miri/tests/fail/read_from_trivial_switch.stderr index 923d836ee0c99..1d0c76c3c087f 100644 --- a/src/tools/miri/tests/fail/read_from_trivial_switch.stderr +++ b/src/tools/miri/tests/fail/read_from_trivial_switch.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory --> tests/fail/read_from_trivial_switch.rs:LL:CC | LL | let &(0 | _) = bad_ref; @@ -9,6 +9,11 @@ LL | let &(0 | _) = bad_ref; = note: BACKTRACE: = note: inside `main` at tests/fail/read_from_trivial_switch.rs:LL:CC +Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation: +ALLOC (stack variable, size: 4, align: 4) { + __ __ __ __ │ ░░░░ +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.stderr b/src/tools/miri/tests/fail/uninit/padding-enum.stderr index a9a5568f4e886..ee3867fc60ba8 100644 --- a/src/tools/miri/tests/fail/uninit/padding-enum.stderr +++ b/src/tools/miri/tests/fail/uninit/padding-enum.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x8..0x9], but memory is uninitialized at [0x8..0x9], and this operation requires initialized memory --> tests/fail/uninit/padding-enum.rs:LL:CC | LL | let _val = *c.add(padding_offset); @@ -9,6 +9,12 @@ LL | let _val = *c.add(padding_offset); = note: BACKTRACE: = note: inside `main` at tests/fail/uninit/padding-enum.rs:LL:CC +Uninitialized memory occurred at ALLOC[0x8..0x9], in this allocation: +ALLOC (stack variable, size: 24, align: 8) { + 0x00 │ 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ │ ........░░░░░░░░ + 0x10 │ __ __ __ __ __ __ __ __ │ ░░░░░░░░ +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/uninit/padding-pair.stderr b/src/tools/miri/tests/fail/uninit/padding-pair.stderr index d281a351d4153..a9841815de392 100644 --- a/src/tools/miri/tests/fail/uninit/padding-pair.stderr +++ b/src/tools/miri/tests/fail/uninit/padding-pair.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x9..0xa], but memory is uninitialized at [0x9..0xa], and this operation requires initialized memory --> tests/fail/uninit/padding-pair.rs:LL:CC | LL | let v = unsafe { *z.offset(first_undef) }; @@ -9,6 +9,11 @@ LL | let v = unsafe { *z.offset(first_undef) }; = note: BACKTRACE: = note: inside `main` at tests/fail/uninit/padding-pair.rs:LL:CC +Uninitialized memory occurred at ALLOC[0x9..0xa], in this allocation: +ALLOC (stack variable, size: 16, align: 8) { + 00 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ │ .........░░░░░░░ +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/uninit/padding-struct.stderr b/src/tools/miri/tests/fail/uninit/padding-struct.stderr index 3298f6a45106e..05d754625d3f3 100644 --- a/src/tools/miri/tests/fail/uninit/padding-struct.stderr +++ b/src/tools/miri/tests/fail/uninit/padding-struct.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x1..0x2], but memory is uninitialized at [0x1..0x2], and this operation requires initialized memory --> tests/fail/uninit/padding-struct.rs:LL:CC | LL | let _val = *c.add(1); @@ -9,6 +9,11 @@ LL | let _val = *c.add(1); = note: BACKTRACE: = note: inside `main` at tests/fail/uninit/padding-struct.rs:LL:CC +Uninitialized memory occurred at ALLOC[0x1..0x2], in this allocation: +ALLOC (stack variable, size: 4, align: 2) { + 00 __ 00 00 │ .░.. +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr index d92d05ae6319b..f6446a5a95b51 100644 --- a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr +++ b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x8..0x9], but memory is uninitialized at [0x8..0x9], and this operation requires initialized memory --> tests/fail/uninit/padding-wide-ptr.rs:LL:CC | LL | let _val = *c.add(mem::size_of::<*const u8>()); @@ -9,6 +9,11 @@ LL | let _val = *c.add(mem::size_of::<*const u8>()); = note: BACKTRACE: = note: inside `main` at tests/fail/uninit/padding-wide-ptr.rs:LL:CC +Uninitialized memory occurred at ALLOC[0x8..0x9], in this allocation: +ALLOC (stack variable, size: 16, align: 8) { + 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ │ ........░░░░░░░░ +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.stderr b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.stderr index 0ae0ce5de9cab..385d877e2ee24 100644 --- a/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.stderr +++ b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x9..0xa], but memory is uninitialized at [0x9..0xa], and this operation requires initialized memory --> tests/fail/uninit/transmute-pair-uninit.rs:LL:CC | LL | let v = unsafe { *z.offset(first_undef) }; @@ -9,6 +9,11 @@ LL | let v = unsafe { *z.offset(first_undef) }; = note: BACKTRACE: = note: inside `main` at tests/fail/uninit/transmute-pair-uninit.rs:LL:CC +Uninitialized memory occurred at ALLOC[0x9..0xa], in this allocation: +ALLOC (stack variable, size: 16, align: 8) { + 00 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ │ .........░░░░░░░ +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/uninit/uninit_byte_read.stderr b/src/tools/miri/tests/fail/uninit/uninit_byte_read.stderr index d2a5a2d383125..5a5aa12987c50 100644 --- a/src/tools/miri/tests/fail/uninit/uninit_byte_read.stderr +++ b/src/tools/miri/tests/fail/uninit/uninit_byte_read.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x5..0x6], but memory is uninitialized at [0x5..0x6], and this operation requires initialized memory --> tests/fail/uninit/uninit_byte_read.rs:LL:CC | LL | let undef = unsafe { *v.as_ptr().add(5) }; @@ -9,6 +9,11 @@ LL | let undef = unsafe { *v.as_ptr().add(5) }; = note: BACKTRACE: = note: inside `main` at tests/fail/uninit/uninit_byte_read.rs:LL:CC +Uninitialized memory occurred at ALLOC[0x5..0x6], in this allocation: +ALLOC (Rust heap, size: 10, align: 1) { + __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░ +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/validity/invalid_int_op.stderr b/src/tools/miri/tests/fail/validity/invalid_int_op.stderr index 6e24cadfc2054..0b1915621b246 100644 --- a/src/tools/miri/tests/fail/validity/invalid_int_op.stderr +++ b/src/tools/miri/tests/fail/validity/invalid_int_op.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory --> tests/fail/validity/invalid_int_op.rs:LL:CC | LL | let i = unsafe { std::mem::MaybeUninit::::uninit().assume_init() }; @@ -9,6 +9,11 @@ LL | let i = unsafe { std::mem::MaybeUninit::::uninit().assume_init() } = note: BACKTRACE: = note: inside `main` at tests/fail/validity/invalid_int_op.rs:LL:CC +Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation: +ALLOC (stack variable, size: 4, align: 4) { + __ __ __ __ │ ░░░░ +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr b/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr index 92b226fe0f718..107179516bc31 100644 --- a/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr +++ b/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr @@ -1,4 +1,4 @@ -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory --> $DIR/invalid-patterns.rs:40:32 | LL | get_flag::(); @@ -26,7 +26,7 @@ LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character 42 │ B } -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC1[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory --> $DIR/invalid-patterns.rs:44:58 | LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); diff --git a/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr b/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr index 92b226fe0f718..107179516bc31 100644 --- a/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr +++ b/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr @@ -1,4 +1,4 @@ -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory --> $DIR/invalid-patterns.rs:40:32 | LL | get_flag::(); @@ -26,7 +26,7 @@ LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character 42 │ B } -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC1[0x0..0x4], but memory is uninitialized at [0x1..0x4], and this operation requires initialized memory --> $DIR/invalid-patterns.rs:44:58 | LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); diff --git a/tests/ui/consts/const-err-enum-discriminant.stderr b/tests/ui/consts/const-err-enum-discriminant.stderr index 8724333ad7a53..f935d1054de63 100644 --- a/tests/ui/consts/const-err-enum-discriminant.stderr +++ b/tests/ui/consts/const-err-enum-discriminant.stderr @@ -1,4 +1,4 @@ -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC0[0x0..0x8], but memory is uninitialized at [0x0..0x8], and this operation requires initialized memory --> $DIR/const-err-enum-discriminant.rs:8:21 | LL | Boo = [unsafe { Foo { b: () }.a }; 4][3], diff --git a/tests/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr b/tests/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr index d28d6841ca9d3..65e846b5741eb 100644 --- a/tests/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr +++ b/tests/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr @@ -43,7 +43,7 @@ LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uin = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC0[0x0..0x10], but memory is uninitialized at [0x8..0x10], and this operation requires initialized memory --> $DIR/const-pointer-values-in-various-types.rs:42:47 | LL | const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 }; @@ -85,7 +85,7 @@ LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC1[0x0..0x10], but memory is uninitialized at [0x8..0x10], and this operation requires initialized memory --> $DIR/const-pointer-values-in-various-types.rs:57:47 | LL | const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 }; diff --git a/tests/ui/consts/const-eval/ub-enum-overwrite.stderr b/tests/ui/consts/const-eval/ub-enum-overwrite.stderr index 52af52d323669..14f369eace47a 100644 --- a/tests/ui/consts/const-eval/ub-enum-overwrite.stderr +++ b/tests/ui/consts/const-eval/ub-enum-overwrite.stderr @@ -1,4 +1,4 @@ -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC0[0x1..0x2], but memory is uninitialized at [0x1..0x2], and this operation requires initialized memory --> $DIR/ub-enum-overwrite.rs:11:14 | LL | unsafe { *p } diff --git a/tests/ui/consts/const-eval/ub-enum.stderr b/tests/ui/consts/const-eval/ub-enum.stderr index 29f7a1f051a71..6665830e2502f 100644 --- a/tests/ui/consts/const-eval/ub-enum.stderr +++ b/tests/ui/consts/const-eval/ub-enum.stderr @@ -56,7 +56,7 @@ LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC0[0x0..0x8], but memory is uninitialized at [0x0..0x8], and this operation requires initialized memory --> $DIR/ub-enum.rs:61:41 | LL | const BAD_ENUM2_UNDEF: Enum2 = unsafe { MaybeUninit { uninit: () }.init }; diff --git a/tests/ui/consts/const-eval/ub-nonnull.stderr b/tests/ui/consts/const-eval/ub-nonnull.stderr index 314141e48370d..c92797f330af0 100644 --- a/tests/ui/consts/const-eval/ub-nonnull.stderr +++ b/tests/ui/consts/const-eval/ub-nonnull.stderr @@ -37,7 +37,7 @@ LL | const NULL_USIZE: NonZero = unsafe { mem::transmute(0usize) }; HEX_DUMP } -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC2[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory --> $DIR/ub-nonnull.rs:36:38 | LL | const UNINIT: NonZero = unsafe { MaybeUninit { uninit: () }.init }; diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.stderr b/tests/ui/consts/const-eval/ub-ref-ptr.stderr index d5ccc396b9036..beb54e435341e 100644 --- a/tests/ui/consts/const-eval/ub-ref-ptr.stderr +++ b/tests/ui/consts/const-eval/ub-ref-ptr.stderr @@ -103,7 +103,7 @@ LL | const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; HEX_DUMP } -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC3[0x0..0x8], but memory is uninitialized at [0x0..0x8], and this operation requires initialized memory --> $DIR/ub-ref-ptr.rs:48:41 | LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init }; @@ -120,7 +120,7 @@ LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) }; HEX_DUMP } -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC4[0x0..0x8], but memory is uninitialized at [0x0..0x8], and this operation requires initialized memory --> $DIR/ub-ref-ptr.rs:53:38 | LL | const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init }; diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.stderr b/tests/ui/consts/const-eval/ub-wide-ptr.stderr index 8724dd9a3c0d3..a3eb5c7203192 100644 --- a/tests/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/tests/ui/consts/const-eval/ub-wide-ptr.stderr @@ -71,7 +71,7 @@ LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUni HEX_DUMP } -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC32[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory --> $DIR/ub-wide-ptr.rs:63:1 | LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { @@ -179,7 +179,7 @@ note: erroneous constant encountered LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC33[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory --> $DIR/ub-wide-ptr.rs:101:1 | LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { diff --git a/tests/ui/consts/const-eval/union-const-eval-field.stderr b/tests/ui/consts/const-eval/union-const-eval-field.stderr index 07ff4c3ca3647..deddf9e0b6d3b 100644 --- a/tests/ui/consts/const-eval/union-const-eval-field.stderr +++ b/tests/ui/consts/const-eval/union-const-eval-field.stderr @@ -1,4 +1,4 @@ -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC0[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory --> $DIR/union-const-eval-field.rs:28:37 | LL | const FIELD3: Field3 = unsafe { UNION.field3 }; diff --git a/tests/ui/consts/const-eval/union-ice.stderr b/tests/ui/consts/const-eval/union-ice.stderr index b00fcc91d68a0..826d7440a8087 100644 --- a/tests/ui/consts/const-eval/union-ice.stderr +++ b/tests/ui/consts/const-eval/union-ice.stderr @@ -1,16 +1,16 @@ -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC0[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory --> $DIR/union-ice.rs:14:33 | LL | const FIELD3: Field3 = unsafe { UNION.field3 }; | ^^^^^^^^^^^^ evaluation of `FIELD3` failed here -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC1[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory --> $DIR/union-ice.rs:19:17 | LL | b: unsafe { UNION.field3 }, | ^^^^^^^^^^^^ evaluation of `FIELD_PATH` failed here -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC2[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory --> $DIR/union-ice.rs:31:18 | LL | unsafe { UNION.field3 }, diff --git a/tests/ui/consts/const-eval/union-ub.32bit.stderr b/tests/ui/consts/const-eval/union-ub.32bit.stderr index 9f0697984e4c2..70bf2cf539081 100644 --- a/tests/ui/consts/const-eval/union-ub.32bit.stderr +++ b/tests/ui/consts/const-eval/union-ub.32bit.stderr @@ -9,7 +9,7 @@ LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool }; 2a │ * } -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC0[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory --> $DIR/union-ub.rs:35:36 | LL | const UNINIT_BOOL: bool = unsafe { DummyUnion { unit: () }.bool }; diff --git a/tests/ui/consts/const-eval/union-ub.64bit.stderr b/tests/ui/consts/const-eval/union-ub.64bit.stderr index 9f0697984e4c2..70bf2cf539081 100644 --- a/tests/ui/consts/const-eval/union-ub.64bit.stderr +++ b/tests/ui/consts/const-eval/union-ub.64bit.stderr @@ -9,7 +9,7 @@ LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool }; 2a │ * } -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC0[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory --> $DIR/union-ub.rs:35:36 | LL | const UNINIT_BOOL: bool = unsafe { DummyUnion { unit: () }.bool }; diff --git a/tests/ui/type/pattern_types/validity.rs b/tests/ui/type/pattern_types/validity.rs index a4e49692c98c6..432aacb9be3fe 100644 --- a/tests/ui/type/pattern_types/validity.rs +++ b/tests/ui/type/pattern_types/validity.rs @@ -11,7 +11,7 @@ const BAD: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(0) }; //~^ ERROR: constructing invalid value: encountered 0 const BAD_UNINIT: pattern_type!(u32 is 1..) = - //~^ ERROR: using uninitialized data, but this operation requires initialized memory + //~^ ERROR: this operation requires initialized memory unsafe { std::mem::transmute(std::mem::MaybeUninit::::uninit()) }; const BAD_PTR: pattern_type!(usize is 1..) = unsafe { std::mem::transmute(&42) }; @@ -27,7 +27,7 @@ const BAD_FOO: Foo = Foo(Bar(unsafe { std::mem::transmute(0) })); //~^ ERROR: constructing invalid value at .0.0: encountered 0 const CHAR_UNINIT: pattern_type!(char is 'A'..'Z') = - //~^ ERROR: using uninitialized data, but this operation requires initialized memory + //~^ ERROR: this operation requires initialized memory unsafe { std::mem::transmute(std::mem::MaybeUninit::::uninit()) }; const CHAR_OOB_PAT: pattern_type!(char is 'A'..'Z') = unsafe { std::mem::transmute('a') }; diff --git a/tests/ui/type/pattern_types/validity.stderr b/tests/ui/type/pattern_types/validity.stderr index 4f4c16028f6b7..76824055d8a1d 100644 --- a/tests/ui/type/pattern_types/validity.stderr +++ b/tests/ui/type/pattern_types/validity.stderr @@ -9,7 +9,7 @@ LL | const BAD: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(0) }; HEX_DUMP } -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory --> $DIR/validity.rs:13:1 | LL | const BAD_UNINIT: pattern_type!(u32 is 1..) = @@ -46,7 +46,7 @@ LL | const BAD_FOO: Foo = Foo(Bar(unsafe { std::mem::transmute(0) })); HEX_DUMP } -error[E0080]: using uninitialized data, but this operation requires initialized memory +error[E0080]: reading memory at ALLOC1[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory --> $DIR/validity.rs:29:1 | LL | const CHAR_UNINIT: pattern_type!(char is 'A'..'Z') = From 2ce0b665d37bceddb29e6dbd45172299380e13f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 18 Jun 2025 15:35:22 +0200 Subject: [PATCH 07/19] HIR ty lowering: Simplify signature of `lower_poly_trait_ref` --- .../src/hir_ty_lowering/bounds.rs | 6 +-- .../src/hir_ty_lowering/dyn_compatibility.rs | 24 ++++------- .../src/hir_ty_lowering/mod.rs | 13 +++--- ...utually-exclusive-trait-bound-modifiers.rs | 3 ++ ...lly-exclusive-trait-bound-modifiers.stderr | 40 ++++++++++++++++--- 5 files changed, 54 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 9a752aeccdd2c..b59ff863383fa 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -482,12 +482,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { match hir_bound { hir::GenericBound::Trait(poly_trait_ref) => { - let hir::TraitBoundModifiers { constness, polarity } = poly_trait_ref.modifiers; let _ = self.lower_poly_trait_ref( - &poly_trait_ref.trait_ref, - poly_trait_ref.span, - constness, - polarity, + poly_trait_ref, param_ty, bounds, predicate_filter, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 364ad38556be0..474025e07afc5 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -18,9 +18,7 @@ use tracing::{debug, instrument}; use super::HirTyLowerer; use crate::errors::SelfInTypeAlias; -use crate::hir_ty_lowering::{ - GenericArgCountMismatch, GenericArgCountResult, PredicateFilter, RegionInferReason, -}; +use crate::hir_ty_lowering::{GenericArgCountMismatch, PredicateFilter, RegionInferReason}; impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// Lower a trait object type from the HIR to our internal notion of a type. @@ -38,24 +36,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut user_written_bounds = Vec::new(); let mut potential_assoc_types = Vec::new(); - for trait_bound in hir_bounds.iter() { - if let hir::BoundPolarity::Maybe(_) = trait_bound.modifiers.polarity { + for poly_trait_ref in hir_bounds.iter() { + if let hir::BoundPolarity::Maybe(_) = poly_trait_ref.modifiers.polarity { continue; } - if let GenericArgCountResult { - correct: - Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }), - .. - } = self.lower_poly_trait_ref( - &trait_bound.trait_ref, - trait_bound.span, - trait_bound.modifiers.constness, - hir::BoundPolarity::Positive, + let result = self.lower_poly_trait_ref( + poly_trait_ref, dummy_self, &mut user_written_bounds, PredicateFilter::SelfOnly, - ) { - potential_assoc_types.extend(cur_potential_assoc_types); + ); + if let Err(GenericArgCountMismatch { invalid_args, .. }) = result.correct { + potential_assoc_types.extend(invalid_args); } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index a5bd7c1a34aef..5521f97059b8e 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -747,17 +747,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>` /// where `'a` is a bound region at depth 0. Similarly, the `trait_ref` would be `Bar<'a>`. /// The lowered poly-trait-ref will track this binder explicitly, however. - #[instrument(level = "debug", skip(self, span, constness, bounds))] + #[instrument(level = "debug", skip(self, bounds))] pub(crate) fn lower_poly_trait_ref( &self, - trait_ref: &hir::TraitRef<'tcx>, - span: Span, - constness: hir::BoundConstness, - polarity: hir::BoundPolarity, + poly_trait_ref: &hir::PolyTraitRef<'tcx>, self_ty: Ty<'tcx>, bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, predicate_filter: PredicateFilter, ) -> GenericArgCountResult { + // We use the *resolved* bound vars later instead of the HIR ones since the former + // also include the bound vars of the overarching predicate if applicable. + let hir::PolyTraitRef { bound_generic_params: _, modifiers, ref trait_ref, span } = + *poly_trait_ref; + let hir::TraitBoundModifiers { constness, polarity } = modifiers; + let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()); let trait_segment = trait_ref.path.segments.last().unwrap(); diff --git a/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.rs b/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.rs index 5f47778a1404f..8d1d3a4c79070 100644 --- a/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.rs +++ b/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.rs @@ -2,9 +2,12 @@ const fn maybe_const_maybe() {} //~^ ERROR `[const]` trait not allowed with `?` trait polarity modifier +//~| ERROR `[const]` can only be applied to `const` traits +//~| ERROR `[const]` can only be applied to `const` traits fn const_maybe() {} //~^ ERROR `const` trait not allowed with `?` trait polarity modifier +//~| ERROR `const` can only be applied to `const` traits const fn maybe_const_negative() {} //~^ ERROR `[const]` trait not allowed with `!` trait polarity modifier diff --git a/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.stderr b/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.stderr index 429131f905f0e..0ac40c512708d 100644 --- a/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.stderr +++ b/tests/ui/traits/const-traits/mutually-exclusive-trait-bound-modifiers.stderr @@ -7,7 +7,7 @@ LL | const fn maybe_const_maybe() {} | there is not a well-defined meaning for a `[const] ?` trait error: `const` trait not allowed with `?` trait polarity modifier - --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:6:25 + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:8:25 | LL | fn const_maybe() {} | ----- ^ @@ -15,7 +15,7 @@ LL | fn const_maybe() {} | there is not a well-defined meaning for a `const ?` trait error: `[const]` trait not allowed with `!` trait polarity modifier - --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:9:42 + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:12:42 | LL | const fn maybe_const_negative() {} | ------- ^ @@ -23,7 +23,7 @@ LL | const fn maybe_const_negative() {} | there is not a well-defined meaning for a `[const] !` trait error: `const` trait not allowed with `!` trait polarity modifier - --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:13:28 + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:16:28 | LL | fn const_negative() {} | ----- ^ @@ -31,16 +31,44 @@ LL | fn const_negative() {} | there is not a well-defined meaning for a `const !` trait error: negative bounds are not supported - --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:9:42 + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:12:42 | LL | const fn maybe_const_negative() {} | ^ error: negative bounds are not supported - --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:13:28 + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:16:28 | LL | fn const_negative() {} | ^ -error: aborting due to 6 previous errors +error: `[const]` can only be applied to `const` traits + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:3:31 + | +LL | const fn maybe_const_maybe() {} + | ^^^^^^^ can't be applied to `Sized` + | +note: `Sized` can't be used with `[const]` because it isn't `const` + --> $SRC_DIR/core/src/marker.rs:LL:COL + +error: `[const]` can only be applied to `const` traits + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:3:31 + | +LL | const fn maybe_const_maybe() {} + | ^^^^^^^ can't be applied to `Sized` + | +note: `Sized` can't be used with `[const]` because it isn't `const` + --> $SRC_DIR/core/src/marker.rs:LL:COL + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `const` can only be applied to `const` traits + --> $DIR/mutually-exclusive-trait-bound-modifiers.rs:8:19 + | +LL | fn const_maybe() {} + | ^^^^^ can't be applied to `Sized` + | +note: `Sized` can't be used with `const` because it isn't `const` + --> $SRC_DIR/core/src/marker.rs:LL:COL + +error: aborting due to 9 previous errors From 10d7e5faf20d019568de77503cb13f0203296d02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 18 Jun 2025 16:43:38 +0200 Subject: [PATCH 08/19] HIR ty lowering: Validate relaxed bounds in trait object types Only relevant to the internal feature `more_maybe_bounds`. --- .../src/hir_ty_lowering/dyn_compatibility.rs | 3 --- .../maybe-bounds-in-dyn-traits.rs | 4 +++ .../maybe-bounds-in-dyn-traits.stderr | 25 +++++++++++++++++-- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 474025e07afc5..813353c12aa02 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -37,9 +37,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut user_written_bounds = Vec::new(); let mut potential_assoc_types = Vec::new(); for poly_trait_ref in hir_bounds.iter() { - if let hir::BoundPolarity::Maybe(_) = poly_trait_ref.modifiers.polarity { - continue; - } let result = self.lower_poly_trait_ref( poly_trait_ref, dummy_self, diff --git a/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.rs b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.rs index 5069cd256b277..e7cca41a47eab 100644 --- a/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.rs +++ b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.rs @@ -64,4 +64,8 @@ fn main() { x.leak_foo(); //~^ ERROR the trait bound `dyn Trait: Leak` is not satisfied x.maybe_leak_foo(); + // Ensure that we validate the generic args of relaxed bounds in trait object types. + let _: dyn Trait + ?Leak<(), Undefined = ()>; + //~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied + //~| ERROR associated type `Undefined` not found for `Leak` } diff --git a/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr index 48745e40268d4..350233b7cbe9d 100644 --- a/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr +++ b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr @@ -18,6 +18,27 @@ note: required by a bound in `Trait::leak_foo` LL | fn leak_foo(&self) {} | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::leak_foo` -error: aborting due to 2 previous errors +error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/maybe-bounds-in-dyn-traits.rs:68:25 + | +LL | let _: dyn Trait + ?Leak<(), Undefined = ()>; + | ^^^^-------------------- help: remove the unnecessary generics + | | + | expected 0 generic arguments + | +note: trait defined here, with 0 generic parameters + --> $DIR/maybe-bounds-in-dyn-traits.rs:44:12 + | +LL | auto trait Leak {} + | ^^^^ + +error[E0220]: associated type `Undefined` not found for `Leak` + --> $DIR/maybe-bounds-in-dyn-traits.rs:68:34 + | +LL | let _: dyn Trait + ?Leak<(), Undefined = ()>; + | ^^^^^^^^^ associated type `Undefined` not found + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0107, E0220, E0277. +For more information about an error, try `rustc --explain E0107`. From 9788f59bbf893965db98dc633e64e4405414b698 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 18 Jun 2025 17:02:51 +0200 Subject: [PATCH 09/19] Update comment about `where Ty:` We no longer move trait predicates where the self ty is a ty param to "the bounds of a ty param". --- .../src/collect/predicates_of.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index f2f1560d8b223..cc53919626e63 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -267,20 +267,16 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen match predicate.kind { hir::WherePredicateKind::BoundPredicate(bound_pred) => { let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty); - let bound_vars = tcx.late_bound_vars(predicate.hir_id); - // Keep the type around in a dummy predicate, in case of no bounds. - // That way, `where Ty:` is not a complete noop (see #53696) and `Ty` - // is still checked for WF. + + // This is a `where Ty:` (sic!). if bound_pred.bounds.is_empty() { if let ty::Param(_) = ty.kind() { - // This is a `where T:`, which can be in the HIR from the - // transformation that moves `?Sized` to `T`'s declaration. - // We can skip the predicate because type parameters are - // trivially WF, but also we *should*, to avoid exposing - // users who never wrote `where Type:,` themselves, to - // compiler/tooling bugs from not handling WF predicates. + // We can skip the predicate because type parameters are trivially WF. } else { + // Keep the type around in a dummy predicate. That way, it's not a complete + // noop (see #53696) and `Ty` is still checked for WF. + let span = bound_pred.bounded_ty.span; let predicate = ty::Binder::bind_with_vars( ty::ClauseKind::WellFormed(ty.into()), From 1df99f22d3a1776b36fc00fc35626fd841f7242f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 18 Jun 2025 22:10:53 +0200 Subject: [PATCH 10/19] AST lowering: More robustly deal with relaxed bounds --- compiler/rustc_ast_lowering/messages.ftl | 3 - compiler/rustc_ast_lowering/src/errors.rs | 7 - compiler/rustc_ast_lowering/src/item.rs | 112 ++++++--------- compiler/rustc_ast_lowering/src/lib.rs | 128 +++++++++++++++--- compiler/rustc_ast_passes/messages.ftl | 5 - .../rustc_ast_passes/src/ast_validation.rs | 23 ---- compiler/rustc_ast_passes/src/errors.rs | 16 --- ...issing-associated_item_or_field_def_ids.rs | 5 +- ...ng-associated_item_or_field_def_ids.stderr | 24 ++-- ...ing-associated-items-of-undefined-trait.rs | 5 +- ...associated-items-of-undefined-trait.stderr | 27 ++-- .../feature-gate-more-maybe-bounds.stderr | 17 ++- .../sized-hierarchy/default-supertrait.stderr | 4 +- ...be-trait-bounds-forbidden-locations.stderr | 2 +- ...re.rs => relaxed-bounds-invalid-places.rs} | 3 + ...r => relaxed-bounds-invalid-places.stderr} | 16 +-- 16 files changed, 188 insertions(+), 209 deletions(-) rename tests/ui/unsized/{maybe-bounds-where.rs => relaxed-bounds-invalid-places.rs} (85%) rename tests/ui/unsized/{maybe-bounds-where.stderr => relaxed-bounds-invalid-places.stderr} (87%) diff --git a/compiler/rustc_ast_lowering/messages.ftl b/compiler/rustc_ast_lowering/messages.ftl index c6472fd45fa98..370b15d2871a9 100644 --- a/compiler/rustc_ast_lowering/messages.ftl +++ b/compiler/rustc_ast_lowering/messages.ftl @@ -127,9 +127,6 @@ ast_lowering_misplaced_impl_trait = `impl Trait` is not allowed in {$position} .note = `impl Trait` is only allowed in arguments and return types of functions and methods -ast_lowering_misplaced_relax_trait_bound = - `?Trait` bounds are only permitted at the point where a type parameter is declared - ast_lowering_never_pattern_with_body = a never pattern is always unreachable .label = this will never be executed diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index b444324ef9143..83f3a976e83f7 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -324,13 +324,6 @@ pub(crate) struct MisplacedDoubleDot { pub span: Span, } -#[derive(Diagnostic)] -#[diag(ast_lowering_misplaced_relax_trait_bound)] -pub(crate) struct MisplacedRelaxTraitBound { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(ast_lowering_match_arm_with_no_body)] pub(crate) struct MatchArmWithNoBody { diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index abd70c7517c83..ddf01b69e7f6a 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -16,14 +16,11 @@ use smallvec::{SmallVec, smallvec}; use thin_vec::ThinVec; use tracing::instrument; -use super::errors::{ - InvalidAbi, InvalidAbiSuggestion, MisplacedRelaxTraitBound, TupleStructWithDefault, - UnionWithDefault, -}; +use super::errors::{InvalidAbi, InvalidAbiSuggestion, TupleStructWithDefault, UnionWithDefault}; use super::stability::{enabled_names, gate_unstable_abi}; use super::{ AstOwner, FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode, - ResolverAstLoweringExt, + RelaxedBoundForbiddenReason, RelaxedBoundPolicy, ResolverAstLoweringExt, }; pub(super) struct ItemLowerer<'a, 'hir> { @@ -435,6 +432,7 @@ impl<'hir> LoweringContext<'_, 'hir> { |this| { let bounds = this.lower_param_bounds( bounds, + RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::SuperTrait), ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ); let items = this.arena.alloc_from_iter( @@ -455,6 +453,7 @@ impl<'hir> LoweringContext<'_, 'hir> { |this| { this.lower_param_bounds( bounds, + RelaxedBoundPolicy::Allowed, ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ) }, @@ -940,6 +939,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::TraitItemKind::Type( this.lower_param_bounds( bounds, + RelaxedBoundPolicy::Allowed, ImplTraitContext::Disallowed(ImplTraitPosition::Generic), ), ty, @@ -1677,61 +1677,6 @@ impl<'hir> LoweringContext<'_, 'hir> { assert!(self.impl_trait_defs.is_empty()); assert!(self.impl_trait_bounds.is_empty()); - // Error if `?Trait` bounds in where clauses don't refer directly to type parameters. - // Note: we used to clone these bounds directly onto the type parameter (and avoid lowering - // these into hir when we lower thee where clauses), but this makes it quite difficult to - // keep track of the Span info. Now, `::add_implicit_sized_bound` - // checks both param bounds and where clauses for `?Sized`. - for pred in &generics.where_clause.predicates { - let WherePredicateKind::BoundPredicate(bound_pred) = &pred.kind else { - continue; - }; - let compute_is_param = || { - // Check if the where clause type is a plain type parameter. - match self - .resolver - .get_partial_res(bound_pred.bounded_ty.id) - .and_then(|r| r.full_res()) - { - Some(Res::Def(DefKind::TyParam, def_id)) - if bound_pred.bound_generic_params.is_empty() => - { - generics - .params - .iter() - .any(|p| def_id == self.local_def_id(p.id).to_def_id()) - } - // Either the `bounded_ty` is not a plain type parameter, or - // it's not found in the generic type parameters list. - _ => false, - } - }; - // We only need to compute this once per `WherePredicate`, but don't - // need to compute this at all unless there is a Maybe bound. - let mut is_param: Option = None; - for bound in &bound_pred.bounds { - if !matches!( - *bound, - GenericBound::Trait(PolyTraitRef { - modifiers: TraitBoundModifiers { polarity: BoundPolarity::Maybe(_), .. }, - .. - }) - ) { - continue; - } - let is_param = *is_param.get_or_insert_with(compute_is_param); - if !is_param && !self.tcx.features().more_maybe_bounds() { - self.tcx - .sess - .create_feature_err( - MisplacedRelaxTraitBound { span: bound.span() }, - sym::more_maybe_bounds, - ) - .emit(); - } - } - } - let mut predicates: SmallVec<[hir::WherePredicate<'hir>; 4]> = SmallVec::new(); predicates.extend(generics.params.iter().filter_map(|param| { self.lower_generic_bound_predicate( @@ -1741,6 +1686,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ¶m.bounds, param.colon_span, generics.span, + RelaxedBoundPolicy::Allowed, itctx, PredicateOrigin::GenericParam, ) @@ -1750,7 +1696,7 @@ impl<'hir> LoweringContext<'_, 'hir> { .where_clause .predicates .iter() - .map(|predicate| self.lower_where_predicate(predicate)), + .map(|predicate| self.lower_where_predicate(predicate, &generics.params)), ); let mut params: SmallVec<[hir::GenericParam<'hir>; 4]> = self @@ -1827,6 +1773,7 @@ impl<'hir> LoweringContext<'_, 'hir> { bounds: &[GenericBound], colon_span: Option, parent_span: Span, + rbp: RelaxedBoundPolicy<'_>, itctx: ImplTraitContext, origin: PredicateOrigin, ) -> Option> { @@ -1835,7 +1782,7 @@ impl<'hir> LoweringContext<'_, 'hir> { return None; } - let bounds = self.lower_param_bounds(bounds, itctx); + let bounds = self.lower_param_bounds(bounds, rbp, itctx); let param_span = ident.span; @@ -1887,7 +1834,11 @@ impl<'hir> LoweringContext<'_, 'hir> { Some(hir::WherePredicate { hir_id, span, kind }) } - fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate<'hir> { + fn lower_where_predicate( + &mut self, + pred: &WherePredicate, + params: &[ast::GenericParam], + ) -> hir::WherePredicate<'hir> { let hir_id = self.lower_node_id(pred.id); let span = self.lower_span(pred.span); self.lower_attrs(hir_id, &pred.attrs, span); @@ -1896,17 +1847,29 @@ impl<'hir> LoweringContext<'_, 'hir> { bound_generic_params, bounded_ty, bounds, - }) => hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate { - bound_generic_params: self - .lower_generic_params(bound_generic_params, hir::GenericParamSource::Binder), - bounded_ty: self - .lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), - bounds: self.lower_param_bounds( - bounds, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), - ), - origin: PredicateOrigin::WhereClause, - }), + }) => { + let rbp = if bound_generic_params.is_empty() { + RelaxedBoundPolicy::AllowedIfOnTyParam(bounded_ty.id, params) + } else { + RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::LateBoundVarsInScope) + }; + hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate { + bound_generic_params: self.lower_generic_params( + bound_generic_params, + hir::GenericParamSource::Binder, + ), + bounded_ty: self.lower_ty( + bounded_ty, + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + ), + bounds: self.lower_param_bounds( + bounds, + rbp, + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + ), + origin: PredicateOrigin::WhereClause, + }) + } WherePredicateKind::RegionPredicate(WhereRegionPredicate { lifetime, bounds }) => { hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate { lifetime: self.lower_lifetime( @@ -1916,6 +1879,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ), bounds: self.lower_param_bounds( bounds, + RelaxedBoundPolicy::Allowed, ImplTraitContext::Disallowed(ImplTraitPosition::Bound), ), in_where_clause: true, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 1c96a375035aa..d3d521e83b090 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -53,14 +53,14 @@ use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId}; use rustc_hir::lints::DelayedLint; use rustc_hir::{ - self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, - LifetimeSource, LifetimeSyntax, ParamName, TraitCandidate, + self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource, + LifetimeSyntax, ParamName, TraitCandidate, }; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_macros::extension; use rustc_middle::span_bug; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; -use rustc_session::parse::add_feature_diagnostics; +use rustc_session::parse::{add_feature_diagnostics, feature_err}; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{DUMMY_SP, DesugaringKind, Span}; use smallvec::SmallVec; @@ -281,6 +281,24 @@ impl ResolverAstLowering { } } +/// How relaxed bounds `?Trait` should be treated. +/// +/// Relaxed bounds should only be allowed in places where we later +/// (namely during HIR ty lowering) perform *sized elaboration*. +#[derive(Clone, Copy, Debug)] +enum RelaxedBoundPolicy<'a> { + Allowed, + AllowedIfOnTyParam(NodeId, &'a [ast::GenericParam]), + Forbidden(RelaxedBoundForbiddenReason), +} + +#[derive(Clone, Copy, Debug)] +enum RelaxedBoundForbiddenReason { + TraitObjectTy, + SuperTrait, + LateBoundVarsInScope, +} + /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree, /// and if so, what meaning it has. #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -1084,10 +1102,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar))); hir::AssocItemConstraintKind::Equality { term: err_ty.into() } } else { - // Desugar `AssocTy: Bounds` into an assoc type binding where the - // later desugars into a trait predicate. - let bounds = self.lower_param_bounds(bounds, itctx); - + // FIXME(#135229): These should be forbidden! + let bounds = + self.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx); hir::AssocItemConstraintKind::Bound { bounds } } } @@ -1216,6 +1233,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: t.span, parens: ast::Parens::No, }, + RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::TraitObjectTy), itctx, ); let bounds = this.arena.alloc_from_iter([bound]); @@ -1271,7 +1289,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { parenthesized: hir::GenericArgsParentheses::No, span_ext: span, }); - let path = self.make_lang_item_qpath(LangItem::Pin, span, Some(args)); + let path = self.make_lang_item_qpath(hir::LangItem::Pin, span, Some(args)); hir::TyKind::Path(path) } TyKind::FnPtr(f) => { @@ -1332,7 +1350,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // takes care of rejecting invalid modifier combinations and // const trait bounds in trait object types. GenericBound::Trait(ty) => { - let trait_ref = this.lower_poly_trait_ref(ty, itctx); + let trait_ref = this.lower_poly_trait_ref( + ty, + RelaxedBoundPolicy::Forbidden( + RelaxedBoundForbiddenReason::TraitObjectTy, + ), + itctx, + ); Some(trait_ref) } GenericBound::Outlives(lifetime) => { @@ -1387,9 +1411,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } path } - ImplTraitContext::InBinding => { - hir::TyKind::TraitAscription(self.lower_param_bounds(bounds, itctx)) - } + ImplTraitContext::InBinding => hir::TyKind::TraitAscription( + self.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx), + ), ImplTraitContext::FeatureGated(position, feature) => { let guar = self .tcx @@ -1505,7 +1529,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None); self.lower_opaque_inner(opaque_ty_node_id, origin, opaque_ty_span, |this| { - this.lower_param_bounds(bounds, itctx) + this.lower_param_bounds(bounds, RelaxedBoundPolicy::Allowed, itctx) }) } @@ -1799,10 +1823,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bound( &mut self, tpb: &GenericBound, + rbp: RelaxedBoundPolicy<'_>, itctx: ImplTraitContext, ) -> hir::GenericBound<'hir> { match tpb { - GenericBound::Trait(p) => hir::GenericBound::Trait(self.lower_poly_trait_ref(p, itctx)), + GenericBound::Trait(p) => { + hir::GenericBound::Trait(self.lower_poly_trait_ref(p, rbp, itctx)) + } GenericBound::Outlives(lifetime) => hir::GenericBound::Outlives(self.lower_lifetime( lifetime, LifetimeSource::OutlivesBound, @@ -2017,19 +2044,75 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { #[instrument(level = "debug", skip(self))] fn lower_poly_trait_ref( &mut self, - p: &PolyTraitRef, + PolyTraitRef { bound_generic_params, modifiers, trait_ref, span, parens: _ }: &PolyTraitRef, + rbp: RelaxedBoundPolicy<'_>, itctx: ImplTraitContext, ) -> hir::PolyTraitRef<'hir> { let bound_generic_params = - self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params); - let trait_ref = self.lower_trait_ref(p.modifiers, &p.trait_ref, itctx); - let modifiers = self.lower_trait_bound_modifiers(p.modifiers); + self.lower_lifetime_binder(trait_ref.ref_id, bound_generic_params); + let trait_ref = self.lower_trait_ref(*modifiers, trait_ref, itctx); + let modifiers = self.lower_trait_bound_modifiers(*modifiers); + + if let ast::BoundPolarity::Maybe(_) = modifiers.polarity { + self.validate_relaxed_bound(trait_ref, *span, rbp); + } + hir::PolyTraitRef { bound_generic_params, modifiers, trait_ref, - span: self.lower_span(p.span), + span: self.lower_span(*span), + } + } + + fn validate_relaxed_bound( + &self, + trait_ref: hir::TraitRef<'_>, + span: Span, + rbp: RelaxedBoundPolicy<'_>, + ) { + let err = |message| feature_err(&self.tcx.sess, sym::more_maybe_bounds, span, message); + + match rbp { + RelaxedBoundPolicy::Allowed => return, + RelaxedBoundPolicy::AllowedIfOnTyParam(id, params) => { + if let Some(res) = self.resolver.get_partial_res(id).and_then(|r| r.full_res()) + && let Res::Def(DefKind::TyParam, def_id) = res + && params.iter().any(|p| def_id == self.local_def_id(p.id).to_def_id()) + { + return; + } + if self.tcx.features().more_maybe_bounds() { + return; + } + } + RelaxedBoundPolicy::Forbidden(reason) => { + if self.tcx.features().more_maybe_bounds() { + return; + } + + match reason { + RelaxedBoundForbiddenReason::TraitObjectTy => { + err("`?Trait` is not permitted in trait object types").emit(); + return; + } + RelaxedBoundForbiddenReason::SuperTrait => { + let mut diag = err("`?Trait` is not permitted in supertraits"); + if let Some(def_id) = trait_ref.trait_def_id() + && self.tcx.is_lang_item(def_id, hir::LangItem::Sized) + { + diag.note("traits are `?Sized` by default"); + } + diag.emit(); + return; + } + RelaxedBoundForbiddenReason::LateBoundVarsInScope => {} + }; + } } + + err("`?Trait` bounds are only permitted at the point where a type parameter is declared") + .emit(); } fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> { @@ -2040,17 +2123,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_param_bounds( &mut self, bounds: &[GenericBound], + rbp: RelaxedBoundPolicy<'_>, itctx: ImplTraitContext, ) -> hir::GenericBounds<'hir> { - self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx)) + self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, rbp, itctx)) } fn lower_param_bounds_mut( &mut self, bounds: &[GenericBound], + rbp: RelaxedBoundPolicy<'_>, itctx: ImplTraitContext, ) -> impl Iterator> { - bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx)) + bounds.iter().map(move |bound| self.lower_param_bound(bound, rbp, itctx)) } #[instrument(level = "debug", skip(self), ret)] @@ -2084,6 +2169,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { bounds, /* colon_span */ None, span, + RelaxedBoundPolicy::Allowed, ImplTraitContext::Universal, hir::PredicateOrigin::ImplTrait, ); diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index e419154d65d1b..af93d55c89826 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -212,11 +212,6 @@ ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier ast_passes_obsolete_auto = `impl Trait for .. {"{}"}` is an obsolete syntax .help = use `auto trait Trait {"{}"}` instead -ast_passes_optional_trait_object = `?Trait` is not permitted in trait object types - -ast_passes_optional_trait_supertrait = `?Trait` is not permitted in supertraits - .note = traits are `?{$path_str}` by default - ast_passes_out_of_order_params = {$param_ord} parameters must be declared prior to {$max_param} parameters .suggestion = reorder the parameters: lifetimes, then consts and types diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index c69250c03052e..a08dae1115307 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1381,29 +1381,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { match bound { GenericBound::Trait(trait_ref) => { match (ctxt, trait_ref.modifiers.constness, trait_ref.modifiers.polarity) { - (BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_)) - if !self.features.more_maybe_bounds() => - { - self.sess - .create_feature_err( - errors::OptionalTraitSupertrait { - span: trait_ref.span, - path_str: pprust::path_to_string(&trait_ref.trait_ref.path), - }, - sym::more_maybe_bounds, - ) - .emit(); - } - (BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_)) - if !self.features.more_maybe_bounds() => - { - self.sess - .create_feature_err( - errors::OptionalTraitObject { span: trait_ref.span }, - sym::more_maybe_bounds, - ) - .emit(); - } ( BoundKind::TraitObject, BoundConstness::Always(_), diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index c1ebd025c7a46..fd4b2528541e3 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -566,22 +566,6 @@ pub(crate) struct NestedLifetimes { pub span: Span, } -#[derive(Diagnostic)] -#[diag(ast_passes_optional_trait_supertrait)] -#[note] -pub(crate) struct OptionalTraitSupertrait { - #[primary_span] - pub span: Span, - pub path_str: String, -} - -#[derive(Diagnostic)] -#[diag(ast_passes_optional_trait_object)] -pub(crate) struct OptionalTraitObject { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(ast_passes_const_bound_trait_object)] pub(crate) struct ConstBoundTraitObject { diff --git a/tests/ui/associated-item/missing-associated_item_or_field_def_ids.rs b/tests/ui/associated-item/missing-associated_item_or_field_def_ids.rs index b90bb9ea4ddf6..18c71e5c74429 100644 --- a/tests/ui/associated-item/missing-associated_item_or_field_def_ids.rs +++ b/tests/ui/associated-item/missing-associated_item_or_field_def_ids.rs @@ -1,8 +1,7 @@ // Regression test for . fn main() -> dyn Iterator + ?Iterator::advance_by(usize) { - //~^ ERROR `?Trait` is not permitted in trait object types - //~| ERROR expected trait, found associated function `Iterator::advance_by` - //~| ERROR the value of the associated type `Item` in `Iterator` must be specified + //~^ ERROR expected trait, found associated function `Iterator::advance_by` + //~| ERROR `?Trait` is not permitted in trait object types todo!() } diff --git a/tests/ui/associated-item/missing-associated_item_or_field_def_ids.stderr b/tests/ui/associated-item/missing-associated_item_or_field_def_ids.stderr index 7f0fbc800ed1c..6ec8e01c78d38 100644 --- a/tests/ui/associated-item/missing-associated_item_or_field_def_ids.stderr +++ b/tests/ui/associated-item/missing-associated_item_or_field_def_ids.stderr @@ -1,25 +1,19 @@ -error[E0658]: `?Trait` is not permitted in trait object types - --> $DIR/missing-associated_item_or_field_def_ids.rs:3:29 - | -LL | fn main() -> dyn Iterator + ?Iterator::advance_by(usize) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0404]: expected trait, found associated function `Iterator::advance_by` --> $DIR/missing-associated_item_or_field_def_ids.rs:3:30 | LL | fn main() -> dyn Iterator + ?Iterator::advance_by(usize) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a trait -error[E0191]: the value of the associated type `Item` in `Iterator` must be specified - --> $DIR/missing-associated_item_or_field_def_ids.rs:3:18 +error[E0658]: `?Trait` is not permitted in trait object types + --> $DIR/missing-associated_item_or_field_def_ids.rs:3:29 | LL | fn main() -> dyn Iterator + ?Iterator::advance_by(usize) { - | ^^^^^^^^ help: specify the associated type: `Iterator` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0191, E0404, E0658. -For more information about an error, try `rustc --explain E0191`. +Some errors have detailed explanations: E0404, E0658. +For more information about an error, try `rustc --explain E0404`. diff --git a/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.rs b/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.rs index f6b749a5100b9..9e0a86abb2e0b 100644 --- a/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.rs +++ b/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.rs @@ -6,7 +6,6 @@ trait Tr { fn main() { let _: dyn Tr + ?Foo; - //~^ ERROR: `?Trait` is not permitted in trait object types - //~| ERROR: cannot find trait `Foo` in this scope - //~| ERROR: the value of the associated type `Item` in `Tr` must be specified + //~^ ERROR: cannot find trait `Foo` in this scope + //~| ERROR: `?Trait` is not permitted in trait object types } diff --git a/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.stderr b/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.stderr index f31a1de76a790..bd83c1a9ea892 100644 --- a/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.stderr +++ b/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.stderr @@ -1,28 +1,19 @@ -error[E0658]: `?Trait` is not permitted in trait object types - --> $DIR/avoid-getting-associated-items-of-undefined-trait.rs:8:21 - | -LL | let _: dyn Tr + ?Foo; - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error[E0405]: cannot find trait `Foo` in this scope --> $DIR/avoid-getting-associated-items-of-undefined-trait.rs:8:22 | LL | let _: dyn Tr + ?Foo; | ^^^ not found in this scope -error[E0191]: the value of the associated type `Item` in `Tr` must be specified - --> $DIR/avoid-getting-associated-items-of-undefined-trait.rs:8:16 +error[E0658]: `?Trait` is not permitted in trait object types + --> $DIR/avoid-getting-associated-items-of-undefined-trait.rs:8:21 | -LL | type Item; - | --------- `Item` defined here -... LL | let _: dyn Tr + ?Foo; - | ^^ help: specify the associated type: `Tr` + | ^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0191, E0405, E0658. -For more information about an error, try `rustc --explain E0191`. +Some errors have detailed explanations: E0405, E0658. +For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr index 729df4eb37cac..f52532a035b46 100644 --- a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr @@ -4,24 +4,23 @@ error[E0658]: `?Trait` is not permitted in supertraits LL | trait Trait3: ?Trait1 {} | ^^^^^^^ | - = note: traits are `?Trait1` by default = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: `?Trait` is not permitted in trait object types - --> $DIR/feature-gate-more-maybe-bounds.rs:10:28 +error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared + --> $DIR/feature-gate-more-maybe-bounds.rs:7:26 | -LL | fn foo(_: Box) {} - | ^^^^^^^ +LL | trait Trait4 where Self: ?Trait1 {} + | ^^^^^^^ | = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/feature-gate-more-maybe-bounds.rs:7:26 +error[E0658]: `?Trait` is not permitted in trait object types + --> $DIR/feature-gate-more-maybe-bounds.rs:10:28 | -LL | trait Trait4 where Self: ?Trait1 {} - | ^^^^^^^ +LL | fn foo(_: Box) {} + | ^^^^^^^ | = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/sized-hierarchy/default-supertrait.stderr b/tests/ui/sized-hierarchy/default-supertrait.stderr index de23936b900bc..0cb4f346a6300 100644 --- a/tests/ui/sized-hierarchy/default-supertrait.stderr +++ b/tests/ui/sized-hierarchy/default-supertrait.stderr @@ -4,9 +4,9 @@ error[E0658]: `?Trait` is not permitted in supertraits LL | trait NegSized: ?Sized { } | ^^^^^^ | - = note: traits are `?Sized` by default = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: traits are `?Sized` by default error[E0658]: `?Trait` is not permitted in supertraits --> $DIR/default-supertrait.rs:13:21 @@ -14,7 +14,6 @@ error[E0658]: `?Trait` is not permitted in supertraits LL | trait NegMetaSized: ?MetaSized { } | ^^^^^^^^^^ | - = note: traits are `?MetaSized` by default = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date @@ -24,7 +23,6 @@ error[E0658]: `?Trait` is not permitted in supertraits LL | trait NegPointeeSized: ?PointeeSized { } | ^^^^^^^^^^^^^ | - = note: traits are `?PointeeSized` by default = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/traits/maybe-trait-bounds-forbidden-locations.stderr b/tests/ui/traits/maybe-trait-bounds-forbidden-locations.stderr index bd0baa580bdf5..5c4100d0e269f 100644 --- a/tests/ui/traits/maybe-trait-bounds-forbidden-locations.stderr +++ b/tests/ui/traits/maybe-trait-bounds-forbidden-locations.stderr @@ -4,9 +4,9 @@ error[E0658]: `?Trait` is not permitted in supertraits LL | trait Tr: ?Sized {} | ^^^^^^ | - = note: traits are `?Sized` by default = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: traits are `?Sized` by default error[E0658]: `?Trait` is not permitted in trait object types --> $DIR/maybe-trait-bounds-forbidden-locations.rs:13:20 diff --git a/tests/ui/unsized/maybe-bounds-where.rs b/tests/ui/unsized/relaxed-bounds-invalid-places.rs similarity index 85% rename from tests/ui/unsized/maybe-bounds-where.rs rename to tests/ui/unsized/relaxed-bounds-invalid-places.rs index 4c4141631a7c5..ce3f35608bebb 100644 --- a/tests/ui/unsized/maybe-bounds-where.rs +++ b/tests/ui/unsized/relaxed-bounds-invalid-places.rs @@ -1,3 +1,6 @@ +// Test that relaxed bounds can only be placed on type parameters defined by the closest item +// (ignoring relaxed bounds inside `impl Trait` and in associated type defs here). + struct S1(T) where (T): ?Sized; //~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared diff --git a/tests/ui/unsized/maybe-bounds-where.stderr b/tests/ui/unsized/relaxed-bounds-invalid-places.stderr similarity index 87% rename from tests/ui/unsized/maybe-bounds-where.stderr rename to tests/ui/unsized/relaxed-bounds-invalid-places.stderr index fb6d37c29660a..3287eb8d1e9d5 100644 --- a/tests/ui/unsized/maybe-bounds-where.stderr +++ b/tests/ui/unsized/relaxed-bounds-invalid-places.stderr @@ -1,5 +1,5 @@ error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/maybe-bounds-where.rs:1:28 + --> $DIR/relaxed-bounds-invalid-places.rs:4:28 | LL | struct S1(T) where (T): ?Sized; | ^^^^^^ @@ -8,7 +8,7 @@ LL | struct S1(T) where (T): ?Sized; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/maybe-bounds-where.rs:4:27 + --> $DIR/relaxed-bounds-invalid-places.rs:7:27 | LL | struct S2(T) where u8: ?Sized; | ^^^^^^ @@ -17,7 +17,7 @@ LL | struct S2(T) where u8: ?Sized; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/maybe-bounds-where.rs:7:35 + --> $DIR/relaxed-bounds-invalid-places.rs:10:35 | LL | struct S3(T) where &'static T: ?Sized; | ^^^^^^ @@ -26,7 +26,7 @@ LL | struct S3(T) where &'static T: ?Sized; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/maybe-bounds-where.rs:12:34 + --> $DIR/relaxed-bounds-invalid-places.rs:15:34 | LL | struct S4(T) where for<'a> T: ?Trait<'a>; | ^^^^^^^^^^ @@ -35,7 +35,7 @@ LL | struct S4(T) where for<'a> T: ?Trait<'a>; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/maybe-bounds-where.rs:21:21 + --> $DIR/relaxed-bounds-invalid-places.rs:24:21 | LL | fn f() where T: ?Sized {} | ^^^^^^ @@ -44,13 +44,13 @@ LL | fn f() where T: ?Sized {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/maybe-bounds-where.rs:12:34 + --> $DIR/relaxed-bounds-invalid-places.rs:15:34 | LL | struct S4(T) where for<'a> T: ?Trait<'a>; | ^^^^^^^^^^ error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/maybe-bounds-where.rs:16:33 + --> $DIR/relaxed-bounds-invalid-places.rs:19:33 | LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; | ^^^^^^^^^^^^^^^ ^^^^^^ @@ -59,7 +59,7 @@ LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/maybe-bounds-where.rs:16:33 + --> $DIR/relaxed-bounds-invalid-places.rs:19:33 | LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; | ^^^^^^^^^^^^^^^ From 652ba279ecc693d8b4310c40e645a62009f5b0ed Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 18 Jun 2025 12:51:47 +0000 Subject: [PATCH 11/19] Show the memory of uninit reads --- .../rustc_const_eval/src/const_eval/error.rs | 25 ++++-- .../src/const_eval/eval_queries.rs | 4 +- .../libc_pthread_cond_double_destroy.rs | 2 + .../libc_pthread_cond_double_destroy.stderr | 10 +-- .../libc_pthread_condattr_double_destroy.rs | 2 + ...ibc_pthread_condattr_double_destroy.stderr | 8 +- .../libc_pthread_mutex_double_destroy.rs | 2 + .../libc_pthread_mutex_double_destroy.stderr | 10 +-- .../libc_pthread_mutexattr_double_destroy.rs | 2 + ...bc_pthread_mutexattr_double_destroy.stderr | 8 +- .../libc_pthread_rwlock_double_destroy.rs | 2 + .../libc_pthread_rwlock_double_destroy.stderr | 11 +-- .../ptr_metadata_uninit_slice_data.rs | 5 +- .../ptr_metadata_uninit_slice_data.stderr | 8 +- .../ptr_metadata_uninit_slice_len.rs | 5 +- .../ptr_metadata_uninit_slice_len.stderr | 8 +- .../intrinsics/ptr_metadata_uninit_thin.rs | 3 + .../ptr_metadata_uninit_thin.stderr | 8 +- .../tests/fail/read_from_trivial_switch.rs | 3 + .../fail/read_from_trivial_switch.stderr | 8 +- .../miri/tests/fail/uninit/padding-enum.rs | 3 + .../tests/fail/uninit/padding-enum.stderr | 9 +-- .../miri/tests/fail/uninit/padding-pair.rs | 3 + .../tests/fail/uninit/padding-pair.stderr | 8 +- .../tests/fail/uninit/padding-wide-ptr.rs | 3 + .../tests/fail/uninit/padding-wide-ptr.stderr | 8 +- .../fail/uninit/transmute-pair-uninit.rs | 3 + .../fail/uninit/transmute-pair-uninit.stderr | 8 +- .../native-lib/fail/tracing/partial_init.rs | 2 +- .../fail/tracing/partial_init.stderr | 7 +- .../invalid-patterns.32bit.stderr | 8 ++ .../invalid-patterns.64bit.stderr | 8 ++ tests/ui/consts/const-compare-bytes-ub.stderr | 8 ++ .../const-err-enum-discriminant.32bit.stderr | 13 ++++ ... const-err-enum-discriminant.64bit.stderr} | 6 +- .../ui/consts/const-err-enum-discriminant.rs | 2 + ...inter-values-in-various-types.64bit.stderr | 12 ++- .../const-eval/ub-enum-overwrite.stderr | 4 + tests/ui/consts/const-eval/ub-enum.rs | 3 +- tests/ui/consts/const-eval/ub-enum.stderr | 34 +++++---- tests/ui/consts/const-eval/ub-nonnull.stderr | 4 + tests/ui/consts/const-eval/ub-ref-ptr.rs | 3 +- tests/ui/consts/const-eval/ub-ref-ptr.stderr | 46 ++++++----- tests/ui/consts/const-eval/ub-wide-ptr.rs | 7 +- tests/ui/consts/const-eval/ub-wide-ptr.stderr | 76 ++++++++++--------- .../const-eval/union-const-eval-field.rs | 1 + .../const-eval/union-const-eval-field.stderr | 10 ++- tests/ui/consts/const-eval/union-ice.stderr | 12 +++ .../consts/const-eval/union-ub.32bit.stderr | 4 + .../consts/const-eval/union-ub.64bit.stderr | 4 + .../intrinsic-raw_eq-const-bad.stderr | 4 + tests/ui/type/pattern_types/validity.stderr | 8 ++ 52 files changed, 302 insertions(+), 163 deletions(-) create mode 100644 tests/ui/consts/const-err-enum-discriminant.32bit.stderr rename tests/ui/consts/{const-err-enum-discriminant.stderr => const-err-enum-discriminant.64bit.stderr} (64%) diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 3e880d0200133..e00fb2c1eaf98 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -2,17 +2,17 @@ use std::mem; use rustc_errors::{Diag, DiagArgName, DiagArgValue, DiagMessage, IntoDiagArg}; use rustc_middle::mir::AssertKind; -use rustc_middle::mir::interpret::{AllocId, Provenance, ReportedErrorInfo}; +use rustc_middle::mir::interpret::{AllocId, Provenance, ReportedErrorInfo, UndefinedBehaviorInfo}; use rustc_middle::query::TyCtxtAt; +use rustc_middle::ty::ConstInt; use rustc_middle::ty::layout::LayoutError; -use rustc_middle::ty::{ConstInt, TyCtxt}; use rustc_span::{Span, Symbol}; use super::CompileTimeMachine; use crate::errors::{self, FrameNote, ReportErrorExt}; use crate::interpret::{ - CtfeProvenance, ErrorHandled, Frame, InterpErrorInfo, InterpErrorKind, MachineStopType, - Pointer, err_inval, err_machine_stop, + CtfeProvenance, ErrorHandled, Frame, InterpCx, InterpErrorInfo, InterpErrorKind, + MachineStopType, Pointer, err_inval, err_machine_stop, }; /// The CTFE machine has some custom error kinds. @@ -163,7 +163,7 @@ pub fn get_span_and_frames<'tcx>( /// You can use it to add a stacktrace of current execution according to /// `get_span_and_frames` or just give context on where the const eval error happened. pub(super) fn report<'tcx, C, F>( - tcx: TyCtxt<'tcx>, + ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>, error: InterpErrorKind<'tcx>, span: Span, get_span_and_frames: C, @@ -173,6 +173,7 @@ where C: FnOnce() -> (Span, Vec), F: FnOnce(&mut Diag<'_>, Span, Vec), { + let tcx = ecx.tcx.tcx; // Special handling for certain errors match error { // Don't emit a new diagnostic for these errors, they are already reported elsewhere or @@ -198,6 +199,20 @@ where InterpErrorKind::ResourceExhaustion(_) | InterpErrorKind::InvalidProgram(_) ); + if let InterpErrorKind::UndefinedBehavior(UndefinedBehaviorInfo::InvalidUninitBytes( + Some((alloc_id, _access)), + )) = error + { + let bytes = ecx.print_alloc_bytes_for_diagnostics(alloc_id); + let info = ecx.get_alloc_info(alloc_id); + let raw_bytes = errors::RawBytesNote { + size: info.size.bytes(), + align: info.align.bytes(), + bytes, + }; + err.subdiagnostic(raw_bytes); + } + error.add_args(&mut err); mk(&mut err, span, frames); diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index ce72d59b8b0e4..f584f6c948e5f 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -411,7 +411,7 @@ fn report_eval_error<'tcx>( let instance = with_no_trimmed_paths!(cid.instance.to_string()); super::report( - *ecx.tcx, + ecx, error, DUMMY_SP, || super::get_span_and_frames(ecx.tcx, ecx.stack()), @@ -451,7 +451,7 @@ fn report_validation_error<'tcx>( errors::RawBytesNote { size: info.size.bytes(), align: info.align.bytes(), bytes }; crate::const_eval::report( - *ecx.tcx, + ecx, error, DUMMY_SP, || crate::const_eval::get_span_and_frames(ecx.tcx, ecx.stack()), diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs index 8624e4d28fbeb..5778765589de9 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs @@ -1,4 +1,6 @@ //@ignore-target: windows # No pthreads on Windows +//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}" +//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]" /// Test that destroying a pthread_cond twice fails, even without a check for number validity diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.stderr index 3318ac7fca592..6156070cf9551 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory --> tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs:LL:CC | LL | libc::pthread_cond_destroy(cond.as_mut_ptr()); @@ -9,12 +9,8 @@ LL | libc::pthread_cond_destroy(cond.as_mut_ptr()); = note: BACKTRACE: = note: inside `main` at tests/fail-dep/concurrency/libc_pthread_cond_double_destroy.rs:LL:CC -Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation: -ALLOC (stack variable, size: 48, align: 8) { - 0x00 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ - 0x10 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ - 0x20 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ -} +Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation: +ALLOC DUMP note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.rs index a510ee77cfb2e..9116966049123 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.rs @@ -1,5 +1,7 @@ //@ignore-target: windows # No pthreads on Windows //@ignore-target: apple # Our macOS condattr don't have any fields so we do not notice this. +//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}" +//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]" /// Test that destroying a pthread_condattr twice fails, even without a check for number validity diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.stderr index 1971bbc721031..da64970ff2e20 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory --> tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.rs:LL:CC | LL | libc::pthread_condattr_destroy(attr.as_mut_ptr()); @@ -9,10 +9,8 @@ LL | libc::pthread_condattr_destroy(attr.as_mut_ptr()); = note: BACKTRACE: = note: inside `main` at tests/fail-dep/concurrency/libc_pthread_condattr_double_destroy.rs:LL:CC -Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation: -ALLOC (stack variable, size: 4, align: 4) { - __ __ __ __ │ ░░░░ -} +Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation: +ALLOC DUMP note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs index 71a8029203299..f04fe8be6b38d 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs @@ -1,4 +1,6 @@ //@ignore-target: windows # No pthreads on Windows +//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}" +//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]" /// Test that destroying a pthread_mutex twice fails, even without a check for number validity diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.stderr index 251f8036e383b..05db823b252bc 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory --> tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs:LL:CC | LL | libc::pthread_mutex_destroy(mutex.as_mut_ptr()); @@ -9,12 +9,8 @@ LL | libc::pthread_mutex_destroy(mutex.as_mut_ptr()); = note: BACKTRACE: = note: inside `main` at tests/fail-dep/concurrency/libc_pthread_mutex_double_destroy.rs:LL:CC -Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation: -ALLOC (stack variable, size: 40, align: 8) { - 0x00 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ - 0x10 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ - 0x20 │ __ __ __ __ __ __ __ __ │ ░░░░░░░░ -} +Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation: +ALLOC DUMP note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.rs index 28dacc9931a42..d9daf5259bbaf 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.rs @@ -1,4 +1,6 @@ //@ignore-target: windows # No pthreads on Windows +//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}" +//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]" /// Test that destroying a pthread_mutexattr twice fails, even without a check for number validity diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.stderr index b341efb7770c6..ee3883de36ba6 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory --> tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.rs:LL:CC | LL | libc::pthread_mutexattr_destroy(attr.as_mut_ptr()); @@ -9,10 +9,8 @@ LL | libc::pthread_mutexattr_destroy(attr.as_mut_ptr()); = note: BACKTRACE: = note: inside `main` at tests/fail-dep/concurrency/libc_pthread_mutexattr_double_destroy.rs:LL:CC -Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation: -ALLOC (stack variable, size: 4, align: 4) { - __ __ __ __ │ ░░░░ -} +Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation: +ALLOC DUMP note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs index a46a124bf2ecc..720ba71d23834 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs @@ -1,4 +1,6 @@ //@ignore-target: windows # No pthreads on Windows +//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}" +//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]" /// Test that destroying a pthread_rwlock twice fails, even without a check for number validity diff --git a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.stderr b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.stderr index 8f388577a27d4..430398dc8fd73 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory --> tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs:LL:CC | LL | libc::pthread_rwlock_destroy(&mut lock); @@ -9,13 +9,8 @@ LL | libc::pthread_rwlock_destroy(&mut lock); = note: BACKTRACE: = note: inside `main` at tests/fail-dep/concurrency/libc_pthread_rwlock_double_destroy.rs:LL:CC -Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation: -ALLOC (stack variable, size: 56, align: 8) { - 0x00 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ - 0x10 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ - 0x20 │ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ │ ░░░░░░░░░░░░░░░░ - 0x30 │ __ __ __ __ __ __ __ __ │ ░░░░░░░░ -} +Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation: +ALLOC DUMP note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs index 16f07c7ee9943..c03e468cfbaa3 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs @@ -1,4 +1,7 @@ //@compile-flags: -Zmiri-disable-validation +//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}" +//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]" + #![feature(core_intrinsics, custom_mir)] use std::intrinsics::mir::*; @@ -9,7 +12,7 @@ use std::intrinsics::mir::*; pub unsafe fn deref_meta(p: *const *const [i32]) -> usize { mir! { { - RET = PtrMetadata(*p); //~ ERROR: /Undefined Behavior: .*, but memory is uninitialized/ + RET = PtrMetadata(*p); //~ ERROR: /Undefined Behavior: .* but memory is uninitialized/ Return() } } diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr index 9bacd80f7d524..1e7f500edb2dd 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_data.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: reading memory at ALLOC[0x0..0x8], but memory is uninitialized at [0x0..0x8], and this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory --> tests/fail/intrinsics/ptr_metadata_uninit_slice_data.rs:LL:CC | LL | RET = PtrMetadata(*p); @@ -14,10 +14,8 @@ note: inside `main` LL | let _meta = deref_meta(p.as_ptr().cast()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Uninitialized memory occurred at ALLOC[0x0..0x8], in this allocation: -ALLOC (stack variable, size: 16, align: 8) { - __ __ __ __ __ __ __ __ 04 00 00 00 00 00 00 00 │ ░░░░░░░░........ -} +Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation: +ALLOC DUMP note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs index 38db894537b78..7053c0f6e1872 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs @@ -1,4 +1,7 @@ //@compile-flags: -Zmiri-disable-validation +//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}" +//@ normalize-stderr-test: "\[0x[0-9a-z]+..0x[0-9a-z]+\]" -> "[0xX..0xY]" + #![feature(core_intrinsics, custom_mir)] use std::intrinsics::mir::*; @@ -9,7 +12,7 @@ use std::intrinsics::mir::*; pub unsafe fn deref_meta(p: *const *const [i32]) -> usize { mir! { { - RET = PtrMetadata(*p); //~ ERROR: /Undefined Behavior: .*, but memory is uninitialized/ + RET = PtrMetadata(*p); //~ ERROR: /Undefined Behavior: .* but memory is uninitialized/ Return() } } diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr index 621325d72ff7a..80b4c8bec0d75 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_slice_len.stderr @@ -12,7 +12,7 @@ LL | (*p.as_mut_ptr().cast::<[*const i32; 2]>())[0] = 4 as *const i32; = note: BACKTRACE: = note: inside `main` at tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs:LL:CC -error: Undefined Behavior: reading memory at ALLOC[0x8..0x10], but memory is uninitialized at [0x8..0x10], and this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory --> tests/fail/intrinsics/ptr_metadata_uninit_slice_len.rs:LL:CC | LL | RET = PtrMetadata(*p); @@ -28,10 +28,8 @@ note: inside `main` LL | let _meta = deref_meta(p.as_ptr().cast()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Uninitialized memory occurred at ALLOC[0x8..0x10], in this allocation: -ALLOC (stack variable, size: 16, align: 8) { - ╾────0x4[wildcard]────╼ __ __ __ __ __ __ __ __ │ ╾──────╼░░░░░░░░ -} +Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation: +ALLOC DUMP note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs index 179fd33ed7c4f..3ba2984733743 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.rs @@ -1,4 +1,7 @@ //@compile-flags: -Zmiri-disable-validation +//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}" +//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]" + #![feature(core_intrinsics, custom_mir)] use std::intrinsics::mir::*; diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr index b0e452420570d..7a1f3d6ea84f6 100644 --- a/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr +++ b/src/tools/miri/tests/fail/intrinsics/ptr_metadata_uninit_thin.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: reading memory at ALLOC[0x0..0x8], but memory is uninitialized at [0x0..0x8], and this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory --> tests/fail/intrinsics/ptr_metadata_uninit_thin.rs:LL:CC | LL | RET = PtrMetadata(*p); @@ -14,10 +14,8 @@ note: inside `main` LL | let _meta = deref_meta(p.as_ptr()); | ^^^^^^^^^^^^^^^^^^^^^^ -Uninitialized memory occurred at ALLOC[0x0..0x8], in this allocation: -ALLOC (stack variable, size: 8, align: 8) { - __ __ __ __ __ __ __ __ │ ░░░░░░░░ -} +Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation: +ALLOC DUMP note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/read_from_trivial_switch.rs b/src/tools/miri/tests/fail/read_from_trivial_switch.rs index 35117c80b7380..2696c42aeae2d 100644 --- a/src/tools/miri/tests/fail/read_from_trivial_switch.rs +++ b/src/tools/miri/tests/fail/read_from_trivial_switch.rs @@ -4,6 +4,9 @@ // // See . +//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}" +//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]" + use std::mem::MaybeUninit; fn main() { diff --git a/src/tools/miri/tests/fail/read_from_trivial_switch.stderr b/src/tools/miri/tests/fail/read_from_trivial_switch.stderr index 1d0c76c3c087f..1dcc341b7e674 100644 --- a/src/tools/miri/tests/fail/read_from_trivial_switch.stderr +++ b/src/tools/miri/tests/fail/read_from_trivial_switch.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: reading memory at ALLOC[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory --> tests/fail/read_from_trivial_switch.rs:LL:CC | LL | let &(0 | _) = bad_ref; @@ -9,10 +9,8 @@ LL | let &(0 | _) = bad_ref; = note: BACKTRACE: = note: inside `main` at tests/fail/read_from_trivial_switch.rs:LL:CC -Uninitialized memory occurred at ALLOC[0x0..0x4], in this allocation: -ALLOC (stack variable, size: 4, align: 4) { - __ __ __ __ │ ░░░░ -} +Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation: +ALLOC DUMP note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.rs b/src/tools/miri/tests/fail/uninit/padding-enum.rs index e1a16bea23ccb..606fa21016fd6 100644 --- a/src/tools/miri/tests/fail/uninit/padding-enum.rs +++ b/src/tools/miri/tests/fail/uninit/padding-enum.rs @@ -1,3 +1,6 @@ +//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}" +//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]" + use std::mem; // We have three fields to avoid the ScalarPair optimization. diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.stderr b/src/tools/miri/tests/fail/uninit/padding-enum.stderr index ee3867fc60ba8..64229ac881729 100644 --- a/src/tools/miri/tests/fail/uninit/padding-enum.stderr +++ b/src/tools/miri/tests/fail/uninit/padding-enum.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: reading memory at ALLOC[0x8..0x9], but memory is uninitialized at [0x8..0x9], and this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory --> tests/fail/uninit/padding-enum.rs:LL:CC | LL | let _val = *c.add(padding_offset); @@ -9,11 +9,8 @@ LL | let _val = *c.add(padding_offset); = note: BACKTRACE: = note: inside `main` at tests/fail/uninit/padding-enum.rs:LL:CC -Uninitialized memory occurred at ALLOC[0x8..0x9], in this allocation: -ALLOC (stack variable, size: 24, align: 8) { - 0x00 │ 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ │ ........░░░░░░░░ - 0x10 │ __ __ __ __ __ __ __ __ │ ░░░░░░░░ -} +Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation: +ALLOC DUMP note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/uninit/padding-pair.rs b/src/tools/miri/tests/fail/uninit/padding-pair.rs index c8c00b3c65a06..70ae48ff77d9d 100644 --- a/src/tools/miri/tests/fail/uninit/padding-pair.rs +++ b/src/tools/miri/tests/fail/uninit/padding-pair.rs @@ -1,3 +1,6 @@ +//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}" +//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]" + #![feature(core_intrinsics)] use std::mem::{self, MaybeUninit}; diff --git a/src/tools/miri/tests/fail/uninit/padding-pair.stderr b/src/tools/miri/tests/fail/uninit/padding-pair.stderr index a9841815de392..2e7a577f204a4 100644 --- a/src/tools/miri/tests/fail/uninit/padding-pair.stderr +++ b/src/tools/miri/tests/fail/uninit/padding-pair.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: reading memory at ALLOC[0x9..0xa], but memory is uninitialized at [0x9..0xa], and this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory --> tests/fail/uninit/padding-pair.rs:LL:CC | LL | let v = unsafe { *z.offset(first_undef) }; @@ -9,10 +9,8 @@ LL | let v = unsafe { *z.offset(first_undef) }; = note: BACKTRACE: = note: inside `main` at tests/fail/uninit/padding-pair.rs:LL:CC -Uninitialized memory occurred at ALLOC[0x9..0xa], in this allocation: -ALLOC (stack variable, size: 16, align: 8) { - 00 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ │ .........░░░░░░░ -} +Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation: +ALLOC DUMP note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs index 4e363dbf81e08..549785e0223b3 100644 --- a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs +++ b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.rs @@ -1,3 +1,6 @@ +//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}" +//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]" + use std::mem; // If this is `None`, the metadata becomes padding. diff --git a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr index f6446a5a95b51..ce11320ca1bf3 100644 --- a/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr +++ b/src/tools/miri/tests/fail/uninit/padding-wide-ptr.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: reading memory at ALLOC[0x8..0x9], but memory is uninitialized at [0x8..0x9], and this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory --> tests/fail/uninit/padding-wide-ptr.rs:LL:CC | LL | let _val = *c.add(mem::size_of::<*const u8>()); @@ -9,10 +9,8 @@ LL | let _val = *c.add(mem::size_of::<*const u8>()); = note: BACKTRACE: = note: inside `main` at tests/fail/uninit/padding-wide-ptr.rs:LL:CC -Uninitialized memory occurred at ALLOC[0x8..0x9], in this allocation: -ALLOC (stack variable, size: 16, align: 8) { - 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ │ ........░░░░░░░░ -} +Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation: +ALLOC DUMP note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.rs b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.rs index 0ba5520a54468..c1d284c7057ca 100644 --- a/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.rs +++ b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.rs @@ -1,3 +1,6 @@ +//@ normalize-stderr-test: "(\n)ALLOC \(.*\) \{\n(.*\n)*\}(\n)" -> "${1}ALLOC DUMP${3}" +//@ normalize-stderr-test: "\[0x[0-9a-z]..0x[0-9a-z]\]" -> "[0xX..0xY]" + #![feature(core_intrinsics)] use std::mem::{self, MaybeUninit}; diff --git a/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.stderr b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.stderr index 385d877e2ee24..eb049dd41ec28 100644 --- a/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.stderr +++ b/src/tools/miri/tests/fail/uninit/transmute-pair-uninit.stderr @@ -1,4 +1,4 @@ -error: Undefined Behavior: reading memory at ALLOC[0x9..0xa], but memory is uninitialized at [0x9..0xa], and this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0xX..0xY], but memory is uninitialized at [0xX..0xY], and this operation requires initialized memory --> tests/fail/uninit/transmute-pair-uninit.rs:LL:CC | LL | let v = unsafe { *z.offset(first_undef) }; @@ -9,10 +9,8 @@ LL | let v = unsafe { *z.offset(first_undef) }; = note: BACKTRACE: = note: inside `main` at tests/fail/uninit/transmute-pair-uninit.rs:LL:CC -Uninitialized memory occurred at ALLOC[0x9..0xa], in this allocation: -ALLOC (stack variable, size: 16, align: 8) { - 00 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ │ .........░░░░░░░ -} +Uninitialized memory occurred at ALLOC[0xX..0xY], in this allocation: +ALLOC DUMP note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/native-lib/fail/tracing/partial_init.rs b/src/tools/miri/tests/native-lib/fail/tracing/partial_init.rs index e267f82e215b5..7ab160773ff30 100644 --- a/src/tools/miri/tests/native-lib/fail/tracing/partial_init.rs +++ b/src/tools/miri/tests/native-lib/fail/tracing/partial_init.rs @@ -20,6 +20,6 @@ fn partial_init() { assert!(*slice_ptr == 0); assert!(*slice_ptr.offset(1) == 0); // Reading the third is UB! - let _val = *slice_ptr.offset(2); //~ ERROR: Undefined Behavior: using uninitialized data + let _val = *slice_ptr.offset(2); //~ ERROR: /Undefined Behavior: reading memory.*, but memory is uninitialized/ } } diff --git a/src/tools/miri/tests/native-lib/fail/tracing/partial_init.stderr b/src/tools/miri/tests/native-lib/fail/tracing/partial_init.stderr index 84fd913b5e5b3..74a599ede5c3c 100644 --- a/src/tools/miri/tests/native-lib/fail/tracing/partial_init.stderr +++ b/src/tools/miri/tests/native-lib/fail/tracing/partial_init.stderr @@ -17,7 +17,7 @@ note: inside `main` LL | partial_init(); | ^^^^^^^^^^^^^^ -error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory +error: Undefined Behavior: reading memory at ALLOC[0x2..0x3], but memory is uninitialized at [0x2..0x3], and this operation requires initialized memory --> tests/native-lib/fail/tracing/partial_init.rs:LL:CC | LL | let _val = *slice_ptr.offset(2); @@ -33,6 +33,11 @@ note: inside `main` LL | partial_init(); | ^^^^^^^^^^^^^^ +Uninitialized memory occurred at ALLOC[0x2..0x3], in this allocation: +ALLOC (stack variable, size: 3, align: 1) { + ╾00[wildcard] (1 ptr byte)╼ ╾00[wildcard] (1 ptr byte)╼ __ │ ━━░ +} + note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr b/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr index 107179516bc31..0c57eddbe937f 100644 --- a/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr +++ b/tests/ui/const-generics/min_const_generics/invalid-patterns.32bit.stderr @@ -3,6 +3,10 @@ error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at | LL | get_flag::(); | ^^^^^^^^^^^^^^^^^^ evaluation of `main::{constant#7}` failed here + | + = note: the raw bytes of the constant (size: 4, align: 4) { + ff __ __ __ │ .░░░ + } error[E0080]: constructing invalid value: encountered 0x42, but expected a boolean --> $DIR/invalid-patterns.rs:42:14 @@ -31,6 +35,10 @@ error[E0080]: reading memory at ALLOC1[0x0..0x4], but memory is uninitialized at | LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); | ^^^^^^^^^^^^^^^^^^ evaluation of `main::{constant#11}` failed here + | + = note: the raw bytes of the constant (size: 4, align: 4) { + ff __ __ __ │ .░░░ + } error[E0308]: mismatched types --> $DIR/invalid-patterns.rs:31:21 diff --git a/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr b/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr index 107179516bc31..0c57eddbe937f 100644 --- a/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr +++ b/tests/ui/const-generics/min_const_generics/invalid-patterns.64bit.stderr @@ -3,6 +3,10 @@ error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at | LL | get_flag::(); | ^^^^^^^^^^^^^^^^^^ evaluation of `main::{constant#7}` failed here + | + = note: the raw bytes of the constant (size: 4, align: 4) { + ff __ __ __ │ .░░░ + } error[E0080]: constructing invalid value: encountered 0x42, but expected a boolean --> $DIR/invalid-patterns.rs:42:14 @@ -31,6 +35,10 @@ error[E0080]: reading memory at ALLOC1[0x0..0x4], but memory is uninitialized at | LL | get_flag::<{ unsafe { bool_raw.boolean } }, { unsafe { char_raw.character } }>(); | ^^^^^^^^^^^^^^^^^^ evaluation of `main::{constant#11}` failed here + | + = note: the raw bytes of the constant (size: 4, align: 4) { + ff __ __ __ │ .░░░ + } error[E0308]: mismatched types --> $DIR/invalid-patterns.rs:31:21 diff --git a/tests/ui/consts/const-compare-bytes-ub.stderr b/tests/ui/consts/const-compare-bytes-ub.stderr index c1706a8c4b0af..770a55cc7267d 100644 --- a/tests/ui/consts/const-compare-bytes-ub.stderr +++ b/tests/ui/consts/const-compare-bytes-ub.stderr @@ -33,12 +33,20 @@ error[E0080]: reading memory at ALLOC2[0x0..0x1], but memory is uninitialized at | LL | compare_bytes(MaybeUninit::uninit().as_ptr(), [1].as_ptr(), 1) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `main::LHS_UNINIT` failed here + | + = note: the raw bytes of the constant (size: 1, align: 1) { + __ │ ░ + } error[E0080]: reading memory at ALLOC3[0x0..0x1], but memory is uninitialized at [0x0..0x1], and this operation requires initialized memory --> $DIR/const-compare-bytes-ub.rs:33:9 | LL | compare_bytes([1].as_ptr(), MaybeUninit::uninit().as_ptr(), 1) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `main::RHS_UNINIT` failed here + | + = note: the raw bytes of the constant (size: 1, align: 1) { + __ │ ░ + } error[E0080]: unable to turn pointer into integer --> $DIR/const-compare-bytes-ub.rs:37:9 diff --git a/tests/ui/consts/const-err-enum-discriminant.32bit.stderr b/tests/ui/consts/const-err-enum-discriminant.32bit.stderr new file mode 100644 index 0000000000000..cc786108f648b --- /dev/null +++ b/tests/ui/consts/const-err-enum-discriminant.32bit.stderr @@ -0,0 +1,13 @@ +error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at [0x0..0x4], and this operation requires initialized memory + --> $DIR/const-err-enum-discriminant.rs:10:21 + | +LL | Boo = [unsafe { Foo { b: () }.a }; 4][3], + | ^^^^^^^^^^^^^^^ evaluation of `Bar::Boo::{constant#0}` failed here + | + = note: the raw bytes of the constant (size: 4, align: 4) { + __ __ __ __ │ ░░░░ + } + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-err-enum-discriminant.stderr b/tests/ui/consts/const-err-enum-discriminant.64bit.stderr similarity index 64% rename from tests/ui/consts/const-err-enum-discriminant.stderr rename to tests/ui/consts/const-err-enum-discriminant.64bit.stderr index f935d1054de63..1d32851aac176 100644 --- a/tests/ui/consts/const-err-enum-discriminant.stderr +++ b/tests/ui/consts/const-err-enum-discriminant.64bit.stderr @@ -1,8 +1,12 @@ error[E0080]: reading memory at ALLOC0[0x0..0x8], but memory is uninitialized at [0x0..0x8], and this operation requires initialized memory - --> $DIR/const-err-enum-discriminant.rs:8:21 + --> $DIR/const-err-enum-discriminant.rs:10:21 | LL | Boo = [unsafe { Foo { b: () }.a }; 4][3], | ^^^^^^^^^^^^^^^ evaluation of `Bar::Boo::{constant#0}` failed here + | + = note: the raw bytes of the constant (size: 8, align: 8) { + __ __ __ __ __ __ __ __ │ ░░░░░░░░ + } error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-err-enum-discriminant.rs b/tests/ui/consts/const-err-enum-discriminant.rs index 190ef47f4362e..5567460058434 100644 --- a/tests/ui/consts/const-err-enum-discriminant.rs +++ b/tests/ui/consts/const-err-enum-discriminant.rs @@ -1,3 +1,5 @@ +//@ stderr-per-bitwidth + #[derive(Copy, Clone)] union Foo { a: isize, diff --git a/tests/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr b/tests/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr index 65e846b5741eb..60f6ef0f64b1c 100644 --- a/tests/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr +++ b/tests/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr @@ -43,11 +43,15 @@ LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uin = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported -error[E0080]: reading memory at ALLOC0[0x0..0x10], but memory is uninitialized at [0x8..0x10], and this operation requires initialized memory +error[E0080]: reading memory at ALLOC2[0x0..0x10], but memory is uninitialized at [0x8..0x10], and this operation requires initialized memory --> $DIR/const-pointer-values-in-various-types.rs:42:47 | LL | const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `main::I32_REF_U128_UNION` failed here + | + = note: the raw bytes of the constant (size: 16, align: 16) { + ╾ALLOC0╼ __ __ __ __ __ __ __ __ │ ╾──────╼░░░░░░░░ + } error[E0080]: unable to turn pointer into integer --> $DIR/const-pointer-values-in-various-types.rs:45:43 @@ -85,11 +89,15 @@ LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported -error[E0080]: reading memory at ALLOC1[0x0..0x10], but memory is uninitialized at [0x8..0x10], and this operation requires initialized memory +error[E0080]: reading memory at ALLOC3[0x0..0x10], but memory is uninitialized at [0x8..0x10], and this operation requires initialized memory --> $DIR/const-pointer-values-in-various-types.rs:57:47 | LL | const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `main::I32_REF_I128_UNION` failed here + | + = note: the raw bytes of the constant (size: 16, align: 16) { + ╾ALLOC1╼ __ __ __ __ __ __ __ __ │ ╾──────╼░░░░░░░░ + } error[E0080]: unable to turn pointer into integer --> $DIR/const-pointer-values-in-various-types.rs:60:45 diff --git a/tests/ui/consts/const-eval/ub-enum-overwrite.stderr b/tests/ui/consts/const-eval/ub-enum-overwrite.stderr index 14f369eace47a..2fd01b67c4928 100644 --- a/tests/ui/consts/const-eval/ub-enum-overwrite.stderr +++ b/tests/ui/consts/const-eval/ub-enum-overwrite.stderr @@ -3,6 +3,10 @@ error[E0080]: reading memory at ALLOC0[0x1..0x2], but memory is uninitialized at | LL | unsafe { *p } | ^^ evaluation of `_` failed here + | + = note: the raw bytes of the constant (size: 2, align: 1) { + 01 __ │ .░ + } error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-eval/ub-enum.rs b/tests/ui/consts/const-eval/ub-enum.rs index 52fc994506837..9c78bb6efed7e 100644 --- a/tests/ui/consts/const-eval/ub-enum.rs +++ b/tests/ui/consts/const-eval/ub-enum.rs @@ -1,7 +1,8 @@ // Strip out raw byte dumps to make comparison platform-independent: //@ normalize-stderr: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" -//@ normalize-stderr: "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" +//@ normalize-stderr: "([0-9a-f][0-9a-f] |__ |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" //@ normalize-stderr: "0x0+" -> "0x0" +//@ normalize-stderr: "0x[0-9](\.\.|\])" -> "0x%$1" //@ dont-require-annotations: NOTE #![feature(never_type)] diff --git a/tests/ui/consts/const-eval/ub-enum.stderr b/tests/ui/consts/const-eval/ub-enum.stderr index 6665830e2502f..5cbd6176c92d1 100644 --- a/tests/ui/consts/const-eval/ub-enum.stderr +++ b/tests/ui/consts/const-eval/ub-enum.stderr @@ -1,5 +1,5 @@ error[E0080]: constructing invalid value at .: encountered 0x01, but expected a valid enum tag - --> $DIR/ub-enum.rs:29:1 + --> $DIR/ub-enum.rs:30:1 | LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -10,7 +10,7 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; } error[E0080]: unable to turn pointer into integer - --> $DIR/ub-enum.rs:32:1 + --> $DIR/ub-enum.rs:33:1 | LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; | ^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM_PTR` failed here @@ -19,7 +19,7 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: unable to turn pointer into integer - --> $DIR/ub-enum.rs:35:1 + --> $DIR/ub-enum.rs:36:1 | LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM_WRAPPED` failed here @@ -28,7 +28,7 @@ LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: constructing invalid value at .: encountered 0x0, but expected a valid enum tag - --> $DIR/ub-enum.rs:47:1 + --> $DIR/ub-enum.rs:48:1 | LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -39,7 +39,7 @@ LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; } error[E0080]: unable to turn pointer into integer - --> $DIR/ub-enum.rs:49:1 + --> $DIR/ub-enum.rs:50:1 | LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM2_PTR` failed here @@ -48,7 +48,7 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: unable to turn pointer into integer - --> $DIR/ub-enum.rs:52:1 + --> $DIR/ub-enum.rs:53:1 | LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM2_WRAPPED` failed here @@ -56,14 +56,18 @@ LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; = help: this code performed an operation that depends on the underlying bytes representing a pointer = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported -error[E0080]: reading memory at ALLOC0[0x0..0x8], but memory is uninitialized at [0x0..0x8], and this operation requires initialized memory - --> $DIR/ub-enum.rs:61:41 +error[E0080]: reading memory at ALLOC0[0x%..0x%], but memory is uninitialized at [0x%..0x%], and this operation requires initialized memory + --> $DIR/ub-enum.rs:62:41 | LL | const BAD_ENUM2_UNDEF: Enum2 = unsafe { MaybeUninit { uninit: () }.init }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM2_UNDEF` failed here + | + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } error[E0080]: unable to turn pointer into integer - --> $DIR/ub-enum.rs:65:1 + --> $DIR/ub-enum.rs:66:1 | LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM2_OPTION_PTR` failed here @@ -72,7 +76,7 @@ LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: constructing invalid value at .: encountered an uninhabited enum variant - --> $DIR/ub-enum.rs:82:1 + --> $DIR/ub-enum.rs:83:1 | LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -83,7 +87,7 @@ LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute } error[E0080]: constructing invalid value at .: encountered an uninhabited enum variant - --> $DIR/ub-enum.rs:84:1 + --> $DIR/ub-enum.rs:85:1 | LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -94,7 +98,7 @@ LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute } error[E0080]: constructing invalid value at ..0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`) - --> $DIR/ub-enum.rs:92:1 + --> $DIR/ub-enum.rs:93:1 | LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -105,19 +109,19 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran } error[E0080]: constructing invalid value at .: encountered an uninhabited enum variant - --> $DIR/ub-enum.rs:97:77 + --> $DIR/ub-enum.rs:98:77 | LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) }; | ^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_UNINHABITED_WITH_DATA1` failed here error[E0080]: constructing invalid value at .: encountered an uninhabited enum variant - --> $DIR/ub-enum.rs:99:77 + --> $DIR/ub-enum.rs:100:77 | LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) }; | ^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_UNINHABITED_WITH_DATA2` failed here error[E0080]: read discriminant of an uninhabited enum variant - --> $DIR/ub-enum.rs:105:9 + --> $DIR/ub-enum.rs:106:9 | LL | std::mem::discriminant(&*(&() as *const () as *const Never)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `TEST_ICE_89765` failed inside this call diff --git a/tests/ui/consts/const-eval/ub-nonnull.stderr b/tests/ui/consts/const-eval/ub-nonnull.stderr index c92797f330af0..19ae66cf3c633 100644 --- a/tests/ui/consts/const-eval/ub-nonnull.stderr +++ b/tests/ui/consts/const-eval/ub-nonnull.stderr @@ -42,6 +42,10 @@ error[E0080]: reading memory at ALLOC2[0x0..0x1], but memory is uninitialized at | LL | const UNINIT: NonZero = unsafe { MaybeUninit { uninit: () }.init }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `UNINIT` failed here + | + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + __ │ ░ + } error[E0080]: constructing invalid value: encountered 42, but expected something in the range 10..=30 --> $DIR/ub-nonnull.rs:44:1 diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.rs b/tests/ui/consts/const-eval/ub-ref-ptr.rs index 64b48939be6de..d8e5102fcbe78 100644 --- a/tests/ui/consts/const-eval/ub-ref-ptr.rs +++ b/tests/ui/consts/const-eval/ub-ref-ptr.rs @@ -1,8 +1,9 @@ // ignore-tidy-linelength // Strip out raw byte dumps to make comparison platform-independent: //@ normalize-stderr: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" -//@ normalize-stderr: "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" +//@ normalize-stderr: "([0-9a-f][0-9a-f] |__ |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" //@ dont-require-annotations: NOTE +//@ normalize-stderr: "0x[0-9](\.\.|\])" -> "0x%$1" #![allow(invalid_value)] diff --git a/tests/ui/consts/const-eval/ub-ref-ptr.stderr b/tests/ui/consts/const-eval/ub-ref-ptr.stderr index beb54e435341e..451ebb6eba1a6 100644 --- a/tests/ui/consts/const-eval/ub-ref-ptr.stderr +++ b/tests/ui/consts/const-eval/ub-ref-ptr.stderr @@ -1,5 +1,5 @@ error[E0080]: constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1) - --> $DIR/ub-ref-ptr.rs:17:1 + --> $DIR/ub-ref-ptr.rs:18:1 | LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; | ^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -10,7 +10,7 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; } error[E0080]: constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1) - --> $DIR/ub-ref-ptr.rs:20:1 + --> $DIR/ub-ref-ptr.rs:21:1 | LL | const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -21,7 +21,7 @@ LL | const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; } error[E0080]: constructing invalid value: encountered a null reference - --> $DIR/ub-ref-ptr.rs:23:1 + --> $DIR/ub-ref-ptr.rs:24:1 | LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -32,7 +32,7 @@ LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; } error[E0080]: constructing invalid value: encountered a null box - --> $DIR/ub-ref-ptr.rs:26:1 + --> $DIR/ub-ref-ptr.rs:27:1 | LL | const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -43,7 +43,7 @@ LL | const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; } error[E0080]: unable to turn pointer into integer - --> $DIR/ub-ref-ptr.rs:33:1 + --> $DIR/ub-ref-ptr.rs:34:1 | LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `REF_AS_USIZE` failed here @@ -52,7 +52,7 @@ LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: unable to turn pointer into integer - --> $DIR/ub-ref-ptr.rs:36:39 + --> $DIR/ub-ref-ptr.rs:37:39 | LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `REF_AS_USIZE_SLICE` failed here @@ -61,13 +61,13 @@ LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported note: erroneous constant encountered - --> $DIR/ub-ref-ptr.rs:36:38 + --> $DIR/ub-ref-ptr.rs:37:38 | LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: unable to turn pointer into integer - --> $DIR/ub-ref-ptr.rs:39:86 + --> $DIR/ub-ref-ptr.rs:40:86 | LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; | ^^^^^^^^^^^^^^^^^^^^ evaluation of `REF_AS_USIZE_BOX_SLICE` failed here @@ -76,13 +76,13 @@ LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[us = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported note: erroneous constant encountered - --> $DIR/ub-ref-ptr.rs:39:85 + --> $DIR/ub-ref-ptr.rs:40:85 | LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; | ^^^^^^^^^^^^^^^^^^^^^ error[E0080]: constructing invalid value: encountered a dangling reference (0x539[noalloc] has no provenance) - --> $DIR/ub-ref-ptr.rs:42:1 + --> $DIR/ub-ref-ptr.rs:43:1 | LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -93,7 +93,7 @@ LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; } error[E0080]: constructing invalid value: encountered a dangling box (0x539[noalloc] has no provenance) - --> $DIR/ub-ref-ptr.rs:45:1 + --> $DIR/ub-ref-ptr.rs:46:1 | LL | const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -103,14 +103,18 @@ LL | const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; HEX_DUMP } -error[E0080]: reading memory at ALLOC3[0x0..0x8], but memory is uninitialized at [0x0..0x8], and this operation requires initialized memory - --> $DIR/ub-ref-ptr.rs:48:41 +error[E0080]: reading memory at ALLOC3[0x%..0x%], but memory is uninitialized at [0x%..0x%], and this operation requires initialized memory + --> $DIR/ub-ref-ptr.rs:49:41 | LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `UNINIT_PTR` failed here + | + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } error[E0080]: constructing invalid value: encountered null pointer, but expected a function pointer - --> $DIR/ub-ref-ptr.rs:51:1 + --> $DIR/ub-ref-ptr.rs:52:1 | LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -120,14 +124,18 @@ LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) }; HEX_DUMP } -error[E0080]: reading memory at ALLOC4[0x0..0x8], but memory is uninitialized at [0x0..0x8], and this operation requires initialized memory - --> $DIR/ub-ref-ptr.rs:53:38 +error[E0080]: reading memory at ALLOC4[0x%..0x%], but memory is uninitialized at [0x%..0x%], and this operation requires initialized memory + --> $DIR/ub-ref-ptr.rs:54:38 | LL | const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `UNINIT_FN_PTR` failed here + | + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } error[E0080]: constructing invalid value: encountered 0xd[noalloc], but expected a function pointer - --> $DIR/ub-ref-ptr.rs:55:1 + --> $DIR/ub-ref-ptr.rs:56:1 | LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -138,7 +146,7 @@ LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) }; } error[E0080]: constructing invalid value: encountered ALLOC2, but expected a function pointer - --> $DIR/ub-ref-ptr.rs:57:1 + --> $DIR/ub-ref-ptr.rs:58:1 | LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; | ^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -149,7 +157,7 @@ LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) }; } error[E0080]: accessing memory based on pointer with alignment 1, but alignment 4 is required - --> $DIR/ub-ref-ptr.rs:64:5 + --> $DIR/ub-ref-ptr.rs:65:5 | LL | ptr.read(); | ^^^^^^^^^^ evaluation of `UNALIGNED_READ` failed here diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.rs b/tests/ui/consts/const-eval/ub-wide-ptr.rs index 86235897e7e8d..0bbb104c0322c 100644 --- a/tests/ui/consts/const-eval/ub-wide-ptr.rs +++ b/tests/ui/consts/const-eval/ub-wide-ptr.rs @@ -6,9 +6,10 @@ use std::{ptr, mem}; // Strip out raw byte dumps to make comparison platform-independent: //@ normalize-stderr: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" -//@ normalize-stderr: "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" +//@ normalize-stderr: "([0-9a-f][0-9a-f] |__ |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" //@ normalize-stderr: "offset \d+" -> "offset N" //@ normalize-stderr: "size \d+" -> "size N" +//@ normalize-stderr: "0x[0-9](\.\.|\])" -> "0x%$1" //@ dont-require-annotations: NOTE /// A newtype wrapper to prevent MIR generation from inserting reborrows that would affect the error @@ -61,7 +62,7 @@ const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: const SLICE_VALID: &[u8] = unsafe { mem::transmute((&42u8, 1usize)) }; // bad slice: length uninit const SLICE_LENGTH_UNINIT: &[u8] = unsafe { -//~^ ERROR uninitialized + //~^ ERROR uninitialized let uninit_len = MaybeUninit:: { uninit: () }; mem::transmute((42, uninit_len)) }; @@ -99,7 +100,7 @@ const RAW_SLICE_VALID: *const [u8] = unsafe { mem::transmute((&42u8, 1usize)) }; const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, 999usize)) }; // ok because raw const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, usize::MAX)) }; // ok because raw const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { -//~^ ERROR uninitialized + //~^ ERROR uninitialized let uninit_len = MaybeUninit:: { uninit: () }; mem::transmute((42, uninit_len)) }; diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.stderr b/tests/ui/consts/const-eval/ub-wide-ptr.stderr index a3eb5c7203192..ab15ba826a5fe 100644 --- a/tests/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/tests/ui/consts/const-eval/ub-wide-ptr.stderr @@ -1,5 +1,5 @@ error[E0080]: constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) - --> $DIR/ub-wide-ptr.rs:39:1 + --> $DIR/ub-wide-ptr.rs:40:1 | LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -10,7 +10,7 @@ LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; } error[E0080]: constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object - --> $DIR/ub-wide-ptr.rs:41:1 + --> $DIR/ub-wide-ptr.rs:42:1 | LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -21,7 +21,7 @@ LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, us } error[E0080]: unable to turn pointer into integer - --> $DIR/ub-wide-ptr.rs:44:1 + --> $DIR/ub-wide-ptr.rs:45:1 | LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `STR_LENGTH_PTR` failed here @@ -30,7 +30,7 @@ LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: unable to turn pointer into integer - --> $DIR/ub-wide-ptr.rs:47:1 + --> $DIR/ub-wide-ptr.rs:48:1 | LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `MY_STR_LENGTH_PTR` failed here @@ -39,7 +39,7 @@ LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object - --> $DIR/ub-wide-ptr.rs:49:1 + --> $DIR/ub-wide-ptr.rs:50:1 | LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -50,7 +50,7 @@ LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize: } error[E0080]: constructing invalid value at .: encountered uninitialized memory, but expected a string - --> $DIR/ub-wide-ptr.rs:53:1 + --> $DIR/ub-wide-ptr.rs:54:1 | LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; | ^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -61,7 +61,7 @@ LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit: } error[E0080]: constructing invalid value at ..0: encountered uninitialized memory, but expected a string - --> $DIR/ub-wide-ptr.rs:56:1 + --> $DIR/ub-wide-ptr.rs:57:1 | LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -71,14 +71,18 @@ LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUni HEX_DUMP } -error[E0080]: reading memory at ALLOC32[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory - --> $DIR/ub-wide-ptr.rs:63:1 +error[E0080]: reading memory at ALLOC32[0x%..0x%], but memory is uninitialized at [0x%..0x%], and this operation requires initialized memory + --> $DIR/ub-wide-ptr.rs:64:1 | LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `SLICE_LENGTH_UNINIT` failed here + | + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } error[E0080]: constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation) - --> $DIR/ub-wide-ptr.rs:69:1 + --> $DIR/ub-wide-ptr.rs:70:1 | LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -89,7 +93,7 @@ LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; } error[E0080]: constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object - --> $DIR/ub-wide-ptr.rs:72:1 + --> $DIR/ub-wide-ptr.rs:73:1 | LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -100,7 +104,7 @@ LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, is } error[E0080]: unable to turn pointer into integer - --> $DIR/ub-wide-ptr.rs:75:1 + --> $DIR/ub-wide-ptr.rs:76:1 | LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `SLICE_LENGTH_PTR` failed here @@ -109,7 +113,7 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation) - --> $DIR/ub-wide-ptr.rs:78:1 + --> $DIR/ub-wide-ptr.rs:79:1 | LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -120,7 +124,7 @@ LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999us } error[E0080]: unable to turn pointer into integer - --> $DIR/ub-wide-ptr.rs:81:1 + --> $DIR/ub-wide-ptr.rs:82:1 | LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `SLICE_LENGTH_PTR_BOX` failed here @@ -129,7 +133,7 @@ LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3) = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported error[E0080]: constructing invalid value at .[0]: encountered 0x03, but expected a boolean - --> $DIR/ub-wide-ptr.rs:85:1 + --> $DIR/ub-wide-ptr.rs:86:1 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -140,13 +144,13 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; } note: erroneous constant encountered - --> $DIR/ub-wide-ptr.rs:85:40 + --> $DIR/ub-wide-ptr.rs:86:40 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: constructing invalid value at ..0: encountered 0x03, but expected a boolean - --> $DIR/ub-wide-ptr.rs:91:1 + --> $DIR/ub-wide-ptr.rs:92:1 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -157,13 +161,13 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3 } note: erroneous constant encountered - --> $DIR/ub-wide-ptr.rs:91:42 + --> $DIR/ub-wide-ptr.rs:92:42 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0080]: constructing invalid value at ..1[0]: encountered 0x03, but expected a boolean - --> $DIR/ub-wide-ptr.rs:94:1 + --> $DIR/ub-wide-ptr.rs:95:1 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -174,19 +178,23 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::tran } note: erroneous constant encountered - --> $DIR/ub-wide-ptr.rs:94:42 + --> $DIR/ub-wide-ptr.rs:95:42 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0080]: reading memory at ALLOC33[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory - --> $DIR/ub-wide-ptr.rs:101:1 +error[E0080]: reading memory at ALLOC33[0x%..0x%], but memory is uninitialized at [0x%..0x%], and this operation requires initialized memory + --> $DIR/ub-wide-ptr.rs:102:1 | LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `RAW_SLICE_LENGTH_UNINIT` failed here + | + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } error[E0080]: constructing invalid value at .0: encountered ALLOC12, but expected a vtable pointer - --> $DIR/ub-wide-ptr.rs:109:1 + --> $DIR/ub-wide-ptr.rs:110:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -197,7 +205,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W(( } error[E0080]: constructing invalid value at .0: encountered ALLOC14, but expected a vtable pointer - --> $DIR/ub-wide-ptr.rs:112:1 + --> $DIR/ub-wide-ptr.rs:113:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -208,7 +216,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W(( } error[E0080]: constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer - --> $DIR/ub-wide-ptr.rs:115:1 + --> $DIR/ub-wide-ptr.rs:116:1 | LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -219,7 +227,7 @@ LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u } error[E0080]: constructing invalid value: encountered ALLOC17, but expected a vtable pointer - --> $DIR/ub-wide-ptr.rs:117:1 + --> $DIR/ub-wide-ptr.rs:118:1 | LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -230,7 +238,7 @@ LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92 } error[E0080]: constructing invalid value: encountered ALLOC19, but expected a vtable pointer - --> $DIR/ub-wide-ptr.rs:119:1 + --> $DIR/ub-wide-ptr.rs:120:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -241,7 +249,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92 } error[E0080]: constructing invalid value: encountered ALLOC21, but expected a vtable pointer - --> $DIR/ub-wide-ptr.rs:121:1 + --> $DIR/ub-wide-ptr.rs:122:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -252,7 +260,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u } error[E0080]: constructing invalid value at .0: encountered ALLOC23, but expected a vtable pointer - --> $DIR/ub-wide-ptr.rs:123:1 + --> $DIR/ub-wide-ptr.rs:124:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -263,7 +271,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::trans } error[E0080]: constructing invalid value at ..: encountered 0x03, but expected a boolean - --> $DIR/ub-wide-ptr.rs:127:1 + --> $DIR/ub-wide-ptr.rs:128:1 | LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -274,7 +282,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, } error[E0080]: constructing invalid value: encountered null pointer, but expected a vtable pointer - --> $DIR/ub-wide-ptr.rs:131:1 + --> $DIR/ub-wide-ptr.rs:132:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -285,7 +293,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute } error[E0080]: constructing invalid value: encountered ALLOC28, but expected a vtable pointer - --> $DIR/ub-wide-ptr.rs:133:1 + --> $DIR/ub-wide-ptr.rs:134:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -296,7 +304,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm } error[E0080]: constructing invalid value: encountered null pointer, but expected a vtable pointer - --> $DIR/ub-wide-ptr.rs:140:1 + --> $DIR/ub-wide-ptr.rs:141:1 | LL | static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value @@ -307,7 +315,7 @@ LL | static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe } error[E0080]: constructing invalid value: encountered ALLOC31, but expected a vtable pointer - --> $DIR/ub-wide-ptr.rs:144:1 + --> $DIR/ub-wide-ptr.rs:145:1 | LL | static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value diff --git a/tests/ui/consts/const-eval/union-const-eval-field.rs b/tests/ui/consts/const-eval/union-const-eval-field.rs index 0ad94eee7f45a..719e59b007c00 100644 --- a/tests/ui/consts/const-eval/union-const-eval-field.rs +++ b/tests/ui/consts/const-eval/union-const-eval-field.rs @@ -1,4 +1,5 @@ //@ dont-require-annotations: NOTE +//@ normalize-stderr: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" type Field1 = i32; type Field2 = f32; diff --git a/tests/ui/consts/const-eval/union-const-eval-field.stderr b/tests/ui/consts/const-eval/union-const-eval-field.stderr index deddf9e0b6d3b..1843ce273ac04 100644 --- a/tests/ui/consts/const-eval/union-const-eval-field.stderr +++ b/tests/ui/consts/const-eval/union-const-eval-field.stderr @@ -1,17 +1,21 @@ error[E0080]: reading memory at ALLOC0[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory - --> $DIR/union-const-eval-field.rs:28:37 + --> $DIR/union-const-eval-field.rs:29:37 | LL | const FIELD3: Field3 = unsafe { UNION.field3 }; | ^^^^^^^^^^^^ evaluation of `read_field3::FIELD3` failed here + | + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + 00 00 80 3f __ __ __ __ │ ...?░░░░ + } note: erroneous constant encountered - --> $DIR/union-const-eval-field.rs:30:5 + --> $DIR/union-const-eval-field.rs:31:5 | LL | FIELD3 | ^^^^^^ note: erroneous constant encountered - --> $DIR/union-const-eval-field.rs:30:5 + --> $DIR/union-const-eval-field.rs:31:5 | LL | FIELD3 | ^^^^^^ diff --git a/tests/ui/consts/const-eval/union-ice.stderr b/tests/ui/consts/const-eval/union-ice.stderr index 826d7440a8087..0506be63ea6f1 100644 --- a/tests/ui/consts/const-eval/union-ice.stderr +++ b/tests/ui/consts/const-eval/union-ice.stderr @@ -3,18 +3,30 @@ error[E0080]: reading memory at ALLOC0[0x0..0x8], but memory is uninitialized at | LL | const FIELD3: Field3 = unsafe { UNION.field3 }; | ^^^^^^^^^^^^ evaluation of `FIELD3` failed here + | + = note: the raw bytes of the constant (size: 8, align: 8) { + 00 00 80 3f __ __ __ __ │ ...?░░░░ + } error[E0080]: reading memory at ALLOC1[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory --> $DIR/union-ice.rs:19:17 | LL | b: unsafe { UNION.field3 }, | ^^^^^^^^^^^^ evaluation of `FIELD_PATH` failed here + | + = note: the raw bytes of the constant (size: 8, align: 8) { + 00 00 80 3f __ __ __ __ │ ...?░░░░ + } error[E0080]: reading memory at ALLOC2[0x0..0x8], but memory is uninitialized at [0x4..0x8], and this operation requires initialized memory --> $DIR/union-ice.rs:31:18 | LL | unsafe { UNION.field3 }, | ^^^^^^^^^^^^ evaluation of `FIELD_PATH2` failed here + | + = note: the raw bytes of the constant (size: 8, align: 8) { + 00 00 80 3f __ __ __ __ │ ...?░░░░ + } error: aborting due to 3 previous errors diff --git a/tests/ui/consts/const-eval/union-ub.32bit.stderr b/tests/ui/consts/const-eval/union-ub.32bit.stderr index 70bf2cf539081..757bcea91c3ca 100644 --- a/tests/ui/consts/const-eval/union-ub.32bit.stderr +++ b/tests/ui/consts/const-eval/union-ub.32bit.stderr @@ -14,6 +14,10 @@ error[E0080]: reading memory at ALLOC0[0x0..0x1], but memory is uninitialized at | LL | const UNINIT_BOOL: bool = unsafe { DummyUnion { unit: () }.bool }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `UNINIT_BOOL` failed here + | + = note: the raw bytes of the constant (size: 1, align: 1) { + __ │ ░ + } error: aborting due to 2 previous errors diff --git a/tests/ui/consts/const-eval/union-ub.64bit.stderr b/tests/ui/consts/const-eval/union-ub.64bit.stderr index 70bf2cf539081..757bcea91c3ca 100644 --- a/tests/ui/consts/const-eval/union-ub.64bit.stderr +++ b/tests/ui/consts/const-eval/union-ub.64bit.stderr @@ -14,6 +14,10 @@ error[E0080]: reading memory at ALLOC0[0x0..0x1], but memory is uninitialized at | LL | const UNINIT_BOOL: bool = unsafe { DummyUnion { unit: () }.bool }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `UNINIT_BOOL` failed here + | + = note: the raw bytes of the constant (size: 1, align: 1) { + __ │ ░ + } error: aborting due to 2 previous errors diff --git a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr index 10f4d8d1a711a..5f4ef14d58697 100644 --- a/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr +++ b/tests/ui/intrinsics/intrinsic-raw_eq-const-bad.stderr @@ -3,6 +3,10 @@ error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at | LL | std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `RAW_EQ_PADDING` failed here + | + = note: the raw bytes of the constant (size: 4, align: 2) { + 01 __ 02 00 │ .░.. + } error[E0080]: unable to turn pointer into integer --> $DIR/intrinsic-raw_eq-const-bad.rs:9:5 diff --git a/tests/ui/type/pattern_types/validity.stderr b/tests/ui/type/pattern_types/validity.stderr index 76824055d8a1d..b545cd75ddb57 100644 --- a/tests/ui/type/pattern_types/validity.stderr +++ b/tests/ui/type/pattern_types/validity.stderr @@ -14,6 +14,10 @@ error[E0080]: reading memory at ALLOC0[0x0..0x4], but memory is uninitialized at | LL | const BAD_UNINIT: pattern_type!(u32 is 1..) = | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_UNINIT` failed here + | + = note: the raw bytes of the constant (size: 4, align: 4) { + __ __ __ __ │ ░░░░ + } error[E0080]: unable to turn pointer into integer --> $DIR/validity.rs:17:1 @@ -51,6 +55,10 @@ error[E0080]: reading memory at ALLOC1[0x0..0x4], but memory is uninitialized at | LL | const CHAR_UNINIT: pattern_type!(char is 'A'..'Z') = | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `CHAR_UNINIT` failed here + | + = note: the raw bytes of the constant (size: 4, align: 4) { + __ __ __ __ │ ░░░░ + } error[E0080]: constructing invalid value: encountered 97, but expected something in the range 65..=89 --> $DIR/validity.rs:33:1 From 8e840f726d013f824cc2e98aa54307f27295b34b Mon Sep 17 00:00:00 2001 From: Maksim Bondarenkov Date: Fri, 18 Jul 2025 11:20:03 +0300 Subject: [PATCH 12/19] opt-dist: make llvm builds optional adds command line option for disabling llvm builds. it's useful in case of user having their own optimized LLVM, so they won't waste time for (at least) 3 LLVM builds. in this case PGO optimized will be already built in Stage 1, so my previous PR should be addressed for this change --- src/tools/opt-dist/src/environment.rs | 5 ++ src/tools/opt-dist/src/exec.rs | 12 ++- src/tools/opt-dist/src/main.rs | 122 +++++++++++++++----------- src/tools/opt-dist/src/training.rs | 4 +- 4 files changed, 87 insertions(+), 56 deletions(-) diff --git a/src/tools/opt-dist/src/environment.rs b/src/tools/opt-dist/src/environment.rs index 946e926a3c010..d41dc80e6b2af 100644 --- a/src/tools/opt-dist/src/environment.rs +++ b/src/tools/opt-dist/src/environment.rs @@ -27,6 +27,7 @@ pub struct Environment { shared_llvm: bool, run_tests: bool, fast_try_build: bool, + build_llvm: bool, } impl Environment { @@ -111,6 +112,10 @@ impl Environment { pub fn is_fast_try_build(&self) -> bool { self.fast_try_build } + + pub fn build_llvm(&self) -> bool { + self.build_llvm + } } /// What is the extension of binary executables on this platform? diff --git a/src/tools/opt-dist/src/exec.rs b/src/tools/opt-dist/src/exec.rs index 0dc6e56b9d5f4..56eff2ca2a7df 100644 --- a/src/tools/opt-dist/src/exec.rs +++ b/src/tools/opt-dist/src/exec.rs @@ -139,8 +139,10 @@ impl Bootstrap { self } - pub fn llvm_pgo_optimize(mut self, profile: &LlvmPGOProfile) -> Self { - self.cmd = self.cmd.arg("--llvm-profile-use").arg(profile.0.as_str()); + pub fn llvm_pgo_optimize(mut self, profile: Option<&LlvmPGOProfile>) -> Self { + if let Some(prof) = profile { + self.cmd = self.cmd.arg("--llvm-profile-use").arg(prof.0.as_str()); + } self } @@ -174,8 +176,10 @@ impl Bootstrap { self } - pub fn with_bolt_profile(mut self, profile: BoltProfile) -> Self { - self.cmd = self.cmd.arg("--reproducible-artifact").arg(profile.0.as_str()); + pub fn with_bolt_profile(mut self, profile: Option) -> Self { + if let Some(prof) = profile { + self.cmd = self.cmd.arg("--reproducible-artifact").arg(prof.0.as_str()); + } self } diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs index 9c8a6637a3b10..7857f196626bc 100644 --- a/src/tools/opt-dist/src/main.rs +++ b/src/tools/opt-dist/src/main.rs @@ -98,6 +98,10 @@ enum EnvironmentCmd { /// Perform tests after final build if it's not a fast try build #[arg(long)] run_tests: bool, + + /// Will be LLVM built during the run? + #[arg(long, default_value_t = true, action(clap::ArgAction::Set))] + build_llvm: bool, }, /// Perform an optimized build on Linux CI, from inside Docker. LinuxCi { @@ -133,6 +137,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec)> benchmark_cargo_config, shared, run_tests, + build_llvm, } => { let env = EnvironmentBuilder::default() .host_tuple(target_triple) @@ -148,6 +153,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec)> .benchmark_cargo_config(benchmark_cargo_config) .run_tests(run_tests) .fast_try_build(is_fast_try_build) + .build_llvm(build_llvm) .build()?; (env, shared.build_args) @@ -172,6 +178,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec)> .skipped_tests(vec![]) .run_tests(true) .fast_try_build(is_fast_try_build) + .build_llvm(true) .build()?; (env, shared.build_args) @@ -193,6 +200,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec)> .skipped_tests(vec![]) .run_tests(true) .fast_try_build(is_fast_try_build) + .build_llvm(true) .build()?; (env, shared.build_args) @@ -255,30 +263,35 @@ fn execute_pipeline( // Stage 2: Gather LLVM PGO profiles // Here we build a PGO instrumented LLVM, reusing the previously PGO optimized rustc. // Then we use the instrumented LLVM to gather LLVM PGO profiles. - let llvm_pgo_profile = timer.section("Stage 2 (LLVM PGO)", |stage| { - // Remove the previous, uninstrumented build of LLVM. - clear_llvm_files(env)?; + let llvm_pgo_profile = if env.build_llvm() { + timer.section("Stage 2 (LLVM PGO)", |stage| { + // Remove the previous, uninstrumented build of LLVM. + clear_llvm_files(env)?; - let llvm_profile_dir_root = env.artifact_dir().join("llvm-pgo"); + let llvm_profile_dir_root = env.artifact_dir().join("llvm-pgo"); - stage.section("Build PGO instrumented LLVM", |section| { - Bootstrap::build(env) - .llvm_pgo_instrument(&llvm_profile_dir_root) - .avoid_rustc_rebuild() - .run(section) - })?; + stage.section("Build PGO instrumented LLVM", |section| { + Bootstrap::build(env) + .llvm_pgo_instrument(&llvm_profile_dir_root) + .avoid_rustc_rebuild() + .run(section) + })?; - let profile = stage - .section("Gather profiles", |_| gather_llvm_profiles(env, &llvm_profile_dir_root))?; + let profile = stage.section("Gather profiles", |_| { + gather_llvm_profiles(env, &llvm_profile_dir_root) + })?; - print_free_disk_space()?; + print_free_disk_space()?; - // Proactively delete the instrumented artifacts, to avoid using them by accident in - // follow-up stages. - clear_llvm_files(env)?; + // Proactively delete the instrumented artifacts, to avoid using them by accident in + // follow-up stages. + clear_llvm_files(env)?; - Ok(profile) - })?; + Ok(Some(profile)) + })? + } else { + None + }; let bolt_profiles = if env.use_bolt() { // Stage 3: Build BOLT instrumented LLVM @@ -286,37 +299,43 @@ fn execute_pipeline( // Note that we don't remove LLVM artifacts after this step, so that they are reused in the final dist build. // BOLT instrumentation is performed "on-the-fly" when the LLVM library is copied to the sysroot of rustc, // therefore the LLVM artifacts on disk are not "tainted" with BOLT instrumentation and they can be reused. + let libdir = env.build_artifacts().join("stage2").join("lib"); timer.section("Stage 3 (BOLT)", |stage| { - stage.section("Build PGO optimized LLVM", |stage| { - Bootstrap::build(env) - .with_llvm_bolt_ldflags() - .llvm_pgo_optimize(&llvm_pgo_profile) - .avoid_rustc_rebuild() - .run(stage) - })?; - - let libdir = env.build_artifacts().join("stage2").join("lib"); - // The actual name will be something like libLLVM.so.18.1-rust-dev. - let llvm_lib = io::find_file_in_dir(&libdir, "libLLVM.so", "")?; - - log::info!("Optimizing {llvm_lib} with BOLT"); - - // FIXME(kobzol): try gather profiles together, at once for LLVM and rustc - // Instrument the libraries and gather profiles - let llvm_profile = with_bolt_instrumented(&llvm_lib, |llvm_profile_dir| { - stage.section("Gather profiles", |_| { - gather_bolt_profiles(env, "LLVM", llvm_benchmarks(env), llvm_profile_dir) - }) - })?; - print_free_disk_space()?; - - // Now optimize the library with BOLT. The `libLLVM-XXX.so` library is actually hard-linked - // from several places, and this specific path (`llvm_lib`) will *not* be packaged into - // the final dist build. However, when BOLT optimizes an artifact, it does so *in-place*, - // therefore it will actually optimize all the hard links, which means that the final - // packaged `libLLVM.so` file *will* be BOLT optimized. - bolt_optimize(&llvm_lib, &llvm_profile, env) - .context("Could not optimize LLVM with BOLT")?; + let llvm_profile = if env.build_llvm() { + stage.section("Build PGO optimized LLVM", |stage| { + Bootstrap::build(env) + .with_llvm_bolt_ldflags() + .llvm_pgo_optimize(llvm_pgo_profile.as_ref()) + .avoid_rustc_rebuild() + .run(stage) + })?; + + // The actual name will be something like libLLVM.so.18.1-rust-dev. + let llvm_lib = io::find_file_in_dir(&libdir, "libLLVM.so", "")?; + + log::info!("Optimizing {llvm_lib} with BOLT"); + + // FIXME(kobzol): try gather profiles together, at once for LLVM and rustc + // Instrument the libraries and gather profiles + let llvm_profile = with_bolt_instrumented(&llvm_lib, |llvm_profile_dir| { + stage.section("Gather profiles", |_| { + gather_bolt_profiles(env, "LLVM", llvm_benchmarks(env), llvm_profile_dir) + }) + })?; + print_free_disk_space()?; + + // Now optimize the library with BOLT. The `libLLVM-XXX.so` library is actually hard-linked + // from several places, and this specific path (`llvm_lib`) will *not* be packaged into + // the final dist build. However, when BOLT optimizes an artifact, it does so *in-place*, + // therefore it will actually optimize all the hard links, which means that the final + // packaged `libLLVM.so` file *will* be BOLT optimized. + bolt_optimize(&llvm_lib, &llvm_profile, env) + .context("Could not optimize LLVM with BOLT")?; + + Some(llvm_profile) + } else { + None + }; let rustc_lib = io::find_file_in_dir(&libdir, "librustc_driver", ".so")?; @@ -334,15 +353,16 @@ fn execute_pipeline( bolt_optimize(&rustc_lib, &rustc_profile, env) .context("Could not optimize rustc with BOLT")?; - // LLVM is not being cleared here, we want to use the BOLT-optimized LLVM - Ok(vec![llvm_profile, rustc_profile]) + // LLVM is not being cleared here. Either we built it and we want to use the BOLT-optimized LLVM, or we + // didn't build it, so we don't want to remove it. + Ok(vec![llvm_profile, Some(rustc_profile)]) })? } else { vec![] }; let mut dist = Bootstrap::dist(env, &dist_args) - .llvm_pgo_optimize(&llvm_pgo_profile) + .llvm_pgo_optimize(llvm_pgo_profile.as_ref()) .rustc_pgo_optimize(&rustc_pgo_profile) .avoid_rustc_rebuild(); diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs index 36a7d6a7cba4f..ae062d5c60c66 100644 --- a/src/tools/opt-dist/src/training.rs +++ b/src/tools/opt-dist/src/training.rs @@ -163,7 +163,9 @@ pub fn gather_rustc_profiles( let merged_profile = env.artifact_dir().join("rustc-pgo.profdata"); log::info!("Merging Rustc PGO profiles to {merged_profile}"); - merge_llvm_profiles(env, &merged_profile, profile_root, LlvmProfdata::Target)?; + let llvm_profdata = if env.build_llvm() { LlvmProfdata::Target } else { LlvmProfdata::Host }; + + merge_llvm_profiles(env, &merged_profile, profile_root, llvm_profdata)?; log_profile_stats("Rustc", &merged_profile, profile_root)?; // We don't need the individual .profraw files now that they have been merged From 84ed70b69daa6865d3713d36fabad90a2fb96afd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Fri, 20 Jun 2025 21:39:19 +0200 Subject: [PATCH 13/19] Reword diagnostics about relaxed bounds in invalid contexts --- compiler/rustc_ast_lowering/src/lib.rs | 26 +++++-- ...issing-associated_item_or_field_def_ids.rs | 2 +- ...ng-associated_item_or_field_def_ids.stderr | 8 +-- ...ing-associated-items-of-undefined-trait.rs | 2 +- ...associated-items-of-undefined-trait.stderr | 8 +-- .../feature-gate-more-maybe-bounds.rs | 8 +-- .../feature-gate-more-maybe-bounds.stderr | 34 ++++----- tests/ui/parser/trait-object-trait-parens.rs | 6 +- .../parser/trait-object-trait-parens.stderr | 18 ++--- .../ui/sized-hierarchy/default-supertrait.rs | 6 +- .../sized-hierarchy/default-supertrait.stderr | 17 ++--- .../maybe-trait-bounds-forbidden-locations.rs | 18 ----- ...be-trait-bounds-forbidden-locations.stderr | 31 -------- tests/ui/traits/wf-object/maybe-bound.rs | 18 ----- tests/ui/traits/wf-object/maybe-bound.stderr | 48 ------------- tests/ui/traits/wf-object/only-maybe-bound.rs | 2 +- .../traits/wf-object/only-maybe-bound.stderr | 8 +-- .../unsized/relaxed-bounds-invalid-places.rs | 35 ++++++---- .../relaxed-bounds-invalid-places.stderr | 70 ++++++++++++------- 19 files changed, 125 insertions(+), 240 deletions(-) delete mode 100644 tests/ui/traits/maybe-trait-bounds-forbidden-locations.rs delete mode 100644 tests/ui/traits/maybe-trait-bounds-forbidden-locations.stderr delete mode 100644 tests/ui/traits/wf-object/maybe-bound.rs delete mode 100644 tests/ui/traits/wf-object/maybe-bound.stderr diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d3d521e83b090..533ee9bff54fa 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -60,7 +60,7 @@ use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_macros::extension; use rustc_middle::span_bug; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; -use rustc_session::parse::{add_feature_diagnostics, feature_err}; +use rustc_session::parse::add_feature_diagnostics; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{DUMMY_SP, DesugaringKind, Span}; use smallvec::SmallVec; @@ -2071,7 +2071,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: Span, rbp: RelaxedBoundPolicy<'_>, ) { - let err = |message| feature_err(&self.tcx.sess, sym::more_maybe_bounds, span, message); + // Even though feature `more_maybe_bounds` bypasses the given policy and (currently) enables + // relaxed bounds in every conceivable position[^1], we don't want to advertise it to the user + // (via a feature gate) since it's super internal. Besides this, it'd be quite distracting. + // + // [^1]: Strictly speaking, this is incorrect (at the very least for `Sized`) because it's + // no longer fully consistent with default trait elaboration in HIR ty lowering. match rbp { RelaxedBoundPolicy::Allowed => return, @@ -2093,11 +2098,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { match reason { RelaxedBoundForbiddenReason::TraitObjectTy => { - err("`?Trait` is not permitted in trait object types").emit(); + self.dcx().span_err( + span, + "relaxed bounds are not permitted in trait object types", + ); return; } RelaxedBoundForbiddenReason::SuperTrait => { - let mut diag = err("`?Trait` is not permitted in supertraits"); + let mut diag = self.dcx().struct_span_err( + span, + "relaxed bounds are not permitted in supertrait bounds", + ); if let Some(def_id) = trait_ref.trait_def_id() && self.tcx.is_lang_item(def_id, hir::LangItem::Sized) { @@ -2111,7 +2122,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } } - err("`?Trait` bounds are only permitted at the point where a type parameter is declared") + self.dcx() + .struct_span_err(span, "this relaxed bound is not permitted here") + .with_note( + "in this context, relaxed bounds are only allowed on \ + type parameters defined by the closest item", + ) .emit(); } diff --git a/tests/ui/associated-item/missing-associated_item_or_field_def_ids.rs b/tests/ui/associated-item/missing-associated_item_or_field_def_ids.rs index 18c71e5c74429..029ce7d0e7e49 100644 --- a/tests/ui/associated-item/missing-associated_item_or_field_def_ids.rs +++ b/tests/ui/associated-item/missing-associated_item_or_field_def_ids.rs @@ -2,6 +2,6 @@ fn main() -> dyn Iterator + ?Iterator::advance_by(usize) { //~^ ERROR expected trait, found associated function `Iterator::advance_by` - //~| ERROR `?Trait` is not permitted in trait object types + //~| ERROR relaxed bounds are not permitted in trait object types todo!() } diff --git a/tests/ui/associated-item/missing-associated_item_or_field_def_ids.stderr b/tests/ui/associated-item/missing-associated_item_or_field_def_ids.stderr index 6ec8e01c78d38..ffe0b14a030d3 100644 --- a/tests/ui/associated-item/missing-associated_item_or_field_def_ids.stderr +++ b/tests/ui/associated-item/missing-associated_item_or_field_def_ids.stderr @@ -4,16 +4,12 @@ error[E0404]: expected trait, found associated function `Iterator::advance_by` LL | fn main() -> dyn Iterator + ?Iterator::advance_by(usize) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a trait -error[E0658]: `?Trait` is not permitted in trait object types +error: relaxed bounds are not permitted in trait object types --> $DIR/missing-associated_item_or_field_def_ids.rs:3:29 | LL | fn main() -> dyn Iterator + ?Iterator::advance_by(usize) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 2 previous errors -Some errors have detailed explanations: E0404, E0658. -For more information about an error, try `rustc --explain E0404`. +For more information about this error, try `rustc --explain E0404`. diff --git a/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.rs b/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.rs index 9e0a86abb2e0b..bac4e60886772 100644 --- a/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.rs +++ b/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.rs @@ -7,5 +7,5 @@ trait Tr { fn main() { let _: dyn Tr + ?Foo; //~^ ERROR: cannot find trait `Foo` in this scope - //~| ERROR: `?Trait` is not permitted in trait object types + //~| ERROR: relaxed bounds are not permitted in trait object types } diff --git a/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.stderr b/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.stderr index bd83c1a9ea892..3660fcece62ae 100644 --- a/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.stderr +++ b/tests/ui/associated-types/avoid-getting-associated-items-of-undefined-trait.stderr @@ -4,16 +4,12 @@ error[E0405]: cannot find trait `Foo` in this scope LL | let _: dyn Tr + ?Foo; | ^^^ not found in this scope -error[E0658]: `?Trait` is not permitted in trait object types +error: relaxed bounds are not permitted in trait object types --> $DIR/avoid-getting-associated-items-of-undefined-trait.rs:8:21 | LL | let _: dyn Tr + ?Foo; | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 2 previous errors -Some errors have detailed explanations: E0405, E0658. -For more information about an error, try `rustc --explain E0405`. +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs index 6a832744e3ee9..3066967f87e2f 100644 --- a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs +++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs @@ -2,13 +2,11 @@ trait Trait1 {} auto trait Trait2 {} -trait Trait3: ?Trait1 {} -//~^ ERROR `?Trait` is not permitted in supertraits -trait Trait4 where Self: ?Trait1 {} -//~^ ERROR ?Trait` bounds are only permitted at the point where a type parameter is declared +trait Trait3: ?Trait1 {} //~ ERROR relaxed bounds are not permitted in supertrait bounds +trait Trait4 where Self: ?Trait1 {} //~ ERROR this relaxed bound is not permitted here fn foo(_: Box) {} -//~^ ERROR `?Trait` is not permitted in trait object types +//~^ ERROR relaxed bounds are not permitted in trait object types fn bar(_: T) {} //~^ ERROR type parameter has more than one relaxed default bound, only one is supported //~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default diff --git a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr index f52532a035b46..35b5b80d69eb9 100644 --- a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr @@ -1,32 +1,25 @@ -error[E0658]: `?Trait` is not permitted in supertraits +error: relaxed bounds are not permitted in supertrait bounds --> $DIR/feature-gate-more-maybe-bounds.rs:5:15 | LL | trait Trait3: ?Trait1 {} | ^^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/feature-gate-more-maybe-bounds.rs:7:26 +error: this relaxed bound is not permitted here + --> $DIR/feature-gate-more-maybe-bounds.rs:6:26 | LL | trait Trait4 where Self: ?Trait1 {} | ^^^^^^^ | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item -error[E0658]: `?Trait` is not permitted in trait object types - --> $DIR/feature-gate-more-maybe-bounds.rs:10:28 +error: relaxed bounds are not permitted in trait object types + --> $DIR/feature-gate-more-maybe-bounds.rs:8:28 | LL | fn foo(_: Box) {} | ^^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/feature-gate-more-maybe-bounds.rs:12:11 + --> $DIR/feature-gate-more-maybe-bounds.rs:10:11 | LL | fn bar(_: T) {} | ^^^^^^^ ^^^^^^^ @@ -35,36 +28,35 @@ LL | fn bar(_: T) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/feature-gate-more-maybe-bounds.rs:12:11 + --> $DIR/feature-gate-more-maybe-bounds.rs:10:11 | LL | fn bar(_: T) {} | ^^^^^^^ error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/feature-gate-more-maybe-bounds.rs:12:21 + --> $DIR/feature-gate-more-maybe-bounds.rs:10:21 | LL | fn bar(_: T) {} | ^^^^^^^ error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/feature-gate-more-maybe-bounds.rs:19:11 + --> $DIR/feature-gate-more-maybe-bounds.rs:17:11 | LL | fn baz(_ : T) {} | ^^^^^^ ^^^^^^ error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/feature-gate-more-maybe-bounds.rs:19:11 + --> $DIR/feature-gate-more-maybe-bounds.rs:17:11 | LL | fn baz(_ : T) {} | ^^^^^^ error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/feature-gate-more-maybe-bounds.rs:19:20 + --> $DIR/feature-gate-more-maybe-bounds.rs:17:20 | LL | fn baz(_ : T) {} | ^^^^^^ error: aborting due to 9 previous errors -Some errors have detailed explanations: E0203, E0658. -For more information about an error, try `rustc --explain E0203`. +For more information about this error, try `rustc --explain E0203`. diff --git a/tests/ui/parser/trait-object-trait-parens.rs b/tests/ui/parser/trait-object-trait-parens.rs index 438034bc38aa4..51f0e2de6116f 100644 --- a/tests/ui/parser/trait-object-trait-parens.rs +++ b/tests/ui/parser/trait-object-trait-parens.rs @@ -6,17 +6,17 @@ fn f Trait<'a>)>() {} fn main() { let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>; - //~^ ERROR `?Trait` is not permitted in trait object types + //~^ ERROR relaxed bounds are not permitted in trait object types //~| ERROR only auto traits can be used as additional traits //~| WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition let _: Box Trait<'a>) + (Obj)>; - //~^ ERROR `?Trait` is not permitted in trait object types + //~^ ERROR relaxed bounds are not permitted in trait object types //~| ERROR only auto traits can be used as additional traits //~| WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition let _: Box Trait<'a> + (Obj) + (?Sized)>; - //~^ ERROR `?Trait` is not permitted in trait object types + //~^ ERROR relaxed bounds are not permitted in trait object types //~| ERROR only auto traits can be used as additional traits //~| WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition diff --git a/tests/ui/parser/trait-object-trait-parens.stderr b/tests/ui/parser/trait-object-trait-parens.stderr index d75352b6811ea..26d388f877980 100644 --- a/tests/ui/parser/trait-object-trait-parens.stderr +++ b/tests/ui/parser/trait-object-trait-parens.stderr @@ -1,29 +1,20 @@ -error[E0658]: `?Trait` is not permitted in trait object types +error: relaxed bounds are not permitted in trait object types --> $DIR/trait-object-trait-parens.rs:8:24 | LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>; | ^^^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: `?Trait` is not permitted in trait object types +error: relaxed bounds are not permitted in trait object types --> $DIR/trait-object-trait-parens.rs:13:16 | LL | let _: Box Trait<'a>) + (Obj)>; | ^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: `?Trait` is not permitted in trait object types +error: relaxed bounds are not permitted in trait object types --> $DIR/trait-object-trait-parens.rs:18:44 | LL | let _: Box Trait<'a> + (Obj) + (?Sized)>; | ^^^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date warning: trait objects without an explicit `dyn` are deprecated --> $DIR/trait-object-trait-parens.rs:8:16 @@ -100,5 +91,4 @@ LL | let _: Box Trait<'a> + (Obj) + (?Sized)>; error: aborting due to 6 previous errors; 3 warnings emitted -Some errors have detailed explanations: E0225, E0658. -For more information about an error, try `rustc --explain E0225`. +For more information about this error, try `rustc --explain E0225`. diff --git a/tests/ui/sized-hierarchy/default-supertrait.rs b/tests/ui/sized-hierarchy/default-supertrait.rs index b25acf9e6ea4f..ab3b28e84db5a 100644 --- a/tests/ui/sized-hierarchy/default-supertrait.rs +++ b/tests/ui/sized-hierarchy/default-supertrait.rs @@ -6,18 +6,18 @@ use std::marker::{MetaSized, PointeeSized}; trait Sized_: Sized { } trait NegSized: ?Sized { } -//~^ ERROR `?Trait` is not permitted in supertraits +//~^ ERROR relaxed bounds are not permitted in supertrait bounds trait MetaSized_: MetaSized { } trait NegMetaSized: ?MetaSized { } -//~^ ERROR `?Trait` is not permitted in supertraits +//~^ ERROR relaxed bounds are not permitted in supertrait bounds trait PointeeSized_: PointeeSized { } trait NegPointeeSized: ?PointeeSized { } -//~^ ERROR `?Trait` is not permitted in supertraits +//~^ ERROR relaxed bounds are not permitted in supertrait bounds trait Bare {} diff --git a/tests/ui/sized-hierarchy/default-supertrait.stderr b/tests/ui/sized-hierarchy/default-supertrait.stderr index 0cb4f346a6300..f5589d6e279cc 100644 --- a/tests/ui/sized-hierarchy/default-supertrait.stderr +++ b/tests/ui/sized-hierarchy/default-supertrait.stderr @@ -1,30 +1,22 @@ -error[E0658]: `?Trait` is not permitted in supertraits +error: relaxed bounds are not permitted in supertrait bounds --> $DIR/default-supertrait.rs:8:17 | LL | trait NegSized: ?Sized { } | ^^^^^^ | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: traits are `?Sized` by default -error[E0658]: `?Trait` is not permitted in supertraits +error: relaxed bounds are not permitted in supertrait bounds --> $DIR/default-supertrait.rs:13:21 | LL | trait NegMetaSized: ?MetaSized { } | ^^^^^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: `?Trait` is not permitted in supertraits +error: relaxed bounds are not permitted in supertrait bounds --> $DIR/default-supertrait.rs:19:24 | LL | trait NegPointeeSized: ?PointeeSized { } | ^^^^^^^^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0277]: the size for values of type `T` cannot be known --> $DIR/default-supertrait.rs:52:38 @@ -119,5 +111,4 @@ LL | fn with_bare_trait() { error: aborting due to 9 previous errors -Some errors have detailed explanations: E0277, E0658. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/maybe-trait-bounds-forbidden-locations.rs b/tests/ui/traits/maybe-trait-bounds-forbidden-locations.rs deleted file mode 100644 index 04963c98765e9..0000000000000 --- a/tests/ui/traits/maybe-trait-bounds-forbidden-locations.rs +++ /dev/null @@ -1,18 +0,0 @@ -//! Test that ?Trait bounds are forbidden in supertraits and trait object types. -//! -//! While `?Sized` and other maybe bounds are allowed in type parameter bounds and where clauses, -//! they are explicitly forbidden in certain syntactic positions: -//! - As supertraits in trait definitions -//! - In trait object type expressions -//! -//! See https://github.com/rust-lang/rust/issues/20503 - -trait Tr: ?Sized {} -//~^ ERROR `?Trait` is not permitted in supertraits - -type A1 = dyn Tr + (?Sized); -//~^ ERROR `?Trait` is not permitted in trait object types -type A2 = dyn for<'a> Tr + (?Sized); -//~^ ERROR `?Trait` is not permitted in trait object types - -fn main() {} diff --git a/tests/ui/traits/maybe-trait-bounds-forbidden-locations.stderr b/tests/ui/traits/maybe-trait-bounds-forbidden-locations.stderr deleted file mode 100644 index 5c4100d0e269f..0000000000000 --- a/tests/ui/traits/maybe-trait-bounds-forbidden-locations.stderr +++ /dev/null @@ -1,31 +0,0 @@ -error[E0658]: `?Trait` is not permitted in supertraits - --> $DIR/maybe-trait-bounds-forbidden-locations.rs:10:11 - | -LL | trait Tr: ?Sized {} - | ^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = note: traits are `?Sized` by default - -error[E0658]: `?Trait` is not permitted in trait object types - --> $DIR/maybe-trait-bounds-forbidden-locations.rs:13:20 - | -LL | type A1 = dyn Tr + (?Sized); - | ^^^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `?Trait` is not permitted in trait object types - --> $DIR/maybe-trait-bounds-forbidden-locations.rs:15:28 - | -LL | type A2 = dyn for<'a> Tr + (?Sized); - | ^^^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/wf-object/maybe-bound.rs b/tests/ui/traits/wf-object/maybe-bound.rs deleted file mode 100644 index 17771e976ef3b..0000000000000 --- a/tests/ui/traits/wf-object/maybe-bound.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Test that `dyn ... + ?Sized + ...` is okay (though `?Sized` has no effect in trait objects). - -trait Foo {} - -type _0 = dyn ?Sized + Foo; -//~^ ERROR `?Trait` is not permitted in trait object types - -type _1 = dyn Foo + ?Sized; -//~^ ERROR `?Trait` is not permitted in trait object types - -type _2 = dyn Foo + ?Sized + ?Sized; -//~^ ERROR `?Trait` is not permitted in trait object types -//~| ERROR `?Trait` is not permitted in trait object types - -type _3 = dyn ?Sized + Foo; -//~^ ERROR `?Trait` is not permitted in trait object types - -fn main() {} diff --git a/tests/ui/traits/wf-object/maybe-bound.stderr b/tests/ui/traits/wf-object/maybe-bound.stderr deleted file mode 100644 index be7afabd0d01d..0000000000000 --- a/tests/ui/traits/wf-object/maybe-bound.stderr +++ /dev/null @@ -1,48 +0,0 @@ -error[E0658]: `?Trait` is not permitted in trait object types - --> $DIR/maybe-bound.rs:5:15 - | -LL | type _0 = dyn ?Sized + Foo; - | ^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `?Trait` is not permitted in trait object types - --> $DIR/maybe-bound.rs:8:21 - | -LL | type _1 = dyn Foo + ?Sized; - | ^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `?Trait` is not permitted in trait object types - --> $DIR/maybe-bound.rs:11:21 - | -LL | type _2 = dyn Foo + ?Sized + ?Sized; - | ^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `?Trait` is not permitted in trait object types - --> $DIR/maybe-bound.rs:11:30 - | -LL | type _2 = dyn Foo + ?Sized + ?Sized; - | ^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: `?Trait` is not permitted in trait object types - --> $DIR/maybe-bound.rs:15:15 - | -LL | type _3 = dyn ?Sized + Foo; - | ^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/wf-object/only-maybe-bound.rs b/tests/ui/traits/wf-object/only-maybe-bound.rs index 3e6db3e997c9b..96360e0331cdb 100644 --- a/tests/ui/traits/wf-object/only-maybe-bound.rs +++ b/tests/ui/traits/wf-object/only-maybe-bound.rs @@ -2,6 +2,6 @@ type _0 = dyn ?Sized; //~^ ERROR at least one trait is required for an object type [E0224] -//~| ERROR ?Trait` is not permitted in trait object types +//~| ERROR relaxed bounds are not permitted in trait object types fn main() {} diff --git a/tests/ui/traits/wf-object/only-maybe-bound.stderr b/tests/ui/traits/wf-object/only-maybe-bound.stderr index 26269476eaaee..6ae4568c699a7 100644 --- a/tests/ui/traits/wf-object/only-maybe-bound.stderr +++ b/tests/ui/traits/wf-object/only-maybe-bound.stderr @@ -1,11 +1,8 @@ -error[E0658]: `?Trait` is not permitted in trait object types +error: relaxed bounds are not permitted in trait object types --> $DIR/only-maybe-bound.rs:3:15 | LL | type _0 = dyn ?Sized; | ^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0224]: at least one trait is required for an object type --> $DIR/only-maybe-bound.rs:3:11 @@ -15,5 +12,4 @@ LL | type _0 = dyn ?Sized; error: aborting due to 2 previous errors -Some errors have detailed explanations: E0224, E0658. -For more information about an error, try `rustc --explain E0224`. +For more information about this error, try `rustc --explain E0224`. diff --git a/tests/ui/unsized/relaxed-bounds-invalid-places.rs b/tests/ui/unsized/relaxed-bounds-invalid-places.rs index ce3f35608bebb..e9f39d5f21170 100644 --- a/tests/ui/unsized/relaxed-bounds-invalid-places.rs +++ b/tests/ui/unsized/relaxed-bounds-invalid-places.rs @@ -1,19 +1,18 @@ -// Test that relaxed bounds can only be placed on type parameters defined by the closest item -// (ignoring relaxed bounds inside `impl Trait` and in associated type defs here). +// Test various places where relaxed bounds are not permitted. +// +// Relaxed bounds are only permitted inside impl-Trait, assoc ty item bounds and +// on type params defined by the closest item. -struct S1(T) where (T): ?Sized; -//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared +struct S1(T) where (T): ?Sized; //~ ERROR this relaxed bound is not permitted here -struct S2(T) where u8: ?Sized; -//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared +struct S2(T) where u8: ?Sized; //~ ERROR this relaxed bound is not permitted here -struct S3(T) where &'static T: ?Sized; -//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared +struct S3(T) where &'static T: ?Sized; //~ ERROR this relaxed bound is not permitted here trait Trait<'a> {} struct S4(T) where for<'a> T: ?Trait<'a>; -//~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared +//~^ ERROR this relaxed bound is not permitted here //~| ERROR relaxing a default bound only does something for `?Sized` struct S5(*const T) where T: ?Trait<'static> + ?Sized; @@ -21,11 +20,17 @@ struct S5(*const T) where T: ?Trait<'static> + ?Sized; //~| ERROR relaxing a default bound only does something for `?Sized` impl S1 { - fn f() where T: ?Sized {} - //~^ ERROR `?Trait` bounds are only permitted at the point where a type parameter is declared + fn f() where T: ?Sized {} //~ ERROR this relaxed bound is not permitted here } -fn main() { - let u = vec![1, 2, 3]; - let _s: S5<[u8]> = S5(&u[..]); // OK -} +trait Tr: ?Sized {} //~ ERROR relaxed bounds are not permitted in supertrait bounds + +// Test that relaxed `Sized` bounds are rejected in trait object types: + +type O1 = dyn Tr + ?Sized; //~ ERROR relaxed bounds are not permitted in trait object types +type O2 = dyn ?Sized + ?Sized + Tr; +//~^ ERROR relaxed bounds are not permitted in trait object types +//~| ERROR relaxed bounds are not permitted in trait object types + +fn main() {} + diff --git a/tests/ui/unsized/relaxed-bounds-invalid-places.stderr b/tests/ui/unsized/relaxed-bounds-invalid-places.stderr index 3287eb8d1e9d5..a08dc15058a51 100644 --- a/tests/ui/unsized/relaxed-bounds-invalid-places.stderr +++ b/tests/ui/unsized/relaxed-bounds-invalid-places.stderr @@ -1,56 +1,77 @@ -error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/relaxed-bounds-invalid-places.rs:4:28 +error: this relaxed bound is not permitted here + --> $DIR/relaxed-bounds-invalid-places.rs:6:28 | LL | struct S1(T) where (T): ?Sized; | ^^^^^^ | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item -error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/relaxed-bounds-invalid-places.rs:7:27 +error: this relaxed bound is not permitted here + --> $DIR/relaxed-bounds-invalid-places.rs:8:27 | LL | struct S2(T) where u8: ?Sized; | ^^^^^^ | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item -error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared +error: this relaxed bound is not permitted here --> $DIR/relaxed-bounds-invalid-places.rs:10:35 | LL | struct S3(T) where &'static T: ?Sized; | ^^^^^^ | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item -error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/relaxed-bounds-invalid-places.rs:15:34 +error: this relaxed bound is not permitted here + --> $DIR/relaxed-bounds-invalid-places.rs:14:34 | LL | struct S4(T) where for<'a> T: ?Trait<'a>; | ^^^^^^^^^^ | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item -error[E0658]: `?Trait` bounds are only permitted at the point where a type parameter is declared - --> $DIR/relaxed-bounds-invalid-places.rs:24:21 +error: this relaxed bound is not permitted here + --> $DIR/relaxed-bounds-invalid-places.rs:23:21 | LL | fn f() where T: ?Sized {} | ^^^^^^ | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item + +error: relaxed bounds are not permitted in supertrait bounds + --> $DIR/relaxed-bounds-invalid-places.rs:26:11 + | +LL | trait Tr: ?Sized {} + | ^^^^^^ + | + = note: traits are `?Sized` by default + +error: relaxed bounds are not permitted in trait object types + --> $DIR/relaxed-bounds-invalid-places.rs:30:20 + | +LL | type O1 = dyn Tr + ?Sized; + | ^^^^^^ + +error: relaxed bounds are not permitted in trait object types + --> $DIR/relaxed-bounds-invalid-places.rs:31:15 + | +LL | type O2 = dyn ?Sized + ?Sized + Tr; + | ^^^^^^ + +error: relaxed bounds are not permitted in trait object types + --> $DIR/relaxed-bounds-invalid-places.rs:31:24 + | +LL | type O2 = dyn ?Sized + ?Sized + Tr; + | ^^^^^^ error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/relaxed-bounds-invalid-places.rs:15:34 + --> $DIR/relaxed-bounds-invalid-places.rs:14:34 | LL | struct S4(T) where for<'a> T: ?Trait<'a>; | ^^^^^^^^^^ error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/relaxed-bounds-invalid-places.rs:19:33 + --> $DIR/relaxed-bounds-invalid-places.rs:18:33 | LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; | ^^^^^^^^^^^^^^^ ^^^^^^ @@ -59,12 +80,11 @@ LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/relaxed-bounds-invalid-places.rs:19:33 + --> $DIR/relaxed-bounds-invalid-places.rs:18:33 | LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; | ^^^^^^^^^^^^^^^ -error: aborting due to 8 previous errors +error: aborting due to 12 previous errors -Some errors have detailed explanations: E0203, E0658. -For more information about an error, try `rustc --explain E0203`. +For more information about this error, try `rustc --explain E0203`. From 879f62bb3c23b7a90ac71bb217056fd49ff8dafb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 19 Jun 2025 18:41:57 +0200 Subject: [PATCH 14/19] Reword diagnostic about relaxing non-`Sized` bound * The phrasing "only does something for" made sense back when this diagnostic was a (hard) warning. Now however, it's simply a hard error and thus completely rules out "doing something". * The primary message was way too long * The new wording more closely mirrors the wording we use for applying other bound modifiers (like `const` and `async`) to incompatible traits. * "all other traits are not bound by default" is no longer accurate under Sized Hierarchy. E.g., traits and assoc tys are (currently) bounded by `MetaSized` by default but can't be relaxed using `?MetaSized` (instead, you relax it by adding `PointeeSized`). * I've decided against adding any diagnositic notes or suggestions for now like "trait `Trait` can't be relaxed as it's not bound by default" which would be incorrect for `MetaSized` and assoc tys as mentioned above) or "consider changing `?MetaSized` to `PointeeSized`" as the Sized Hierarchy impl is still WIP) --- .../src/hir_ty_lowering/bounds.rs | 27 ++++++++--- .../src/hir_ty_lowering/errors.rs | 47 +++++++++---------- .../feature-gate-more-maybe-bounds.rs | 8 ++-- .../feature-gate-more-maybe-bounds.stderr | 8 ++-- .../impl-trait/opt-out-bound-not-satisfied.rs | 4 +- .../opt-out-bound-not-satisfied.stderr | 4 +- tests/ui/issues/issue-37534.rs | 2 +- tests/ui/issues/issue-37534.stderr | 2 +- tests/ui/issues/issue-87199.rs | 8 ++-- tests/ui/issues/issue-87199.stderr | 8 ++-- tests/ui/sized-hierarchy/default-bound.rs | 4 +- tests/ui/sized-hierarchy/default-bound.stderr | 4 +- .../trait-bounds/maybe-bound-has-path-args.rs | 2 +- .../maybe-bound-has-path-args.stderr | 2 +- .../ui/trait-bounds/maybe-bound-with-assoc.rs | 4 +- .../maybe-bound-with-assoc.stderr | 4 +- tests/ui/trait-bounds/more_maybe_bounds.rs | 29 ++++++++++++ .../ui/trait-bounds/more_maybe_bounds.stderr | 20 ++++++++ tests/ui/traits/maybe-polarity-pass.rs | 25 ---------- tests/ui/traits/maybe-polarity-pass.stderr | 20 -------- tests/ui/traits/maybe-polarity-repeated.rs | 4 +- .../ui/traits/maybe-polarity-repeated.stderr | 4 +- .../unsized/relaxed-bounds-invalid-places.rs | 4 +- .../relaxed-bounds-invalid-places.stderr | 4 +- 24 files changed, 131 insertions(+), 117 deletions(-) create mode 100644 tests/ui/trait-bounds/more_maybe_bounds.rs create mode 100644 tests/ui/trait-bounds/more_maybe_bounds.stderr delete mode 100644 tests/ui/traits/maybe-polarity-pass.rs delete mode 100644 tests/ui/traits/maybe-polarity-pass.stderr diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index b59ff863383fa..dbd22fabab8b8 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -85,17 +85,17 @@ fn search_bounds_for<'tcx>( } } -fn collect_unbounds<'tcx>( +fn collect_relaxed_bounds<'tcx>( hir_bounds: &'tcx [hir::GenericBound<'tcx>], self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, ) -> SmallVec<[&'tcx PolyTraitRef<'tcx>; 1]> { - let mut unbounds: SmallVec<[_; 1]> = SmallVec::new(); + let mut relaxed_bounds: SmallVec<[_; 1]> = SmallVec::new(); search_bounds_for(hir_bounds, self_ty_where_predicates, |ptr| { if matches!(ptr.modifiers.polarity, hir::BoundPolarity::Maybe(_)) { - unbounds.push(ptr); + relaxed_bounds.push(ptr); } }); - unbounds + relaxed_bounds } fn collect_bounds<'a, 'tcx>( @@ -209,9 +209,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return; } } else { - // Report invalid unbounds on sizedness-bounded generic parameters. - let unbounds = collect_unbounds(hir_bounds, self_ty_where_predicates); - self.check_and_report_invalid_unbounds_on_param(unbounds); + // Report invalid relaxed bounds. + // FIXME: Since we only call this validation function here in this function, we only + // fully validate relaxed bounds in contexts where we perform + // "sized elaboration". In most cases that doesn't matter because we *usually* + // reject such relaxed bounds outright during AST lowering. + // However, this can easily get out of sync! Ideally, we would perform this step + // where we are guaranteed to catch *all* bounds like in + // `Self::lower_poly_trait_ref`. List of concrete issues: + // FIXME(more_maybe_bounds): We don't call this for e.g., trait object tys or + // supertrait bounds! + // FIXME(trait_alias, #143122): We don't call it for the RHS. Arguably however, + // AST lowering should reject them outright. + // FIXME(associated_type_bounds): We don't call this for them. However, AST + // lowering should reject them outright (#135229). + let bounds = collect_relaxed_bounds(hir_bounds, self_ty_where_predicates); + self.check_and_report_invalid_relaxed_bounds(bounds); } let collected = collect_sizedness_bounds(tcx, hir_bounds, self_ty_where_predicates, span); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 5d85a3f8455e0..8c99a41f62685 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -8,7 +8,7 @@ use rustc_errors::{ }; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, HirId, LangItem, PolyTraitRef}; +use rustc_hir::{self as hir, HirId, PolyTraitRef}; use rustc_middle::bug; use rustc_middle::ty::fast_reject::{TreatParams, simplify_type}; use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _}; @@ -35,26 +35,24 @@ use crate::fluent_generated as fluent; use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer}; impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { - /// Check for multiple relaxed default bounds and relaxed bounds of non-sizedness traits. - pub(crate) fn check_and_report_invalid_unbounds_on_param( + /// Check for multiple relaxed bounds and relaxed bounds of non-default traits. + pub(crate) fn check_and_report_invalid_relaxed_bounds( &self, - unbounds: SmallVec<[&PolyTraitRef<'_>; 1]>, + relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>, ) { let tcx = self.tcx(); - let sized_did = tcx.require_lang_item(LangItem::Sized, DUMMY_SP); - let mut unique_bounds = FxIndexSet::default(); let mut seen_repeat = false; - for unbound in &unbounds { - if let Res::Def(DefKind::Trait, unbound_def_id) = unbound.trait_ref.path.res { - seen_repeat |= !unique_bounds.insert(unbound_def_id); + for bound in &relaxed_bounds { + if let Res::Def(DefKind::Trait, trait_def_id) = bound.trait_ref.path.res { + seen_repeat |= !unique_bounds.insert(trait_def_id); } } - if unbounds.len() > 1 { + if relaxed_bounds.len() > 1 { let err = errors::MultipleRelaxedDefaultBounds { - spans: unbounds.iter().map(|ptr| ptr.span).collect(), + spans: relaxed_bounds.iter().map(|ptr| ptr.span).collect(), }; if seen_repeat { @@ -64,24 +62,23 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }; } - for unbound in unbounds { - if let Res::Def(DefKind::Trait, did) = unbound.trait_ref.path.res - && ((did == sized_did) || tcx.is_default_trait(did)) + let sized_def_id = tcx.require_lang_item(hir::LangItem::Sized, DUMMY_SP); + + for bound in relaxed_bounds { + if let Res::Def(DefKind::Trait, def_id) = bound.trait_ref.path.res + && (def_id == sized_def_id || tcx.is_default_trait(def_id)) { continue; } - - let unbound_traits = match tcx.sess.opts.unstable_opts.experimental_default_bounds { - true => "`?Sized` and `experimental_default_bounds`", - false => "`?Sized`", - }; self.dcx().span_err( - unbound.span, - format!( - "relaxing a default bound only does something for {}; all other traits are \ - not bound by default", - unbound_traits - ), + bound.span, + if tcx.sess.opts.unstable_opts.experimental_default_bounds + || tcx.features().more_maybe_bounds() + { + "bound modifier `?` can only be applied to default traits like `Sized`" + } else { + "bound modifier `?` can only be applied to `Sized`" + }, ); } } diff --git a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs index 3066967f87e2f..7c9d88462f631 100644 --- a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs +++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs @@ -9,14 +9,14 @@ fn foo(_: Box) {} //~^ ERROR relaxed bounds are not permitted in trait object types fn bar(_: T) {} //~^ ERROR type parameter has more than one relaxed default bound, only one is supported -//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default -//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +//~| ERROR bound modifier `?` can only be applied to `Sized` +//~| ERROR bound modifier `?` can only be applied to `Sized` trait Trait {} // Do not suggest `#![feature(more_maybe_bounds)]` for repetitions fn baz(_ : T) {} //~^ ERROR type parameter has more than one relaxed default bound, only one is supported -//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default -//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +//~| ERROR bound modifier `?` can only be applied to `Sized` +//~| ERROR bound modifier `?` can only be applied to `Sized` fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr index 35b5b80d69eb9..c6d940db57bf2 100644 --- a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr @@ -27,13 +27,13 @@ LL | fn bar(_: T) {} = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/feature-gate-more-maybe-bounds.rs:10:11 | LL | fn bar(_: T) {} | ^^^^^^^ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/feature-gate-more-maybe-bounds.rs:10:21 | LL | fn bar(_: T) {} @@ -45,13 +45,13 @@ error[E0203]: type parameter has more than one relaxed default bound, only one i LL | fn baz(_ : T) {} | ^^^^^^ ^^^^^^ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/feature-gate-more-maybe-bounds.rs:17:11 | LL | fn baz(_ : T) {} | ^^^^^^ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/feature-gate-more-maybe-bounds.rs:17:20 | LL | fn baz(_ : T) {} diff --git a/tests/ui/impl-trait/opt-out-bound-not-satisfied.rs b/tests/ui/impl-trait/opt-out-bound-not-satisfied.rs index 27c493a13bf91..7e0e1eadf9c75 100644 --- a/tests/ui/impl-trait/opt-out-bound-not-satisfied.rs +++ b/tests/ui/impl-trait/opt-out-bound-not-satisfied.rs @@ -3,8 +3,8 @@ use std::future::Future; fn foo() -> impl ?Future { - //~^ ERROR: relaxing a default bound only does something for `?Sized` - //~| ERROR: relaxing a default bound only does something for `?Sized` + //~^ ERROR: bound modifier `?` can only be applied to `Sized` + //~| ERROR: bound modifier `?` can only be applied to `Sized` () } diff --git a/tests/ui/impl-trait/opt-out-bound-not-satisfied.stderr b/tests/ui/impl-trait/opt-out-bound-not-satisfied.stderr index dc4314c58ad2f..f99d6a7e5f6d0 100644 --- a/tests/ui/impl-trait/opt-out-bound-not-satisfied.stderr +++ b/tests/ui/impl-trait/opt-out-bound-not-satisfied.stderr @@ -1,10 +1,10 @@ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/opt-out-bound-not-satisfied.rs:5:18 | LL | fn foo() -> impl ?Future { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/opt-out-bound-not-satisfied.rs:5:18 | LL | fn foo() -> impl ?Future { diff --git a/tests/ui/issues/issue-37534.rs b/tests/ui/issues/issue-37534.rs index 09d60b7786b99..63f6479ae2e24 100644 --- a/tests/ui/issues/issue-37534.rs +++ b/tests/ui/issues/issue-37534.rs @@ -1,5 +1,5 @@ struct Foo {} //~^ ERROR expected trait, found derive macro `Hash` -//~| ERROR relaxing a default bound only does something for `?Sized` +//~| ERROR bound modifier `?` can only be applied to `Sized` fn main() {} diff --git a/tests/ui/issues/issue-37534.stderr b/tests/ui/issues/issue-37534.stderr index 3219854bc70ce..0860735420301 100644 --- a/tests/ui/issues/issue-37534.stderr +++ b/tests/ui/issues/issue-37534.stderr @@ -9,7 +9,7 @@ help: consider importing this trait instead LL + use std::hash::Hash; | -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/issue-37534.rs:1:15 | LL | struct Foo {} diff --git a/tests/ui/issues/issue-87199.rs b/tests/ui/issues/issue-87199.rs index 4e4e35c6a71e8..dd9dfc74ca352 100644 --- a/tests/ui/issues/issue-87199.rs +++ b/tests/ui/issues/issue-87199.rs @@ -6,12 +6,12 @@ // Check that these function definitions only emit warnings, not errors fn arg(_: T) {} -//~^ ERROR: relaxing a default bound only does something for `?Sized` +//~^ ERROR: bound modifier `?` can only be applied to `Sized` fn ref_arg(_: &T) {} -//~^ ERROR: relaxing a default bound only does something for `?Sized` +//~^ ERROR: bound modifier `?` can only be applied to `Sized` fn ret() -> impl Iterator + ?Send { std::iter::empty() } -//~^ ERROR: relaxing a default bound only does something for `?Sized` -//~| ERROR: relaxing a default bound only does something for `?Sized` +//~^ ERROR: bound modifier `?` can only be applied to `Sized` +//~| ERROR: bound modifier `?` can only be applied to `Sized` // Check that there's no `?Sized` relaxation! fn main() { diff --git a/tests/ui/issues/issue-87199.stderr b/tests/ui/issues/issue-87199.stderr index acc4e84779c9c..8a930a3d704c1 100644 --- a/tests/ui/issues/issue-87199.stderr +++ b/tests/ui/issues/issue-87199.stderr @@ -1,22 +1,22 @@ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/issue-87199.rs:8:11 | LL | fn arg(_: T) {} | ^^^^^ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/issue-87199.rs:10:15 | LL | fn ref_arg(_: &T) {} | ^^^^^ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/issue-87199.rs:12:40 | LL | fn ret() -> impl Iterator + ?Send { std::iter::empty() } | ^^^^^ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/issue-87199.rs:12:40 | LL | fn ret() -> impl Iterator + ?Send { std::iter::empty() } diff --git a/tests/ui/sized-hierarchy/default-bound.rs b/tests/ui/sized-hierarchy/default-bound.rs index 12b2eb2b5c1b4..bbb2c6d96baa8 100644 --- a/tests/ui/sized-hierarchy/default-bound.rs +++ b/tests/ui/sized-hierarchy/default-bound.rs @@ -14,13 +14,13 @@ fn neg_sized() {} fn metasized() {} fn neg_metasized() {} -//~^ ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +//~^ ERROR bound modifier `?` can only be applied to `Sized` fn pointeesized() { } fn neg_pointeesized() { } -//~^ ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +//~^ ERROR bound modifier `?` can only be applied to `Sized` fn main() { diff --git a/tests/ui/sized-hierarchy/default-bound.stderr b/tests/ui/sized-hierarchy/default-bound.stderr index 22f0fa29d3e23..0a4ea6f44d8ed 100644 --- a/tests/ui/sized-hierarchy/default-bound.stderr +++ b/tests/ui/sized-hierarchy/default-bound.stderr @@ -1,10 +1,10 @@ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/default-bound.rs:16:21 | LL | fn neg_metasized() {} | ^^^^^^^^^^ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/default-bound.rs:22:24 | LL | fn neg_pointeesized() { } diff --git a/tests/ui/trait-bounds/maybe-bound-has-path-args.rs b/tests/ui/trait-bounds/maybe-bound-has-path-args.rs index e5abcae5d219b..14a2667049775 100644 --- a/tests/ui/trait-bounds/maybe-bound-has-path-args.rs +++ b/tests/ui/trait-bounds/maybe-bound-has-path-args.rs @@ -2,6 +2,6 @@ trait Trait {} fn test::Trait>() {} //~^ ERROR type arguments are not allowed on module `maybe_bound_has_path_args` -//~| ERROR relaxing a default bound only does something for `?Sized` +//~| ERROR bound modifier `?` can only be applied to `Sized` fn main() {} diff --git a/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr b/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr index dc55b26c9183c..bf968b05af085 100644 --- a/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr +++ b/tests/ui/trait-bounds/maybe-bound-has-path-args.stderr @@ -1,4 +1,4 @@ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/maybe-bound-has-path-args.rs:3:12 | LL | fn test::Trait>() {} diff --git a/tests/ui/trait-bounds/maybe-bound-with-assoc.rs b/tests/ui/trait-bounds/maybe-bound-with-assoc.rs index 9127c2de16d5e..e123f18474d1c 100644 --- a/tests/ui/trait-bounds/maybe-bound-with-assoc.rs +++ b/tests/ui/trait-bounds/maybe-bound-with-assoc.rs @@ -2,11 +2,11 @@ trait HasAssoc { type Assoc; } fn hasassoc>() {} -//~^ ERROR relaxing a default bound +//~^ ERROR bound modifier `?` can only be applied to `Sized` trait NoAssoc {} fn noassoc>() {} -//~^ ERROR relaxing a default bound +//~^ ERROR bound modifier `?` can only be applied to `Sized` //~| ERROR associated type `Missing` not found for `NoAssoc` fn main() {} diff --git a/tests/ui/trait-bounds/maybe-bound-with-assoc.stderr b/tests/ui/trait-bounds/maybe-bound-with-assoc.stderr index 36a1e0ade2063..b2ae0584aff91 100644 --- a/tests/ui/trait-bounds/maybe-bound-with-assoc.stderr +++ b/tests/ui/trait-bounds/maybe-bound-with-assoc.stderr @@ -1,10 +1,10 @@ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/maybe-bound-with-assoc.rs:4:16 | LL | fn hasassoc>() {} | ^^^^^^^^^^^^^^^^^^^^^ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/maybe-bound-with-assoc.rs:8:15 | LL | fn noassoc>() {} diff --git a/tests/ui/trait-bounds/more_maybe_bounds.rs b/tests/ui/trait-bounds/more_maybe_bounds.rs new file mode 100644 index 0000000000000..61b630479ac3e --- /dev/null +++ b/tests/ui/trait-bounds/more_maybe_bounds.rs @@ -0,0 +1,29 @@ +// FIXME(more_maybe_bounds): Even under `more_maybe_bounds` / `-Zexperimental-default-bounds`, +// trying to relax non-default bounds should still be an error in all contexts! As you can see +// there are placed like supertrait bounds and trait object types where we currently don't perform +// this check. +#![feature(auto_traits, more_maybe_bounds, negative_impls)] + +trait Trait1 {} +auto trait Trait2 {} + +// FIXME: `?Trait1` should be rejected, `Trait1` isn't marked `#[lang = "default_traitN"]`. +trait Trait3: ?Trait1 {} +trait Trait4 where Self: Trait1 {} + +// FIXME: `?Trait2` should be rejected, `Trait2` isn't marked `#[lang = "default_traitN"]`. +fn foo(_: Box<(dyn Trait3 + ?Trait2)>) {} +fn bar(_: &T) {} +//~^ ERROR bound modifier `?` can only be applied to default traits like `Sized` +//~| ERROR bound modifier `?` can only be applied to default traits like `Sized` +//~| ERROR bound modifier `?` can only be applied to default traits like `Sized` + +struct S; +impl !Trait2 for S {} +impl Trait1 for S {} +impl Trait3 for S {} + +fn main() { + foo(Box::new(S)); + bar(&S); +} diff --git a/tests/ui/trait-bounds/more_maybe_bounds.stderr b/tests/ui/trait-bounds/more_maybe_bounds.stderr new file mode 100644 index 0000000000000..09c9fc311657e --- /dev/null +++ b/tests/ui/trait-bounds/more_maybe_bounds.stderr @@ -0,0 +1,20 @@ +error: bound modifier `?` can only be applied to default traits like `Sized` + --> $DIR/more_maybe_bounds.rs:16:20 + | +LL | fn bar(_: &T) {} + | ^^^^^^^ + +error: bound modifier `?` can only be applied to default traits like `Sized` + --> $DIR/more_maybe_bounds.rs:16:30 + | +LL | fn bar(_: &T) {} + | ^^^^^^^ + +error: bound modifier `?` can only be applied to default traits like `Sized` + --> $DIR/more_maybe_bounds.rs:16:40 + | +LL | fn bar(_: &T) {} + | ^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/traits/maybe-polarity-pass.rs b/tests/ui/traits/maybe-polarity-pass.rs deleted file mode 100644 index 1ccd52bc1694a..0000000000000 --- a/tests/ui/traits/maybe-polarity-pass.rs +++ /dev/null @@ -1,25 +0,0 @@ -#![feature(auto_traits)] -#![feature(more_maybe_bounds)] -#![feature(negative_impls)] - -trait Trait1 {} -auto trait Trait2 {} - -trait Trait3 : ?Trait1 {} -trait Trait4 where Self: Trait1 {} - -fn foo(_: Box<(dyn Trait3 + ?Trait2)>) {} -fn bar(_: &T) {} -//~^ ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default -//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default -//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - -struct S; -impl !Trait2 for S {} -impl Trait1 for S {} -impl Trait3 for S {} - -fn main() { - foo(Box::new(S)); - bar(&S); -} diff --git a/tests/ui/traits/maybe-polarity-pass.stderr b/tests/ui/traits/maybe-polarity-pass.stderr deleted file mode 100644 index 1f378dd665ae6..0000000000000 --- a/tests/ui/traits/maybe-polarity-pass.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/maybe-polarity-pass.rs:12:20 - | -LL | fn bar(_: &T) {} - | ^^^^^^^ - -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/maybe-polarity-pass.rs:12:30 - | -LL | fn bar(_: &T) {} - | ^^^^^^^ - -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default - --> $DIR/maybe-polarity-pass.rs:12:40 - | -LL | fn bar(_: &T) {} - | ^^^^^^^ - -error: aborting due to 3 previous errors - diff --git a/tests/ui/traits/maybe-polarity-repeated.rs b/tests/ui/traits/maybe-polarity-repeated.rs index fd1ef567b3eab..962e3d5dbc5cc 100644 --- a/tests/ui/traits/maybe-polarity-repeated.rs +++ b/tests/ui/traits/maybe-polarity-repeated.rs @@ -3,7 +3,7 @@ trait Trait {} fn foo(_: T) {} //~^ ERROR type parameter has more than one relaxed default bound, only one is supported -//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default -//~| ERROR relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +//~| ERROR bound modifier `?` can only be applied to default traits like `Sized` +//~| ERROR bound modifier `?` can only be applied to default traits like `Sized` fn main() {} diff --git a/tests/ui/traits/maybe-polarity-repeated.stderr b/tests/ui/traits/maybe-polarity-repeated.stderr index 4fa1dc45bda85..de16c14718005 100644 --- a/tests/ui/traits/maybe-polarity-repeated.stderr +++ b/tests/ui/traits/maybe-polarity-repeated.stderr @@ -4,13 +4,13 @@ error[E0203]: type parameter has more than one relaxed default bound, only one i LL | fn foo(_: T) {} | ^^^^^^ ^^^^^^ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to default traits like `Sized` --> $DIR/maybe-polarity-repeated.rs:4:11 | LL | fn foo(_: T) {} | ^^^^^^ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to default traits like `Sized` --> $DIR/maybe-polarity-repeated.rs:4:20 | LL | fn foo(_: T) {} diff --git a/tests/ui/unsized/relaxed-bounds-invalid-places.rs b/tests/ui/unsized/relaxed-bounds-invalid-places.rs index e9f39d5f21170..64d4523ac4996 100644 --- a/tests/ui/unsized/relaxed-bounds-invalid-places.rs +++ b/tests/ui/unsized/relaxed-bounds-invalid-places.rs @@ -13,11 +13,11 @@ trait Trait<'a> {} struct S4(T) where for<'a> T: ?Trait<'a>; //~^ ERROR this relaxed bound is not permitted here -//~| ERROR relaxing a default bound only does something for `?Sized` +//~| ERROR bound modifier `?` can only be applied to `Sized` struct S5(*const T) where T: ?Trait<'static> + ?Sized; //~^ ERROR type parameter has more than one relaxed default bound -//~| ERROR relaxing a default bound only does something for `?Sized` +//~| ERROR bound modifier `?` can only be applied to `Sized` impl S1 { fn f() where T: ?Sized {} //~ ERROR this relaxed bound is not permitted here diff --git a/tests/ui/unsized/relaxed-bounds-invalid-places.stderr b/tests/ui/unsized/relaxed-bounds-invalid-places.stderr index a08dc15058a51..cfa0d274b26c1 100644 --- a/tests/ui/unsized/relaxed-bounds-invalid-places.stderr +++ b/tests/ui/unsized/relaxed-bounds-invalid-places.stderr @@ -64,7 +64,7 @@ error: relaxed bounds are not permitted in trait object types LL | type O2 = dyn ?Sized + ?Sized + Tr; | ^^^^^^ -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/relaxed-bounds-invalid-places.rs:14:34 | LL | struct S4(T) where for<'a> T: ?Trait<'a>; @@ -79,7 +79,7 @@ LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: relaxing a default bound only does something for `?Sized`; all other traits are not bound by default +error: bound modifier `?` can only be applied to `Sized` --> $DIR/relaxed-bounds-invalid-places.rs:18:33 | LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; From cdc3d701cb4ff37e9d0c96c1c68b2e8789c19441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Fri, 18 Jul 2025 12:24:56 +0200 Subject: [PATCH 15/19] Don't reject *multiple* relaxed bounds, reject *duplicate* ones. Having multiple relaxed bounds like `?Sized + ?Iterator` is actually *fine*. We actually want to reject *duplicate* relaxed bounds like `?Sized + ?Sized` because these most certainly represent a user error. Note that this doesn't mean that we accept more code because a bound like `?Iterator` is still invalid as it's not relaxing a *default* trait and the only way to define / use more default bounds is under the experimental and internal feature `more_maybe_bounds` plus `lang_items` plus unstable flag `-Zexperimental-default-bounds` (historical context: for the longest time, bounds like `?Iterator` were actually allowed and lead to a hard warning). Ultimately, this simply *reframes* the diagnostic. The scope of `more_maybe_bounds` / `-Zexperimental-default-bounds` remains unchanged as well. --- .../src/error_codes/E0203.md | 10 ++-- compiler/rustc_hir_analysis/messages.ftl | 3 -- compiler/rustc_hir_analysis/src/errors.rs | 7 --- .../src/hir_ty_lowering/errors.rs | 26 +++++----- .../feature-gate-more-maybe-bounds.rs | 10 +--- .../feature-gate-more-maybe-bounds.stderr | 30 +----------- .../trait-bounds/duplicate-relaxed-bounds.rs | 22 +++++++++ .../duplicate-relaxed-bounds.stderr | 47 +++++++++++++++++++ ...7441.rs => fix-dyn-sized-fn-param-sugg.rs} | 25 +++++----- ...err => fix-dyn-sized-fn-param-sugg.stderr} | 40 ++++++++-------- tests/ui/trait-bounds/more_maybe_bounds.rs | 2 +- tests/ui/traits/maybe-polarity-repeated.rs | 9 ---- .../ui/traits/maybe-polarity-repeated.stderr | 21 --------- .../unsized/relaxed-bounds-invalid-places.rs | 4 +- .../relaxed-bounds-invalid-places.stderr | 22 +++------ 15 files changed, 128 insertions(+), 150 deletions(-) create mode 100644 tests/ui/trait-bounds/duplicate-relaxed-bounds.rs create mode 100644 tests/ui/trait-bounds/duplicate-relaxed-bounds.stderr rename tests/ui/trait-bounds/{bad-suggestionf-for-repeated-unsized-bound-127441.rs => fix-dyn-sized-fn-param-sugg.rs} (51%) rename tests/ui/trait-bounds/{bad-suggestionf-for-repeated-unsized-bound-127441.stderr => fix-dyn-sized-fn-param-sugg.stderr} (80%) delete mode 100644 tests/ui/traits/maybe-polarity-repeated.rs delete mode 100644 tests/ui/traits/maybe-polarity-repeated.stderr diff --git a/compiler/rustc_error_codes/src/error_codes/E0203.md b/compiler/rustc_error_codes/src/error_codes/E0203.md index 1edb519275f79..a4dceedbf1fd1 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0203.md +++ b/compiler/rustc_error_codes/src/error_codes/E0203.md @@ -1,15 +1,15 @@ -Having multiple relaxed default bounds is unsupported. +Having duplicate relaxed default bounds is unsupported. Erroneous code example: ```compile_fail,E0203 -struct Bad{ - inner: T +struct Bad{ + inner: T, } ``` -Here the type `T` cannot have a relaxed bound for multiple default traits -(`Sized` and `Send`). This can be fixed by only using one relaxed bound. +Here the type parameter `T` cannot have duplicate relaxed bounds for default +trait `Sized`. This can be fixed by only using one relaxed bound: ``` struct Good{ diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index a20becbe7e843..90cb172703401 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -371,9 +371,6 @@ hir_analysis_missing_type_params = *[other] parameters } must be specified on the object type -hir_analysis_multiple_relaxed_default_bounds = - type parameter has more than one relaxed default bound, only one is supported - hir_analysis_must_be_name_of_associated_function = must be a name of an associated function hir_analysis_must_implement_not_function = not a function diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index eb65050c17c78..3283ce95ee055 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -278,13 +278,6 @@ pub(crate) struct CopyImplOnTypeWithDtor { pub span: Span, } -#[derive(Diagnostic)] -#[diag(hir_analysis_multiple_relaxed_default_bounds, code = E0203)] -pub(crate) struct MultipleRelaxedDefaultBounds { - #[primary_span] - pub spans: Vec, -} - #[derive(Diagnostic)] #[diag(hir_analysis_copy_impl_on_non_adt, code = E0206)] pub(crate) struct CopyImplOnNonAdt { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 8c99a41f62685..3db78db931abd 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -35,31 +35,29 @@ use crate::fluent_generated as fluent; use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer}; impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { - /// Check for multiple relaxed bounds and relaxed bounds of non-default traits. + /// Check for duplicate relaxed bounds and relaxed bounds of non-default traits. pub(crate) fn check_and_report_invalid_relaxed_bounds( &self, relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>, ) { let tcx = self.tcx(); - let mut unique_bounds = FxIndexSet::default(); - let mut seen_repeat = false; + let mut grouped_bounds = FxIndexMap::<_, Vec<_>>::default(); + for bound in &relaxed_bounds { if let Res::Def(DefKind::Trait, trait_def_id) = bound.trait_ref.path.res { - seen_repeat |= !unique_bounds.insert(trait_def_id); + grouped_bounds.entry(trait_def_id).or_default().push(bound.span); } } - if relaxed_bounds.len() > 1 { - let err = errors::MultipleRelaxedDefaultBounds { - spans: relaxed_bounds.iter().map(|ptr| ptr.span).collect(), - }; - - if seen_repeat { - tcx.dcx().emit_err(err); - } else if !tcx.features().more_maybe_bounds() { - tcx.sess.create_feature_err(err, sym::more_maybe_bounds).emit(); - }; + for (trait_def_id, spans) in grouped_bounds { + if spans.len() > 1 { + let name = tcx.item_name(trait_def_id); + self.dcx() + .struct_span_err(spans, format!("duplicate relaxed `{name}` bounds")) + .with_code(E0203) + .emit(); + } } let sized_def_id = tcx.require_lang_item(hir::LangItem::Sized, DUMMY_SP); diff --git a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs index 7c9d88462f631..9c727ae3aad4c 100644 --- a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs +++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.rs @@ -8,15 +8,7 @@ trait Trait4 where Self: ?Trait1 {} //~ ERROR this relaxed bound is not permitte fn foo(_: Box) {} //~^ ERROR relaxed bounds are not permitted in trait object types fn bar(_: T) {} -//~^ ERROR type parameter has more than one relaxed default bound, only one is supported -//~| ERROR bound modifier `?` can only be applied to `Sized` -//~| ERROR bound modifier `?` can only be applied to `Sized` - -trait Trait {} -// Do not suggest `#![feature(more_maybe_bounds)]` for repetitions -fn baz(_ : T) {} -//~^ ERROR type parameter has more than one relaxed default bound, only one is supported -//~| ERROR bound modifier `?` can only be applied to `Sized` +//~^ ERROR bound modifier `?` can only be applied to `Sized` //~| ERROR bound modifier `?` can only be applied to `Sized` fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr index c6d940db57bf2..da6ad5f16e20c 100644 --- a/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-more-maybe-bounds.stderr @@ -18,15 +18,6 @@ error: relaxed bounds are not permitted in trait object types LL | fn foo(_: Box) {} | ^^^^^^^ -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/feature-gate-more-maybe-bounds.rs:10:11 - | -LL | fn bar(_: T) {} - | ^^^^^^^ ^^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error: bound modifier `?` can only be applied to `Sized` --> $DIR/feature-gate-more-maybe-bounds.rs:10:11 | @@ -39,24 +30,5 @@ error: bound modifier `?` can only be applied to `Sized` LL | fn bar(_: T) {} | ^^^^^^^ -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/feature-gate-more-maybe-bounds.rs:17:11 - | -LL | fn baz(_ : T) {} - | ^^^^^^ ^^^^^^ - -error: bound modifier `?` can only be applied to `Sized` - --> $DIR/feature-gate-more-maybe-bounds.rs:17:11 - | -LL | fn baz(_ : T) {} - | ^^^^^^ - -error: bound modifier `?` can only be applied to `Sized` - --> $DIR/feature-gate-more-maybe-bounds.rs:17:20 - | -LL | fn baz(_ : T) {} - | ^^^^^^ - -error: aborting due to 9 previous errors +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0203`. diff --git a/tests/ui/trait-bounds/duplicate-relaxed-bounds.rs b/tests/ui/trait-bounds/duplicate-relaxed-bounds.rs new file mode 100644 index 0000000000000..a1681ddec77b0 --- /dev/null +++ b/tests/ui/trait-bounds/duplicate-relaxed-bounds.rs @@ -0,0 +1,22 @@ +fn dupes() {} +//~^ ERROR duplicate relaxed `Sized` bounds +//~| ERROR duplicate relaxed `Iterator` bounds +//~| ERROR bound modifier `?` can only be applied to `Sized` +//~| ERROR bound modifier `?` can only be applied to `Sized` + +trait Trait { + // We used to say "type parameter has more than one relaxed default bound" + // even on *associated types* like here. Test that we no longer do that. + type Type: ?Sized + ?Sized; + //~^ ERROR duplicate relaxed `Sized` bounds + //~| ERROR duplicate relaxed `Sized` bounds +} + +// We used to emit an additional error about "multiple relaxed default bounds". +// However, multiple relaxed bounds are actually *fine* if they're distinct. +// Ultimately, we still reject this because `Sized` is +// the only (stable) default trait, so we're fine. +fn not_dupes() {} +//~^ ERROR bound modifier `?` can only be applied to `Sized` + +fn main() {} diff --git a/tests/ui/trait-bounds/duplicate-relaxed-bounds.stderr b/tests/ui/trait-bounds/duplicate-relaxed-bounds.stderr new file mode 100644 index 0000000000000..ccc723fc7a653 --- /dev/null +++ b/tests/ui/trait-bounds/duplicate-relaxed-bounds.stderr @@ -0,0 +1,47 @@ +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/duplicate-relaxed-bounds.rs:1:13 + | +LL | fn dupes() {} + | ^^^^^^ ^^^^^^ + +error[E0203]: duplicate relaxed `Iterator` bounds + --> $DIR/duplicate-relaxed-bounds.rs:1:31 + | +LL | fn dupes() {} + | ^^^^^^^^^ ^^^^^^^^^ + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/duplicate-relaxed-bounds.rs:1:31 + | +LL | fn dupes() {} + | ^^^^^^^^^ + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/duplicate-relaxed-bounds.rs:1:43 + | +LL | fn dupes() {} + | ^^^^^^^^^ + +error: bound modifier `?` can only be applied to `Sized` + --> $DIR/duplicate-relaxed-bounds.rs:19:26 + | +LL | fn not_dupes() {} + | ^^^^^^^^^ + +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/duplicate-relaxed-bounds.rs:10:16 + | +LL | type Type: ?Sized + ?Sized; + | ^^^^^^ ^^^^^^ + +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/duplicate-relaxed-bounds.rs:10:16 + | +LL | type Type: ?Sized + ?Sized; + | ^^^^^^ ^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0203`. diff --git a/tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.rs b/tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.rs similarity index 51% rename from tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.rs rename to tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.rs index e6d7f74880fb2..1aa36207bc3ea 100644 --- a/tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.rs +++ b/tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.rs @@ -1,39 +1,38 @@ -// Regression test for #127441 - -// Tests that we make the correct suggestion -// in case there are more than one `?Sized` -// bounds on a function parameter +// Test that we emit a correct structured suggestions for dynamically sized ("maybe unsized") +// function parameters. +// We used to emit a butchered suggestion if duplicate relaxed `Sized` bounds were present. +// issue: . use std::fmt::Debug; fn foo1(a: T) {} -//~^ ERROR he size for values of type `T` cannot be known at compilation time +//~^ ERROR the size for values of type `T` cannot be known at compilation time fn foo2(a: T) {} -//~^ ERROR type parameter has more than one relaxed default bound, only one is supported +//~^ ERROR duplicate relaxed `Sized` bounds //~| ERROR the size for values of type `T` cannot be known at compilation time fn foo3(a: T) {} -//~^ ERROR type parameter has more than one relaxed default bound, only one is supported -//~| ERROR he size for values of type `T` cannot be known at compilation time +//~^ ERROR duplicate relaxed `Sized` bounds +//~| ERROR the size for values of type `T` cannot be known at compilation time fn foo4(a: T) {} -//~^ ERROR type parameter has more than one relaxed default bound, only one is supported +//~^ ERROR duplicate relaxed `Sized` bounds //~| ERROR the size for values of type `T` cannot be known at compilation time fn foo5(_: impl ?Sized) {} //~^ ERROR the size for values of type `impl ?Sized` cannot be known at compilation time fn foo6(_: impl ?Sized + ?Sized) {} -//~^ ERROR type parameter has more than one relaxed default bound, only one is supported +//~^ ERROR duplicate relaxed `Sized` bounds //~| ERROR the size for values of type `impl ?Sized + ?Sized` cannot be known at compilation tim fn foo7(_: impl ?Sized + ?Sized + Debug) {} -//~^ ERROR type parameter has more than one relaxed default bound, only one is supported +//~^ ERROR duplicate relaxed `Sized` bounds //~| ERROR the size for values of type `impl ?Sized + ?Sized + Debug` cannot be known at compilation time fn foo8(_: impl ?Sized + Debug + ?Sized ) {} -//~^ ERROR type parameter has more than one relaxed default bound, only one is supported +//~^ ERROR duplicate relaxed `Sized` bounds //~| ERROR the size for values of type `impl ?Sized + Debug + ?Sized` cannot be known at compilation time fn main() {} diff --git a/tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.stderr b/tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.stderr similarity index 80% rename from tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.stderr rename to tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.stderr index 363f52d6df8d5..7a9c2f043ac41 100644 --- a/tests/ui/trait-bounds/bad-suggestionf-for-repeated-unsized-bound-127441.stderr +++ b/tests/ui/trait-bounds/fix-dyn-sized-fn-param-sugg.stderr @@ -1,41 +1,41 @@ -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:12:12 +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:11:12 | LL | fn foo2(a: T) {} | ^^^^^^ ^^^^^^ -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:16:12 +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:15:12 | LL | fn foo3(a: T) {} | ^^^^^^ ^^^^^^ -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:20:12 +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:19:12 | LL | fn foo4(a: T) {} | ^^^^^^ ^^^^^^ -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:27:17 +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:26:17 | LL | fn foo6(_: impl ?Sized + ?Sized) {} | ^^^^^^ ^^^^^^ -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:31:17 +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:30:17 | LL | fn foo7(_: impl ?Sized + ?Sized + Debug) {} | ^^^^^^ ^^^^^^ -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:35:17 +error[E0203]: duplicate relaxed `Sized` bounds + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:34:17 | LL | fn foo8(_: impl ?Sized + Debug + ?Sized ) {} | ^^^^^^ ^^^^^^ error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:9:23 + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:8:23 | LL | fn foo1(a: T) {} | - ^ doesn't have a size known at compile-time @@ -54,7 +54,7 @@ LL | fn foo1(a: &T) {} | + error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:12:32 + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:11:32 | LL | fn foo2(a: T) {} | - ^ doesn't have a size known at compile-time @@ -73,7 +73,7 @@ LL | fn foo2(a: &T) {} | + error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:16:40 + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:15:40 | LL | fn foo3(a: T) {} | - ^ doesn't have a size known at compile-time @@ -92,7 +92,7 @@ LL | fn foo3(a: &T) {} | + error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:20:41 + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:19:41 | LL | fn foo4(a: T) {} | - ^ doesn't have a size known at compile-time @@ -111,7 +111,7 @@ LL | fn foo4(a: &T) {} | + error[E0277]: the size for values of type `impl ?Sized` cannot be known at compilation time - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:24:12 + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:23:12 | LL | fn foo5(_: impl ?Sized) {} | ^^^^^^^^^^^ @@ -131,7 +131,7 @@ LL | fn foo5(_: &impl ?Sized) {} | + error[E0277]: the size for values of type `impl ?Sized + ?Sized` cannot be known at compilation time - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:27:12 + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:26:12 | LL | fn foo6(_: impl ?Sized + ?Sized) {} | ^^^^^^^^^^^^^^^^^^^^ @@ -151,7 +151,7 @@ LL | fn foo6(_: &impl ?Sized + ?Sized) {} | + error[E0277]: the size for values of type `impl ?Sized + ?Sized + Debug` cannot be known at compilation time - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:31:12 + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:30:12 | LL | fn foo7(_: impl ?Sized + ?Sized + Debug) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -171,7 +171,7 @@ LL | fn foo7(_: &impl ?Sized + ?Sized + Debug) {} | + error[E0277]: the size for values of type `impl ?Sized + Debug + ?Sized` cannot be known at compilation time - --> $DIR/bad-suggestionf-for-repeated-unsized-bound-127441.rs:35:12 + --> $DIR/fix-dyn-sized-fn-param-sugg.rs:34:12 | LL | fn foo8(_: impl ?Sized + Debug + ?Sized ) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/trait-bounds/more_maybe_bounds.rs b/tests/ui/trait-bounds/more_maybe_bounds.rs index 61b630479ac3e..47348b0a0dd78 100644 --- a/tests/ui/trait-bounds/more_maybe_bounds.rs +++ b/tests/ui/trait-bounds/more_maybe_bounds.rs @@ -1,6 +1,6 @@ // FIXME(more_maybe_bounds): Even under `more_maybe_bounds` / `-Zexperimental-default-bounds`, // trying to relax non-default bounds should still be an error in all contexts! As you can see -// there are placed like supertrait bounds and trait object types where we currently don't perform +// there are places like supertrait bounds and trait object types where we currently don't perform // this check. #![feature(auto_traits, more_maybe_bounds, negative_impls)] diff --git a/tests/ui/traits/maybe-polarity-repeated.rs b/tests/ui/traits/maybe-polarity-repeated.rs deleted file mode 100644 index 962e3d5dbc5cc..0000000000000 --- a/tests/ui/traits/maybe-polarity-repeated.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(more_maybe_bounds)] - -trait Trait {} -fn foo(_: T) {} -//~^ ERROR type parameter has more than one relaxed default bound, only one is supported -//~| ERROR bound modifier `?` can only be applied to default traits like `Sized` -//~| ERROR bound modifier `?` can only be applied to default traits like `Sized` - -fn main() {} diff --git a/tests/ui/traits/maybe-polarity-repeated.stderr b/tests/ui/traits/maybe-polarity-repeated.stderr deleted file mode 100644 index de16c14718005..0000000000000 --- a/tests/ui/traits/maybe-polarity-repeated.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/maybe-polarity-repeated.rs:4:11 - | -LL | fn foo(_: T) {} - | ^^^^^^ ^^^^^^ - -error: bound modifier `?` can only be applied to default traits like `Sized` - --> $DIR/maybe-polarity-repeated.rs:4:11 - | -LL | fn foo(_: T) {} - | ^^^^^^ - -error: bound modifier `?` can only be applied to default traits like `Sized` - --> $DIR/maybe-polarity-repeated.rs:4:20 - | -LL | fn foo(_: T) {} - | ^^^^^^ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0203`. diff --git a/tests/ui/unsized/relaxed-bounds-invalid-places.rs b/tests/ui/unsized/relaxed-bounds-invalid-places.rs index 64d4523ac4996..b8eda1e7786b5 100644 --- a/tests/ui/unsized/relaxed-bounds-invalid-places.rs +++ b/tests/ui/unsized/relaxed-bounds-invalid-places.rs @@ -16,8 +16,7 @@ struct S4(T) where for<'a> T: ?Trait<'a>; //~| ERROR bound modifier `?` can only be applied to `Sized` struct S5(*const T) where T: ?Trait<'static> + ?Sized; -//~^ ERROR type parameter has more than one relaxed default bound -//~| ERROR bound modifier `?` can only be applied to `Sized` +//~^ ERROR bound modifier `?` can only be applied to `Sized` impl S1 { fn f() where T: ?Sized {} //~ ERROR this relaxed bound is not permitted here @@ -33,4 +32,3 @@ type O2 = dyn ?Sized + ?Sized + Tr; //~| ERROR relaxed bounds are not permitted in trait object types fn main() {} - diff --git a/tests/ui/unsized/relaxed-bounds-invalid-places.stderr b/tests/ui/unsized/relaxed-bounds-invalid-places.stderr index cfa0d274b26c1..30285d6269362 100644 --- a/tests/ui/unsized/relaxed-bounds-invalid-places.stderr +++ b/tests/ui/unsized/relaxed-bounds-invalid-places.stderr @@ -31,7 +31,7 @@ LL | struct S4(T) where for<'a> T: ?Trait<'a>; = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item error: this relaxed bound is not permitted here - --> $DIR/relaxed-bounds-invalid-places.rs:23:21 + --> $DIR/relaxed-bounds-invalid-places.rs:22:21 | LL | fn f() where T: ?Sized {} | ^^^^^^ @@ -39,7 +39,7 @@ LL | fn f() where T: ?Sized {} = note: in this context, relaxed bounds are only allowed on type parameters defined by the closest item error: relaxed bounds are not permitted in supertrait bounds - --> $DIR/relaxed-bounds-invalid-places.rs:26:11 + --> $DIR/relaxed-bounds-invalid-places.rs:25:11 | LL | trait Tr: ?Sized {} | ^^^^^^ @@ -47,19 +47,19 @@ LL | trait Tr: ?Sized {} = note: traits are `?Sized` by default error: relaxed bounds are not permitted in trait object types - --> $DIR/relaxed-bounds-invalid-places.rs:30:20 + --> $DIR/relaxed-bounds-invalid-places.rs:29:20 | LL | type O1 = dyn Tr + ?Sized; | ^^^^^^ error: relaxed bounds are not permitted in trait object types - --> $DIR/relaxed-bounds-invalid-places.rs:31:15 + --> $DIR/relaxed-bounds-invalid-places.rs:30:15 | LL | type O2 = dyn ?Sized + ?Sized + Tr; | ^^^^^^ error: relaxed bounds are not permitted in trait object types - --> $DIR/relaxed-bounds-invalid-places.rs:31:24 + --> $DIR/relaxed-bounds-invalid-places.rs:30:24 | LL | type O2 = dyn ?Sized + ?Sized + Tr; | ^^^^^^ @@ -70,21 +70,11 @@ error: bound modifier `?` can only be applied to `Sized` LL | struct S4(T) where for<'a> T: ?Trait<'a>; | ^^^^^^^^^^ -error[E0203]: type parameter has more than one relaxed default bound, only one is supported - --> $DIR/relaxed-bounds-invalid-places.rs:18:33 - | -LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; - | ^^^^^^^^^^^^^^^ ^^^^^^ - | - = help: add `#![feature(more_maybe_bounds)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - error: bound modifier `?` can only be applied to `Sized` --> $DIR/relaxed-bounds-invalid-places.rs:18:33 | LL | struct S5(*const T) where T: ?Trait<'static> + ?Sized; | ^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error: aborting due to 11 previous errors -For more information about this error, try `rustc --explain E0203`. From 82a02aefe07092c737c852daccebf49ca25507e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Fri, 20 Jun 2025 23:13:11 +0200 Subject: [PATCH 16/19] HIR ty lowering: Validate `PointeeSized` bounds --- compiler/rustc_hir_analysis/messages.ftl | 2 - compiler/rustc_hir_analysis/src/errors.rs | 7 -- .../src/hir_ty_lowering/bounds.rs | 36 ++------- .../src/hir_ty_lowering/dyn_compatibility.rs | 8 -- .../src/hir_ty_lowering/errors.rs | 6 +- .../src/hir_ty_lowering/mod.rs | 49 ++++++------ .../ui/sized-hierarchy/pointee-validation.rs | 20 +++++ .../sized-hierarchy/pointee-validation.stderr | 76 +++++++++++++++++++ .../reject-dyn-pointeesized.rs | 4 +- .../reject-dyn-pointeesized.stderr | 5 +- 10 files changed, 135 insertions(+), 78 deletions(-) create mode 100644 tests/ui/sized-hierarchy/pointee-validation.rs create mode 100644 tests/ui/sized-hierarchy/pointee-validation.stderr diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 90cb172703401..7f55f9b2303d5 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -445,8 +445,6 @@ hir_analysis_parenthesized_fn_trait_expansion = hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind} .label = not allowed in type signatures -hir_analysis_pointee_sized_trait_object = `PointeeSized` cannot be used with trait objects - hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias .label = `Self` is not a generic argument, but an alias to the type of the {$what} diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 3283ce95ee055..5e75a42e82450 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -311,13 +311,6 @@ pub(crate) struct TraitObjectDeclaredWithNoTraits { pub trait_alias_span: Option, } -#[derive(Diagnostic)] -#[diag(hir_analysis_pointee_sized_trait_object)] -pub(crate) struct PointeeSizedTraitObject { - #[primary_span] - pub span: Span, -} - #[derive(Diagnostic)] #[diag(hir_analysis_ambiguous_lifetime_bound, code = E0227)] pub(crate) struct AmbiguousLifetimeBound { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index dbd22fabab8b8..d7a827c649ddc 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -6,7 +6,7 @@ use rustc_errors::struct_span_code_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; -use rustc_hir::{AmbigArg, LangItem, PolyTraitRef}; +use rustc_hir::{AmbigArg, PolyTraitRef}; use rustc_middle::bug; use rustc_middle::ty::{ self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, @@ -124,13 +124,13 @@ fn collect_sizedness_bounds<'tcx>( self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, span: Span, ) -> CollectedSizednessBounds { - let sized_did = tcx.require_lang_item(LangItem::Sized, span); + let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span); let sized = collect_bounds(hir_bounds, self_ty_where_predicates, sized_did); - let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span); + let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span); let meta_sized = collect_bounds(hir_bounds, self_ty_where_predicates, meta_sized_did); - let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span); + let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span); let pointee_sized = collect_bounds(hir_bounds, self_ty_where_predicates, pointee_sized_did); CollectedSizednessBounds { sized, meta_sized, pointee_sized } @@ -151,24 +151,6 @@ fn add_trait_bound<'tcx>( } impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { - /// Skip `PointeeSized` bounds. - /// - /// `PointeeSized` is a "fake bound" insofar as anywhere a `PointeeSized` bound exists, there - /// is actually the absence of any bounds. This avoids limitations around non-global where - /// clauses being preferred over item bounds (where `PointeeSized` bounds would be - /// proven) - which can result in errors when a `PointeeSized` supertrait/bound/predicate is - /// added to some items. - pub(crate) fn should_skip_sizedness_bound<'hir>( - &self, - bound: &'hir hir::GenericBound<'tcx>, - ) -> bool { - bound - .trait_ref() - .and_then(|tr| tr.trait_def_id()) - .map(|did| self.tcx().is_lang_item(did, LangItem::PointeeSized)) - .unwrap_or(false) - } - /// Adds sizedness bounds to a trait, trait alias, parameter, opaque type or associated type. /// /// - On parameters, opaque type and associated types, add default `Sized` bound if no explicit @@ -193,8 +175,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return; } - let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span); - let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span); + let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span); + let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span); // If adding sizedness bounds to a trait, then there are some relevant early exits if let Some(trait_did) = trait_did { @@ -244,7 +226,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } else { // If there are no explicit sizedness bounds on a parameter then add a default // `Sized` bound. - let sized_did = tcx.require_lang_item(LangItem::Sized, span); + let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span); add_trait_bound(tcx, bounds, self_ty, sized_did, span); } } @@ -476,10 +458,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { 'tcx: 'hir, { for hir_bound in hir_bounds { - if self.should_skip_sizedness_bound(hir_bound) { - continue; - } - // In order to avoid cycles, when we're lowering `SelfTraitThatDefines`, // we skip over any traits that don't define the given associated type. if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 813353c12aa02..76bb59e3f0901 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -2,7 +2,6 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; -use rustc_hir::LangItem; use rustc_hir::def::{DefKind, Res}; use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS; use rustc_middle::ty::elaborate::ClauseWithSupertraitSpan; @@ -70,13 +69,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let guar = self.report_trait_object_addition_traits(®ular_traits); return Ty::new_error(tcx, guar); } - // We don't support `PointeeSized` principals - let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span); - if regular_traits.iter().any(|(pred, _)| pred.def_id() == pointee_sized_did) { - let guar = self.report_pointee_sized_trait_object(span); - return Ty::new_error(tcx, guar); - } - // Don't create a dyn trait if we have errors in the principal. if let Err(guar) = regular_traits.error_reported() { return Ty::new_error(tcx, guar); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 3db78db931abd..287a5532f0168 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -29,7 +29,7 @@ use tracing::debug; use super::InherentAssocCandidate; use crate::errors::{ self, AssocItemConstraintsNotAllowedHere, ManualImplementation, MissingTypeParams, - ParenthesizedFnTraitExpansion, PointeeSizedTraitObject, TraitObjectDeclaredWithNoTraits, + ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits, }; use crate::fluent_generated as fluent; use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer}; @@ -1405,10 +1405,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.dcx().emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span }) } - - pub(super) fn report_pointee_sized_trait_object(&self, span: Span) -> ErrorGuaranteed { - self.dcx().emit_err(PointeeSizedTraitObject { span }) - } } /// Emit an error for the given associated item constraint. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 5521f97059b8e..78794cd8eb684 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -755,6 +755,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, predicate_filter: PredicateFilter, ) -> GenericArgCountResult { + let tcx = self.tcx(); + // We use the *resolved* bound vars later instead of the HIR ones since the former // also include the bound vars of the overarching predicate if applicable. let hir::PolyTraitRef { bound_generic_params: _, modifiers, ref trait_ref, span } = @@ -762,6 +764,29 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let hir::TraitBoundModifiers { constness, polarity } = modifiers; let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()); + + // Relaxed bounds `?Trait` and `PointeeSized` bounds aren't represented in the `middle::ty` IR + // as they denote the *absence* of a default bound. However, we can't bail out early here since + // we still need to perform several validation steps (see below). Instead, simply "pour" all + // resulting bounds "down the drain", i.e., into a new `Vec` that just gets dropped at the end. + let (polarity, bounds) = match polarity { + rustc_ast::BoundPolarity::Positive + if tcx.is_lang_item(trait_def_id, hir::LangItem::PointeeSized) => + { + // To elaborate on the comment directly above, regarding `PointeeSized` specifically, + // we don't "reify" such bounds to avoid trait system limitations -- namely, + // non-global where-clauses being preferred over item bounds (where `PointeeSized` + // bounds would be proven) -- which can result in errors when a `PointeeSized` + // supertrait / bound / predicate is added to some items. + (ty::PredicatePolarity::Positive, &mut Vec::new()) + } + rustc_ast::BoundPolarity::Positive => (ty::PredicatePolarity::Positive, bounds), + rustc_ast::BoundPolarity::Negative(_) => (ty::PredicatePolarity::Negative, bounds), + rustc_ast::BoundPolarity::Maybe(_) => { + (ty::PredicatePolarity::Positive, &mut Vec::new()) + } + }; + let trait_segment = trait_ref.path.segments.last().unwrap(); let _ = self.prohibit_generic_args( @@ -778,7 +803,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Some(self_ty), ); - let tcx = self.tcx(); let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id); debug!(?bound_vars); @@ -789,27 +813,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { debug!(?poly_trait_ref); - let polarity = match polarity { - rustc_ast::BoundPolarity::Positive => ty::PredicatePolarity::Positive, - rustc_ast::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative, - rustc_ast::BoundPolarity::Maybe(_) => { - // Validate associated type at least. We may want to reject these - // outright in the future... - for constraint in trait_segment.args().constraints { - let _ = self.lower_assoc_item_constraint( - trait_ref.hir_ref_id, - poly_trait_ref, - constraint, - &mut Default::default(), - &mut Default::default(), - constraint.span, - predicate_filter, - ); - } - return arg_count; - } - }; - // We deal with const conditions later. match predicate_filter { PredicateFilter::All @@ -912,7 +915,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Don't register any associated item constraints for negative bounds, // since we should have emitted an error for them earlier, and they // would not be well-formed! - if polarity != ty::PredicatePolarity::Positive { + if polarity == ty::PredicatePolarity::Negative { self.dcx().span_delayed_bug( constraint.span, "negative trait bounds should not have assoc item constraints", diff --git a/tests/ui/sized-hierarchy/pointee-validation.rs b/tests/ui/sized-hierarchy/pointee-validation.rs new file mode 100644 index 0000000000000..dfc28829e08c4 --- /dev/null +++ b/tests/ui/sized-hierarchy/pointee-validation.rs @@ -0,0 +1,20 @@ +// Test that despite us dropping `PointeeSized` bounds during HIR ty lowering +// we still validate it first. +// issue: +#![feature(sized_hierarchy)] + +use std::marker::PointeeSized; + +struct T where (): PointeeSized<(), Undefined = ()>; +//~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied +//~| ERROR associated type `Undefined` not found for `PointeeSized` + +const fn test() where T: const PointeeSized, U: [const] PointeeSized {} +//~^ ERROR `const` can only be applied to `const` traits +//~| ERROR `const` can only be applied to `const` traits +//~| ERROR const trait impls are experimental +//~| ERROR `[const]` can only be applied to `const` traits +//~| ERROR `[const]` can only be applied to `const` traits +//~| ERROR const trait impls are experimental + +fn main() {} diff --git a/tests/ui/sized-hierarchy/pointee-validation.stderr b/tests/ui/sized-hierarchy/pointee-validation.stderr new file mode 100644 index 0000000000000..a056d5483561a --- /dev/null +++ b/tests/ui/sized-hierarchy/pointee-validation.stderr @@ -0,0 +1,76 @@ +error[E0658]: const trait impls are experimental + --> $DIR/pointee-validation.rs:12:32 + | +LL | const fn test() where T: const PointeeSized, U: [const] PointeeSized {} + | ^^^^^ + | + = note: see issue #143874 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: const trait impls are experimental + --> $DIR/pointee-validation.rs:12:55 + | +LL | const fn test() where T: const PointeeSized, U: [const] PointeeSized {} + | ^^^^^^^ + | + = note: see issue #143874 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/pointee-validation.rs:8:20 + | +LL | struct T where (): PointeeSized<(), Undefined = ()>; + | ^^^^^^^^^^^^-------------------- help: remove the unnecessary generics + | | + | expected 0 generic arguments + +error[E0220]: associated type `Undefined` not found for `PointeeSized` + --> $DIR/pointee-validation.rs:8:37 + | +LL | struct T where (): PointeeSized<(), Undefined = ()>; + | ^^^^^^^^^ associated type `Undefined` not found + +error: `const` can only be applied to `const` traits + --> $DIR/pointee-validation.rs:12:32 + | +LL | const fn test() where T: const PointeeSized, U: [const] PointeeSized {} + | ^^^^^ can't be applied to `PointeeSized` + | +note: `PointeeSized` can't be used with `const` because it isn't `const` + --> $SRC_DIR/core/src/marker.rs:LL:COL + +error: `[const]` can only be applied to `const` traits + --> $DIR/pointee-validation.rs:12:55 + | +LL | const fn test() where T: const PointeeSized, U: [const] PointeeSized {} + | ^^^^^^^ can't be applied to `PointeeSized` + | +note: `PointeeSized` can't be used with `[const]` because it isn't `const` + --> $SRC_DIR/core/src/marker.rs:LL:COL + +error: `const` can only be applied to `const` traits + --> $DIR/pointee-validation.rs:12:32 + | +LL | const fn test() where T: const PointeeSized, U: [const] PointeeSized {} + | ^^^^^ can't be applied to `PointeeSized` + | +note: `PointeeSized` can't be used with `const` because it isn't `const` + --> $SRC_DIR/core/src/marker.rs:LL:COL + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: `[const]` can only be applied to `const` traits + --> $DIR/pointee-validation.rs:12:55 + | +LL | const fn test() where T: const PointeeSized, U: [const] PointeeSized {} + | ^^^^^^^ can't be applied to `PointeeSized` + | +note: `PointeeSized` can't be used with `[const]` because it isn't `const` + --> $SRC_DIR/core/src/marker.rs:LL:COL + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0107, E0220, E0658. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/sized-hierarchy/reject-dyn-pointeesized.rs b/tests/ui/sized-hierarchy/reject-dyn-pointeesized.rs index ece1702679d00..89e4c15371d4a 100644 --- a/tests/ui/sized-hierarchy/reject-dyn-pointeesized.rs +++ b/tests/ui/sized-hierarchy/reject-dyn-pointeesized.rs @@ -3,7 +3,7 @@ use std::marker::PointeeSized; type Foo = dyn PointeeSized; -//~^ ERROR `PointeeSized` cannot be used with trait objects +//~^ ERROR at least one trait is required for an object type fn foo(f: &Foo) {} @@ -12,5 +12,5 @@ fn main() { let x = main; let y: Box = x; -//~^ ERROR `PointeeSized` cannot be used with trait objects +//~^ ERROR at least one trait is required for an object type } diff --git a/tests/ui/sized-hierarchy/reject-dyn-pointeesized.stderr b/tests/ui/sized-hierarchy/reject-dyn-pointeesized.stderr index a833c6952fdc5..616b2400f8650 100644 --- a/tests/ui/sized-hierarchy/reject-dyn-pointeesized.stderr +++ b/tests/ui/sized-hierarchy/reject-dyn-pointeesized.stderr @@ -1,10 +1,10 @@ -error: `PointeeSized` cannot be used with trait objects +error[E0224]: at least one trait is required for an object type --> $DIR/reject-dyn-pointeesized.rs:5:12 | LL | type Foo = dyn PointeeSized; | ^^^^^^^^^^^^^^^^ -error: `PointeeSized` cannot be used with trait objects +error[E0224]: at least one trait is required for an object type --> $DIR/reject-dyn-pointeesized.rs:14:16 | LL | let y: Box = x; @@ -12,3 +12,4 @@ LL | let y: Box = x; error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0224`. From 466d33cb5cc79b74691db619d448f80a97baff61 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Tue, 15 Jul 2025 16:34:57 +0200 Subject: [PATCH 17/19] inline CrateLoader inside of CStore --- compiler/rustc_metadata/src/creader.rs | 286 +++++++++--------- .../rustc_resolve/src/build_reduced_graph.rs | 9 +- compiler/rustc_resolve/src/diagnostics.rs | 3 +- .../rustc_resolve/src/late/diagnostics.rs | 3 +- compiler/rustc_resolve/src/lib.rs | 26 +- 5 files changed, 169 insertions(+), 158 deletions(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index e65c7a684260d..438eff330548d 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -12,7 +12,6 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::owned_slice::OwnedSlice; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{self, FreezeReadGuard, FreezeWriteGuard}; -use rustc_errors::DiagCtxtHandle; use rustc_expand::base::SyntaxExtension; use rustc_fs_util::try_canonicalize; use rustc_hir as hir; @@ -23,8 +22,10 @@ use rustc_middle::bug; use rustc_middle::ty::data_structures::IndexSet; use rustc_middle::ty::{TyCtxt, TyCtxtFeed}; use rustc_proc_macro::bridge::client::ProcMacro; +use rustc_session::Session; use rustc_session::config::{ - CrateType, ExtendedTargetModifierInfo, ExternLocation, OptionsTargetModifiers, TargetModifier, + CrateType, ExtendedTargetModifierInfo, ExternLocation, Externs, OptionsTargetModifiers, + TargetModifier, }; use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate, ExternCrateSource}; use rustc_session::lint::{self, BuiltinLintDiag}; @@ -70,6 +71,8 @@ pub struct CStore { /// Unused externs of the crate unused_externs: Vec, + + used_extern_options: FxHashSet, } impl std::fmt::Debug for CStore { @@ -78,28 +81,6 @@ impl std::fmt::Debug for CStore { } } -pub struct CrateLoader<'a, 'tcx: 'a> { - // Immutable configuration. - tcx: TyCtxt<'tcx>, - // Mutable output. - cstore: &'a mut CStore, - used_extern_options: &'a mut FxHashSet, -} - -impl<'a, 'tcx> std::ops::Deref for CrateLoader<'a, 'tcx> { - type Target = TyCtxt<'tcx>; - - fn deref(&self) -> &Self::Target { - &self.tcx - } -} - -impl<'a, 'tcx> CrateLoader<'a, 'tcx> { - fn dcx(&self) -> DiagCtxtHandle<'tcx> { - self.tcx.dcx() - } -} - pub enum LoadedMacro { MacroDef { def: MacroDef, @@ -227,8 +208,8 @@ impl CStore { fn intern_stable_crate_id<'tcx>( &mut self, - root: &CrateRoot, tcx: TyCtxt<'tcx>, + root: &CrateRoot, ) -> Result, CrateError> { assert_eq!(self.metas.len(), tcx.untracked().stable_crate_ids.read().len()); let num = tcx.create_crate_num(root.stable_crate_id()).map_err(|existing| { @@ -495,21 +476,18 @@ impl CStore { has_global_allocator: false, has_alloc_error_handler: false, unused_externs: Vec::new(), + used_extern_options: Default::default(), } } -} -impl<'a, 'tcx> CrateLoader<'a, 'tcx> { - pub fn new( - tcx: TyCtxt<'tcx>, - cstore: &'a mut CStore, - used_extern_options: &'a mut FxHashSet, - ) -> Self { - CrateLoader { tcx, cstore, used_extern_options } - } - - fn existing_match(&self, name: Symbol, hash: Option, kind: PathKind) -> Option { - for (cnum, data) in self.cstore.iter_crate_data() { + fn existing_match( + &self, + externs: &Externs, + name: Symbol, + hash: Option, + kind: PathKind, + ) -> Option { + for (cnum, data) in self.iter_crate_data() { if data.name() != name { trace!("{} did not match {}", data.name(), name); continue; @@ -533,8 +511,8 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // We're also sure to compare *paths*, not actual byte slices. The // `source` stores paths which are normalized which may be different // from the strings on the command line. - let source = self.cstore.get_crate_data(cnum).cdata.source(); - if let Some(entry) = self.sess.opts.externs.get(name.as_str()) { + let source = self.get_crate_data(cnum).cdata.source(); + if let Some(entry) = externs.get(name.as_str()) { // Only use `--extern crate_name=path` here, not `--extern crate_name`. if let Some(mut files) = entry.files() { if files.any(|l| { @@ -587,6 +565,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { /// command parameter is set to `public-dependency` fn is_private_dep( &self, + externs: &Externs, name: Symbol, private_dep: Option, origin: CrateOrigin<'_>, @@ -595,7 +574,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { return true; } - let extern_private = self.sess.opts.externs.get(name.as_str()).map(|e| e.is_private_dep); + let extern_private = externs.get(name.as_str()).map(|e| e.is_private_dep); match (extern_private, private_dep) { // Explicit non-private via `--extern`, explicit non-private from metadata, or // unspecified with default to public. @@ -605,8 +584,9 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } - fn register_crate( + fn register_crate<'tcx>( &mut self, + tcx: TyCtxt<'tcx>, host_lib: Option, origin: CrateOrigin<'_>, lib: Library, @@ -615,15 +595,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { private_dep: Option, ) -> Result { let _prof_timer = - self.sess.prof.generic_activity_with_arg("metadata_register_crate", name.as_str()); + tcx.sess.prof.generic_activity_with_arg("metadata_register_crate", name.as_str()); let Library { source, metadata } = lib; let crate_root = metadata.get_root(); let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash()); - let private_dep = self.is_private_dep(name, private_dep, origin); + let private_dep = self.is_private_dep(&tcx.sess.opts.externs, name, private_dep, origin); // Claim this crate number and cache it - let feed = self.cstore.intern_stable_crate_id(&crate_root, self.tcx)?; + let feed = self.intern_stable_crate_id(tcx, &crate_root)?; let cnum = feed.key(); info!( @@ -643,8 +623,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { &crate_paths }; - let cnum_map = - self.resolve_crate_deps(dep_root, &crate_root, &metadata, cnum, dep_kind, private_dep)?; + let cnum_map = self.resolve_crate_deps( + tcx, + dep_root, + &crate_root, + &metadata, + cnum, + dep_kind, + private_dep, + )?; let raw_proc_macros = if crate_root.is_proc_macro_crate() { let temp_root; @@ -656,14 +643,14 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { None => (&source, &crate_root), }; let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate"); - Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.stable_crate_id())?) + Some(self.dlsym_proc_macros(tcx.sess, &dlsym_dylib.0, dlsym_root.stable_crate_id())?) } else { None }; let crate_metadata = CrateMetadata::new( - self.sess, - self.cstore, + tcx.sess, + self, metadata, crate_root, raw_proc_macros, @@ -675,13 +662,14 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { host_hash, ); - self.cstore.set_crate_data(cnum, crate_metadata); + self.set_crate_data(cnum, crate_metadata); Ok(cnum) } - fn load_proc_macro<'b>( + fn load_proc_macro<'a, 'b>( &self, + sess: &'a Session, locator: &mut CrateLocator<'b>, crate_rejections: &mut CrateRejections, path_kind: PathKind, @@ -690,13 +678,13 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { where 'a: 'b, { - if self.sess.opts.unstable_opts.dual_proc_macros { + if sess.opts.unstable_opts.dual_proc_macros { // Use a new crate locator and crate rejections so trying to load a proc macro doesn't // affect the error message we emit let mut proc_macro_locator = locator.clone(); // Try to load a proc macro - proc_macro_locator.for_target_proc_macro(self.sess, path_kind); + proc_macro_locator.for_target_proc_macro(sess, path_kind); // Load the proc macro crate for the target let target_result = @@ -713,7 +701,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { *crate_rejections = CrateRejections::default(); // Load the proc macro crate for the host - locator.for_proc_macro(self.sess, path_kind); + locator.for_proc_macro(sess, path_kind); locator.hash = host_hash; @@ -734,7 +722,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { let mut proc_macro_locator = locator.clone(); // Load the proc macro crate for the host - proc_macro_locator.for_proc_macro(self.sess, path_kind); + proc_macro_locator.for_proc_macro(sess, path_kind); let Some(host_result) = self.load(&mut proc_macro_locator, &mut CrateRejections::default())? @@ -746,32 +734,39 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } - fn resolve_crate( + fn resolve_crate<'tcx>( &mut self, + tcx: TyCtxt<'tcx>, name: Symbol, span: Span, dep_kind: CrateDepKind, origin: CrateOrigin<'_>, ) -> Option { self.used_extern_options.insert(name); - match self.maybe_resolve_crate(name, dep_kind, origin) { + match self.maybe_resolve_crate(tcx, name, dep_kind, origin) { Ok(cnum) => { - self.cstore.set_used_recursively(cnum); + self.set_used_recursively(cnum); Some(cnum) } Err(err) => { debug!("failed to resolve crate {} {:?}", name, dep_kind); let missing_core = self - .maybe_resolve_crate(sym::core, CrateDepKind::Explicit, CrateOrigin::Extern) + .maybe_resolve_crate( + tcx, + sym::core, + CrateDepKind::Explicit, + CrateOrigin::Extern, + ) .is_err(); - err.report(self.sess, span, missing_core); + err.report(tcx.sess, span, missing_core); None } } } - fn maybe_resolve_crate<'b>( + fn maybe_resolve_crate<'b, 'tcx>( &'b mut self, + tcx: TyCtxt<'tcx>, name: Symbol, mut dep_kind: CrateDepKind, origin: CrateOrigin<'b>, @@ -789,17 +784,19 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { let path_kind = if dep.is_some() { PathKind::Dependency } else { PathKind::Crate }; let private_dep = origin.private_dep(); - let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) { + let result = if let Some(cnum) = + self.existing_match(&tcx.sess.opts.externs, name, hash, path_kind) + { (LoadResult::Previous(cnum), None) } else { info!("falling back to a load"); let mut locator = CrateLocator::new( - self.sess, - &*self.cstore.metadata_loader, + tcx.sess, + &*self.metadata_loader, name, // The all loop is because `--crate-type=rlib --crate-type=rlib` is // legal and produces both inside this type. - self.tcx.crate_types().iter().all(|c| *c == CrateType::Rlib), + tcx.crate_types().iter().all(|c| *c == CrateType::Rlib), hash, extra_filename, path_kind, @@ -812,6 +809,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { info!("falling back to loading proc_macro"); dep_kind = CrateDepKind::MacrosOnly; match self.load_proc_macro( + tcx.sess, &mut locator, &mut crate_rejections, path_kind, @@ -831,8 +829,9 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // not specified by `--extern` on command line parameters, it may be // `private-dependency` when `register_crate` is called for the first time. Then it must be updated to // `public-dependency` here. - let private_dep = self.is_private_dep(name, private_dep, origin); - let data = self.cstore.get_crate_data_mut(cnum); + let private_dep = + self.is_private_dep(&tcx.sess.opts.externs, name, private_dep, origin); + let data = self.get_crate_data_mut(cnum); if data.is_proc_macro_crate() { dep_kind = CrateDepKind::MacrosOnly; } @@ -842,7 +841,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } (LoadResult::Loaded(library), host_library) => { info!("register newly loaded library for `{}`", name); - self.register_crate(host_library, origin, library, dep_kind, name, private_dep) + self.register_crate(tcx, host_library, origin, library, dep_kind, name, private_dep) } _ => panic!(), } @@ -863,7 +862,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // duplicates by just using the first crate. let root = library.metadata.get_root(); let mut result = LoadResult::Loaded(library); - for (cnum, data) in self.cstore.iter_crate_data() { + for (cnum, data) in self.iter_crate_data() { if data.name() == root.name() && root.hash() == data.hash() { assert!(locator.hash.is_none()); info!("load success, going to previous cnum: {}", cnum); @@ -877,6 +876,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { /// Go through the crate metadata and load any crates that it references. fn resolve_crate_deps( &mut self, + tcx: TyCtxt<'_>, dep_root: &CratePaths, crate_root: &CrateRoot, metadata: &MetadataBlob, @@ -913,6 +913,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { _ => dep.kind, }; let cnum = self.maybe_resolve_crate( + tcx, dep.name, dep_kind, CrateOrigin::IndirectDependency { @@ -930,10 +931,11 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { fn dlsym_proc_macros( &self, + sess: &Session, path: &Path, stable_crate_id: StableCrateId, ) -> Result<&'static [ProcMacro], CrateError> { - let sym_name = self.sess.generate_proc_macro_decls_symbol(stable_crate_id); + let sym_name = sess.generate_proc_macro_decls_symbol(stable_crate_id); debug!("trying to dlsym proc_macros {} for symbol `{}`", path.display(), sym_name); unsafe { @@ -955,10 +957,10 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } - fn inject_panic_runtime(&mut self, krate: &ast::Crate) { + fn inject_panic_runtime(&mut self, tcx: TyCtxt<'_>, krate: &ast::Crate) { // If we're only compiling an rlib, then there's no need to select a // panic runtime, so we just skip this section entirely. - let only_rlib = self.tcx.crate_types().iter().all(|ct| *ct == CrateType::Rlib); + let only_rlib = tcx.crate_types().iter().all(|ct| *ct == CrateType::Rlib); if only_rlib { info!("panic runtime injection skipped, only generating rlib"); return; @@ -968,7 +970,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // the same time we perform some general validation of the DAG we've got // going such as ensuring everything has a compatible panic strategy. let mut needs_panic_runtime = attr::contains_name(&krate.attrs, sym::needs_panic_runtime); - for (_cnum, data) in self.cstore.iter_crate_data() { + for (_cnum, data) in self.iter_crate_data() { needs_panic_runtime |= data.needs_panic_runtime(); } @@ -987,7 +989,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // Also note that we have yet to perform validation of the crate graph // in terms of everyone has a compatible panic runtime format, that's // performed later as part of the `dependency_format` module. - let desired_strategy = self.sess.panic_strategy(); + let desired_strategy = tcx.sess.panic_strategy(); let name = match desired_strategy { PanicStrategy::Unwind => sym::panic_unwind, PanicStrategy::Abort => sym::panic_abort, @@ -995,64 +997,64 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { info!("panic runtime not found -- loading {}", name); let Some(cnum) = - self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, CrateOrigin::Injected) + self.resolve_crate(tcx, name, DUMMY_SP, CrateDepKind::Implicit, CrateOrigin::Injected) else { return; }; - let data = self.cstore.get_crate_data(cnum); + let data = self.get_crate_data(cnum); // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. if !data.is_panic_runtime() { - self.dcx().emit_err(errors::CrateNotPanicRuntime { crate_name: name }); + tcx.dcx().emit_err(errors::CrateNotPanicRuntime { crate_name: name }); } if data.required_panic_strategy() != Some(desired_strategy) { - self.dcx() + tcx.dcx() .emit_err(errors::NoPanicStrategy { crate_name: name, strategy: desired_strategy }); } - self.cstore.injected_panic_runtime = Some(cnum); + self.injected_panic_runtime = Some(cnum); } - fn inject_profiler_runtime(&mut self) { + fn inject_profiler_runtime(&mut self, tcx: TyCtxt<'_>) { let needs_profiler_runtime = - self.sess.instrument_coverage() || self.sess.opts.cg.profile_generate.enabled(); - if !needs_profiler_runtime || self.sess.opts.unstable_opts.no_profiler_runtime { + tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled(); + if !needs_profiler_runtime || tcx.sess.opts.unstable_opts.no_profiler_runtime { return; } info!("loading profiler"); - let name = Symbol::intern(&self.sess.opts.unstable_opts.profiler_runtime); + let name = Symbol::intern(&tcx.sess.opts.unstable_opts.profiler_runtime); let Some(cnum) = - self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, CrateOrigin::Injected) + self.resolve_crate(tcx, name, DUMMY_SP, CrateDepKind::Implicit, CrateOrigin::Injected) else { return; }; - let data = self.cstore.get_crate_data(cnum); + let data = self.get_crate_data(cnum); // Sanity check the loaded crate to ensure it is indeed a profiler runtime if !data.is_profiler_runtime() { - self.dcx().emit_err(errors::NotProfilerRuntime { crate_name: name }); + tcx.dcx().emit_err(errors::NotProfilerRuntime { crate_name: name }); } } - fn inject_allocator_crate(&mut self, krate: &ast::Crate) { - self.cstore.has_global_allocator = + fn inject_allocator_crate(&mut self, tcx: TyCtxt<'_>, krate: &ast::Crate) { + self.has_global_allocator = match &*fn_spans(krate, Symbol::intern(&global_fn_name(sym::alloc))) { [span1, span2, ..] => { - self.dcx() + tcx.dcx() .emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 }); true } spans => !spans.is_empty(), }; - self.cstore.has_alloc_error_handler = match &*fn_spans( + self.has_alloc_error_handler = match &*fn_spans( krate, Symbol::intern(alloc_error_handler_name(AllocatorKind::Global)), ) { [span1, span2, ..] => { - self.dcx() + tcx.dcx() .emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 }); true } @@ -1063,7 +1065,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // about through the `#![needs_allocator]` attribute and is typically // written down in liballoc. if !attr::contains_name(&krate.attrs, sym::needs_allocator) - && !self.cstore.iter_crate_data().any(|(_, data)| data.needs_allocator()) + && !self.iter_crate_data().any(|(_, data)| data.needs_allocator()) { return; } @@ -1071,7 +1073,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // At this point we've determined that we need an allocator. Let's see // if our compilation session actually needs an allocator based on what // we're emitting. - let all_rlib = self.tcx.crate_types().iter().all(|ct| matches!(*ct, CrateType::Rlib)); + let all_rlib = tcx.crate_types().iter().all(|ct| matches!(*ct, CrateType::Rlib)); if all_rlib { return; } @@ -1086,12 +1088,12 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { #[allow(rustc::symbol_intern_string_literal)] let this_crate = Symbol::intern("this crate"); - let mut global_allocator = self.cstore.has_global_allocator.then_some(this_crate); - for (_, data) in self.cstore.iter_crate_data() { + let mut global_allocator = self.has_global_allocator.then_some(this_crate); + for (_, data) in self.iter_crate_data() { if data.has_global_allocator() { match global_allocator { Some(other_crate) => { - self.dcx().emit_err(errors::ConflictingGlobalAlloc { + tcx.dcx().emit_err(errors::ConflictingGlobalAlloc { crate_name: data.name(), other_crate_name: other_crate, }); @@ -1100,12 +1102,12 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } } - let mut alloc_error_handler = self.cstore.has_alloc_error_handler.then_some(this_crate); - for (_, data) in self.cstore.iter_crate_data() { + let mut alloc_error_handler = self.has_alloc_error_handler.then_some(this_crate); + for (_, data) in self.iter_crate_data() { if data.has_alloc_error_handler() { match alloc_error_handler { Some(other_crate) => { - self.dcx().emit_err(errors::ConflictingAllocErrorHandler { + tcx.dcx().emit_err(errors::ConflictingAllocErrorHandler { crate_name: data.name(), other_crate_name: other_crate, }); @@ -1116,35 +1118,36 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } if global_allocator.is_some() { - self.cstore.allocator_kind = Some(AllocatorKind::Global); + self.allocator_kind = Some(AllocatorKind::Global); } else { // Ok we haven't found a global allocator but we still need an // allocator. At this point our allocator request is typically fulfilled // by the standard library, denoted by the `#![default_lib_allocator]` // attribute. if !attr::contains_name(&krate.attrs, sym::default_lib_allocator) - && !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator()) + && !self.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator()) { - self.dcx().emit_err(errors::GlobalAllocRequired); + tcx.dcx().emit_err(errors::GlobalAllocRequired); } - self.cstore.allocator_kind = Some(AllocatorKind::Default); + self.allocator_kind = Some(AllocatorKind::Default); } if alloc_error_handler.is_some() { - self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Global); + self.alloc_error_handler_kind = Some(AllocatorKind::Global); } else { // The alloc crate provides a default allocation error handler if // one isn't specified. - self.cstore.alloc_error_handler_kind = Some(AllocatorKind::Default); + self.alloc_error_handler_kind = Some(AllocatorKind::Default); } } - fn inject_forced_externs(&mut self) { - for (name, entry) in self.sess.opts.externs.iter() { + fn inject_forced_externs(&mut self, tcx: TyCtxt<'_>) { + for (name, entry) in tcx.sess.opts.externs.iter() { if entry.force { let name_interned = Symbol::intern(name); if !self.used_extern_options.contains(&name_interned) { self.resolve_crate( + tcx, name_interned, DUMMY_SP, CrateDepKind::Explicit, @@ -1156,7 +1159,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } /// Inject the `compiler_builtins` crate if it is not already in the graph. - fn inject_compiler_builtins(&mut self, krate: &ast::Crate) { + fn inject_compiler_builtins(&mut self, tcx: TyCtxt<'_>, krate: &ast::Crate) { // `compiler_builtins` does not get extern builtins, nor do `#![no_core]` crates if attr::contains_name(&krate.attrs, sym::compiler_builtins) || attr::contains_name(&krate.attrs, sym::no_core) @@ -1167,7 +1170,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // If a `#![compiler_builtins]` crate already exists, avoid injecting it twice. This is // the common case since usually it appears as a dependency of `std` or `alloc`. - for (cnum, cmeta) in self.cstore.iter_crate_data() { + for (cnum, cmeta) in self.iter_crate_data() { if cmeta.is_compiler_builtins() { info!("`compiler_builtins` already exists (cnum = {cnum}); skipping injection"); return; @@ -1176,6 +1179,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // `compiler_builtins` is not yet in the graph; inject it. Error on resolution failure. let Some(cnum) = self.resolve_crate( + tcx, sym::compiler_builtins, krate.spans.inner_span.shrink_to_lo(), CrateDepKind::Explicit, @@ -1186,17 +1190,17 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { }; // Sanity check that the loaded crate is `#![compiler_builtins]` - let cmeta = self.cstore.get_crate_data(cnum); + let cmeta = self.get_crate_data(cnum); if !cmeta.is_compiler_builtins() { - self.dcx().emit_err(errors::CrateNotCompilerBuiltins { crate_name: cmeta.name() }); + tcx.dcx().emit_err(errors::CrateNotCompilerBuiltins { crate_name: cmeta.name() }); } } - fn report_unused_deps(&mut self, krate: &ast::Crate) { + fn report_unused_deps_in_crate(&mut self, tcx: TyCtxt<'_>, krate: &ast::Crate) { // Make a point span rather than covering the whole file let span = krate.spans.inner_span.shrink_to_lo(); // Complain about anything left over - for (name, entry) in self.sess.opts.externs.iter() { + for (name, entry) in tcx.sess.opts.externs.iter() { if let ExternLocation::FoundInLibrarySearchDirectories = entry.location { // Don't worry about pathless `--extern foo` sysroot references continue; @@ -1211,25 +1215,25 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } // Got a real unused --extern - if self.sess.opts.json_unused_externs.is_enabled() { - self.cstore.unused_externs.push(name_interned); + if tcx.sess.opts.json_unused_externs.is_enabled() { + self.unused_externs.push(name_interned); continue; } - self.sess.psess.buffer_lint( + tcx.sess.psess.buffer_lint( lint::builtin::UNUSED_CRATE_DEPENDENCIES, span, ast::CRATE_NODE_ID, BuiltinLintDiag::UnusedCrateDependency { extern_crate: name_interned, - local_crate: self.tcx.crate_name(LOCAL_CRATE), + local_crate: tcx.crate_name(LOCAL_CRATE), }, ); } } - fn report_future_incompatible_deps(&self, krate: &ast::Crate) { - let name = self.tcx.crate_name(LOCAL_CRATE); + fn report_future_incompatible_deps(&self, tcx: TyCtxt<'_>, krate: &ast::Crate) { + let name = tcx.crate_name(LOCAL_CRATE); if name.as_str() == "wasm_bindgen" { let major = env::var("CARGO_PKG_VERSION_MAJOR") @@ -1257,26 +1261,27 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // Make a point span rather than covering the whole file let span = krate.spans.inner_span.shrink_to_lo(); - self.sess.dcx().emit_err(errors::WasmCAbi { span }); + tcx.sess.dcx().emit_err(errors::WasmCAbi { span }); } } - pub fn postprocess(&mut self, krate: &ast::Crate) { - self.inject_compiler_builtins(krate); - self.inject_forced_externs(); - self.inject_profiler_runtime(); - self.inject_allocator_crate(krate); - self.inject_panic_runtime(krate); + pub fn postprocess(&mut self, tcx: TyCtxt<'_>, krate: &ast::Crate) { + self.inject_compiler_builtins(tcx, krate); + self.inject_forced_externs(tcx); + self.inject_profiler_runtime(tcx); + self.inject_allocator_crate(tcx, krate); + self.inject_panic_runtime(tcx, krate); - self.report_unused_deps(krate); - self.report_future_incompatible_deps(krate); + self.report_unused_deps_in_crate(tcx, krate); + self.report_future_incompatible_deps(tcx, krate); - info!("{:?}", CrateDump(self.cstore)); + info!("{:?}", CrateDump(self)); } /// Process an `extern crate foo` AST node. pub fn process_extern_crate( &mut self, + tcx: TyCtxt<'_>, item: &ast::Item, def_id: LocalDefId, definitions: &Definitions, @@ -1286,7 +1291,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { debug!("resolving extern crate stmt. ident: {} orig_name: {:?}", ident, orig_name); let name = match orig_name { Some(orig_name) => { - validate_crate_name(self.sess, orig_name, Some(item.span)); + validate_crate_name(tcx.sess, orig_name, Some(item.span)); orig_name } None => ident.name, @@ -1297,10 +1302,11 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { CrateDepKind::Explicit }; - let cnum = self.resolve_crate(name, item.span, dep_kind, CrateOrigin::Extern)?; + let cnum = + self.resolve_crate(tcx, name, item.span, dep_kind, CrateOrigin::Extern)?; let path_len = definitions.def_path(def_id).data.len(); - self.cstore.update_extern_crate( + self.update_extern_crate( cnum, ExternCrate { src: ExternCrateSource::Extern(def_id.to_def_id()), @@ -1315,10 +1321,16 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { } } - pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> Option { - let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit, CrateOrigin::Extern)?; + pub fn process_path_extern( + &mut self, + tcx: TyCtxt<'_>, + name: Symbol, + span: Span, + ) -> Option { + let cnum = + self.resolve_crate(tcx, name, span, CrateDepKind::Explicit, CrateOrigin::Extern)?; - self.cstore.update_extern_crate( + self.update_extern_crate( cnum, ExternCrate { src: ExternCrateSource::Path, @@ -1332,8 +1344,8 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { Some(cnum) } - pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option { - self.maybe_resolve_crate(name, CrateDepKind::Explicit, CrateOrigin::Extern).ok() + pub fn maybe_process_path_extern(&mut self, tcx: TyCtxt<'_>, name: Symbol) -> Option { + self.maybe_resolve_crate(tcx, name, CrateDepKind::Explicit, CrateOrigin::Extern).ok() } } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index e56aabfd4144e..737577baa7ade 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -897,9 +897,12 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { Some(self.r.graph_root) } else { let tcx = self.r.tcx; - let crate_id = self.r.crate_loader(|c| { - c.process_extern_crate(item, local_def_id, &tcx.definitions_untracked()) - }); + let crate_id = self.r.cstore_mut().process_extern_crate( + self.r.tcx, + item, + local_def_id, + &tcx.definitions_untracked(), + ); crate_id.map(|crate_id| { self.r.extern_crate_map.insert(local_def_id, crate_id); self.r.expect_module(crate_id.as_def_id()) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index f6f45adabe98b..d72fbc189e70e 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1425,7 +1425,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // otherwise cause duplicate suggestions. continue; } - let Some(crate_id) = self.crate_loader(|c| c.maybe_process_path_extern(ident.name)) + let Some(crate_id) = + self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name) else { continue; }; diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index ee462d9076491..69095942f5246 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2485,7 +2485,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let extern_prelude = self.r.extern_prelude.clone(); names.extend(extern_prelude.iter().flat_map(|(ident, _)| { self.r - .crate_loader(|c| c.maybe_process_path_extern(ident.name)) + .cstore_mut() + .maybe_process_path_extern(self.r.tcx, ident.name) .and_then(|crate_id| { let crate_mod = Res::Def(DefKind::Mod, crate_id.as_def_id()); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index dae30b77ec1c3..0d41a822e8a8d 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -45,7 +45,7 @@ use rustc_attr_data_structures::StrippedCfgItem; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_data_structures::steal::Steal; -use rustc_data_structures::sync::FreezeReadGuard; +use rustc_data_structures::sync::{FreezeReadGuard, FreezeWriteGuard}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::{Applicability, Diag, ErrCode, ErrorGuaranteed}; use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind}; @@ -58,7 +58,7 @@ use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, use rustc_hir::definitions::DisambiguatorState; use rustc_hir::{PrimTy, TraitCandidate}; use rustc_index::bit_set::DenseBitSet; -use rustc_metadata::creader::{CStore, CrateLoader}; +use rustc_metadata::creader::CStore; use rustc_middle::metadata::ModChild; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::query::Providers; @@ -1110,7 +1110,6 @@ pub struct Resolver<'ra, 'tcx> { builtin_types_bindings: FxHashMap>, builtin_attrs_bindings: FxHashMap>, registered_tool_bindings: FxHashMap>, - used_extern_options: FxHashSet, macro_names: FxHashSet, builtin_macros: FxHashMap, registered_tools: &'tcx RegisteredTools, @@ -1546,7 +1545,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { (*ident, binding) }) .collect(), - used_extern_options: Default::default(), macro_names: FxHashSet::default(), builtin_macros: Default::default(), registered_tools, @@ -1733,18 +1731,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { StableHashingContext::new(self.tcx.sess, self.tcx.untracked()) } - fn crate_loader(&mut self, f: impl FnOnce(&mut CrateLoader<'_, '_>) -> T) -> T { - f(&mut CrateLoader::new( - self.tcx, - &mut CStore::from_tcx_mut(self.tcx), - &mut self.used_extern_options, - )) - } - fn cstore(&self) -> FreezeReadGuard<'_, CStore> { CStore::from_tcx(self.tcx) } + fn cstore_mut(&self) -> FreezeWriteGuard<'_, CStore> { + CStore::from_tcx_mut(self.tcx) + } + fn dummy_ext(&self, macro_kind: MacroKind) -> Arc { match macro_kind { MacroKind::Bang => Arc::clone(&self.dummy_ext_bang), @@ -1790,7 +1784,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.tcx.sess.time("resolve_report_errors", || self.report_errors(krate)); self.tcx .sess - .time("resolve_postprocess", || self.crate_loader(|c| c.postprocess(krate))); + .time("resolve_postprocess", || self.cstore_mut().postprocess(self.tcx, krate)); }); // Make sure we don't mutate the cstore from here on. @@ -2156,7 +2150,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Some(if let Some(binding) = entry.binding { if finalize { if !entry.is_import() { - self.crate_loader(|c| c.process_path_extern(ident.name, ident.span)); + self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span); } else if entry.introduced_by_item { self.record_use(ident, binding, Used::Other); } @@ -2165,13 +2159,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } else { let crate_id = if finalize { let Some(crate_id) = - self.crate_loader(|c| c.process_path_extern(ident.name, ident.span)) + self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span) else { return Some(self.dummy_binding); }; crate_id } else { - self.crate_loader(|c| c.maybe_process_path_extern(ident.name))? + self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name)? }; let res = Res::Def(DefKind::Mod, crate_id.as_def_id()); self.arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT) From 181c1bda0ef33c36e59628de6dd5c6ddf95f599f Mon Sep 17 00:00:00 2001 From: xizheyin Date: Thu, 10 Jul 2025 16:27:40 +0800 Subject: [PATCH 18/19] Deduplicate `unmatched_delims` in `rustc_parse` to reduce confusion Signed-off-by: xizheyin --- compiler/rustc_parse/src/lexer/diagnostics.rs | 20 ++++++++++++------- compiler/rustc_parse/src/lexer/tokentrees.rs | 15 ++++++++++++-- tests/ui/parser/deli-ident-issue-2.rs | 2 +- tests/ui/parser/deli-ident-issue-2.stderr | 12 +++-------- tests/ui/parser/issues/issue-104367.stderr | 1 - tests/ui/parser/issues/issue-105209.rs | 2 +- tests/ui/parser/issues/issue-105209.stderr | 9 ++++----- tests/ui/parser/issues/issue-62973.stderr | 6 ++---- tests/ui/parser/issues/issue-63116.stderr | 5 ++--- ...invalid-syntax-in-enum-discriminant.stderr | 12 ++++------- .../issues/issue-68987-unmatch-issue-2.rs | 2 +- .../issues/issue-68987-unmatch-issue-2.stderr | 12 +++-------- .../issues/issue-68987-unmatch-issue-3.rs | 2 +- .../issues/issue-68987-unmatch-issue-3.stderr | 12 +++-------- tests/ui/parser/issues/issue-81827.stderr | 5 ++--- .../issues/unnessary-error-issue-138401.rs | 3 +-- .../unnessary-error-issue-138401.stderr | 17 +++++----------- tests/ui/suggestions/issue-94171.stderr | 4 +--- tests/ui/typeck/issue-91334.stderr | 5 ++--- 19 files changed, 62 insertions(+), 84 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/diagnostics.rs b/compiler/rustc_parse/src/lexer/diagnostics.rs index 0b97d4e6993bb..6de001fc9985a 100644 --- a/compiler/rustc_parse/src/lexer/diagnostics.rs +++ b/compiler/rustc_parse/src/lexer/diagnostics.rs @@ -34,9 +34,12 @@ pub(super) fn same_indentation_level(sm: &SourceMap, open_sp: Span, close_sp: Sp // When we get a `)` or `]` for `{`, we should emit help message here // it's more friendly compared to report `unmatched error` in later phase -fn report_missing_open_delim(err: &mut Diag<'_>, unmatched_delims: &[UnmatchedDelim]) -> bool { +pub(super) fn report_missing_open_delim( + err: &mut Diag<'_>, + unmatched_delims: &mut Vec, +) -> bool { let mut reported_missing_open = false; - for unmatch_brace in unmatched_delims.iter() { + unmatched_delims.retain(|unmatch_brace| { if let Some(delim) = unmatch_brace.found_delim && matches!(delim, Delimiter::Parenthesis | Delimiter::Bracket) { @@ -45,13 +48,20 @@ fn report_missing_open_delim(err: &mut Diag<'_>, unmatched_delims: &[UnmatchedDe Delimiter::Bracket => "[", _ => unreachable!(), }; + + if let Some(unclosed_span) = unmatch_brace.unclosed_span { + err.span_label(unclosed_span, "the nearest open delimiter"); + } err.span_label( unmatch_brace.found_span.shrink_to_lo(), format!("missing open `{missed_open}` for this delimiter"), ); reported_missing_open = true; + false + } else { + true } - } + }); reported_missing_open } @@ -61,10 +71,6 @@ pub(super) fn report_suspicious_mismatch_block( sm: &SourceMap, delim: Delimiter, ) { - if report_missing_open_delim(err, &diag_info.unmatched_delims) { - return; - } - let mut matched_spans: Vec<(Span, bool)> = diag_info .matching_block_spans .iter() diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index fbea958dcc598..64748199f28d1 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -3,7 +3,9 @@ use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, Toke use rustc_ast_pretty::pprust::token_to_string; use rustc_errors::Diag; -use super::diagnostics::{report_suspicious_mismatch_block, same_indentation_level}; +use super::diagnostics::{ + report_missing_open_delim, report_suspicious_mismatch_block, same_indentation_level, +}; use super::{Lexer, UnmatchedDelim}; impl<'psess, 'src> Lexer<'psess, 'src> { @@ -244,7 +246,16 @@ impl<'psess, 'src> Lexer<'psess, 'src> { let msg = format!("unexpected closing delimiter: `{token_str}`"); let mut err = self.dcx().struct_span_err(self.token.span, msg); - report_suspicious_mismatch_block(&mut err, &self.diag_info, self.psess.source_map(), delim); + // if there is no missing open delim, report suspicious mismatch block + if !report_missing_open_delim(&mut err, &mut self.diag_info.unmatched_delims) { + report_suspicious_mismatch_block( + &mut err, + &self.diag_info, + self.psess.source_map(), + delim, + ); + } + err.span_label(self.token.span, "unexpected closing delimiter"); err } diff --git a/tests/ui/parser/deli-ident-issue-2.rs b/tests/ui/parser/deli-ident-issue-2.rs index 5394760df7026..419933c68ad69 100644 --- a/tests/ui/parser/deli-ident-issue-2.rs +++ b/tests/ui/parser/deli-ident-issue-2.rs @@ -1,6 +1,6 @@ fn main() { if 1 < 2 { - let _a = vec!]; //~ ERROR mismatched closing delimiter + let _a = vec!]; } } //~ ERROR unexpected closing delimiter diff --git a/tests/ui/parser/deli-ident-issue-2.stderr b/tests/ui/parser/deli-ident-issue-2.stderr index e0188cdfb4af8..703cbf196267a 100644 --- a/tests/ui/parser/deli-ident-issue-2.stderr +++ b/tests/ui/parser/deli-ident-issue-2.stderr @@ -1,19 +1,13 @@ -error: mismatched closing delimiter: `]` - --> $DIR/deli-ident-issue-2.rs:2:14 - | -LL | if 1 < 2 { - | ^ unclosed delimiter -LL | let _a = vec!]; - | ^ mismatched closing delimiter - error: unexpected closing delimiter: `}` --> $DIR/deli-ident-issue-2.rs:5:1 | +LL | if 1 < 2 { + | - the nearest open delimiter LL | let _a = vec!]; | - missing open `[` for this delimiter LL | } LL | } | ^ unexpected closing delimiter -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-104367.stderr b/tests/ui/parser/issues/issue-104367.stderr index c067d12e2d96c..f01fa4a1265f5 100644 --- a/tests/ui/parser/issues/issue-104367.stderr +++ b/tests/ui/parser/issues/issue-104367.stderr @@ -18,7 +18,6 @@ LL | d: [u32; { LL | #![cfg] { | - unclosed delimiter LL | #![w,) - | - missing open `(` for this delimiter LL | | ^ diff --git a/tests/ui/parser/issues/issue-105209.rs b/tests/ui/parser/issues/issue-105209.rs index f4e331523bf42..12c902e1d809f 100644 --- a/tests/ui/parser/issues/issue-105209.rs +++ b/tests/ui/parser/issues/issue-105209.rs @@ -1,3 +1,3 @@ //@ compile-flags: -Zunpretty=ast-tree #![c={#![c[)x //~ ERROR mismatched closing delimiter - //~ ERROR this file contains an unclosed delimiter + //~ ERROR this file contains an unclosed delimiter diff --git a/tests/ui/parser/issues/issue-105209.stderr b/tests/ui/parser/issues/issue-105209.stderr index 72017e4327de4..75643d180292b 100644 --- a/tests/ui/parser/issues/issue-105209.stderr +++ b/tests/ui/parser/issues/issue-105209.stderr @@ -7,16 +7,15 @@ LL | #![c={#![c[)x | unclosed delimiter error: this file contains an unclosed delimiter - --> $DIR/issue-105209.rs:3:68 + --> $DIR/issue-105209.rs:3:56 | LL | #![c={#![c[)x - | - - - - missing open `(` for this delimiter - | | | | - | | | unclosed delimiter + | - - - unclosed delimiter + | | | | | unclosed delimiter | unclosed delimiter LL | - | ^ + | ^ error: aborting due to 2 previous errors diff --git a/tests/ui/parser/issues/issue-62973.stderr b/tests/ui/parser/issues/issue-62973.stderr index ea3e2bebee404..c7fc5bc29edae 100644 --- a/tests/ui/parser/issues/issue-62973.stderr +++ b/tests/ui/parser/issues/issue-62973.stderr @@ -18,10 +18,8 @@ error: this file contains an unclosed delimiter --> $DIR/issue-62973.rs:10:2 | LL | fn p() { match s { v, E { [) {) } - | - - - - missing open `(` for this delimiter - | | | | - | | | missing open `(` for this delimiter - | | unclosed delimiter + | - - unclosed delimiter + | | | unclosed delimiter LL | LL | diff --git a/tests/ui/parser/issues/issue-63116.stderr b/tests/ui/parser/issues/issue-63116.stderr index e5bad84d11262..736a0ac2cf61b 100644 --- a/tests/ui/parser/issues/issue-63116.stderr +++ b/tests/ui/parser/issues/issue-63116.stderr @@ -10,9 +10,8 @@ error: this file contains an unclosed delimiter --> $DIR/issue-63116.rs:4:18 | LL | impl W $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:23:65 | -LL | V = [PhantomData; { [ () ].len() ].len() as isize, - | - missing open `[` for this delimiter -... -LL | V = [Vec::new; { [].len() ].len() as isize, - | - missing open `[` for this delimiter -... LL | mod c { | - unclosed delimiter LL | enum Bug { -LL | V = [Vec::new; { [0].len() ].len() as isize, - | - missing open `[` for this delimiter + | - this delimiter might not be properly closed... ... +LL | } + | - ...as it matches this but it has different indentation +LL | LL | fn main() {} | ^ diff --git a/tests/ui/parser/issues/issue-68987-unmatch-issue-2.rs b/tests/ui/parser/issues/issue-68987-unmatch-issue-2.rs index 89aaa68ba4095..9b4452ed2a1ac 100644 --- a/tests/ui/parser/issues/issue-68987-unmatch-issue-2.rs +++ b/tests/ui/parser/issues/issue-68987-unmatch-issue-2.rs @@ -1,7 +1,7 @@ // FIXME: this case need more work to fix // currently the TokenTree matching ')' with '{', which is not user friendly for diagnostics async fn obstest() -> Result<> { - let obs_connect = || -> Result<(), MyError) { //~ ERROR mismatched closing delimiter + let obs_connect = || -> Result<(), MyError) { async { } } diff --git a/tests/ui/parser/issues/issue-68987-unmatch-issue-2.stderr b/tests/ui/parser/issues/issue-68987-unmatch-issue-2.stderr index 0ecb748a0a4ce..c29a4ff8dbe68 100644 --- a/tests/ui/parser/issues/issue-68987-unmatch-issue-2.stderr +++ b/tests/ui/parser/issues/issue-68987-unmatch-issue-2.stderr @@ -1,19 +1,13 @@ -error: mismatched closing delimiter: `)` - --> $DIR/issue-68987-unmatch-issue-2.rs:3:32 - | -LL | async fn obstest() -> Result<> { - | ^ unclosed delimiter -LL | let obs_connect = || -> Result<(), MyError) { - | ^ mismatched closing delimiter - error: unexpected closing delimiter: `}` --> $DIR/issue-68987-unmatch-issue-2.rs:14:1 | +LL | async fn obstest() -> Result<> { + | - the nearest open delimiter LL | let obs_connect = || -> Result<(), MyError) { | - missing open `(` for this delimiter ... LL | } | ^ unexpected closing delimiter -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-68987-unmatch-issue-3.rs b/tests/ui/parser/issues/issue-68987-unmatch-issue-3.rs index e98df8d7c3c4e..e71e2730980e4 100644 --- a/tests/ui/parser/issues/issue-68987-unmatch-issue-3.rs +++ b/tests/ui/parser/issues/issue-68987-unmatch-issue-3.rs @@ -3,6 +3,6 @@ fn f(i: u32, j: u32) { let res = String::new(); let mut cnt = i; while cnt < j { - write!&mut res, " "); //~ ERROR mismatched closing delimiter + write!&mut res, " "); } } //~ ERROR unexpected closing delimiter diff --git a/tests/ui/parser/issues/issue-68987-unmatch-issue-3.stderr b/tests/ui/parser/issues/issue-68987-unmatch-issue-3.stderr index dfc4407ed6565..6b012af1af311 100644 --- a/tests/ui/parser/issues/issue-68987-unmatch-issue-3.stderr +++ b/tests/ui/parser/issues/issue-68987-unmatch-issue-3.stderr @@ -1,19 +1,13 @@ -error: mismatched closing delimiter: `)` - --> $DIR/issue-68987-unmatch-issue-3.rs:5:19 - | -LL | while cnt < j { - | ^ unclosed delimiter -LL | write!&mut res, " "); - | ^ mismatched closing delimiter - error: unexpected closing delimiter: `}` --> $DIR/issue-68987-unmatch-issue-3.rs:8:1 | +LL | while cnt < j { + | - the nearest open delimiter LL | write!&mut res, " "); | - missing open `(` for this delimiter LL | } LL | } | ^ unexpected closing delimiter -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-81827.stderr b/tests/ui/parser/issues/issue-81827.stderr index 986ed6b7e70f9..9737c8c90ae7c 100644 --- a/tests/ui/parser/issues/issue-81827.stderr +++ b/tests/ui/parser/issues/issue-81827.stderr @@ -11,9 +11,8 @@ error: this file contains an unclosed delimiter --> $DIR/issue-81827.rs:7:27 | LL | fn r()->i{0|{#[cfg(r(0{]0 - | - - - ^ - | | | | - | | | missing open `[` for this delimiter + | - - ^ + | | | | | unclosed delimiter | unclosed delimiter diff --git a/tests/ui/parser/issues/unnessary-error-issue-138401.rs b/tests/ui/parser/issues/unnessary-error-issue-138401.rs index e5e5f1ee4e9ce..208c516365a82 100644 --- a/tests/ui/parser/issues/unnessary-error-issue-138401.rs +++ b/tests/ui/parser/issues/unnessary-error-issue-138401.rs @@ -1,6 +1,5 @@ pub fn foo(x: i64) -> i64 { - x.abs) - //~^ ERROR mismatched closing delimiter + x.abs) } //~^ ERROR unexpected closing delimiter: `}` diff --git a/tests/ui/parser/issues/unnessary-error-issue-138401.stderr b/tests/ui/parser/issues/unnessary-error-issue-138401.stderr index b50f77f1247cd..54c73b50a42ae 100644 --- a/tests/ui/parser/issues/unnessary-error-issue-138401.stderr +++ b/tests/ui/parser/issues/unnessary-error-issue-138401.stderr @@ -1,19 +1,12 @@ -error: mismatched closing delimiter: `)` - --> $DIR/unnessary-error-issue-138401.rs:1:27 - | -LL | pub fn foo(x: i64) -> i64 { - | ^ unclosed delimiter -LL | x.abs) - | ^ mismatched closing delimiter - error: unexpected closing delimiter: `}` - --> $DIR/unnessary-error-issue-138401.rs:4:1 + --> $DIR/unnessary-error-issue-138401.rs:3:1 | -LL | x.abs) +LL | pub fn foo(x: i64) -> i64 { + | - the nearest open delimiter +LL | x.abs) | - missing open `(` for this delimiter -LL | LL | } | ^ unexpected closing delimiter -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/issue-94171.stderr b/tests/ui/suggestions/issue-94171.stderr index bcbd46cd8ecd5..52306a2465f1a 100644 --- a/tests/ui/suggestions/issue-94171.stderr +++ b/tests/ui/suggestions/issue-94171.stderr @@ -22,9 +22,7 @@ error: this file contains an unclosed delimiter --> $DIR/issue-94171.rs:5:52 | LL | fn L(]{match - | -- unclosed delimiter - | | - | missing open `[` for this delimiter + | - unclosed delimiter LL | (; {` | - - unclosed delimiter | | diff --git a/tests/ui/typeck/issue-91334.stderr b/tests/ui/typeck/issue-91334.stderr index 01e34919ce67d..a348e1ebf7e5a 100644 --- a/tests/ui/typeck/issue-91334.stderr +++ b/tests/ui/typeck/issue-91334.stderr @@ -11,9 +11,8 @@ error: this file contains an unclosed delimiter --> $DIR/issue-91334.rs:7:23 | LL | fn f(){||yield(((){), - | - - - ^ - | | | | - | | | missing open `(` for this delimiter + | - - ^ + | | | | | unclosed delimiter | unclosed delimiter From c65d3ce365ecb6d6f36b413edb591d4746f52305 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 3 Jul 2025 08:00:47 +0000 Subject: [PATCH 19/19] Generalize `unsize` and `unsize_into` destinations --- compiler/rustc_const_eval/src/interpret/cast.rs | 7 ++++--- compiler/rustc_mir_transform/src/gvn.rs | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 7a73d70fc85dc..de4fbc7b4752e 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -17,6 +17,7 @@ use super::{ throw_ub_custom, }; use crate::fluent_generated as fluent; +use crate::interpret::Writeable; impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { pub fn cast( @@ -358,7 +359,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { fn unsize_into_ptr( &mut self, src: &OpTy<'tcx, M::Provenance>, - dest: &PlaceTy<'tcx, M::Provenance>, + dest: &impl Writeable<'tcx, M::Provenance>, // The pointee types source_ty: Ty<'tcx>, cast_ty: Ty<'tcx>, @@ -455,7 +456,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { &mut self, src: &OpTy<'tcx, M::Provenance>, cast_ty: TyAndLayout<'tcx>, - dest: &PlaceTy<'tcx, M::Provenance>, + dest: &impl Writeable<'tcx, M::Provenance>, ) -> InterpResult<'tcx> { trace!("Unsizing {:?} of type {} into {}", *src, src.layout.ty, cast_ty.ty); match (src.layout.ty.kind(), cast_ty.ty.kind()) { @@ -496,7 +497,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.cur_span(), "unsize_into: invalid conversion: {:?} -> {:?}", src.layout, - dest.layout + dest.layout() ) } } diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 07717b7c06948..6657f89ceb595 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -579,7 +579,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize, _) => { let src = self.evaluated[value].as_ref()?; let dest = self.ecx.allocate(ty, MemoryKind::Stack).discard_err()?; - self.ecx.unsize_into(src, ty, &dest.clone().into()).discard_err()?; + self.ecx.unsize_into(src, ty, &dest).discard_err()?; self.ecx .alloc_mark_immutable(dest.ptr().provenance.unwrap().alloc_id()) .discard_err()?;