How can/should I obtain a &[MaybeUninit<T>] from a &[T]?
Intuitively, I should be allowed to treat initialized memory as being possibly uninitialized, but intuition and unsafe do not always mix well... Since MaybeUninit<T> is guaranteed to have the same size and alignment as T, it should be safe to transmute a &[T] into a &[MaybeUninit<T>]?
Then again, the current implementation of MaybeUninit::new(val) does more than just transmuting, it adds a ManuallyDrop::new(val) wrapper. Does this mean that if I implemented slice_as_maybeuninit via transmuting, I'd run into problems with destructors not being run? Which is not unsafe, but still undesirable enough to restrict such a function to slices of data that implement Copy (i.e., which do not implement Drop).
To make my question(s) more precise:
fn slice_as_maybeuninit<'a, T>(s: &'a [T]) -> &'a [MaybeUninit<T>], if at all?fn slice_as_maybeuninit<'a, T: Copy>(s: &'a [T]) -> &'a [MaybeUninit<T>]? // note the T: Copy boundstd::mem::MaybeUninit not provide these operations for me?A transmutation from [T] to [MaybeUninit<T>] is completely safe. Docs on its layout:
MaybeUninit<T>is guaranteed to have the same size, alignment, and ABI asT:
You do however want to use from_raw_parts to construct the new slice instead of just transmute.
fn slice_as_maybeuninit<T>(s: &[T]) -> &[MaybeUninit<T>] {
unsafe { std::slice::from_raw_parts(s.as_ptr() as *const MaybeUninit<T>, s.len()) }
}
[Will I] run into problems with destructors not being run?
No. In other circumstances you could, MaybeUninit relaxes the initialization criteria so it won't drop its contents since it alone doesn't know if its contents are initialized. However, you are only transmuting a &[T] which is only a reference to the contents; so it won't try to drop values anyway.
Copy is not necessary since no values of T are being created.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With