Why not just reborrow as a &mut when you need to guarantee anyways that all it's invariants are upheld (uniqueness and non-null). It makes it very clear that what you assume is, that it is safe to use this mutable raw pointer as a mutable reference.
fn main() {
let mut x = Foo(0);
let x_ptr = &raw mut x;
// Safety: x_ptr is the only thing pointing to x and it is not null.
Foo::foo(unsafe{&mut *x_ptr});
}
&mut T and *mut T are intended to be fully ABI compatible. Also, your code passes Miri. So I'd expect it to be OK. That said, do you really need to do a transmute? If you just need to pass fn(&mut T) where fn(*mut T) is expected, you could always write a simple ad-hoc closure
The linked playground is simplified. In fact I was implementing sort of vtable mechanism, which requires to cast some safe function pointer types to their "looser" version (with lifetime or even type erased). But I'm not quite sure if this would cause UB.
IIRC, the answer is "maybe". I did a very similar thing myself, and I believe the answer was that while it isn't guaranteed to be the same, it works, and is very unlikely to ever change.
It's probably clear, but just for completeness since most of the answers focused on the specific aspect of calling a function through a different signature. There are 3 possible ways to get UB when transmuting from fn(&mut T) to fn(*mut T):
The transmute itself. But in this case, there's no UB (same validity invariant).
Calling an fn(&mut T) through a fn(*mut T). That's what was focused on in this thread. Not a problem either (ABI compatible).
Exposing the transmuted value outside the scope of unsafe (the safe abstraction around the transmute). When transmuting to a safe type, you must make sure that either the value is within the safety invariant of that type (it's not the case here since the safety invariant of fn(*mut T) is much smaller than fn(&mut T) because the safety invariant of &mut T is much smaller than *mut T and by contra-variance of function arguments[1]) or that this value is only used within the scope of unsafe (here making sure it's always called with a *mut T that satisfies the safety invariant of &mut T[2]). Alternatively you could transmute to unsafe fn(*mut T) and document the pre-condition if you need to expose the result of transmute to your public API.
Actually that's not the only reason, calling a function through a different signature transmutes all arguments so you must also make sure your *mut T is actually valid for &mut T (not only safe[2:1]). ↩︎
Note that the *mut T being safe for &mut T is not strictly necessary if the initial function is robust. Only the validity is really required. ↩︎↩︎