Description
Consider this function:
pub fn f(xr : &mut Cell<i32>) -> i32 {
*xr = Cell::new(-1);
shouldnt_escape(&mut *xr);
*xr = Cell::new(1337); // the write should invalidate all children
do_something();
xr.get() // ...so the compiler should be able to optimize
// this to return 1337
}
If this was an &mut i32
reference, then the *xr = ...
assignment would invalidate all child references and hence we could rely on do_something
not being able to use anything derived from the reference passed to shouldnt_escape
.
But it turns out under current Tree Borrows rules, that optimization would be wrong, as demonstrated by this example (due to @JoJoDeveloping).
The reason this works is that two-phase mutable references to !Freeze
types in their reservation stage accept foreign write accesses. This is necessary to make code like this (entirely safe code!) not UB.
This is probably undesirable. But I am not sure what the best way is to make the safe code example allowed but make the counterexample for the optimization above have UB.