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