2
2
//@ normalize-stderr-test: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)"
3
3
//@ normalize-stderr-test: "([0-9a-f][0-9a-f] |╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼ )+ *│.*" -> "HEX_DUMP"
4
4
5
+ #![ allow( static_mut_refs) ]
5
6
#![ deny( const_eval_mutable_ptr_in_final_value) ]
6
7
use std:: cell:: UnsafeCell ;
8
+ use std:: sync:: atomic:: * ;
9
+
10
+ // # Plain `&mut` in the final value
7
11
8
12
// This requires walking nested statics.
9
13
static FOO : & & mut u32 = & & mut 42 ;
10
14
//~^ 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
12
19
static BAR : & mut ( ) = & mut ( ) ;
13
20
//~^ ERROR encountered mutable pointer in final value of static
14
21
//~| WARNING this was previously accepted by the compiler
@@ -19,15 +26,92 @@ static BOO: &mut Foo<()> = &mut Foo(());
19
26
//~^ ERROR encountered mutable pointer in final value of static
20
27
//~| WARNING this was previously accepted by the compiler
21
28
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
+
22
39
struct Meh {
23
40
x : & ' static UnsafeCell < i32 > ,
24
41
}
25
42
unsafe impl Sync for Meh { }
26
43
static MEH : Meh = Meh { x : & UnsafeCell :: new ( 42 ) } ;
27
44
//~^ 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
28
114
29
- static OH_YES : & mut i32 = & mut 42 ;
30
- //~^ ERROR it is undefined behavior to use this value
31
115
32
116
fn main ( ) {
33
117
unsafe {
0 commit comments