interpret: project_downcast: do not ICE for uninhabited variants
This commit is contained in:
parent
69db514ed9
commit
1025a12b64
@ -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)
|
||||
|
@ -1074,6 +1074,8 @@ pub enum ProjectionElem<V, T> {
|
||||
/// "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<Symbol>, VariantIdx),
|
||||
|
||||
/// Like an explicit cast from an opaque type to a concrete type, but without
|
||||
|
@ -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
tests/ui/consts/let-irrefutable-pattern-ice-120337.rs
Normal file
10
tests/ui/consts/let-irrefutable-pattern-ice-120337.rs
Normal file
@ -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() {}
|
Loading…
x
Reference in New Issue
Block a user