Skip to content

DerefMut auto-deref error for union fields sometimes doesn't trigger #141621

Open
@Alexendoo

Description

@Alexendoo

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

https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=3df4479c28c8a9ce5d2372e161c0e292

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

https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=223c79eac2bb82ba9834354d2043d67f

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;
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-frontendArea: Compiler frontend (errors, parsing and HIR)C-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions