From 0702701297d5ec7b49dd2debbd777531676c48e2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 16 Feb 2024 09:58:53 +0100 Subject: [PATCH 1/4] allow mutable references in const values when they point to no memory --- compiler/rustc_const_eval/messages.ftl | 2 +- compiler/rustc_const_eval/src/errors.rs | 24 +++--- .../src/interpret/validity.rs | 85 +++++++++---------- .../rustc_middle/src/mir/interpret/error.rs | 9 +- .../consts/const-mut-refs/const_mut_refs.rs | 6 ++ ...ut_ref_in_final_dynamic_check.32bit.stderr | 17 ++-- ...ut_ref_in_final_dynamic_check.64bit.stderr | 17 ++-- .../mut_ref_in_final_dynamic_check.rs | 17 ++-- 8 files changed, 93 insertions(+), 84 deletions(-) diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 4a6d4fe930cf3..c456e40d7c15b 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -453,7 +453,7 @@ const_eval_validation_invalid_fn_ptr = {$front_matter}: encountered {$value}, bu const_eval_validation_invalid_ref_meta = {$front_matter}: encountered invalid reference metadata: total size is bigger than largest supported object const_eval_validation_invalid_ref_slice_meta = {$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object const_eval_validation_invalid_vtable_ptr = {$front_matter}: encountered {$value}, but expected a vtable pointer -const_eval_validation_mutable_ref_in_const = {$front_matter}: encountered mutable reference in a `const` or `static` +const_eval_validation_mutable_ref_in_const_or_static = {$front_matter}: encountered mutable reference in a `const` or `static` const_eval_validation_mutable_ref_to_immutable = {$front_matter}: encountered mutable reference or box pointing to read-only memory const_eval_validation_never_val = {$front_matter}: encountered a value of the never type `!` const_eval_validation_null_box = {$front_matter}: encountered a null box diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 11679ab77e351..2fd34b3c7fc31 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -603,18 +603,18 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { PtrToUninhabited { ptr_kind: PointerKind::Box, .. } => { const_eval_validation_box_to_uninhabited } - PtrToUninhabited { ptr_kind: PointerKind::Ref, .. } => { + PtrToUninhabited { ptr_kind: PointerKind::Ref(_), .. } => { const_eval_validation_ref_to_uninhabited } PtrToStatic { ptr_kind: PointerKind::Box } => const_eval_validation_box_to_static, - PtrToStatic { ptr_kind: PointerKind::Ref } => const_eval_validation_ref_to_static, + PtrToStatic { ptr_kind: PointerKind::Ref(_) } => const_eval_validation_ref_to_static, PointerAsInt { .. } => const_eval_validation_pointer_as_int, PartialPointer => const_eval_validation_partial_pointer, ConstRefToMutable => const_eval_validation_const_ref_to_mutable, ConstRefToExtern => const_eval_validation_const_ref_to_extern, - MutableRefInConst => const_eval_validation_mutable_ref_in_const, + MutableRefInConstOrStatic => const_eval_validation_mutable_ref_in_const_or_static, MutableRefToImmutable => const_eval_validation_mutable_ref_to_immutable, NullFnPtr => const_eval_validation_null_fn_ptr, NeverVal => const_eval_validation_never_val, @@ -630,37 +630,39 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Box } => { const_eval_validation_invalid_box_slice_meta } - InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Ref } => { + InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Ref(_) } => { const_eval_validation_invalid_ref_slice_meta } InvalidMetaTooLarge { ptr_kind: PointerKind::Box } => { const_eval_validation_invalid_box_meta } - InvalidMetaTooLarge { ptr_kind: PointerKind::Ref } => { + InvalidMetaTooLarge { ptr_kind: PointerKind::Ref(_) } => { const_eval_validation_invalid_ref_meta } - UnalignedPtr { ptr_kind: PointerKind::Ref, .. } => const_eval_validation_unaligned_ref, + UnalignedPtr { ptr_kind: PointerKind::Ref(_), .. } => { + const_eval_validation_unaligned_ref + } UnalignedPtr { ptr_kind: PointerKind::Box, .. } => const_eval_validation_unaligned_box, NullPtr { ptr_kind: PointerKind::Box } => const_eval_validation_null_box, - NullPtr { ptr_kind: PointerKind::Ref } => const_eval_validation_null_ref, + NullPtr { ptr_kind: PointerKind::Ref(_) } => const_eval_validation_null_ref, DanglingPtrNoProvenance { ptr_kind: PointerKind::Box, .. } => { const_eval_validation_dangling_box_no_provenance } - DanglingPtrNoProvenance { ptr_kind: PointerKind::Ref, .. } => { + DanglingPtrNoProvenance { ptr_kind: PointerKind::Ref(_), .. } => { const_eval_validation_dangling_ref_no_provenance } DanglingPtrOutOfBounds { ptr_kind: PointerKind::Box } => { const_eval_validation_dangling_box_out_of_bounds } - DanglingPtrOutOfBounds { ptr_kind: PointerKind::Ref } => { + DanglingPtrOutOfBounds { ptr_kind: PointerKind::Ref(_) } => { const_eval_validation_dangling_ref_out_of_bounds } DanglingPtrUseAfterFree { ptr_kind: PointerKind::Box } => { const_eval_validation_dangling_box_use_after_free } - DanglingPtrUseAfterFree { ptr_kind: PointerKind::Ref } => { + DanglingPtrUseAfterFree { ptr_kind: PointerKind::Ref(_) } => { const_eval_validation_dangling_ref_use_after_free } InvalidBool { .. } => const_eval_validation_invalid_bool, @@ -766,7 +768,7 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { } NullPtr { .. } | PtrToStatic { .. } - | MutableRefInConst + | MutableRefInConstOrStatic | ConstRefToMutable | ConstRefToExtern | MutableRefToImmutable diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 08a2e38bfa1b7..460a7d2407bb0 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -445,22 +445,22 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // Determine whether this pointer expects to be pointing to something mutable. let ptr_expected_mutbl = match ptr_kind { PointerKind::Box => Mutability::Mut, - PointerKind::Ref => { - let tam = value.layout.ty.builtin_deref(false).unwrap(); - // ZST never require mutability. We do not take into account interior mutability - // here since we cannot know if there really is an `UnsafeCell` inside - // `Option` -- so we check that in the recursive descent behind this - // reference. - if size == Size::ZERO { Mutability::Not } else { tam.mutbl } + PointerKind::Ref(mutbl) => { + // We do not take into account interior mutability here since we cannot know if + // there really is an `UnsafeCell` inside `Option` -- so we check + // that in the recursive descent behind this reference (controlled by + // `allow_immutable_unsafe_cell`). + mutbl } }; // Proceed recursively even for ZST, no reason to skip them! // `!` is a ZST and we want to validate it. if let Ok((alloc_id, _offset, _prov)) = self.ecx.ptr_try_get_alloc_id(place.ptr()) { + let mut skip_recursive_check = false; // Let's see what kind of memory this points to. // `unwrap` since dangling pointers have already been handled. let alloc_kind = self.ecx.tcx.try_get_global_alloc(alloc_id).unwrap(); - match alloc_kind { + let alloc_actual_mutbl = match alloc_kind { GlobalAlloc::Static(did) => { // Special handling for pointers to statics (irrespective of their type). assert!(!self.ecx.tcx.is_thread_local_static(did)); @@ -474,12 +474,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' .no_bound_vars() .expect("statics should not have generic parameters") .is_freeze(*self.ecx.tcx, ty::ParamEnv::reveal_all()); - // Mutability check. - if ptr_expected_mutbl == Mutability::Mut { - if !is_mut { - throw_validation_failure!(self.path, MutableRefToImmutable); - } - } // Mode-specific checks match self.ctfe_mode { Some( @@ -494,15 +488,9 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' // trigger cycle errors if we try to compute the value of the other static // and that static refers back to us (potentially through a promoted). // This could miss some UB, but that's fine. - return Ok(()); + skip_recursive_check = true; } Some(CtfeValidationMode::Const { .. }) => { - // For consts on the other hand we have to recursively check; - // pattern matching assumes a valid value. However we better make - // sure this is not mutable. - if is_mut { - throw_validation_failure!(self.path, ConstRefToMutable); - } // We can't recursively validate `extern static`, so we better reject them. if self.ecx.tcx.is_foreign_item(did) { throw_validation_failure!(self.path, ConstRefToExtern); @@ -510,26 +498,39 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' } None => {} } + // Return alloc mutability + if is_mut { Mutability::Mut } else { Mutability::Not } } - GlobalAlloc::Memory(alloc) => { - if alloc.inner().mutability == Mutability::Mut - && matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. })) - { - throw_validation_failure!(self.path, ConstRefToMutable); - } - if ptr_expected_mutbl == Mutability::Mut - && alloc.inner().mutability == Mutability::Not - { - throw_validation_failure!(self.path, MutableRefToImmutable); - } - } + GlobalAlloc::Memory(alloc) => alloc.inner().mutability, GlobalAlloc::Function(..) | GlobalAlloc::VTable(..) => { // These are immutable, we better don't allow mutable pointers here. - if ptr_expected_mutbl == Mutability::Mut { - throw_validation_failure!(self.path, MutableRefToImmutable); - } + Mutability::Not + } + }; + // Mutability check. + // If this allocation has size zero, there is no actual mutability here. + let (size, _align, _alloc_kind) = self.ecx.get_alloc_info(alloc_id); + if size != Size::ZERO { + if ptr_expected_mutbl == Mutability::Mut + && alloc_actual_mutbl == Mutability::Not + { + throw_validation_failure!(self.path, MutableRefToImmutable); + } + if ptr_expected_mutbl == Mutability::Mut + && self.ctfe_mode.is_some_and(|c| !c.may_contain_mutable_ref()) + { + throw_validation_failure!(self.path, MutableRefInConstOrStatic); + } + if alloc_actual_mutbl == Mutability::Mut + && matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. })) + { + throw_validation_failure!(self.path, ConstRefToMutable); } } + // Potentially skip recursive check. + if skip_recursive_check { + return Ok(()); + } } let path = &self.path; ref_tracking.track(place, || { @@ -598,16 +599,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' } Ok(true) } - ty::Ref(_, ty, mutbl) => { - if self.ctfe_mode.is_some_and(|c| !c.may_contain_mutable_ref()) - && *mutbl == Mutability::Mut - { - let layout = self.ecx.layout_of(*ty)?; - if !layout.is_zst() { - throw_validation_failure!(self.path, MutableRefInConst); - } - } - self.check_safe_pointer(value, PointerKind::Ref)?; + ty::Ref(_, _ty, mutbl) => { + self.check_safe_pointer(value, PointerKind::Ref(*mutbl))?; Ok(true) } ty::FnPtr(_sig) => { diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 9d4ec7d25bb69..125fac48df877 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -12,6 +12,7 @@ use rustc_macros::HashStable; use rustc_session::CtfeBacktrace; use rustc_span::{def_id::DefId, Span, DUMMY_SP}; use rustc_target::abi::{call, Align, Size, VariantIdx, WrappingRange}; +use rustc_type_ir::Mutability; use std::borrow::Cow; use std::{any::Any, backtrace::Backtrace, fmt}; @@ -367,7 +368,7 @@ pub enum UndefinedBehaviorInfo<'tcx> { #[derive(Debug, Clone, Copy)] pub enum PointerKind { - Ref, + Ref(Mutability), Box, } @@ -375,7 +376,7 @@ impl IntoDiagnosticArg for PointerKind { fn into_diagnostic_arg(self) -> DiagnosticArgValue { DiagnosticArgValue::Str( match self { - Self::Ref => "ref", + Self::Ref(_) => "ref", Self::Box => "box", } .into(), @@ -408,7 +409,7 @@ impl From for ExpectedKind { fn from(x: PointerKind) -> ExpectedKind { match x { PointerKind::Box => ExpectedKind::Box, - PointerKind::Ref => ExpectedKind::Reference, + PointerKind::Ref(_) => ExpectedKind::Reference, } } } @@ -419,7 +420,7 @@ pub enum ValidationErrorKind<'tcx> { PartialPointer, PtrToUninhabited { ptr_kind: PointerKind, ty: Ty<'tcx> }, PtrToStatic { ptr_kind: PointerKind }, - MutableRefInConst, + MutableRefInConstOrStatic, ConstRefToMutable, ConstRefToExtern, MutableRefToImmutable, diff --git a/tests/ui/consts/const-mut-refs/const_mut_refs.rs b/tests/ui/consts/const-mut-refs/const_mut_refs.rs index 544458dfcd8bb..96321a1defdfa 100644 --- a/tests/ui/consts/const-mut-refs/const_mut_refs.rs +++ b/tests/ui/consts/const-mut-refs/const_mut_refs.rs @@ -1,6 +1,8 @@ // check-pass #![feature(const_mut_refs)] +use std::sync::Mutex; + struct Foo { x: usize } @@ -28,6 +30,10 @@ const fn bazz(foo: &mut Foo) -> usize { foo.x } +// Empty slices get promoted so this passes the static checks. +// Make sure it also passes the dynamic checks. +static MUTABLE_REFERENCE_HOLDER: Mutex<&mut [u8]> = Mutex::new(&mut []); + fn main() { let _: [(); foo().bar()] = [(); 1]; let _: [(); baz(&mut foo())] = [(); 2]; diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.32bit.stderr b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.32bit.stderr index 87420a0375147..acb6f121bbf02 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.32bit.stderr +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.32bit.stderr @@ -1,19 +1,24 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/mut_ref_in_final_dynamic_check.rs:15:1 + --> $DIR/mut_ref_in_final_dynamic_check.rs:16:1 | LL | const A: Option<&mut i32> = helper(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered mutable reference in a `const` or `static` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 4, align: 4) { - 2a 00 00 00 │ *... + ╾ALLOC0╼ │ ╾──╼ } -error: encountered dangling pointer in final value of constant - --> $DIR/mut_ref_in_final_dynamic_check.rs:22:1 +error[E0080]: it is undefined behavior to use this value + --> $DIR/mut_ref_in_final_dynamic_check.rs:18:1 + | +LL | static A_STATIC: Option<&mut i32> = helper(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered mutable reference in a `const` or `static` | -LL | const B: Option<&mut i32> = helper2(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 4, align: 4) { + ╾ALLOC0╼ │ ╾──╼ + } error: aborting due to 2 previous errors diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.64bit.stderr b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.64bit.stderr index fc68207512c09..6dc7d85139154 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.64bit.stderr +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.64bit.stderr @@ -1,19 +1,24 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/mut_ref_in_final_dynamic_check.rs:15:1 + --> $DIR/mut_ref_in_final_dynamic_check.rs:16:1 | LL | const A: Option<&mut i32> = helper(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered mutable reference in a `const` or `static` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: 8, align: 8) { - 2a 00 00 00 00 00 00 00 │ *....... + ╾ALLOC0╼ │ ╾──────╼ } -error: encountered dangling pointer in final value of constant - --> $DIR/mut_ref_in_final_dynamic_check.rs:22:1 +error[E0080]: it is undefined behavior to use this value + --> $DIR/mut_ref_in_final_dynamic_check.rs:18:1 + | +LL | static A_STATIC: Option<&mut i32> = helper(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered mutable reference in a `const` or `static` | -LL | const B: Option<&mut i32> = helper2(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: 8, align: 8) { + ╾ALLOC0╼ │ ╾──────╼ + } error: aborting due to 2 previous errors diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs index 455b557b97c4e..26b4796c6c43e 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs @@ -1,5 +1,5 @@ // stderr-per-bitwidth -#![feature(const_mut_refs)] +#![feature(const_mut_refs, const_refs_to_static)] #![feature(raw_ref_op)] // This file checks that our dynamic checks catch things that the static checks miss. @@ -8,17 +8,14 @@ // do that without causing the borrow checker to complain (see the B4/helper test in // mut_ref_in_final.rs). +static mut BUFFER: i32 = 42; + const fn helper() -> Option<&'static mut i32> { unsafe { - // Undefined behaviour (integer as pointer), who doesn't love tests like this. - Some(&mut *(42 as *mut i32)) + Some(&mut *std::ptr::addr_of_mut!(BUFFER)) } } const A: Option<&mut i32> = helper(); //~ ERROR it is undefined behavior to use this value -//~^ encountered mutable reference in a `const` - -const fn helper2() -> Option<&'static mut i32> { unsafe { - // Undefined behaviour (dangling pointer), who doesn't love tests like this. - Some(&mut *(&mut 42 as *mut i32)) -} } -const B: Option<&mut i32> = helper2(); //~ ERROR encountered dangling pointer in final value of constant +//~^ encountered mutable reference +static A_STATIC: Option<&mut i32> = helper(); //~ ERROR it is undefined behavior to use this value +//~^ encountered mutable reference fn main() {} From f68e79dcac3acb635c58ff2fa4178b9a0b040fe4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 16 Feb 2024 10:01:43 +0100 Subject: [PATCH 2/4] remove stderr-per-bitwidth from some tests --- .../validate_uninhabited_zsts.64bit.stderr | 52 ----------- .../const-eval/validate_uninhabited_zsts.rs | 2 - ...tderr => validate_uninhabited_zsts.stderr} | 16 ++-- .../const-mut-refs/issue-76510.64bit.stderr | 26 ------ tests/ui/consts/const-mut-refs/issue-76510.rs | 2 - ...-76510.32bit.stderr => issue-76510.stderr} | 6 +- ...ut_ref_in_final_dynamic_check.64bit.stderr | 25 ------ .../mut_ref_in_final_dynamic_check.rs | 3 +- ... => mut_ref_in_final_dynamic_check.stderr} | 12 +-- .../const_refers_to_static.64bit.stderr | 65 -------------- .../miri_unleashed/const_refers_to_static.rs | 3 +- ...t.stderr => const_refers_to_static.stderr} | 24 ++--- ..._refers_to_static_cross_crate.64bit.stderr | 89 ------------------- .../const_refers_to_static_cross_crate.rs | 3 +- ...const_refers_to_static_cross_crate.stderr} | 36 ++++---- 15 files changed, 53 insertions(+), 311 deletions(-) delete mode 100644 tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr rename tests/ui/consts/const-eval/{validate_uninhabited_zsts.32bit.stderr => validate_uninhabited_zsts.stderr} (81%) delete mode 100644 tests/ui/consts/const-mut-refs/issue-76510.64bit.stderr rename tests/ui/consts/const-mut-refs/{issue-76510.32bit.stderr => issue-76510.stderr} (91%) delete mode 100644 tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.64bit.stderr rename tests/ui/consts/const-mut-refs/{mut_ref_in_final_dynamic_check.32bit.stderr => mut_ref_in_final_dynamic_check.stderr} (73%) delete mode 100644 tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr rename tests/ui/consts/miri_unleashed/{const_refers_to_static.32bit.stderr => const_refers_to_static.stderr} (78%) delete mode 100644 tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr rename tests/ui/consts/miri_unleashed/{const_refers_to_static_cross_crate.32bit.stderr => const_refers_to_static_cross_crate.stderr} (70%) diff --git a/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr b/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr deleted file mode 100644 index b423edbdcec8d..0000000000000 --- a/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr +++ /dev/null @@ -1,52 +0,0 @@ -warning: the type `!` does not permit zero-initialization - --> $DIR/validate_uninhabited_zsts.rs:4:14 - | -LL | unsafe { std::mem::transmute(()) } - | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed - | - = note: the `!` type has no valid value - = note: `#[warn(invalid_value)]` on by default - -error[E0080]: evaluation of constant value failed - --> $DIR/validate_uninhabited_zsts.rs:4:14 - | -LL | unsafe { std::mem::transmute(()) } - | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of the never type `!` - | -note: inside `foo` - --> $DIR/validate_uninhabited_zsts.rs:4:14 - | -LL | unsafe { std::mem::transmute(()) } - | ^^^^^^^^^^^^^^^^^^^^^^^ -note: inside `FOO` - --> $DIR/validate_uninhabited_zsts.rs:19:33 - | -LL | const FOO: [empty::Empty; 3] = [foo(); 3]; - | ^^^^^ - -error[E0080]: evaluation of constant value failed - --> $DIR/validate_uninhabited_zsts.rs:21:42 - | -LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; - | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered a value of uninhabited type `Void` - -warning: the type `empty::Empty` does not permit zero-initialization - --> $DIR/validate_uninhabited_zsts.rs:21:42 - | -LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; - | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed - | -note: in this struct field - --> $DIR/validate_uninhabited_zsts.rs:16:22 - | -LL | pub struct Empty(Void); - | ^^^^ -note: enums with no inhabited variants have no valid value - --> $DIR/validate_uninhabited_zsts.rs:13:5 - | -LL | enum Void {} - | ^^^^^^^^^ - -error: aborting due to 2 previous errors; 2 warnings emitted - -For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-eval/validate_uninhabited_zsts.rs b/tests/ui/consts/const-eval/validate_uninhabited_zsts.rs index b6783175dd379..5fc0674c576c2 100644 --- a/tests/ui/consts/const-eval/validate_uninhabited_zsts.rs +++ b/tests/ui/consts/const-eval/validate_uninhabited_zsts.rs @@ -1,5 +1,3 @@ -// stderr-per-bitwidth - const fn foo() -> ! { unsafe { std::mem::transmute(()) } //~^ ERROR evaluation of constant value failed diff --git a/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr b/tests/ui/consts/const-eval/validate_uninhabited_zsts.stderr similarity index 81% rename from tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr rename to tests/ui/consts/const-eval/validate_uninhabited_zsts.stderr index b423edbdcec8d..4c50ab5319ef9 100644 --- a/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr +++ b/tests/ui/consts/const-eval/validate_uninhabited_zsts.stderr @@ -1,5 +1,5 @@ warning: the type `!` does not permit zero-initialization - --> $DIR/validate_uninhabited_zsts.rs:4:14 + --> $DIR/validate_uninhabited_zsts.rs:2:14 | LL | unsafe { std::mem::transmute(()) } | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed @@ -8,41 +8,41 @@ LL | unsafe { std::mem::transmute(()) } = note: `#[warn(invalid_value)]` on by default error[E0080]: evaluation of constant value failed - --> $DIR/validate_uninhabited_zsts.rs:4:14 + --> $DIR/validate_uninhabited_zsts.rs:2:14 | LL | unsafe { std::mem::transmute(()) } | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of the never type `!` | note: inside `foo` - --> $DIR/validate_uninhabited_zsts.rs:4:14 + --> $DIR/validate_uninhabited_zsts.rs:2:14 | LL | unsafe { std::mem::transmute(()) } | ^^^^^^^^^^^^^^^^^^^^^^^ note: inside `FOO` - --> $DIR/validate_uninhabited_zsts.rs:19:33 + --> $DIR/validate_uninhabited_zsts.rs:17:33 | LL | const FOO: [empty::Empty; 3] = [foo(); 3]; | ^^^^^ error[E0080]: evaluation of constant value failed - --> $DIR/validate_uninhabited_zsts.rs:21:42 + --> $DIR/validate_uninhabited_zsts.rs:19:42 | LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; | ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered a value of uninhabited type `Void` warning: the type `empty::Empty` does not permit zero-initialization - --> $DIR/validate_uninhabited_zsts.rs:21:42 + --> $DIR/validate_uninhabited_zsts.rs:19:42 | LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; | ^^^^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed | note: in this struct field - --> $DIR/validate_uninhabited_zsts.rs:16:22 + --> $DIR/validate_uninhabited_zsts.rs:14:22 | LL | pub struct Empty(Void); | ^^^^ note: enums with no inhabited variants have no valid value - --> $DIR/validate_uninhabited_zsts.rs:13:5 + --> $DIR/validate_uninhabited_zsts.rs:11:5 | LL | enum Void {} | ^^^^^^^^^ diff --git a/tests/ui/consts/const-mut-refs/issue-76510.64bit.stderr b/tests/ui/consts/const-mut-refs/issue-76510.64bit.stderr deleted file mode 100644 index dc04d85770e7b..0000000000000 --- a/tests/ui/consts/const-mut-refs/issue-76510.64bit.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error[E0764]: mutable references are not allowed in the final value of constants - --> $DIR/issue-76510.rs:5:29 - | -LL | const S: &'static mut str = &mut " hello "; - | ^^^^^^^^^^^^^^ - -error[E0658]: mutation through a reference is not allowed in constants - --> $DIR/issue-76510.rs:5:29 - | -LL | const S: &'static mut str = &mut " hello "; - | ^^^^^^^^^^^^^^ - | - = note: see issue #57349 for more information - = help: add `#![feature(const_mut_refs)]` 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[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/issue-76510.rs:5:29 - | -LL | const S: &'static mut str = &mut " hello "; - | ^^^^^^^^^^^^^^ cannot borrow as mutable - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0596, E0658, E0764. -For more information about an error, try `rustc --explain E0596`. diff --git a/tests/ui/consts/const-mut-refs/issue-76510.rs b/tests/ui/consts/const-mut-refs/issue-76510.rs index 143d2fb6b9a3a..b6a73abb09cae 100644 --- a/tests/ui/consts/const-mut-refs/issue-76510.rs +++ b/tests/ui/consts/const-mut-refs/issue-76510.rs @@ -1,5 +1,3 @@ -// stderr-per-bitwidth - use std::mem::{transmute, ManuallyDrop}; const S: &'static mut str = &mut " hello "; diff --git a/tests/ui/consts/const-mut-refs/issue-76510.32bit.stderr b/tests/ui/consts/const-mut-refs/issue-76510.stderr similarity index 91% rename from tests/ui/consts/const-mut-refs/issue-76510.32bit.stderr rename to tests/ui/consts/const-mut-refs/issue-76510.stderr index dc04d85770e7b..8a1b19baff7c6 100644 --- a/tests/ui/consts/const-mut-refs/issue-76510.32bit.stderr +++ b/tests/ui/consts/const-mut-refs/issue-76510.stderr @@ -1,11 +1,11 @@ error[E0764]: mutable references are not allowed in the final value of constants - --> $DIR/issue-76510.rs:5:29 + --> $DIR/issue-76510.rs:3:29 | LL | const S: &'static mut str = &mut " hello "; | ^^^^^^^^^^^^^^ error[E0658]: mutation through a reference is not allowed in constants - --> $DIR/issue-76510.rs:5:29 + --> $DIR/issue-76510.rs:3:29 | LL | const S: &'static mut str = &mut " hello "; | ^^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | const S: &'static mut str = &mut " hello "; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/issue-76510.rs:5:29 + --> $DIR/issue-76510.rs:3:29 | LL | const S: &'static mut str = &mut " hello "; | ^^^^^^^^^^^^^^ cannot borrow as mutable diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.64bit.stderr b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.64bit.stderr deleted file mode 100644 index 6dc7d85139154..0000000000000 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.64bit.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error[E0080]: it is undefined behavior to use this value - --> $DIR/mut_ref_in_final_dynamic_check.rs:16:1 - | -LL | const A: Option<&mut i32> = helper(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered mutable reference in a `const` or `static` - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 8, align: 8) { - ╾ALLOC0╼ │ ╾──────╼ - } - -error[E0080]: it is undefined behavior to use this value - --> $DIR/mut_ref_in_final_dynamic_check.rs:18:1 - | -LL | static A_STATIC: Option<&mut i32> = helper(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered mutable reference in a `const` or `static` - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 8, align: 8) { - ╾ALLOC0╼ │ ╾──────╼ - } - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs index 26b4796c6c43e..081353a47c872 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs @@ -1,4 +1,5 @@ -// stderr-per-bitwidth +// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" #![feature(const_mut_refs, const_refs_to_static)] #![feature(raw_ref_op)] diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.32bit.stderr b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr similarity index 73% rename from tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.32bit.stderr rename to tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr index acb6f121bbf02..8625c445f99b4 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.32bit.stderr +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr @@ -1,23 +1,23 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/mut_ref_in_final_dynamic_check.rs:16:1 + --> $DIR/mut_ref_in_final_dynamic_check.rs:17:1 | LL | const A: Option<&mut i32> = helper(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered mutable reference in a `const` or `static` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 4, align: 4) { - ╾ALLOC0╼ │ ╾──╼ + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP } error[E0080]: it is undefined behavior to use this value - --> $DIR/mut_ref_in_final_dynamic_check.rs:18:1 + --> $DIR/mut_ref_in_final_dynamic_check.rs:19:1 | LL | static A_STATIC: Option<&mut i32> = helper(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered mutable reference in a `const` or `static` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 4, align: 4) { - ╾ALLOC0╼ │ ╾──╼ + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP } error: aborting due to 2 previous errors diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr deleted file mode 100644 index 989d3c75cd684..0000000000000 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr +++ /dev/null @@ -1,65 +0,0 @@ -error[E0080]: evaluation of constant value failed - --> $DIR/const_refers_to_static.rs:9:5 - | -LL | FOO.fetch_add(1, Ordering::Relaxed) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `AtomicUsize::fetch_add` - -error[E0080]: evaluation of constant value failed - --> $DIR/const_refers_to_static.rs:14:14 - | -LL | unsafe { *(&FOO as *const _ as *const usize) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses mutable global memory - -error[E0080]: evaluation of constant value failed - --> $DIR/const_refers_to_static.rs:18:32 - | -LL | const READ_MUT: u32 = unsafe { MUTABLE }; - | ^^^^^^^ constant accesses mutable global memory - -error[E0080]: it is undefined behavior to use this value - --> $DIR/const_refers_to_static.rs:21:1 - | -LL | const REF_INTERIOR_MUT: &usize = { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const` - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 8, align: 8) { - ╾ALLOC0╼ │ ╾──────╼ - } - -warning: skipping const checks - | -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static.rs:9:5 - | -LL | FOO.fetch_add(1, Ordering::Relaxed) - | ^^^ -help: skipping check that does not even have a feature gate - --> $DIR/const_refers_to_static.rs:9:5 - | -LL | FOO.fetch_add(1, Ordering::Relaxed) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static.rs:14:17 - | -LL | unsafe { *(&FOO as *const _ as *const usize) } - | ^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static.rs:18:32 - | -LL | const READ_MUT: u32 = unsafe { MUTABLE }; - | ^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static.rs:24:18 - | -LL | unsafe { &*(&FOO as *const _ as *const usize) } - | ^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static.rs:29:25 - | -LL | const REF_IMMUT: &u8 = &MY_STATIC; - | ^^^^^^^^^ - -error: aborting due to 4 previous errors; 1 warning emitted - -For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.rs b/tests/ui/consts/miri_unleashed/const_refers_to_static.rs index f8d956b3dd86e..212003deba3da 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static.rs +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.rs @@ -1,5 +1,6 @@ // compile-flags: -Zunleash-the-miri-inside-of-you -// stderr-per-bitwidth +// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static.stderr similarity index 78% rename from tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr rename to tests/ui/consts/miri_unleashed/const_refers_to_static.stderr index 9e76b87385844..df910546d11ad 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static.stderr @@ -1,61 +1,61 @@ error[E0080]: evaluation of constant value failed - --> $DIR/const_refers_to_static.rs:9:5 + --> $DIR/const_refers_to_static.rs:10:5 | LL | FOO.fetch_add(1, Ordering::Relaxed) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `AtomicUsize::fetch_add` error[E0080]: evaluation of constant value failed - --> $DIR/const_refers_to_static.rs:14:14 + --> $DIR/const_refers_to_static.rs:15:14 | LL | unsafe { *(&FOO as *const _ as *const usize) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses mutable global memory error[E0080]: evaluation of constant value failed - --> $DIR/const_refers_to_static.rs:18:32 + --> $DIR/const_refers_to_static.rs:19:32 | LL | const READ_MUT: u32 = unsafe { MUTABLE }; | ^^^^^^^ constant accesses mutable global memory error[E0080]: it is undefined behavior to use this value - --> $DIR/const_refers_to_static.rs:21:1 + --> $DIR/const_refers_to_static.rs:22:1 | LL | const REF_INTERIOR_MUT: &usize = { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 4, align: 4) { - ╾ALLOC0╼ │ ╾──╼ + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP } warning: skipping const checks | help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static.rs:9:5 + --> $DIR/const_refers_to_static.rs:10:5 | LL | FOO.fetch_add(1, Ordering::Relaxed) | ^^^ help: skipping check that does not even have a feature gate - --> $DIR/const_refers_to_static.rs:9:5 + --> $DIR/const_refers_to_static.rs:10:5 | LL | FOO.fetch_add(1, Ordering::Relaxed) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static.rs:14:17 + --> $DIR/const_refers_to_static.rs:15:17 | LL | unsafe { *(&FOO as *const _ as *const usize) } | ^^^ help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static.rs:18:32 + --> $DIR/const_refers_to_static.rs:19:32 | LL | const READ_MUT: u32 = unsafe { MUTABLE }; | ^^^^^^^ help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static.rs:24:18 + --> $DIR/const_refers_to_static.rs:25:18 | LL | unsafe { &*(&FOO as *const _ as *const usize) } | ^^^ help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static.rs:29:25 + --> $DIR/const_refers_to_static.rs:30:25 | LL | const REF_IMMUT: &u8 = &MY_STATIC; | ^^^^^^^^^ diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr deleted file mode 100644 index 200faf3558762..0000000000000 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr +++ /dev/null @@ -1,89 +0,0 @@ -error[E0080]: it is undefined behavior to use this value - --> $DIR/const_refers_to_static_cross_crate.rs:11:1 - | -LL | const SLICE_MUT: &[u8; 1] = { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const` - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 8, align: 8) { - ╾ALLOC0╼ │ ╾──────╼ - } - -error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:39:9 - | -LL | SLICE_MUT => true, - | ^^^^^^^^^ - -error[E0080]: it is undefined behavior to use this value - --> $DIR/const_refers_to_static_cross_crate.rs:16:1 - | -LL | const U8_MUT: &u8 = { - | ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const` - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 8, align: 8) { - ╾ALLOC0╼ │ ╾──────╼ - } - -error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:47:9 - | -LL | U8_MUT => true, - | ^^^^^^ - -error[E0080]: it is undefined behavior to use this value - --> $DIR/const_refers_to_static_cross_crate.rs:22:1 - | -LL | const U8_MUT2: &u8 = { - | ^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const` - | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 8, align: 8) { - ╾ALLOC0╼ │ ╾──────╼ - } - -error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:57:9 - | -LL | U8_MUT2 => true, - | ^^^^^^^ - -error[E0080]: evaluation of constant value failed - --> $DIR/const_refers_to_static_cross_crate.rs:28:15 - | -LL | match static_cross_crate::OPT_ZERO { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses mutable global memory - -error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:64:9 - | -LL | U8_MUT3 => true, - | ^^^^^^^ - -warning: skipping const checks - | -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:13:15 - | -LL | unsafe { &static_cross_crate::ZERO } - | ^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:18:15 - | -LL | unsafe { &static_cross_crate::ZERO[0] } - | ^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:24:17 - | -LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:28:15 - | -LL | match static_cross_crate::OPT_ZERO { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 8 previous errors; 1 warning emitted - -For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs index bcd29f8b03441..783b3d1805155 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs @@ -1,6 +1,7 @@ // compile-flags: -Zunleash-the-miri-inside-of-you // aux-build:static_cross_crate.rs -// stderr-per-bitwidth +// normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" +// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" #![feature(exclusive_range_pattern, half_open_range_patterns_in_slices)] #![allow(static_mut_ref)] diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr similarity index 70% rename from tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr rename to tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr index db7e8b6847a73..7b22fa4399fcd 100644 --- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr +++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr @@ -1,62 +1,62 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/const_refers_to_static_cross_crate.rs:11:1 + --> $DIR/const_refers_to_static_cross_crate.rs:12:1 | LL | const SLICE_MUT: &[u8; 1] = { | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 4, align: 4) { - ╾ALLOC0╼ │ ╾──╼ + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP } error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:39:9 + --> $DIR/const_refers_to_static_cross_crate.rs:40:9 | LL | SLICE_MUT => true, | ^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/const_refers_to_static_cross_crate.rs:16:1 + --> $DIR/const_refers_to_static_cross_crate.rs:17:1 | LL | const U8_MUT: &u8 = { | ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 4, align: 4) { - ╾ALLOC0╼ │ ╾──╼ + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP } error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:47:9 + --> $DIR/const_refers_to_static_cross_crate.rs:48:9 | LL | U8_MUT => true, | ^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/const_refers_to_static_cross_crate.rs:22:1 + --> $DIR/const_refers_to_static_cross_crate.rs:23:1 | LL | const U8_MUT2: &u8 = { | ^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered reference to mutable memory in `const` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. - = note: the raw bytes of the constant (size: 4, align: 4) { - ╾ALLOC0╼ │ ╾──╼ + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP } error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:57:9 + --> $DIR/const_refers_to_static_cross_crate.rs:58:9 | LL | U8_MUT2 => true, | ^^^^^^^ error[E0080]: evaluation of constant value failed - --> $DIR/const_refers_to_static_cross_crate.rs:28:15 + --> $DIR/const_refers_to_static_cross_crate.rs:29:15 | LL | match static_cross_crate::OPT_ZERO { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses mutable global memory error: could not evaluate constant pattern - --> $DIR/const_refers_to_static_cross_crate.rs:64:9 + --> $DIR/const_refers_to_static_cross_crate.rs:65:9 | LL | U8_MUT3 => true, | ^^^^^^^ @@ -64,22 +64,22 @@ LL | U8_MUT3 => true, warning: skipping const checks | help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:13:15 + --> $DIR/const_refers_to_static_cross_crate.rs:14:15 | LL | unsafe { &static_cross_crate::ZERO } | ^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:18:15 + --> $DIR/const_refers_to_static_cross_crate.rs:19:15 | LL | unsafe { &static_cross_crate::ZERO[0] } | ^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:24:17 + --> $DIR/const_refers_to_static_cross_crate.rs:25:17 | LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: skipping check for `const_refs_to_static` feature - --> $DIR/const_refers_to_static_cross_crate.rs:28:15 + --> $DIR/const_refers_to_static_cross_crate.rs:29:15 | LL | match static_cross_crate::OPT_ZERO { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 2611fac03fbb9fa79e7550f968d08f4815fb8d86 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 16 Feb 2024 10:06:23 +0100 Subject: [PATCH 3/4] add back some more attempts at having &mut in the final value of a const/static --- .../mut_ref_in_final_dynamic_check.rs | 20 ++++++++- .../mut_ref_in_final_dynamic_check.stderr | 44 ++++++++++++++++--- 2 files changed, 57 insertions(+), 7 deletions(-) diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs index 081353a47c872..331c2de55cc4d 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs @@ -14,9 +14,25 @@ static mut BUFFER: i32 = 42; const fn helper() -> Option<&'static mut i32> { unsafe { Some(&mut *std::ptr::addr_of_mut!(BUFFER)) } } -const A: Option<&mut i32> = helper(); //~ ERROR it is undefined behavior to use this value +const MUT: Option<&mut i32> = helper(); //~ ERROR it is undefined behavior to use this value //~^ encountered mutable reference -static A_STATIC: Option<&mut i32> = helper(); //~ ERROR it is undefined behavior to use this value +static MUT_STATIC: Option<&mut i32> = helper(); //~ ERROR it is undefined behavior to use this value //~^ encountered mutable reference +const fn helper_int2ptr() -> Option<&'static mut i32> { unsafe { + // Undefined behaviour (integer as pointer), who doesn't love tests like this. + Some(&mut *(42 as *mut i32)) +} } +const INT2PTR: Option<&mut i32> = helper_int2ptr(); //~ ERROR it is undefined behavior to use this value +//~^ encountered a dangling reference +static INT2PTR_STATIC: Option<&mut i32> = helper_int2ptr(); //~ ERROR it is undefined behavior to use this value +//~^ encountered a dangling reference + +const fn helper_dangling() -> Option<&'static mut i32> { unsafe { + // Undefined behaviour (dangling pointer), who doesn't love tests like this. + Some(&mut *(&mut 42 as *mut i32)) +} } +const DANGLING: Option<&mut i32> = helper_dangling(); //~ ERROR encountered dangling pointer +static DANGLING_STATIC: Option<&mut i32> = helper_dangling(); //~ ERROR encountered dangling pointer + fn main() {} diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr index 8625c445f99b4..a7cd32a7c5f0b 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr @@ -1,8 +1,8 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/mut_ref_in_final_dynamic_check.rs:17:1 | -LL | const A: Option<&mut i32> = helper(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered mutable reference in a `const` or `static` +LL | const MUT: Option<&mut i32> = helper(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered mutable reference in a `const` or `static` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { @@ -12,14 +12,48 @@ LL | const A: Option<&mut i32> = helper(); error[E0080]: it is undefined behavior to use this value --> $DIR/mut_ref_in_final_dynamic_check.rs:19:1 | -LL | static A_STATIC: Option<&mut i32> = helper(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered mutable reference in a `const` or `static` +LL | static MUT_STATIC: Option<&mut i32> = helper(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered mutable reference in a `const` or `static` | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { HEX_DUMP } -error: aborting due to 2 previous errors +error[E0080]: it is undefined behavior to use this value + --> $DIR/mut_ref_in_final_dynamic_check.rs:26:1 + | +LL | const INT2PTR: Option<&mut i32> = helper_int2ptr(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a dangling reference (0x2a[noalloc] has no provenance) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error[E0080]: it is undefined behavior to use this value + --> $DIR/mut_ref_in_final_dynamic_check.rs:28:1 + | +LL | static INT2PTR_STATIC: Option<&mut i32> = helper_int2ptr(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a dangling reference (0x2a[noalloc] has no provenance) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error: encountered dangling pointer in final value of constant + --> $DIR/mut_ref_in_final_dynamic_check.rs:35:1 + | +LL | const DANGLING: Option<&mut i32> = helper_dangling(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: encountered dangling pointer in final value of static + --> $DIR/mut_ref_in_final_dynamic_check.rs:36:1 + | +LL | static DANGLING_STATIC: Option<&mut i32> = helper_dangling(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0080`. From d3fc69ae450530dffa0f307ef2cb669c7b0a1c3b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 16 Feb 2024 11:35:20 +0100 Subject: [PATCH 4/4] add test ensuring we detect a static actually having a mutable reference --- .../mut_ref_in_final_dynamic_check.rs | 12 ++++++++- .../mut_ref_in_final_dynamic_check.stderr | 25 +++++++++++++------ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs index 331c2de55cc4d..19f0ad8a5a442 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs @@ -1,8 +1,11 @@ // normalize-stderr-test "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" -// normalize-stderr-test "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" +// normalize-stderr-test "( 0x[0-9a-f][0-9a-f] │)? ([0-9a-f][0-9a-f] |__ |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> " HEX_DUMP" +// normalize-stderr-test "HEX_DUMP\s*\n\s*HEX_DUMP" -> "HEX_DUMP" #![feature(const_mut_refs, const_refs_to_static)] #![feature(raw_ref_op)] +use std::sync::Mutex; + // This file checks that our dynamic checks catch things that the static checks miss. // We do not have static checks for these, because we do not look into function bodies. // We treat all functions as not returning a mutable reference, because there is no way to @@ -35,4 +38,11 @@ const fn helper_dangling() -> Option<&'static mut i32> { unsafe { const DANGLING: Option<&mut i32> = helper_dangling(); //~ ERROR encountered dangling pointer static DANGLING_STATIC: Option<&mut i32> = helper_dangling(); //~ ERROR encountered dangling pointer +// Variant of the real-world case in . +// Maybe we should allow this in the future (then the rest should move to `const_mut_refs.rs`), +// but for now we reject it. +static mut MUT_ARRAY: &mut [u8] = &mut [42]; +static MUTEX: Mutex<&mut [u8]> = Mutex::new(unsafe { &mut *MUT_ARRAY }); //~ ERROR it is undefined behavior to use this value +//~^ encountered mutable reference + fn main() {} diff --git a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr index a7cd32a7c5f0b..a99d158493207 100644 --- a/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr +++ b/tests/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/mut_ref_in_final_dynamic_check.rs:17:1 + --> $DIR/mut_ref_in_final_dynamic_check.rs:20:1 | LL | const MUT: Option<&mut i32> = helper(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered mutable reference in a `const` or `static` @@ -10,7 +10,7 @@ LL | const MUT: Option<&mut i32> = helper(); } error[E0080]: it is undefined behavior to use this value - --> $DIR/mut_ref_in_final_dynamic_check.rs:19:1 + --> $DIR/mut_ref_in_final_dynamic_check.rs:22:1 | LL | static MUT_STATIC: Option<&mut i32> = helper(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered mutable reference in a `const` or `static` @@ -21,7 +21,7 @@ LL | static MUT_STATIC: Option<&mut i32> = helper(); } error[E0080]: it is undefined behavior to use this value - --> $DIR/mut_ref_in_final_dynamic_check.rs:26:1 + --> $DIR/mut_ref_in_final_dynamic_check.rs:29:1 | LL | const INT2PTR: Option<&mut i32> = helper_int2ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a dangling reference (0x2a[noalloc] has no provenance) @@ -32,7 +32,7 @@ LL | const INT2PTR: Option<&mut i32> = helper_int2ptr(); } error[E0080]: it is undefined behavior to use this value - --> $DIR/mut_ref_in_final_dynamic_check.rs:28:1 + --> $DIR/mut_ref_in_final_dynamic_check.rs:31:1 | LL | static INT2PTR_STATIC: Option<&mut i32> = helper_int2ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at ..0: encountered a dangling reference (0x2a[noalloc] has no provenance) @@ -43,17 +43,28 @@ LL | static INT2PTR_STATIC: Option<&mut i32> = helper_int2ptr(); } error: encountered dangling pointer in final value of constant - --> $DIR/mut_ref_in_final_dynamic_check.rs:35:1 + --> $DIR/mut_ref_in_final_dynamic_check.rs:38:1 | LL | const DANGLING: Option<&mut i32> = helper_dangling(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: encountered dangling pointer in final value of static - --> $DIR/mut_ref_in_final_dynamic_check.rs:36:1 + --> $DIR/mut_ref_in_final_dynamic_check.rs:39:1 | LL | static DANGLING_STATIC: Option<&mut i32> = helper_dangling(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error[E0080]: it is undefined behavior to use this value + --> $DIR/mut_ref_in_final_dynamic_check.rs:45:1 + | +LL | static MUTEX: Mutex<&mut [u8]> = Mutex::new(unsafe { &mut *MUT_ARRAY }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .data.value: encountered mutable reference in a `const` or `static` + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0080`.