Thank you for posting the link to my RFC.
The motivation for &out and &uninit is to create a safe way to create write-only contracts and to express uninitialized values. I don’t particularly like MaybeUninit, because it is unsafe, and it is already possible to do everything MaybeUninit does just using other unsafe code. Also I think MaybeUninit is trying to limit the usage of core::mem::uninitialized, which is wildly unsafe, and hard to use correctly.
Currently, there is no safe way to handle uninit, without overhead (of at least an Option), or to enforce a write-only contract, which is useful when interfacing certain hardware, as a powerful design tool, or as proof of intent. All of these are useful and important. I believe having a safe way to do this is a net positive for Rust.
This is something I love about Rust, but sometimes it is helpful to show intent in a compiler enforceable way, which &out could help with. Also &uninit can help build abstractions like the Placement New, and the box syntax as just library items with a little sugar, which I think is good.
Placement New (with Vec)
impl<T> Vec<T> {
fn emplace_back<F: FnOnce(&uninit T)>(&mut self, init: F) {
/// This code is taken from the Vec push implementation is the std lib
/// and adapted to use &uninit to show how it will be used for placement new
if self.len == self.buf.cap() {
self.reserve(1);
}
unsafe {
let end: &uninit T = &uninit *self.as_mut_ptr().add(self.len);
init(end); // this line has been changed for the purposes of placement new
self.len += 1;
}
}
}
and with some sugar, for placement new, this could be called like this
vec.emplace_back() <- value;
This implementation is panic safe because even if the function init panics, the uninit won’t be dropped by the Vec, because self.len hasn’t been incremented yet, so the uninit won’t be dropped. Also due to the rules around &uninit (that I laid out in the RFC), the function init is guaranteed to initialize the uninit if it doesn’t panic, so this implementation is safe.