Open
Description
An implicit DerefMut
of a MaybeUninit
union
field is an error, but sometimes that error does not fire. This is not a soundness issue as it's more like a lint
use std::mem::ManuallyDrop;
union U {
x: (),
f: ManuallyDrop<(Vec<u8>,)>,
}
fn main() {
let mut u = U { x: () };
// Errors about the implicit deref of the ManuallyDrop
unsafe { u.f.0 = Vec::new() };
// equivalent to (*u.f).0
let r = &mut u;
// implicitly derefs the ManuallyDrop but does not error
unsafe { r.f.0 = Vec::new() };
// equivalent to (*(*r).f).0
}
I expected to see this happen: Both assignments should error
Instead, this happened: Only the first produces an error
error: not automatically applying `DerefMut` on `ManuallyDrop` union field
--> src/main.rs:24:9
|
24 | a.tup.0.num = 0;
| ^^^^^^^
|
= help: writing to this reference calls the destructor for the old value
= help: add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor
We ran into a similar case in rust-lang/rust-clippy#14387
use std::mem::ManuallyDrop;
struct Data {
num: u64,
}
union DataWithPadding {
u: (),
tup: (ManuallyDrop<Data>, ()),
}
fn main() {
let mut a = DataWithPadding { u: () };
unsafe {
// No error, but the ManuallyDrop in the tuple is being implicitly dereferenced
(*&mut a.tup).0.num = 0;
// equivalent to (*(*&mut a.tup).0).num
// similar
(&mut a.tup).0.num = 0;
// Does error when written plainly
a.tup.0.num = 0;
}
}