Skip to content

Commit

Permalink
interpret: project_downcast: do not ICE for uninhabited variants
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Jan 26, 2024
1 parent 69db514 commit 7799a86
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 19 deletions.
21 changes: 2 additions & 19 deletions compiler/rustc_const_eval/src/interpret/projection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 <https://github.com/rust-lang/rust/issues/120337>.

// This cannot be `transmute` as variants *can* have a smaller size than the entire enum.
base.offset(Size::ZERO, layout, self)
Expand Down
Original file line number Diff line number Diff line change
@@ -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 };
}
10 changes: 10 additions & 0 deletions tests/ui/consts/let-irrefutable-pattern-ice-120337.rs
Original file line number Diff line number Diff line change
@@ -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() {}

0 comments on commit 7799a86

Please sign in to comment.