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 T
s, 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