diff --git a/src/stacked_borrows.rs b/src/stacked_borrows.rs index 250def0c7ce6..bac35796ed13 100644 --- a/src/stacked_borrows.rs +++ b/src/stacked_borrows.rs @@ -625,6 +625,11 @@ trait EvalContextPrivExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, }; // Reborrow. + // TODO: With `two_phase == true`, this performs a weak reborrow for a `Unique`. That + // can lead to some possibly surprising effects, if the parent permission is + // `SharedReadWrite` then we now have a `Unique` in the middle of them, which "splits" + // them in terms of what remains valid when the `Unique` gets used. Is that really + // what we want? this.reborrow(place, size, kind, new_tag, /*force_weak:*/ two_phase, protect)?; let new_place = place.replace_tag(new_tag); // Handle two-phase borrows. diff --git a/tests/compile-fail/stacked_borrows/illegal_read7.rs b/tests/compile-fail/stacked_borrows/illegal_read7.rs new file mode 100644 index 000000000000..25d0878c0455 --- /dev/null +++ b/tests/compile-fail/stacked_borrows/illegal_read7.rs @@ -0,0 +1,20 @@ +// Creating a shared reference does not leak the data to raw pointers, +// not even when interior mutability is involved. + +use std::cell::Cell; +use std::ptr; + +fn main() { unsafe { + let x = &mut Cell::new(0); + let raw = x as *mut Cell; + let x = &mut *raw; + let _shr = &*x; + // The state here is interesting because the top of the stack is [Unique, SharedReadWrite], + // just like if we had done `x as *mut _`. + // If we said that reading from a lower item is fine if the top item is `SharedReadWrite` + // (one way to maybe preserve a stack discipline), then we could now read from `raw` + // without invalidating `x`. That would be bad! It would mean that creating `shr` + // leaked `x` to `raw`. + let _val = ptr::read(raw); + let _val = *x.get_mut(); //~ ERROR borrow stack +} }