This would be allowed with slice::from_raw_parts, as that one is more explicit about its interaction with reinterpreting memory.
I think the correct interpretation is that the Vec::from_raw_parts documentation itself does not allow this. However, given the guarantees provided for Vec's structure/layout, I think this is effectively guaranteed to work.
The tricky part, ofc, is that while Vec<[u8; 2]> -> Vec<u8> is rather simple (half element size, double capacity and length), the reverse direction is a lot harder, as you have to ensure that the capacity evenly divides into the new type.
(And just a reminder for readers: alignment must stay the same when owning an allocation, and may not be changed in any way.)
it is safe to transmute from a &'lt mut [T; orig_len] to a &'lt mut [U; new_len]
this implies, for instance, that mem::size_of::<T>() * orig_len must be ≥ mem::size_of::<U>() * new_len
Nitpick
The above is not completely accurate; while that is sufficient (for the from_raw_parts) to be sound,
the necessary looser bound for this second property is that:
it is safe to transmute:
from &'lt mut ReprC<[T; orig_len], [MU<T>; orig_cap - orig_len]>
to &'lt mut [U; new_len]
Where:
use ::core::mem::MaybeUninit as MU; and
#[repr(C)] struct ReprC<_0, _1>(_0, _1);
(An interesting thing here, is that this second property is always trivially met when new_len = 0...)
Since T = [u8; 2], U = u8 ≅ [u8; 1] and new_{len,cap} = 2 * orig_{len,cap} satisfy these two properties, the operation is sound.