Skip to content

What is the behavior of a place-to-value/reference conversion of a variant place? #120369

Open
@RalfJung

Description

MIR in principle can represent code like this (but custom MIR currently cannot):

fn enum_shenanigans(_1: S) -> () {
    let mut _0: ();
    let mut _2: ??;
    let mut _3: ??;

    bb0: {
        _2 = (_1 as variant#0);
        _3 = &raw (_1 as variant#0);
        return;
    }
}

I think things would explode in all sorts of ways if such MIR was fed to Miri: enum variants can have ABIs that are entirely different from the enum they are contained in, so the projection can produce ImmTy that are incoherent. Currently this works because it seems to only affect enum variants without fields / uninhabited variants (but maybe I just haven't found the right example yet), and rustc only generates variant projections that are immediately followed by field projections.

But this is not very satisfying. We have an invariant (an Immediate::Scalar must have Scalar type, and similar for ScalarPair), and that invariant is blatantly violated by valid MIR -- or at least MIR that does not break any documented rule I am aware of. It's also unclear what code like the above should even mean: given that enum variants have no type, what should the type of _2 and _3 be?

I can think of two proper solutions here:

  • Instead of a separate Variant projection, have a combined "Variant+Field" projection for accessing enum fields.
  • Give enum variants a proper type, and to ensure that downcasts can't go from Scalar to non-Scalar ABI. The fact that downcast places do not have a proper type has already caused me plenty of confusion and pain so this would be a good change to do anyway IMO, even if we don't expose those types to the user. (One day we might want to expose them as well, but that's not the goal of this issue.)

Cc @oli-obk @JakobDegen @tmiasko @cjgillot

Activity

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

Metadata

Assignees

No one assigned

    Labels

    T-opsemRelevant to the opsem team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions