It's not as painless as it could be though, because many of the MaybeUninit<T> -> T conversion fns are unstable. Eg the code in TFA needs `&mut [MaybeUninit<T>] -> &mut [T]` but `[T]::assume_init_mut()` is unstable. But reimplementing them is just a matter of copying the libstd impl, that in turn is usually just a straightforward reinterpret-cast one-liner.
There are two actual differences in this regard: C pointers are more ergonomic than Rust pointers. And Rust has an additional feature called references, which enable a lot more aggressive compiler optimizations, but which have the restriction that you can’t have a reference to uninitialized memory.
let mut data = Vec::with_capacity(sz);
unsafe { data.set_len(sz) };
buf.copy_to_slice(data.as_mut_slice());
is UB?It’s strictly more complicated and slower than the obvious thing to do and only exists to satisfy the abstract machine.
let mut data = Vec::with_capacity(sz);
let mut dst_uninit = data.spare_capacity_mut();
let uninit_src: &[MaybeUninit<T>] = unsafe { transmute(buf) };
dst_uninit.copy_from_slice(uninit_src);
unsafe { data.set_len(sz) };UB is weird and valgrind is not a tool for detecting UB. For that you want Miri or UBSAN. Valgrind’s equivalent is ASAN and MSAN which catch UB issues incidentally in some rare cases and not necessarily where the UB actually happened.
Currently, the team is leaning in the direction of not requiring recursive validity for references. This would mean your code is not language UB as long as you can assume `set_len` and `copy_to_slice` never read from 'data`. However, it's still considered library UB, as this assumption is not documented or specified anywhere and is not guaranteed -- changes to safe code in your program or in the standard library can turn this into language UB, so by doing something like this you're writing fragile code that gives up a lot of Rust's safety by design.
let mut data = Vec::with_capacity(sz);
data.extend(&buf[..sz]);
Vec::extend extends a container from an iterable. A Vec/slice is iterable.And from the doc:
> This implementation is specialized for slice iterators, where it uses copy_from_slice to append the entire slice at once.
Of course this trivial example could also be written as:
let mut data = buf.clone();