diff --git a/src/stacked_borrows.rs b/src/stacked_borrows.rs index b088a6e845f5..3cf4365e35aa 100644 --- a/src/stacked_borrows.rs +++ b/src/stacked_borrows.rs @@ -661,14 +661,14 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> { // Primitives of reference type, that is the one thing we are interested in. fn visit_primitive(&mut self, place: MPlaceTy<'tcx, Borrow>) -> EvalResult<'tcx> { - match place.layout.ty.sty { - ty::Ref(_, _, mutbl) => { - let val = self.ecx.read_immediate(place.into())?; - let val = self.ecx.retag_reference(val, mutbl)?; - self.ecx.write_immediate(val, place.into())?; - } - _ => {}, // nothing to do - } + let mutbl = match place.layout.ty.sty { + ty::Ref(_, _, mutbl) => mutbl, + ty::Adt(..) if place.layout.ty.is_box() => MutMutable, + _ => return Ok(()), // nothing to do + }; + let val = self.ecx.read_immediate(place.into())?; + let val = self.ecx.retag_reference(val, mutbl)?; + self.ecx.write_immediate(val, place.into())?; Ok(()) } } diff --git a/tests/compile-fail-fullmir/stacked_borrows/box_exclusive_violation1.rs b/tests/compile-fail-fullmir/stacked_borrows/box_exclusive_violation1.rs new file mode 100644 index 000000000000..73631173b932 --- /dev/null +++ b/tests/compile-fail-fullmir/stacked_borrows/box_exclusive_violation1.rs @@ -0,0 +1,29 @@ +fn demo_mut_advanced_unique(mut our: Box) -> i32 { + unknown_code_1(&*our); + + // This "re-asserts" uniqueness of the reference: After writing, we know + // our tag is at the top of the stack. + *our = 5; + + unknown_code_2(); + + // We know this will return 5 + *our //~ ERROR does not exist on the stack +} + +// Now comes the evil context +use std::ptr; + +static mut LEAK: *mut i32 = ptr::null_mut(); + +fn unknown_code_1(x: &i32) { unsafe { + LEAK = x as *const _ as *mut _; +} } + +fn unknown_code_2() { unsafe { + *LEAK = 7; +} } + +fn main() { + assert_eq!(demo_mut_advanced_unique(Box::new(0)), 5); +}