I want to write code that looks like the following:
pub fn drop_in_place_static<T>(r: &'static mut T) -> &'static mut MaybeUninit<T> {
// Safety: r: 'static, so nobody else can ever use this reference again,
// except through r2 (which assumes only that the referenced memory is a
// `MaybeUninit<T>`), and all valid `T` are also valid `MaybeUninit<T>`.
let r2: &'static mut MaybeUninit<T> = unsafe { core::mem::transmute(r) };
// Safety: `r2` was transmuted from a reference to a `T`, so must be initialized.
unsafe { r2.assume_init_drop(); }
*r2 = MaybeUninit::uninit();
r2
}
I was under the impression (I think from a mis-remembered #524) that this was already something that was guaranteed to be sound (on the basis that you can change the memory referenced by a &mut T arbitrarily as long as you leave a valid T in the memory by the time the reference's lifetime ends, and an &'static mut T's lifetime never ends so you can just change the memory arbitrarily forever), but trying to find where the guarantee was actually made, I couldn't find it.
Instead, I found #84, which is a bit concerning for code like this because some of the potential solutions to #84 would consider code like this to be undefined behavior (although, as far as I can tell, the solution currently under discussion doesn't).
Note that (as this is intended to be a safe API that's sound for arbitrary safe code to use) I'm concerned that restricting this to types T that have no niche might not be sufficient, because Rust has APIs that convert references to niched types to references to the entire non-niched memory containing them (such as Cell::from_mut), so it is possible that a reference might have a non-niched type even if references an enum field whose niche is being used to store a discriminant. I didn't find any such APIs that return mutable references, but it seems plausible that one might be added (or already exist).
My question is: has there actually been / could there be a commitment made that such code is sound (in the sense that choosing a solution to #84 that makes it unsound would be considered a breaking change)? Or is this something which is still subject to change, and thus should be avoided at present?
(I have two main motivations for wanting this function. One is to make sound code easier to write: I'm trying to produce a set of safe wrappers for unsafe primitives that can be used to write certain sorts of low-level code without needing further unsafe, meaning that the compiler could prove it to be sound as long as the primitives were sound, and this one is one of the more useful ones. The other is for optimization purposes: writing the equivalent of this using raw pointers instead misses a huge number of optimizations, whereas using references instead gives the compiler more aliasing information and this leads to better-optimized code as a consequence.)
I want to write code that looks like the following:
I was under the impression (I think from a mis-remembered #524) that this was already something that was guaranteed to be sound (on the basis that you can change the memory referenced by a
&mut Tarbitrarily as long as you leave a validTin the memory by the time the reference's lifetime ends, and an&'static mut T's lifetime never ends so you can just change the memory arbitrarily forever), but trying to find where the guarantee was actually made, I couldn't find it.Instead, I found #84, which is a bit concerning for code like this because some of the potential solutions to #84 would consider code like this to be undefined behavior (although, as far as I can tell, the solution currently under discussion doesn't).
Note that (as this is intended to be a safe API that's sound for arbitrary safe code to use) I'm concerned that restricting this to types
Tthat have no niche might not be sufficient, because Rust has APIs that convert references to niched types to references to the entire non-niched memory containing them (such asCell::from_mut), so it is possible that a reference might have a non-niched type even if references anenumfield whose niche is being used to store a discriminant. I didn't find any such APIs that return mutable references, but it seems plausible that one might be added (or already exist).My question is: has there actually been / could there be a commitment made that such code is sound (in the sense that choosing a solution to #84 that makes it unsound would be considered a breaking change)? Or is this something which is still subject to change, and thus should be avoided at present?
(I have two main motivations for wanting this function. One is to make sound code easier to write: I'm trying to produce a set of safe wrappers for unsafe primitives that can be used to write certain sorts of low-level code without needing further
unsafe, meaning that the compiler could prove it to be sound as long as the primitives were sound, and this one is one of the more useful ones. The other is for optimization purposes: writing the equivalent of this using raw pointers instead misses a huge number of optimizations, whereas using references instead gives the compiler more aliasing information and this leads to better-optimized code as a consequence.)