//@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); }