Closed
Description
Stacked Borrows does per-location tracking of whether something has interior mutability. This means if the discriminant is stored on the same location as an UnsafeCell
, it can surprisingly change:
/// Sets `x` to `None`.
fn evil<T>(x: &Option<Cell<&T>>) {
assert_eq!(
mem::size_of_val(x), mem::size_of_val(x.as_ref().unwrap()),
"layout optimization did not kick in?",
);
unsafe { *(x as *const _ as *mut usize) = 0; }
}
fn main() {
let my = Some(Cell::new(&0));
evil(&my);
dbg!(my);
}
This passes in Miri and prints "None".
Note that right now, this would pass in Miri even with no enum layout optimizations as I simplified the handling of interior mutability (see rust-lang/miri#931). The old, more precise handling was a total mess and basically impossible to reason about. But even the most precise handling I can imagine would still allow the code above.