diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index bd60e066f72..3a441c1d649 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -201,25 +201,8 @@ where // see https://github.com/rust-lang/rust/issues/93688#issuecomment-1032929496.) // So we just "offset" by 0. let layout = base.layout().for_variant(self, variant); - // In the future we might want to allow this to permit code like this: - // (this is a Rust/MIR pseudocode mix) - // ``` - // enum Option2 { - // Some(i32, !), - // None, - // } - // - // fn panic() -> ! { panic!() } - // - // let x: Option2; - // x.Some.0 = 42; - // x.Some.1 = panic(); - // SetDiscriminant(x, Some); - // ``` - // However, for now we don't generate such MIR, and this check here *has* found real - // bugs (see https://github.com/rust-lang/rust/issues/115145), so we will keep rejecting - // it. - assert!(!layout.abi.is_uninhabited()); + // This variant may in fact be uninhabited. + // See . // This cannot be `transmute` as variants *can* have a smaller size than the entire enum. base.offset(Size::ZERO, layout, self) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index a5c229879a7..a4b6c4f9c3f 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1074,6 +1074,8 @@ pub enum ProjectionElem { /// "Downcast" to a variant of an enum or a coroutine. /// /// The included Symbol is the name of the variant, used for printing MIR. + /// + /// This operation itself is never UB, all it does is change the type of the place. Downcast(Option, VariantIdx), /// Like an explicit cast from an opaque type to a concrete type, but without diff --git a/src/tools/miri/tests/pass/issues/issue-120337-irrefutable-let-ice.rs b/src/tools/miri/tests/pass/issues/issue-120337-irrefutable-let-ice.rs new file mode 100644 index 00000000000..5af0d0e4bbd --- /dev/null +++ b/src/tools/miri/tests/pass/issues/issue-120337-irrefutable-let-ice.rs @@ -0,0 +1,16 @@ +// Validation stops the test before the ICE we used to hit +//@compile-flags: -Zmiri-disable-validation + +#![feature(never_type)] +#[derive(Copy, Clone)] +pub enum E { + A(!), +} +pub union U { + u: (), + e: E, +} + +fn main() { + let E::A(ref _a) = unsafe { &(&U { u: () }).e }; +} diff --git a/tests/ui/consts/let-irrefutable-pattern-ice-120337.rs b/tests/ui/consts/let-irrefutable-pattern-ice-120337.rs new file mode 100644 index 00000000000..7da6b7ca285 --- /dev/null +++ b/tests/ui/consts/let-irrefutable-pattern-ice-120337.rs @@ -0,0 +1,10 @@ +// check-pass +#![feature(never_type)] +#[derive(Copy, Clone)] +pub enum E { A(!), } +pub union U { u: (), e: E, } +pub const C: () = { + let E::A(ref a) = unsafe { &(&U { u: () }).e}; +}; + +fn main() {}