This code does not have UB under Stacked Borrows and Tree Borrows:
fn main() {
let mut data = 1;
let x = &mut data;
let mut y = &mut 2;
unsafe { std::ptr::copy_nonoverlapping(&raw const x, &raw mut y, 1); }
*x = 3;
*y = 4;
*x = 5;
*y = 6;
}
This is expected behavior. The copy_nonoverlapping makes y a perfect copy of x, those two just contain the same pointer. Mutable references are unique in the sense that no "other" pointer is allowed to be used while they are live -- but here, there's no "other" pointer, it's twice the same pointer.
Within the framework that SB and TB are built in, I don't see any way to avoid that. I don't think *x = 3 should mutate x itself, so it follows that x and y just are and remain the same pointer.
I am filing this issue mostly to remind us that when we move towards making decisions around the aliasing model, we should explicitly discuss this case. But maybe someone has an idea for how a model could make this UB?