2018-10-19 11:38:23 -05:00
|
|
|
// The compiler inserts some reborrows, enable optimizations to
|
|
|
|
// get rid of them.
|
|
|
|
// compile-flags: -Zmir-opt-level=1
|
|
|
|
|
|
|
|
use std::mem;
|
|
|
|
|
|
|
|
// This is an example of a piece of code that intuitively seems like we might
|
|
|
|
// want to reject it, but that doesn't turn out to be possible.
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
let target = 42;
|
|
|
|
// Make sure a cannot use a raw-tagged `&mut` pointing to a frozen location, not
|
|
|
|
// even to create a raw.
|
2018-10-30 04:41:01 -05:00
|
|
|
let reference = ⌖ // freeze
|
|
|
|
let ptr = reference as *const _ as *mut i32; // raw ptr, with raw tag
|
2018-10-19 11:38:23 -05:00
|
|
|
let mut_ref: &mut i32 = unsafe { mem::transmute(ptr) }; // &mut, with raw tag
|
|
|
|
// Now we have an &mut to a frozen location, but that is completely normal:
|
|
|
|
// We'd just unfreeze the location if we used it.
|
|
|
|
let bad_ptr = mut_ref as *mut i32; // even just creating this is like a use of `mut_ref`.
|
|
|
|
// That violates the location being frozen! However, we do not properly detect this:
|
|
|
|
// We first see a `&mut` with a `Raw` tag being deref'd for a frozen location,
|
|
|
|
// which can happen legitimately if the compiler optimized away an `&mut*` that
|
|
|
|
// turns a raw into a `&mut`. Next, we create a raw ref to a frozen location
|
|
|
|
// from a `Raw` tag, which can happen legitimately when interior mutability
|
|
|
|
// is involved.
|
2018-10-30 04:41:01 -05:00
|
|
|
let _val = *reference; // Make sure it is still frozen.
|
2018-10-19 11:38:23 -05:00
|
|
|
|
|
|
|
// We only actually unfreeze once we muteate through the bad pointer.
|
2018-10-22 11:01:32 -05:00
|
|
|
unsafe { *bad_ptr = 42 }; //~ ERROR does not exist on the stack
|
2018-10-30 04:41:01 -05:00
|
|
|
let _val = *reference;
|
2018-10-19 11:38:23 -05:00
|
|
|
}
|