The issue is that you can't mix &mut
and *mut
the way you are.
Disclaimer: miri is not exact -- it may miss actual UB -- and the borrowing model it enforces is not neccesarily the exact superset of safe Rust's that is (will be?) required of unsafe
code (though it is quite likely that it's close).
If I'm not mistaken, your code exhibits UB even when you inline fn point_me_to
, it's just miri's nonexact checking that causes it to miss the UB in that case.
Desugaring a little should help make this clearer:
fn make_proxy(&mut self) -> Proxy<'_> {
let ref_s = &mut self.s;
let ptr_s = point_me_to(&mut *ref_s);
Proxy {
ref_a: S::gimme_an_a(&mut *ref_s),
ptr_s,
}
}
The underlying issue is that &mut S
is a unique reference to the entirety of S
. When you use it, that invalidates any raw references derived from it, which includes ptr_s
, meaning they can no longer be used soundly.
I believe miri misses the UB when you inline point_me_to
because that eliminates the reborrow involved in calling it, but misses that the reborrow to call S::gimme_an_a
invalidates the pointer due to inexact tracking.
Without seeing larger context, I believe the solution for your BTreeMap
is just to use *mut
more and stop trying to mix &mut
and *mut
to the same "allocated object".