Rollup merge of #121782 - RalfJung:mutable-ref-in-static, r=oli-obk
allow statics pointing to mutable statics Fixes https://github.com/rust-lang/rust/issues/120450 for good. We can even simplify our checks: no need to specifically go looking for mutable references in const, we can just reject any reference that points to something mutable. r? `@oli-obk`
This commit is contained in:
commit
255fdcc858
@ -453,7 +453,6 @@ 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_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
|
||||
|
@ -613,7 +613,6 @@ fn diagnostic_message(&self) -> DiagnosticMessage {
|
||||
PartialPointer => const_eval_validation_partial_pointer,
|
||||
ConstRefToMutable => const_eval_validation_const_ref_to_mutable,
|
||||
ConstRefToExtern => const_eval_validation_const_ref_to_extern,
|
||||
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,
|
||||
@ -767,7 +766,6 @@ fn add_range_arg<G: EmissionGuarantee>(
|
||||
}
|
||||
NullPtr { .. }
|
||||
| PtrToStatic { .. }
|
||||
| MutableRefInConstOrStatic
|
||||
| ConstRefToMutable
|
||||
| ConstRefToExtern
|
||||
| MutableRefToImmutable
|
||||
|
@ -148,14 +148,6 @@ fn allow_immutable_unsafe_cell(self) -> bool {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn may_contain_mutable_ref(self) -> bool {
|
||||
match self {
|
||||
CtfeValidationMode::Static { mutbl } => mutbl == Mutability::Mut,
|
||||
CtfeValidationMode::Promoted { .. } => false,
|
||||
CtfeValidationMode::Const { .. } => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// State for tracking recursive validation of references
|
||||
@ -511,22 +503,21 @@ fn check_safe_pointer(
|
||||
// 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 {
|
||||
// Mutable pointer to immutable memory is no good.
|
||||
if ptr_expected_mutbl == Mutability::Mut
|
||||
&& alloc_actual_mutbl == Mutability::Not
|
||||
{
|
||||
throw_validation_failure!(self.path, MutableRefToImmutable);
|
||||
}
|
||||
// In a const, everything must be completely immutable.
|
||||
if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { .. })) {
|
||||
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 { .. }))
|
||||
|| alloc_actual_mutbl == Mutability::Mut
|
||||
{
|
||||
throw_validation_failure!(self.path, ConstRefToMutable);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Potentially skip recursive check.
|
||||
if skip_recursive_check {
|
||||
return Ok(());
|
||||
|
@ -420,7 +420,6 @@ pub enum ValidationErrorKind<'tcx> {
|
||||
PartialPointer,
|
||||
PtrToUninhabited { ptr_kind: PointerKind, ty: Ty<'tcx> },
|
||||
PtrToStatic { ptr_kind: PointerKind },
|
||||
MutableRefInConstOrStatic,
|
||||
ConstRefToMutable,
|
||||
ConstRefToExtern,
|
||||
MutableRefToImmutable,
|
||||
|
@ -33,6 +33,11 @@ const fn bazz(foo: &mut Foo) -> usize {
|
||||
// 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 []);
|
||||
// This variant with a non-empty slice also seems entirely reasonable.
|
||||
static MUTABLE_REFERENCE_HOLDER2: Mutex<&mut [u8]> = unsafe {
|
||||
static mut FOO: [u8; 1] = [42]; // a private static that we are sure nobody else will reference
|
||||
Mutex::new(&mut *std::ptr::addr_of_mut!(FOO))
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let _: [(); foo().bar()] = [(); 1];
|
||||
|
@ -18,9 +18,7 @@ const fn helper() -> Option<&'static mut i32> { unsafe {
|
||||
Some(&mut *std::ptr::addr_of_mut!(BUFFER))
|
||||
} }
|
||||
const MUT: Option<&mut i32> = helper(); //~ ERROR it is undefined behavior to use this value
|
||||
//~^ encountered mutable reference
|
||||
static MUT_STATIC: Option<&mut i32> = helper(); //~ ERROR it is undefined behavior to use this value
|
||||
//~^ encountered mutable reference
|
||||
//~^ encountered reference to mutable
|
||||
|
||||
const fn helper_int2ptr() -> Option<&'static mut i32> { unsafe {
|
||||
// Undefined behaviour (integer as pointer), who doesn't love tests like this.
|
||||
@ -38,11 +36,9 @@ 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 <https://github.com/rust-lang/rust/issues/120450>.
|
||||
// Maybe we should allow this in the future (then the rest should move to `const_mut_refs.rs`),
|
||||
// but for now we reject it.
|
||||
// These are fine! Just statics pointing to mutable statics, nothing fundamentally wrong with this.
|
||||
static MUT_STATIC: Option<&mut i32> = helper();
|
||||
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
|
||||
static MUTEX: Mutex<&mut [u8]> = Mutex::new(unsafe { &mut *MUT_ARRAY });
|
||||
|
||||
fn main() {}
|
||||
|
@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/mut_ref_in_final_dynamic_check.rs:20:1
|
||||
|
|
||||
LL | const MUT: Option<&mut i32> = helper();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0: encountered mutable reference in a `const` or `static`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0: 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: $SIZE, align: $ALIGN) {
|
||||
@ -10,18 +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:22:1
|
||||
|
|
||||
LL | static MUT_STATIC: Option<&mut i32> = helper();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.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[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/mut_ref_in_final_dynamic_check.rs:29:1
|
||||
--> $DIR/mut_ref_in_final_dynamic_check.rs:27:1
|
||||
|
|
||||
LL | const INT2PTR: Option<&mut i32> = helper_int2ptr();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0: encountered a dangling reference (0x2a[noalloc] has no provenance)
|
||||
@ -32,7 +21,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:31:1
|
||||
--> $DIR/mut_ref_in_final_dynamic_check.rs:29:1
|
||||
|
|
||||
LL | static INT2PTR_STATIC: Option<&mut i32> = helper_int2ptr();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0: encountered a dangling reference (0x2a[noalloc] has no provenance)
|
||||
@ -43,28 +32,17 @@ 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:38:1
|
||||
--> $DIR/mut_ref_in_final_dynamic_check.rs:36: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:39:1
|
||||
--> $DIR/mut_ref_in_final_dynamic_check.rs:37:1
|
||||
|
|
||||
LL | static DANGLING_STATIC: Option<&mut i32> = helper_dangling();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
||||
|
@ -1,180 +0,0 @@
|
||||
error: encountered mutable pointer in final value of constant
|
||||
--> $DIR/mutable_references_err.rs:17:1
|
||||
|
|
||||
LL | const MUH: Meh = Meh {
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: encountered mutable pointer in final value of constant
|
||||
--> $DIR/mutable_references_err.rs:28:1
|
||||
|
|
||||
LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/mutable_references_err.rs:33:1
|
||||
|
|
||||
LL | const SUBTLE: &mut i32 = unsafe { &mut FOO };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid 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: 8, align: 8) {
|
||||
╾ALLOC0╼ │ ╾──────╼
|
||||
}
|
||||
|
||||
error: encountered mutable pointer in final value of constant
|
||||
--> $DIR/mutable_references_err.rs:36:1
|
||||
|
|
||||
LL | const BLUNT: &mut i32 = &mut 42;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/mutable_references_err.rs:41:1
|
||||
|
|
||||
LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory
|
||||
|
|
||||
= 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) {
|
||||
╾ALLOC1<imm>╼ │ ╾──────╼
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/mutable_references_err.rs:48:1
|
||||
|
|
||||
LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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) {
|
||||
╾ALLOC2<imm>╼ │ ╾──────╼
|
||||
}
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/mutable_references_err.rs:50:34
|
||||
|
|
||||
LL | const READS_FROM_MUTABLE: i32 = *POINTS_TO_MUTABLE1;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/mutable_references_err.rs:52:43
|
||||
|
|
||||
LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF };
|
||||
| ^^^^^^^^^^^^^ constant accesses mutable global memory
|
||||
|
||||
error: encountered mutable pointer in final value of constant
|
||||
--> $DIR/mutable_references_err.rs:56:1
|
||||
|
|
||||
LL | const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: encountered mutable pointer in final value of constant
|
||||
--> $DIR/mutable_references_err.rs:58:1
|
||||
|
|
||||
LL | const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: encountered mutable pointer in final value of constant
|
||||
--> $DIR/mutable_references_err.rs:60:1
|
||||
|
|
||||
LL | const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: encountered mutable pointer in final value of constant
|
||||
--> $DIR/mutable_references_err.rs:72:1
|
||||
|
|
||||
LL | const RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: encountered mutable pointer in final value of constant
|
||||
--> $DIR/mutable_references_err.rs:74:1
|
||||
|
|
||||
LL | const RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x: &mut 42 as *mut _ as *const _ };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: encountered mutable pointer in final value of constant
|
||||
--> $DIR/mutable_references_err.rs:76:1
|
||||
|
|
||||
LL | const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: skipping const checks
|
||||
|
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/mutable_references_err.rs:19:8
|
||||
|
|
||||
LL | x: &UnsafeCell::new(42),
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/mutable_references_err.rs:28:27
|
||||
|
|
||||
LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: skipping check for `const_refs_to_static` feature
|
||||
--> $DIR/mutable_references_err.rs:33:40
|
||||
|
|
||||
LL | const SUBTLE: &mut i32 = unsafe { &mut FOO };
|
||||
| ^^^
|
||||
help: skipping check for `const_mut_refs` feature
|
||||
--> $DIR/mutable_references_err.rs:33:35
|
||||
|
|
||||
LL | const SUBTLE: &mut i32 = unsafe { &mut FOO };
|
||||
| ^^^^^^^^
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/mutable_references_err.rs:36:25
|
||||
|
|
||||
LL | const BLUNT: &mut i32 = &mut 42;
|
||||
| ^^^^^^^
|
||||
help: skipping check for `const_mut_refs` feature
|
||||
--> $DIR/mutable_references_err.rs:41:49
|
||||
|
|
||||
LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: skipping check for `const_mut_refs` feature
|
||||
--> $DIR/mutable_references_err.rs:41:49
|
||||
|
|
||||
LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: skipping check for `const_refs_to_static` feature
|
||||
--> $DIR/mutable_references_err.rs:48:44
|
||||
|
|
||||
LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE };
|
||||
| ^^^^^^^
|
||||
help: skipping check for `const_refs_to_static` feature
|
||||
--> $DIR/mutable_references_err.rs:52:45
|
||||
|
|
||||
LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF };
|
||||
| ^^^^^^^^^^^
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/mutable_references_err.rs:56:45
|
||||
|
|
||||
LL | const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _;
|
||||
| ^^^^^^^
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/mutable_references_err.rs:58:46
|
||||
|
|
||||
LL | const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _;
|
||||
| ^^^^^^^
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/mutable_references_err.rs:60:47
|
||||
|
|
||||
LL | const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/mutable_references_err.rs:72:51
|
||||
|
|
||||
LL | const RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/mutable_references_err.rs:74:49
|
||||
|
|
||||
LL | const RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x: &mut 42 as *mut _ as *const _ };
|
||||
| ^^^^^^^
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/mutable_references_err.rs:76:51
|
||||
|
|
||||
LL | const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 13 previous errors; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0080`.
|
@ -1,5 +1,6 @@
|
||||
//@ stderr-per-bitwidth
|
||||
//@ compile-flags: -Zunleash-the-miri-inside-of-you
|
||||
//@ 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]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
|
||||
#![allow(invalid_reference_casting, static_mut_refs)]
|
||||
|
||||
use std::cell::UnsafeCell;
|
||||
|
@ -1,98 +1,98 @@
|
||||
error: encountered mutable pointer in final value of constant
|
||||
--> $DIR/mutable_references_err.rs:17:1
|
||||
--> $DIR/mutable_references_err.rs:18:1
|
||||
|
|
||||
LL | const MUH: Meh = Meh {
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: encountered mutable pointer in final value of constant
|
||||
--> $DIR/mutable_references_err.rs:28:1
|
||||
--> $DIR/mutable_references_err.rs:29:1
|
||||
|
|
||||
LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/mutable_references_err.rs:33:1
|
||||
--> $DIR/mutable_references_err.rs:34:1
|
||||
|
|
||||
LL | const SUBTLE: &mut i32 = unsafe { &mut FOO };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference in a `const` or `static`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ 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: encountered mutable pointer in final value of constant
|
||||
--> $DIR/mutable_references_err.rs:36:1
|
||||
--> $DIR/mutable_references_err.rs:37:1
|
||||
|
|
||||
LL | const BLUNT: &mut i32 = &mut 42;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/mutable_references_err.rs:41:1
|
||||
--> $DIR/mutable_references_err.rs:42:1
|
||||
|
|
||||
LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference or box pointing to read-only memory
|
||||
|
|
||||
= 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) {
|
||||
╾ALLOC1<imm>╼ │ ╾──╼
|
||||
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
|
||||
HEX_DUMP
|
||||
}
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/mutable_references_err.rs:48:1
|
||||
--> $DIR/mutable_references_err.rs:49:1
|
||||
|
|
||||
LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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) {
|
||||
╾ALLOC2<imm>╼ │ ╾──╼
|
||||
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
|
||||
HEX_DUMP
|
||||
}
|
||||
|
||||
note: erroneous constant encountered
|
||||
--> $DIR/mutable_references_err.rs:50:34
|
||||
--> $DIR/mutable_references_err.rs:51:34
|
||||
|
|
||||
LL | const READS_FROM_MUTABLE: i32 = *POINTS_TO_MUTABLE1;
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0080]: evaluation of constant value failed
|
||||
--> $DIR/mutable_references_err.rs:52:43
|
||||
--> $DIR/mutable_references_err.rs:53:43
|
||||
|
|
||||
LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF };
|
||||
| ^^^^^^^^^^^^^ constant accesses mutable global memory
|
||||
|
||||
error: encountered mutable pointer in final value of constant
|
||||
--> $DIR/mutable_references_err.rs:56:1
|
||||
--> $DIR/mutable_references_err.rs:57:1
|
||||
|
|
||||
LL | const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: encountered mutable pointer in final value of constant
|
||||
--> $DIR/mutable_references_err.rs:58:1
|
||||
--> $DIR/mutable_references_err.rs:59:1
|
||||
|
|
||||
LL | const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: encountered mutable pointer in final value of constant
|
||||
--> $DIR/mutable_references_err.rs:60:1
|
||||
--> $DIR/mutable_references_err.rs:61:1
|
||||
|
|
||||
LL | const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: encountered mutable pointer in final value of constant
|
||||
--> $DIR/mutable_references_err.rs:72:1
|
||||
--> $DIR/mutable_references_err.rs:73:1
|
||||
|
|
||||
LL | const RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: encountered mutable pointer in final value of constant
|
||||
--> $DIR/mutable_references_err.rs:74:1
|
||||
--> $DIR/mutable_references_err.rs:75:1
|
||||
|
|
||||
LL | const RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x: &mut 42 as *mut _ as *const _ };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: encountered mutable pointer in final value of constant
|
||||
--> $DIR/mutable_references_err.rs:76:1
|
||||
--> $DIR/mutable_references_err.rs:77:1
|
||||
|
|
||||
LL | const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -100,77 +100,77 @@ LL | const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
|
||||
warning: skipping const checks
|
||||
|
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/mutable_references_err.rs:19:8
|
||||
--> $DIR/mutable_references_err.rs:20:8
|
||||
|
|
||||
LL | x: &UnsafeCell::new(42),
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/mutable_references_err.rs:28:27
|
||||
--> $DIR/mutable_references_err.rs:29:27
|
||||
|
|
||||
LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: skipping check for `const_refs_to_static` feature
|
||||
--> $DIR/mutable_references_err.rs:33:40
|
||||
--> $DIR/mutable_references_err.rs:34:40
|
||||
|
|
||||
LL | const SUBTLE: &mut i32 = unsafe { &mut FOO };
|
||||
| ^^^
|
||||
help: skipping check for `const_mut_refs` feature
|
||||
--> $DIR/mutable_references_err.rs:33:35
|
||||
--> $DIR/mutable_references_err.rs:34:35
|
||||
|
|
||||
LL | const SUBTLE: &mut i32 = unsafe { &mut FOO };
|
||||
| ^^^^^^^^
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/mutable_references_err.rs:36:25
|
||||
--> $DIR/mutable_references_err.rs:37:25
|
||||
|
|
||||
LL | const BLUNT: &mut i32 = &mut 42;
|
||||
| ^^^^^^^
|
||||
help: skipping check for `const_mut_refs` feature
|
||||
--> $DIR/mutable_references_err.rs:41:49
|
||||
--> $DIR/mutable_references_err.rs:42:49
|
||||
|
|
||||
LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: skipping check for `const_mut_refs` feature
|
||||
--> $DIR/mutable_references_err.rs:41:49
|
||||
--> $DIR/mutable_references_err.rs:42:49
|
||||
|
|
||||
LL | static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: skipping check for `const_refs_to_static` feature
|
||||
--> $DIR/mutable_references_err.rs:48:44
|
||||
--> $DIR/mutable_references_err.rs:49:44
|
||||
|
|
||||
LL | const POINTS_TO_MUTABLE1: &i32 = unsafe { &MUTABLE };
|
||||
| ^^^^^^^
|
||||
help: skipping check for `const_refs_to_static` feature
|
||||
--> $DIR/mutable_references_err.rs:52:45
|
||||
--> $DIR/mutable_references_err.rs:53:45
|
||||
|
|
||||
LL | const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF };
|
||||
| ^^^^^^^^^^^
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/mutable_references_err.rs:56:45
|
||||
--> $DIR/mutable_references_err.rs:57:45
|
||||
|
|
||||
LL | const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _;
|
||||
| ^^^^^^^
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/mutable_references_err.rs:58:46
|
||||
--> $DIR/mutable_references_err.rs:59:46
|
||||
|
|
||||
LL | const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _;
|
||||
| ^^^^^^^
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/mutable_references_err.rs:60:47
|
||||
--> $DIR/mutable_references_err.rs:61:47
|
||||
|
|
||||
LL | const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/mutable_references_err.rs:72:51
|
||||
--> $DIR/mutable_references_err.rs:73:51
|
||||
|
|
||||
LL | const RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/mutable_references_err.rs:74:49
|
||||
--> $DIR/mutable_references_err.rs:75:49
|
||||
|
|
||||
LL | const RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x: &mut 42 as *mut _ as *const _ };
|
||||
| ^^^^^^^
|
||||
help: skipping check that does not even have a feature gate
|
||||
--> $DIR/mutable_references_err.rs:76:51
|
||||
--> $DIR/mutable_references_err.rs:77:51
|
||||
|
|
||||
LL | const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
|
||||
| ^^^^^^
|
@ -15,8 +15,4 @@
|
||||
static CONST_REF: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed
|
||||
//~| WARN taking a mutable
|
||||
|
||||
static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M };
|
||||
//~^ WARN mutable reference to mutable static is discouraged [static_mut_refs]
|
||||
//~| ERROR undefined behavior
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,18 +1,3 @@
|
||||
warning: creating a mutable reference to mutable static is discouraged
|
||||
--> $DIR/E0017.rs:18:52
|
||||
|
|
||||
LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M };
|
||||
| ^^^^^^ mutable reference to mutable static
|
||||
|
|
||||
= note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
|
||||
= note: this will be a hard error in the 2024 edition
|
||||
= note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior
|
||||
= note: `#[warn(static_mut_refs)]` on by default
|
||||
help: use `addr_of_mut!` instead to create a raw pointer
|
||||
|
|
||||
LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { addr_of_mut!(M) };
|
||||
| ~~~~~~~~~~~~~~~
|
||||
|
||||
warning: taking a mutable reference to a `const` item
|
||||
--> $DIR/E0017.rs:10:30
|
||||
|
|
||||
@ -60,18 +45,7 @@ error[E0764]: mutable references are not allowed in the final value of statics
|
||||
LL | static CONST_REF: &'static mut i32 = &mut C;
|
||||
| ^^^^^^
|
||||
|
||||
error[E0080]: it is undefined behavior to use this value
|
||||
--> $DIR/E0017.rs:18:1
|
||||
|
|
||||
LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid 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 {
|
||||
╾ALLOC0╼
|
||||
}
|
||||
error: aborting due to 3 previous errors; 2 warnings emitted
|
||||
|
||||
error: aborting due to 4 previous errors; 3 warnings emitted
|
||||
|
||||
Some errors have detailed explanations: E0080, E0596, E0764.
|
||||
For more information about an error, try `rustc --explain E0080`.
|
||||
Some errors have detailed explanations: E0596, E0764.
|
||||
For more information about an error, try `rustc --explain E0596`.
|
||||
|
Loading…
Reference in New Issue
Block a user