Consider the following two functions:
unsafe fn f1(a: &mut u32) {
let ptr1: *mut u32 = std::mem::transmute(a);
*a = 1;
}
unsafe fn f2(a: &mut u32) {
let ptr1: *mut u32 = a;
*a = 1;
}
With current Rust, the first gives a borrowck error, the second doesn’t. The behavior of transmute is easy to understand: it consumes the reference, so future uses will go through the pointer instead. The conversion, on the other hand, is like transmute_copy: it gives you a pointer, but the original reference is still valid. This seems ridiculous: why does the simpler version default to behavior equivalent to transmute_copy?
If we changed the borrow checker to treat f1 and f2 the same way, it would make split-at-mut-via-duplication from http://smallcultfollowing.com/babysteps/blog/2016/05/27/the-tootsie-pop-model-for-unsafe-code/ simply illegal, so nobody could make a mistake like that.
If you actually want the old behavior, you could still write let ptr1 : *mut u32 = &mut *a;
.
Has something like this been discussed before?