#![feature(const_mut_refs)] #![feature(const_fn)] #![feature(const_transmute)] #![feature(raw_ref_op)] #![feature(const_raw_ptr_deref)] const NULL: *mut i32 = std::ptr::null_mut(); const A: *const i32 = &4; // It could be made sound to allow it to compile, // but we do not want to allow this to compile, // as that would be an enormous footgun in oli-obk's opinion. const B: *mut i32 = &mut 4; //~ ERROR mutable references are not allowed // Ok, no actual mutable allocation exists const B2: Option<&mut i32> = None; // Not ok, can't prove that no mutable allocation ends up in final value const B3: Option<&mut i32> = Some(&mut 42); //~ ERROR temporary value dropped while borrowed const fn helper() -> Option<&'static mut i32> { unsafe { // Undefined behaviour, who doesn't love tests like this. // This code never gets executed, because the static checks fail before that. Some(&mut *(42 as *mut i32)) } } // Check that we do not look into function bodies. // We treat all functions as not returning a mutable reference, because there is no way to // do that without causing the borrow checker to complain (see the B5/helper2 test below). const B4: Option<&mut i32> = helper(); const fn helper2(x: &mut i32) -> Option<&mut i32> { Some(x) } const B5: Option<&mut i32> = helper2(&mut 42); //~ ERROR temporary value dropped while borrowed // Ok, because no references to mutable data exist here, since the `{}` moves // its value and then takes a reference to that. const C: *const i32 = &{ let mut x = 42; x += 3; x }; use std::cell::UnsafeCell; struct NotAMutex(UnsafeCell); unsafe impl Sync for NotAMutex {} const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); //~^ ERROR temporary value dropped while borrowed static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); //~^ ERROR temporary value dropped while borrowed static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); //~^ ERROR temporary value dropped while borrowed // `BAR` works, because `&42` promotes immediately instead of relying on // the enclosing scope rule. const BAR: NotAMutex<&i32> = NotAMutex(UnsafeCell::new(&42)); fn main() { println!("{}", unsafe { *A }); unsafe { *B = 4 } // Bad news unsafe { **FOO.0.get() = 99; assert_eq!(**FOO.0.get(), 99); } }