blob: a2e8a533c43ad175a68dd79f069e7655e7679acc [file] [log] [blame]
//@compile-flags: -Zmiri-tree-borrows
// We invalidate a reference during a 2-phase borrow by doing a Foreign
// Write in between the initial reborrow and function entry. UB occurs
// on function entry when reborrow from a Disabled fails.
// This test would pass under Stacked Borrows, but Tree Borrows
// is more strict on 2-phase borrows.
struct Foo(u64);
impl Foo {
fn add(&mut self, n: u64) -> u64 {
//~^ ERROR: /reborrow through .* is forbidden/
self.0 + n
}
}
pub fn main() {
let mut f = Foo(0);
let alias = &mut f.0 as *mut u64;
let res = f.add(unsafe {
// This is the access at fault, but it's not immediately apparent because
// the reference that got invalidated is not under a Protector.
*alias = 42;
0
});
// `res` could be optimized to be `0`, since at the time the reference for the `self` argument
// is created, it has value `0`, and then later we add `0` to that. But turns out there is
// a sneaky alias that's used to change the value of `*self` before it is read...
assert_eq!(res, 42);
}