2021-01-03 12:46:20 -06:00
|
|
|
#![feature(const_mut_refs)]
|
|
|
|
#![feature(const_fn)]
|
2021-01-23 05:58:58 -06:00
|
|
|
#![feature(const_transmute)]
|
2021-01-03 12:46:20 -06:00
|
|
|
#![feature(raw_ref_op)]
|
2021-01-23 05:58:58 -06:00
|
|
|
#![feature(const_raw_ptr_deref)]
|
|
|
|
|
2021-01-03 12:46:20 -06:00
|
|
|
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
|
|
|
|
|
2021-01-23 05:58:58 -06:00
|
|
|
// 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
|
|
|
|
|
2021-01-16 11:31:22 -06:00
|
|
|
// Ok, because no references to mutable data exist here, since the `{}` moves
|
|
|
|
// its value and then takes a reference to that.
|
2021-01-03 12:46:20 -06:00
|
|
|
const C: *const i32 = &{
|
|
|
|
let mut x = 42;
|
|
|
|
x += 3;
|
|
|
|
x
|
|
|
|
};
|
|
|
|
|
2021-01-23 05:58:58 -06:00
|
|
|
use std::cell::UnsafeCell;
|
|
|
|
struct NotAMutex<T>(UnsafeCell<T>);
|
|
|
|
|
|
|
|
unsafe impl<T> Sync for NotAMutex<T> {}
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
2021-01-03 12:46:20 -06:00
|
|
|
fn main() {
|
|
|
|
println!("{}", unsafe { *A });
|
|
|
|
unsafe { *B = 4 } // Bad news
|
2021-01-23 05:58:58 -06:00
|
|
|
|
|
|
|
unsafe {
|
|
|
|
**FOO.0.get() = 99;
|
|
|
|
assert_eq!(**FOO.0.get(), 99);
|
|
|
|
}
|
2021-01-03 12:46:20 -06:00
|
|
|
}
|