add dedicated error variant for writing the discriminant of an uninhabited enum variant
This commit is contained in:
parent
eeb16a2a89
commit
c5a68cf0a6
3 changed files with 20 additions and 1 deletions
|
@ -618,6 +618,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read discriminant, return the runtime value as well as the variant index.
|
/// Read discriminant, return the runtime value as well as the variant index.
|
||||||
|
/// Can also legally be called on non-enums (e.g. through the discriminant_value intrinsic)!
|
||||||
pub fn read_discriminant(
|
pub fn read_discriminant(
|
||||||
&self,
|
&self,
|
||||||
op: &OpTy<'tcx, M::PointerTag>,
|
op: &OpTy<'tcx, M::PointerTag>,
|
||||||
|
|
|
@ -988,10 +988,23 @@ where
|
||||||
variant_index: VariantIdx,
|
variant_index: VariantIdx,
|
||||||
dest: &PlaceTy<'tcx, M::PointerTag>,
|
dest: &PlaceTy<'tcx, M::PointerTag>,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
|
// This must be an enum or generator.
|
||||||
|
match dest.layout.ty.kind() {
|
||||||
|
ty::Adt(adt, _) => assert!(adt.is_enum()),
|
||||||
|
ty::Generator(..) => {}
|
||||||
|
_ => span_bug!(
|
||||||
|
self.cur_span(),
|
||||||
|
"write_discriminant called on non-variant-type (neither enum nor generator)"
|
||||||
|
),
|
||||||
|
}
|
||||||
// Layout computation excludes uninhabited variants from consideration
|
// Layout computation excludes uninhabited variants from consideration
|
||||||
// therefore there's no way to represent those variants in the given layout.
|
// therefore there's no way to represent those variants in the given layout.
|
||||||
|
// Essentially, uninhabited variants do not have a tag that corresponds to their
|
||||||
|
// discriminant, so we cannot do anything here.
|
||||||
|
// When evaluating we will always error before even getting here, but ConstProp 'executes'
|
||||||
|
// dead code, so we cannot ICE here.
|
||||||
if dest.layout.for_variant(self, variant_index).abi.is_uninhabited() {
|
if dest.layout.for_variant(self, variant_index).abi.is_uninhabited() {
|
||||||
throw_ub!(Unreachable);
|
throw_ub!(UninhabitedEnumVariantWritten)
|
||||||
}
|
}
|
||||||
|
|
||||||
match dest.layout.variants {
|
match dest.layout.variants {
|
||||||
|
|
|
@ -287,6 +287,8 @@ pub enum UndefinedBehaviorInfo<'tcx> {
|
||||||
target_size: u64,
|
target_size: u64,
|
||||||
data_size: u64,
|
data_size: u64,
|
||||||
},
|
},
|
||||||
|
/// A discriminant of an uninhabited enum variant is written.
|
||||||
|
UninhabitedEnumVariantWritten,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for UndefinedBehaviorInfo<'_> {
|
impl fmt::Display for UndefinedBehaviorInfo<'_> {
|
||||||
|
@ -391,6 +393,9 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> {
|
||||||
"scalar size mismatch: expected {} bytes but got {} bytes instead",
|
"scalar size mismatch: expected {} bytes but got {} bytes instead",
|
||||||
target_size, data_size
|
target_size, data_size
|
||||||
),
|
),
|
||||||
|
UninhabitedEnumVariantWritten => {
|
||||||
|
write!(f, "writing discriminant of an uninhabited enum")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue