Skip to content

Commit 4315b72

Browse files
Do not project to uninhabited variant in GVN
1 parent 95402c7 commit 4315b72

File tree

4 files changed

+100
-1
lines changed

4 files changed

+100
-1
lines changed

compiler/rustc_mir_transform/src/gvn.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
577577
return None;
578578
}
579579
}
580-
ProjectionElem::Downcast(name, index) => ProjectionElem::Downcast(name, index),
580+
ProjectionElem::Downcast(name, index) => {
581+
if let Some(ct) = self.eval_to_const(value)
582+
&& ct.layout.for_variant(&self.ecx, index).abi.is_uninhabited()
583+
{
584+
return None;
585+
}
586+
ProjectionElem::Downcast(name, index)
587+
}
581588
ProjectionElem::Field(f, ty) => {
582589
if let Value::Aggregate(_, _, fields) = self.get(value) {
583590
return Some(fields[f.as_usize()]);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
- // MIR for `f` before GVN
2+
+ // MIR for `f` after GVN
3+
4+
fn f() -> u32 {
5+
let mut _0: u32;
6+
let _1: u32;
7+
let mut _2: E;
8+
let mut _3: &U;
9+
let _4: U;
10+
scope 1 {
11+
debug i => _1;
12+
}
13+
scope 2 {
14+
let mut _5: &U;
15+
}
16+
17+
bb0: {
18+
StorageLive(_2);
19+
StorageLive(_3);
20+
_5 = const _;
21+
_3 = &(*_5);
22+
_2 = ((*_3).1: E);
23+
- StorageLive(_1);
24+
+ nop;
25+
_1 = ((_2 as A).1: u32);
26+
StorageDead(_3);
27+
StorageDead(_2);
28+
_0 = _1;
29+
- StorageDead(_1);
30+
+ nop;
31+
return;
32+
}
33+
}
34+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
- // MIR for `f` before GVN
2+
+ // MIR for `f` after GVN
3+
4+
fn f() -> u32 {
5+
let mut _0: u32;
6+
let _1: u32;
7+
let mut _2: E;
8+
let mut _3: &U;
9+
let _4: U;
10+
scope 1 {
11+
debug i => _1;
12+
}
13+
scope 2 {
14+
let mut _5: &U;
15+
}
16+
17+
bb0: {
18+
StorageLive(_2);
19+
StorageLive(_3);
20+
_5 = const _;
21+
_3 = &(*_5);
22+
_2 = ((*_3).1: E);
23+
- StorageLive(_1);
24+
+ nop;
25+
_1 = ((_2 as A).1: u32);
26+
StorageDead(_3);
27+
StorageDead(_2);
28+
_0 = _1;
29+
- StorageDead(_1);
30+
+ nop;
31+
return;
32+
}
33+
}
34+

tests/mir-opt/gvn_uninhabited.rs

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// unit-test: GVN
2+
// compile-flags: -O
3+
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
4+
// skip-filecheck
5+
6+
#![feature(never_type)]
7+
8+
#[derive(Copy, Clone)]
9+
pub enum E {
10+
A(!, u32),
11+
}
12+
13+
pub union U {
14+
i: u32,
15+
e: E,
16+
}
17+
18+
// EMIT_MIR gvn_uninhabited.f.GVN.diff
19+
pub const fn f() -> u32 {
20+
let E::A(_, i) = unsafe { (&U { i: 0 }).e };
21+
i
22+
}
23+
24+
fn main() {}

0 commit comments

Comments
 (0)