Skip to content

Commit 0082c26

Browse files
authored
Rollup merge of rust-lang#89859 - RalfJung:write-discriminant, r=oli-obk
add dedicated error variant for writing the discriminant of an uninhabited enum variant This is conceptually different from hitting an `Unreachable` terminator. Also add some sanity check making sure we don't write discriminants of things that do not have discriminants. r? `@oli-obk`
2 parents d9a9d6e + c5a68cf commit 0082c26

File tree

3 files changed

+20
-1
lines changed

3 files changed

+20
-1
lines changed

compiler/rustc_const_eval/src/interpret/operand.rs

+1
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
618618
}
619619

620620
/// Read discriminant, return the runtime value as well as the variant index.
621+
/// Can also legally be called on non-enums (e.g. through the discriminant_value intrinsic)!
621622
pub fn read_discriminant(
622623
&self,
623624
op: &OpTy<'tcx, M::PointerTag>,

compiler/rustc_const_eval/src/interpret/place.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -988,10 +988,23 @@ where
988988
variant_index: VariantIdx,
989989
dest: &PlaceTy<'tcx, M::PointerTag>,
990990
) -> InterpResult<'tcx> {
991+
// This must be an enum or generator.
992+
match dest.layout.ty.kind() {
993+
ty::Adt(adt, _) => assert!(adt.is_enum()),
994+
ty::Generator(..) => {}
995+
_ => span_bug!(
996+
self.cur_span(),
997+
"write_discriminant called on non-variant-type (neither enum nor generator)"
998+
),
999+
}
9911000
// Layout computation excludes uninhabited variants from consideration
9921001
// therefore there's no way to represent those variants in the given layout.
1002+
// Essentially, uninhabited variants do not have a tag that corresponds to their
1003+
// discriminant, so we cannot do anything here.
1004+
// When evaluating we will always error before even getting here, but ConstProp 'executes'
1005+
// dead code, so we cannot ICE here.
9931006
if dest.layout.for_variant(self, variant_index).abi.is_uninhabited() {
994-
throw_ub!(Unreachable);
1007+
throw_ub!(UninhabitedEnumVariantWritten)
9951008
}
9961009

9971010
match dest.layout.variants {

compiler/rustc_middle/src/mir/interpret/error.rs

+5
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,8 @@ pub enum UndefinedBehaviorInfo<'tcx> {
287287
target_size: u64,
288288
data_size: u64,
289289
},
290+
/// A discriminant of an uninhabited enum variant is written.
291+
UninhabitedEnumVariantWritten,
290292
}
291293

292294
impl fmt::Display for UndefinedBehaviorInfo<'_> {
@@ -391,6 +393,9 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> {
391393
"scalar size mismatch: expected {} bytes but got {} bytes instead",
392394
target_size, data_size
393395
),
396+
UninhabitedEnumVariantWritten => {
397+
write!(f, "writing discriminant of an uninhabited enum")
398+
}
394399
}
395400
}
396401
}

0 commit comments

Comments
 (0)