]>
Commit | Line | Data |
---|---|---|
5869c6ff | 1 | #![feature(const_mut_refs)] |
5869c6ff | 2 | #![feature(raw_ref_op)] |
5869c6ff XL |
3 | |
4 | const NULL: *mut i32 = std::ptr::null_mut(); | |
5 | const A: *const i32 = &4; | |
6 | ||
7 | // It could be made sound to allow it to compile, | |
8 | // but we do not want to allow this to compile, | |
9 | // as that would be an enormous footgun in oli-obk's opinion. | |
10 | const B: *mut i32 = &mut 4; //~ ERROR mutable references are not allowed | |
11 | ||
12 | // Ok, no actual mutable allocation exists | |
13 | const B2: Option<&mut i32> = None; | |
14 | ||
15 | // Not ok, can't prove that no mutable allocation ends up in final value | |
16 | const B3: Option<&mut i32> = Some(&mut 42); //~ ERROR temporary value dropped while borrowed | |
17 | ||
18 | const fn helper(x: &mut i32) -> Option<&mut i32> { Some(x) } | |
19 | const B4: Option<&mut i32> = helper(&mut 42); //~ ERROR temporary value dropped while borrowed | |
20 | ||
21 | // Ok, because no references to mutable data exist here, since the `{}` moves | |
22 | // its value and then takes a reference to that. | |
23 | const C: *const i32 = &{ | |
24 | let mut x = 42; | |
25 | x += 3; | |
26 | x | |
27 | }; | |
28 | ||
29 | use std::cell::UnsafeCell; | |
30 | struct NotAMutex<T>(UnsafeCell<T>); | |
31 | ||
32 | unsafe impl<T> Sync for NotAMutex<T> {} | |
33 | ||
34 | const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | |
35 | //~^ ERROR temporary value dropped while borrowed | |
36 | ||
37 | static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | |
38 | //~^ ERROR temporary value dropped while borrowed | |
39 | ||
40 | static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); | |
41 | //~^ ERROR temporary value dropped while borrowed | |
42 | ||
43 | // `BAR` works, because `&42` promotes immediately instead of relying on | |
44 | // the enclosing scope rule. | |
45 | const BAR: NotAMutex<&i32> = NotAMutex(UnsafeCell::new(&42)); | |
46 | ||
47 | fn main() { | |
48 | println!("{}", unsafe { *A }); | |
49 | unsafe { *B = 4 } // Bad news | |
50 | ||
51 | unsafe { | |
52 | **FOO.0.get() = 99; | |
53 | assert_eq!(**FOO.0.get(), 99); | |
54 | } | |
55 | } |