3 ms·
The article says > A mutable reference must also never point to an invalid object, so doing let role = &mut *uninit.as_mut_ptr() if that object is not fully in
by mkeeter 5y ago
The article says
> A mutable reference must also never point to an invalid object, so doing let role = &mut *uninit.as_mut_ptr() if that object is not fully initialized is also wrong.
I'm curious who's right here, because I've seen your pattern in code recently!
- steveklabnik 5y agoThe docs for as_mut_ptr: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.as_mut_ptr https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.h... > Incorrect usage of this method: let mut x = MaybeUninit::<Vec<u32>>::uninit(); let x_vec = unsafe { &mut *x.as_mut_ptr() }; // We have created a reference to an uninitialized vector! This is undefined behavior. Also, above, it explicitly describes the intended API for partially initializing a struct: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#initializing-a-struct-field-by-field https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.h...
- mkeeter 5y agoThanks Steve! It turns out I had misremembered; the cast I was thinking of is https://github.com/oxidecomputer/hubris/blob/master/sys/kern/src/startup.rs#L131-L134 https://github.com/oxidecomputer/hubris/blob/master/sys/kern... from &mut MaybeUninit<[T]> to &mut [MaybeUninit<T>], which doesn't construct a reference to something uninitialized.
- remram 5y agoAren't all the `(*role)` in their code "mutable references" too? (*role).name = "basic";
- nickitolas 5y agoNo, this is specifically not creating a mutable reference. So it's fine except for the fact that writing via assignment like this calls the destructor/drop for the old value, if the type has a Drop implementation. That's why &str is fine but String is not, since it will call Drop on a zeroed String (Which is not guaranteed to work) or on an uninitialized String. Using ptr::write instead explicitly does not Drop the old value that is being overwritten. Basically, if you have something like let v = vec![1,2,3]; v = vec![4,5,6]; // Here vec![1,2,3] is dropped otherwise we would be leaking
- remram 5y agoDo you have a source/explanation for *role not being a mutable reference? What is this expression's type then? You mention ptr::write() but it is not used here, and I don't see how you could use it to write to a field?