Yes, only valid when it’s used. However, the user is not entirely in control of that, since enum layout optimization can convert accesses to a something else into an access of fields in your struct. So that would have to be exempted somehow.
Now I’ll try to make this more concrete by reimplementing “arrayvec” using the ideas in this thread.
The implementation is here (playground).
ArrayVector<[String; 8]>
is there really implemented as ArrayVector { array: [MaybeUninit<String>; 8], len: usize }
and I think that was what you wanted us to do. The “HKT” part of associating [T; 8] → [MaybeUninit<T>; 8]
seems to be no harder than what the existing code does for “generic” arrays.
My question is the part about initializing part of an array, lines 85-101. There is no expression that allows us to create [MaybeUninit<T>; N]
for arbitrary N
, so we do as usual, create an uninitialized value and write into part of it. Then reinterpret it as [MaybeUninit<T>; N]
. Is that valid? Is it an improvement over using mem::uninitialized()
on line 91 (indicated below)?
fn make_array<A, I>(iter: I) -> ArrayVector<A>
where A: ArrayExt<Item=I::Item>,
I: IntoIterator,
{
// Create an uninitialized array.
// This is an MaybeUninit<[MaybeUninit<T>; N]> where T is the element type (I::Item)
let mut array: MaybeUninit<A::RawArray> = MaybeUninit { empty: () }; /* LINE 91 */
let mut len = 0;
unsafe {
// write into the uninitialized space
for (element, slot) in iter.into_iter().zip(array.value.as_slice_mut()) {
ptr::write(slot, MaybeUninit { value: element });
len += 1;
}
ArrayVector {
array: array.value,
len: len,
}
}
}