diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 4f96cb698915d..33161dfa52c7b 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -410,6 +410,12 @@ where stride * field } layout::FieldPlacement::Union(count) => { + // This is a narrow bug-fix for rust-lang/rust#69191: if we are + // trying to access absent field of uninhabited variant, then + // signal UB (but don't ICE the compiler). + if field >= count as u64 && base.layout.abi == layout::Abi::Uninhabited { + throw_ub!(Unreachable); + } assert!( field < count as u64, "Tried to access field {} of union {:#?} with {} fields", diff --git a/src/test/ui/consts/issue-69191-ice-on-uninhabited-enum-field.rs b/src/test/ui/consts/issue-69191-ice-on-uninhabited-enum-field.rs new file mode 100644 index 0000000000000..e22ddb0f5ae0c --- /dev/null +++ b/src/test/ui/consts/issue-69191-ice-on-uninhabited-enum-field.rs @@ -0,0 +1,31 @@ +// build-pass +// +// (this is deliberately *not* check-pass; I have confirmed that the bug in +// question does not replicate when one uses `cargo check` alone.) + +pub enum Void {} + +enum UninhabitedUnivariant { _Variant(Void), } + +#[repr(C)] +enum UninhabitedUnivariantC { _Variant(Void), } + +#[repr(i32)] +enum UninhabitedUnivariant32 { _Variant(Void), } + +fn main() { + let _seed: UninhabitedUnivariant = None.unwrap(); + match _seed { + UninhabitedUnivariant::_Variant(_x) => {} + } + + let _seed: UninhabitedUnivariantC = None.unwrap(); + match _seed { + UninhabitedUnivariantC::_Variant(_x) => {} + } + + let _seed: UninhabitedUnivariant32 = None.unwrap(); + match _seed { + UninhabitedUnivariant32::_Variant(_x) => {} + } +}