22//@ normalize-stderr-test: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
33//@ normalize-stderr-test: "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
44
5+ #![allow(static_mut_refs)]
56#![deny(const_eval_mutable_ptr_in_final_value)]
67use std::cell::UnsafeCell;
8+ use std::sync::atomic::*;
9+
10+ // # Plain `&mut` in the final value
711
812// This requires walking nested statics.
913static FOO: &&mut u32 = &&mut 42;
1014//~^ ERROR it is undefined behavior to use this value
11-
15+ //~| pointing to read-only memory
16+ static OH_YES: &mut i32 = &mut 42;
17+ //~^ ERROR it is undefined behavior to use this value
18+ //~| pointing to read-only memory
1219static BAR: &mut () = &mut ();
1320//~^ ERROR encountered mutable pointer in final value of static
1421//~| WARNING this was previously accepted by the compiler
@@ -19,15 +26,92 @@ static BOO: &mut Foo<()> = &mut Foo(());
1926//~^ ERROR encountered mutable pointer in final value of static
2027//~| WARNING this was previously accepted by the compiler
2128
29+ const BLUNT: &mut i32 = &mut 42;
30+ //~^ ERROR: it is undefined behavior to use this value
31+ //~| pointing to read-only memory
32+
33+ const SUBTLE: &mut i32 = unsafe { static mut STATIC: i32 = 0; &mut STATIC };
34+ //~^ ERROR: it is undefined behavior to use this value
35+ //~| static
36+
37+ // # Interior mutability
38+
2239struct Meh {
2340 x: &'static UnsafeCell<i32>,
2441}
2542unsafe impl Sync for Meh {}
2643static MEH: Meh = Meh { x: &UnsafeCell::new(42) };
2744//~^ ERROR it is undefined behavior to use this value
45+ //~| `UnsafeCell` in read-only memory
46+ // Same with a const:
47+ // the following will never be ok! no interior mut behind consts, because
48+ // all allocs interned here will be marked immutable.
49+ const MUH: Meh = Meh {
50+ //~^ ERROR it is undefined behavior to use this value
51+ //~| `UnsafeCell` in read-only memory
52+ x: &UnsafeCell::new(42),
53+ };
54+
55+ struct Synced {
56+ x: UnsafeCell<i32>,
57+ }
58+ unsafe impl Sync for Synced {}
59+
60+ // Make sure we also catch this behind a type-erased `dyn Trait` reference.
61+ const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
62+ //~^ ERROR: it is undefined behavior to use this value
63+ //~| `UnsafeCell` in read-only memory
64+
65+ // # Check for mutable references to read-only memory
66+
67+ static READONLY: i32 = 0;
68+ static mut MUT_TO_READONLY: &mut i32 = unsafe { &mut *(&READONLY as *const _ as *mut _) };
69+ //~^ ERROR: it is undefined behavior to use this value
70+ //~| pointing to read-only memory
71+
72+ // # Check for consts pointing to mutable memory
73+
74+ static mut MUTABLE: i32 = 42;
75+ const POINTS_TO_MUTABLE: &i32 = unsafe { &MUTABLE }; //~ERROR: undefined behavior
76+ //~| encountered reference to mutable memory
77+ static mut MUTABLE_REF: &mut i32 = &mut 42;
78+ const POINTS_TO_MUTABLE2: &i32 = unsafe { &*MUTABLE_REF };
79+ //~^ ERROR: evaluation of constant value failed
80+ //~| accesses mutable global memory
81+
82+ const POINTS_TO_MUTABLE_INNER: *const i32 = &mut 42 as *mut _ as *const _;
83+ //~^ ERROR: mutable pointer in final value
84+ //~| WARNING this was previously accepted by the compiler
85+
86+ const POINTS_TO_MUTABLE_INNER2: *const i32 = &mut 42 as *const _;
87+ //~^ ERROR: mutable pointer in final value
88+ //~| WARNING this was previously accepted by the compiler
89+
90+ const INTERIOR_MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
91+ //~^ ERROR: mutable pointer in final value
92+ //~| WARNING this was previously accepted by the compiler
93+
94+ struct SyncPtr<T> {
95+ x: *const T,
96+ }
97+ unsafe impl<T> Sync for SyncPtr<T> {}
98+
99+ // These pass the lifetime checks because of the "tail expression" / "outer scope" rule.
100+ // (This relies on `SyncPtr` being a curly brace struct.)
101+ // However, we intern the inner memory as read-only, so this must be rejected.
102+ // (Also see `static-no-inner-mut` for similar tests on `static`.)
103+ const RAW_SYNC: SyncPtr<AtomicI32> = SyncPtr { x: &AtomicI32::new(42) };
104+ //~^ ERROR mutable pointer in final value
105+ //~| WARNING this was previously accepted by the compiler
106+
107+ const RAW_MUT_CAST: SyncPtr<i32> = SyncPtr { x: &mut 42 as *mut _ as *const _ };
108+ //~^ ERROR mutable pointer in final value
109+ //~| WARNING this was previously accepted by the compiler
110+
111+ const RAW_MUT_COERCE: SyncPtr<i32> = SyncPtr { x: &mut 0 };
112+ //~^ ERROR mutable pointer in final value
113+ //~| WARNING this was previously accepted by the compiler
28114
29- static OH_YES: &mut i32 = &mut 42;
30- //~^ ERROR it is undefined behavior to use this value
31115
32116fn main() {
33117 unsafe {
0 commit comments