Skip to content

Layout and MIR field accesses are incoherent #69763

Closed

Description

I propose that we should have the following invariant: Whenever, anywhere in MIR, there is a field projection with some index i, then i is actually a valid field index in the (statically known) layout of the type being projected into.

Right now, this is not the case. This code:

pub enum Void {}

enum UninhabitedUnivariant { _Variant(Void), }

fn main() {
    let _seed: UninhabitedUnivariant = None.unwrap();
    match _seed {
        UninhabitedUnivariant::_Variant(_x) => {}
    }
}

generates the following MIR:

    bb1: {
        StorageDead(_2);                 // bb1[0]: scope 0 at src/main.rs:6:52: 6:53
        StorageLive(_3);                 // bb1[1]: scope 1 at src/main.rs:8:41: 8:43
        _3 = move ((_1 as _Variant).0: Void); // bb1[2]: scope 1 at src/main.rs:8:41: 8:43
        StorageDead(_3);                 // bb1[3]: scope 1 at src/main.rs:9:5: 9:6
        StorageDead(_1);                 // bb1[4]: scope 0 at src/main.rs:10:1: 10:2
        return;                          // bb1[5]: scope 0 at src/main.rs:10:2: 10:2
    }

but the layout of _Variant is that of a union with 0 fields.

A consequence of this incoherence is that all codegen backends and Miri (and possibly more MIR consumers) all need to be on their guard when considering field projections, always protecting against the case where the projection is ill-formed (usually that happens by special-casing uninhabited types before considering the projection).

I think instead of putting that burden on every MIR consumer, we should fix either the layout or the MIR to not violate the invariant in the first place.

Cc @eddyb with whom I anyway recently talked about those odd Union layouts. Is there some fundamental issue with the invariant I am proposing? Also Cc @oli-obk @wesleywiser

If we decide to go with this, we should

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlC-cleanupCategory: PRs that clean code up or issues documenting cleanup.T-compilerRelevant to the compiler 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