about summary refs log tree commit diff
path: root/src/tools/miri/tests/fail/tree_borrows/write-during-2phase.rs
blob: a2e8a533c43ad175a68dd79f069e7655e7679acc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//@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);
}