What is the behavior of a place-to-value/reference conversion of a variant place? #120369
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.)
Activity