Aside from completeness, is there any reason for an &uninit pointer according to this scheme?
Actually, thinking about this a bit more, I think &uninit would often be more useful than &in. Consider a read function that doesn’t require passing it initialized data to be written-over. We can make it take either an &unint or an &in.
fn read_uninit(buffer: &uninit [u8]) -> io::Result<(&out [u8], &uninit [u8])>;
fn read_in(buffer: &in [u8]) -> io::Result<(&mut [u8], &in [u8])>;
It has to return the written and the still-uninitialized data as two seperate slices. read_uninit we could use like this:
let foo() -> io::Result<()> {
let buffer: [u8; 1024];
let (x, _) = read_uninit(&uninit buffer[..])?;
println!("got {:x}", x);
drop(*x);
Ok(())
}
Presumably we wouldn’t even need the drop(*x) because the compiler could automatically add drops for any &out pointers that haven’t been moved out of yet at the end of a function. The read_in version would be harder to use though.
fn foo() -> io::Result<()> {
let buffer: [u8; 1024];
let (x, y) = read_in(&in buffer[..])?;
println!("got {:x}", x);
// What do we do here?
Ok(())
}
In this version we’re left with a &mut pointer that we can’t move out of and an &in pointer that we’d obliged to write something to before we can drop it. So we end up having to initialize the rest of the buffer anyway before the end of the function so that it can be clearly in either an entirely-initialized or entirely-uninitialized state.