1
Fork 0

make no-variant types a dedicated Variants variant

This commit is contained in:
Ralf Jung 2024-12-01 17:33:01 +01:00
parent 21de42bf8d
commit e023590de4
53 changed files with 246 additions and 495 deletions

View file

@ -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

View file

@ -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, .. } => {

View file

@ -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(())

View file

@ -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.