1
1
#![ feature( const_mut_refs) ]
2
2
#![ feature( const_fn) ]
3
+ #![ feature( const_transmute) ]
3
4
#![ feature( raw_ref_op) ]
5
+ #![ feature( const_raw_ptr_deref) ]
6
+
4
7
const NULL : * mut i32 = std:: ptr:: null_mut ( ) ;
5
8
const A : * const i32 = & 4 ;
6
9
@@ -9,6 +12,25 @@ const A: *const i32 = &4;
9
12
// as that would be an enormous footgun in oli-obk's opinion.
10
13
const B : * mut i32 = & mut 4 ; //~ ERROR mutable references are not allowed
11
14
15
+ // Ok, no actual mutable allocation exists
16
+ const B2 : Option < & mut i32 > = None ;
17
+
18
+ // Not ok, can't prove that no mutable allocation ends up in final value
19
+ const B3 : Option < & mut i32 > = Some ( & mut 42 ) ; //~ ERROR temporary value dropped while borrowed
20
+
21
+ const fn helper ( ) -> Option < & ' static mut i32 > { unsafe {
22
+ // Undefined behaviour, who doesn't love tests like this.
23
+ // This code never gets executed, because the static checks fail before that.
24
+ Some ( & mut * ( 42 as * mut i32 ) )
25
+ } }
26
+ // Check that we do not look into function bodies.
27
+ // We treat all functions as not returning a mutable reference, because there is no way to
28
+ // do that without causing the borrow checker to complain (see the B5/helper2 test below).
29
+ const B4 : Option < & mut i32 > = helper ( ) ;
30
+
31
+ const fn helper2 ( x : & mut i32 ) -> Option < & mut i32 > { Some ( x) }
32
+ const B5 : Option < & mut i32 > = helper2 ( & mut 42 ) ; //~ ERROR temporary value dropped while borrowed
33
+
12
34
// Ok, because no references to mutable data exist here, since the `{}` moves
13
35
// its value and then takes a reference to that.
14
36
const C : * const i32 = & {
@@ -17,7 +39,30 @@ const C: *const i32 = &{
17
39
x
18
40
} ;
19
41
42
+ use std:: cell:: UnsafeCell ;
43
+ struct NotAMutex < T > ( UnsafeCell < T > ) ;
44
+
45
+ unsafe impl < T > Sync for NotAMutex < T > { }
46
+
47
+ const FOO : NotAMutex < & mut i32 > = NotAMutex ( UnsafeCell :: new ( & mut 42 ) ) ;
48
+ //~^ ERROR temporary value dropped while borrowed
49
+
50
+ static FOO2 : NotAMutex < & mut i32 > = NotAMutex ( UnsafeCell :: new ( & mut 42 ) ) ;
51
+ //~^ ERROR temporary value dropped while borrowed
52
+
53
+ static mut FOO3 : NotAMutex < & mut i32 > = NotAMutex ( UnsafeCell :: new ( & mut 42 ) ) ;
54
+ //~^ ERROR temporary value dropped while borrowed
55
+
56
+ // `BAR` works, because `&42` promotes immediately instead of relying on
57
+ // the enclosing scope rule.
58
+ const BAR : NotAMutex < & i32 > = NotAMutex ( UnsafeCell :: new ( & 42 ) ) ;
59
+
20
60
fn main ( ) {
21
61
println ! ( "{}" , unsafe { * A } ) ;
22
62
unsafe { * B = 4 } // Bad news
63
+
64
+ unsafe {
65
+ * * FOO . 0 . get ( ) = 99 ;
66
+ assert_eq ! ( * * FOO . 0 . get( ) , 99 ) ;
67
+ }
23
68
}
0 commit comments