Skip to content

Commit 1025a12

Browse files
committed
interpret: project_downcast: do not ICE for uninhabited variants
1 parent 69db514 commit 1025a12

File tree

4 files changed

+30
-19
lines changed

4 files changed

+30
-19
lines changed

compiler/rustc_const_eval/src/interpret/projection.rs

+2-19
Original file line numberDiff line numberDiff line change
@@ -201,25 +201,8 @@ where
201201
// see https://github.com/rust-lang/rust/issues/93688#issuecomment-1032929496.)
202202
// So we just "offset" by 0.
203203
let layout = base.layout().for_variant(self, variant);
204-
// In the future we might want to allow this to permit code like this:
205-
// (this is a Rust/MIR pseudocode mix)
206-
// ```
207-
// enum Option2 {
208-
// Some(i32, !),
209-
// None,
210-
// }
211-
//
212-
// fn panic() -> ! { panic!() }
213-
//
214-
// let x: Option2;
215-
// x.Some.0 = 42;
216-
// x.Some.1 = panic();
217-
// SetDiscriminant(x, Some);
218-
// ```
219-
// However, for now we don't generate such MIR, and this check here *has* found real
220-
// bugs (see https://github.com/rust-lang/rust/issues/115145), so we will keep rejecting
221-
// it.
222-
assert!(!layout.abi.is_uninhabited());
204+
// This variant may in fact be uninhabited.
205+
// See <https://github.com/rust-lang/rust/issues/120337>.
223206

224207
// This cannot be `transmute` as variants *can* have a smaller size than the entire enum.
225208
base.offset(Size::ZERO, layout, self)

compiler/rustc_middle/src/mir/syntax.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1074,6 +1074,8 @@ pub enum ProjectionElem<V, T> {
10741074
/// "Downcast" to a variant of an enum or a coroutine.
10751075
///
10761076
/// The included Symbol is the name of the variant, used for printing MIR.
1077+
///
1078+
/// This operation itself is never UB, all it does is change the type of the place.
10771079
Downcast(Option<Symbol>, VariantIdx),
10781080

10791081
/// Like an explicit cast from an opaque type to a concrete type, but without
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Validation stops the test before the ICE we used to hit
2+
//@compile-flags: -Zmiri-disable-validation
3+
4+
#![feature(never_type)]
5+
#[derive(Copy, Clone)]
6+
pub enum E {
7+
A(!),
8+
}
9+
pub union U {
10+
u: (),
11+
e: E,
12+
}
13+
14+
fn main() {
15+
let E::A(ref _a) = unsafe { &(&U { u: () }).e };
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// check-pass
2+
#![feature(never_type)]
3+
#[derive(Copy, Clone)]
4+
pub enum E { A(!), }
5+
pub union U { u: (), e: E, }
6+
pub const C: () = {
7+
let E::A(ref a) = unsafe { &(&U { u: () }).e};
8+
};
9+
10+
fn main() {}

0 commit comments

Comments
 (0)