Skip to content

When nested subfield of a union is moved, move checker incorrectly permits access to its "uncle" fields #41126

Closed
@petrochenkov

Description

@petrochenkov
#![feature(untagged_unions)]
#![allow(unused)]

#[allow(unions_with_drop_fields)]
union U {
    x: (Vec<u8>, Vec<u8>),
    y: Vec<u8>,
}

fn main() { unsafe {
    let u = U { x: (Vec::new(), Vec::new()) };
    let a = u.x.0;
    let a = u.y; // This is incorrectly accepted despite u.y being "collaterally moved"
}}

When implementing move checking for unions I incorrectly assumed that moves automatically "propagate" to parent "loan paths", like in borrow checker, e.g.

    let a = &mut u.x.0;
    let a = &u.y; // This currently gives correct error due to u.y being "collaterally borrowed"

, this turns out to not be the case.
This case was missed in tests, so the error went unnoticed.

I have some quick fix, will submit tomorrow.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-borrow-checkerArea: The borrow checkerI-needs-decisionIssue: In need of a decision.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessT-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