pub unsafe fn mark_initialized<T, const N: usize>(
src: [MaybeUninit<T>; N],
) -> [T; N]Expand description
Convert a [MaybeUninit<T>; N] to a [T; N]
let mut buffer = uninit_buf::<i32, 1000>();
for elem in &mut buffer {
elem.write(123);
}
let result = unsafe { mark_initialized(buffer) };
assert_eq!(result, [123; 1000])This largely acts as a workaround to the fact that core::mem::transmute cannot be used with
const generic arrays, as it can’t prove they have the same size (even when intuitively they are
the same, e.g. [i32; N] and [u32; N]).
This is similar to the nightly-only core::mem::MaybeUninit::array_assume_init
§Safety
Internally, this uses core::mem::transmute_copy to convert a [MaybeUninit<T>; N] to [T; N].
As such, you must make sure every element has been initialized before calling this function. If
there are uninitialized elements in src, these will be converted to Ts, which is UB. For
example:
// ⚠️ This example produces UB ⚠️
let bools = uninit_buf::<bool, 10>();
let uh_oh = unsafe { mark_initialized(bools) }; // UB: creating an invalid instance
if uh_oh[0] { // double UB: reading from unintiailized memory
// ...
}Even if you never use a value, it’s still UB. This is especially true for types with
core::ops::Drop implementations:
// ⚠️ This example produces UB ⚠️
let strings = uninit_buf::<String, 10>();
let uh_oh = unsafe { mark_initialized(strings) }; // UB: creating an invalid instance
// uh_oh is dropped here, freeing memory at random addresses