make no-variant types a dedicated Variants variant
This commit is contained in:
parent
21de42bf8d
commit
e023590de4
53 changed files with 246 additions and 495 deletions
|
@ -65,15 +65,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
// We use "tag" to refer to how the discriminant is encoded in memory, which can be either
|
||||
// straight-forward (`TagEncoding::Direct`) or with a niche (`TagEncoding::Niche`).
|
||||
let (tag_scalar_layout, tag_encoding, tag_field) = match op.layout().variants {
|
||||
Variants::Empty => {
|
||||
throw_ub!(UninhabitedEnumVariantRead(None));
|
||||
}
|
||||
Variants::Single { index } => {
|
||||
if op.layout().is_uninhabited() {
|
||||
// For consistency with `write_discriminant`, and to make sure that
|
||||
// `project_downcast` cannot fail due to strange layouts, we declare immediate UB
|
||||
// for uninhabited enums.
|
||||
throw_ub!(UninhabitedEnumVariantRead(None));
|
||||
throw_ub!(UninhabitedEnumVariantRead(Some(index)));
|
||||
}
|
||||
// Since the type is inhabited, there must be an index.
|
||||
return interp_ok(index.unwrap());
|
||||
return interp_ok(index);
|
||||
}
|
||||
Variants::Multiple { tag, ref tag_encoding, tag_field, .. } => {
|
||||
(tag, tag_encoding, tag_field)
|
||||
|
@ -238,6 +241,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
}
|
||||
|
||||
match layout.variants {
|
||||
abi::Variants::Empty => unreachable!("we already handled uninhabited types"),
|
||||
abi::Variants::Single { .. } => {
|
||||
// The tag of a `Single` enum is like the tag of the niched
|
||||
// variant: there's no tag as the discriminant is encoded
|
||||
|
|
|
@ -302,7 +302,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
|
|||
};
|
||||
}
|
||||
}
|
||||
Variants::Single { .. } => {}
|
||||
Variants::Single { .. } | Variants::Empty => {}
|
||||
}
|
||||
|
||||
// Now we know we are projecting to a field, so figure out which one.
|
||||
|
@ -342,10 +342,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
|
|||
match layout.variants {
|
||||
Variants::Single { index } => {
|
||||
// Inside a variant
|
||||
PathElem::Field(
|
||||
def.variant(index.unwrap()).fields[FieldIdx::from_usize(field)].name,
|
||||
)
|
||||
PathElem::Field(def.variant(index).fields[FieldIdx::from_usize(field)].name)
|
||||
}
|
||||
Variants::Empty => panic!("there is no field in Variants::Empty types"),
|
||||
Variants::Multiple { .. } => bug!("we handled variants above"),
|
||||
}
|
||||
}
|
||||
|
@ -1012,7 +1011,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
|
|||
}
|
||||
// Don't forget potential other variants.
|
||||
match &layout.variants {
|
||||
Variants::Single { .. } => {
|
||||
Variants::Single { .. } | Variants::Empty => {
|
||||
// Fully handled above.
|
||||
}
|
||||
Variants::Multiple { variants, .. } => {
|
||||
|
|
|
@ -218,8 +218,8 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
|
|||
// recurse with the inner type
|
||||
self.visit_variant(v, idx, &inner)?;
|
||||
}
|
||||
// For single-variant layouts, we already did anything there is to do.
|
||||
Variants::Single { .. } => {}
|
||||
// For single-variant layouts, we already did everything there is to do.
|
||||
Variants::Single { .. } | Variants::Empty => {}
|
||||
}
|
||||
|
||||
interp_ok(())
|
||||
|
|
|
@ -155,6 +155,7 @@ fn check_validity_requirement_lax<'tcx>(
|
|||
}
|
||||
|
||||
match &this.variants {
|
||||
Variants::Empty => return Ok(false),
|
||||
Variants::Single { .. } => {
|
||||
// All fields of this single variant have already been checked above, there is nothing
|
||||
// else to do.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue