Replace the default branch with an unreachable branch If it is the last variant
This commit is contained in:
parent
d8b7b5be7d
commit
08ae8380ce
23 changed files with 997 additions and 11 deletions
|
@ -74,6 +74,17 @@ impl SwitchTargets {
|
||||||
pub fn target_for_value(&self, value: u128) -> BasicBlock {
|
pub fn target_for_value(&self, value: u128) -> BasicBlock {
|
||||||
self.iter().find_map(|(v, t)| (v == value).then_some(t)).unwrap_or_else(|| self.otherwise())
|
self.iter().find_map(|(v, t)| (v == value).then_some(t)).unwrap_or_else(|| self.otherwise())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds a new target to the switch. But You cannot add an already present value.
|
||||||
|
#[inline]
|
||||||
|
pub fn add_target(&mut self, value: u128, bb: BasicBlock) {
|
||||||
|
let value = Pu128(value);
|
||||||
|
if self.values.contains(&value) {
|
||||||
|
bug!("target value {:?} already present", value);
|
||||||
|
}
|
||||||
|
self.values.push(value);
|
||||||
|
self.targets.insert(self.targets.len() - 1, bb);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SwitchTargetsIter<'a> {
|
pub struct SwitchTargetsIter<'a> {
|
||||||
|
|
|
@ -78,6 +78,7 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
|
||||||
trace!("UninhabitedEnumBranching starting for {:?}", body.source);
|
trace!("UninhabitedEnumBranching starting for {:?}", body.source);
|
||||||
|
|
||||||
let mut removable_switchs = Vec::new();
|
let mut removable_switchs = Vec::new();
|
||||||
|
let mut otherwise_is_last_variant_switchs = Vec::new();
|
||||||
|
|
||||||
for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
|
for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
|
||||||
trace!("processing block {:?}", bb);
|
trace!("processing block {:?}", bb);
|
||||||
|
@ -92,7 +93,7 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
|
||||||
tcx.param_env_reveal_all_normalized(body.source.def_id()).and(discriminant_ty),
|
tcx.param_env_reveal_all_normalized(body.source.def_id()).and(discriminant_ty),
|
||||||
);
|
);
|
||||||
|
|
||||||
let allowed_variants = if let Ok(layout) = layout {
|
let mut allowed_variants = if let Ok(layout) = layout {
|
||||||
variant_discriminants(&layout, discriminant_ty, tcx)
|
variant_discriminants(&layout, discriminant_ty, tcx)
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
|
@ -103,20 +104,31 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
|
||||||
let terminator = bb_data.terminator();
|
let terminator = bb_data.terminator();
|
||||||
let TerminatorKind::SwitchInt { targets, .. } = &terminator.kind else { bug!() };
|
let TerminatorKind::SwitchInt { targets, .. } = &terminator.kind else { bug!() };
|
||||||
|
|
||||||
let mut reachable_count = 0;
|
|
||||||
for (index, (val, _)) in targets.iter().enumerate() {
|
for (index, (val, _)) in targets.iter().enumerate() {
|
||||||
if allowed_variants.contains(&val) {
|
if !allowed_variants.remove(&val) {
|
||||||
reachable_count += 1;
|
|
||||||
} else {
|
|
||||||
removable_switchs.push((bb, index));
|
removable_switchs.push((bb, index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if reachable_count == allowed_variants.len() {
|
if allowed_variants.is_empty() {
|
||||||
removable_switchs.push((bb, targets.iter().count()));
|
removable_switchs.push((bb, targets.iter().count()));
|
||||||
|
} else if allowed_variants.len() == 1
|
||||||
|
&& !body.basic_blocks[targets.otherwise()].is_empty_unreachable()
|
||||||
|
{
|
||||||
|
#[allow(rustc::potential_query_instability)]
|
||||||
|
let last_variant = *allowed_variants.iter().next().unwrap();
|
||||||
|
otherwise_is_last_variant_switchs.push((bb, last_variant));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (bb, last_variant) in otherwise_is_last_variant_switchs {
|
||||||
|
let bb_data = &mut body.basic_blocks.as_mut()[bb];
|
||||||
|
let terminator = bb_data.terminator_mut();
|
||||||
|
let TerminatorKind::SwitchInt { targets, .. } = &mut terminator.kind else { bug!() };
|
||||||
|
targets.add_target(last_variant, targets.otherwise());
|
||||||
|
removable_switchs.push((bb, targets.iter().count()));
|
||||||
|
}
|
||||||
|
|
||||||
if removable_switchs.is_empty() {
|
if removable_switchs.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
24
tests/codegen/enum/uninhabited_enum_default_branch.rs
Normal file
24
tests/codegen/enum/uninhabited_enum_default_branch.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
//@ compile-flags: -O
|
||||||
|
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub struct Int(u32);
|
||||||
|
|
||||||
|
const A: Int = Int(201);
|
||||||
|
const B: Int = Int(270);
|
||||||
|
const C: Int = Int(153);
|
||||||
|
|
||||||
|
// CHECK-LABEL: @foo(
|
||||||
|
// CHECK-SAME: [[TMP0:%.*]])
|
||||||
|
// CHECK-NEXT: start:
|
||||||
|
// CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], -201
|
||||||
|
// CHECK-NEXT: icmp ult i32 [[TMP1]], 70
|
||||||
|
// CHECK-NEXT: icmp eq i32 [[TMP0]], 153
|
||||||
|
// CHECK-NEXT: [[SPEC_SELECT:%.*]] = or i1
|
||||||
|
// CHECK-NEXT: ret i1 [[SPEC_SELECT]]
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn foo(x: Int) -> bool {
|
||||||
|
(x >= A && x <= B)
|
||||||
|
|| x == C
|
||||||
|
}
|
|
@ -69,7 +69,7 @@
|
||||||
StorageLive(_6);
|
StorageLive(_6);
|
||||||
_6 = ((*_1).4: std::option::Option<usize>);
|
_6 = ((*_1).4: std::option::Option<usize>);
|
||||||
_7 = discriminant(_6);
|
_7 = discriminant(_6);
|
||||||
switchInt(move _7) -> [1: bb4, otherwise: bb6];
|
switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
|
@ -135,5 +135,9 @@
|
||||||
StorageDead(_6);
|
StorageDead(_6);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bb9: {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@
|
||||||
StorageLive(_6);
|
StorageLive(_6);
|
||||||
_6 = ((*_1).4: std::option::Option<usize>);
|
_6 = ((*_1).4: std::option::Option<usize>);
|
||||||
_7 = discriminant(_6);
|
_7 = discriminant(_6);
|
||||||
switchInt(move _7) -> [1: bb4, otherwise: bb6];
|
switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb4: {
|
bb4: {
|
||||||
|
@ -135,5 +135,9 @@
|
||||||
StorageDead(_6);
|
StorageDead(_6);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bb9: {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
StorageDead(_2);
|
StorageDead(_2);
|
||||||
_5 = discriminant((_1.0: std::option::Option<u8>));
|
_5 = discriminant((_1.0: std::option::Option<u8>));
|
||||||
switchInt(move _5) -> [1: bb1, otherwise: bb3];
|
switchInt(move _5) -> [1: bb1, 0: bb3, otherwise: bb5];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
|
@ -46,5 +46,9 @@
|
||||||
StorageDead(_1);
|
StorageDead(_1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bb5: {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
StorageDead(_3);
|
StorageDead(_3);
|
||||||
StorageDead(_2);
|
StorageDead(_2);
|
||||||
_5 = discriminant((_1.0: std::option::Option<u8>));
|
_5 = discriminant((_1.0: std::option::Option<u8>));
|
||||||
switchInt(move _5) -> [1: bb1, otherwise: bb3];
|
switchInt(move _5) -> [1: bb1, 0: bb3, otherwise: bb5];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
|
@ -46,5 +46,9 @@
|
||||||
StorageDead(_1);
|
StorageDead(_1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bb5: {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
- // MIR for `otherwise_t1` before UninhabitedEnumBranching
|
||||||
|
+ // MIR for `otherwise_t1` after UninhabitedEnumBranching
|
||||||
|
|
||||||
|
fn otherwise_t1() -> () {
|
||||||
|
let mut _0: ();
|
||||||
|
let _1: &str;
|
||||||
|
let mut _2: Test1;
|
||||||
|
let mut _3: isize;
|
||||||
|
let _4: &str;
|
||||||
|
let _5: &str;
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_1);
|
||||||
|
StorageLive(_2);
|
||||||
|
_2 = Test1::C;
|
||||||
|
_3 = discriminant(_2);
|
||||||
|
- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
|
||||||
|
+ switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
StorageLive(_5);
|
||||||
|
_5 = const "C";
|
||||||
|
_1 = &(*_5);
|
||||||
|
StorageDead(_5);
|
||||||
|
goto -> bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
_1 = const "A(Empty)";
|
||||||
|
goto -> bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
StorageLive(_4);
|
||||||
|
_4 = const "B(Empty)";
|
||||||
|
_1 = &(*_4);
|
||||||
|
StorageDead(_4);
|
||||||
|
goto -> bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb4: {
|
||||||
|
StorageDead(_2);
|
||||||
|
StorageDead(_1);
|
||||||
|
_0 = const ();
|
||||||
|
return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bb5: {
|
||||||
|
+ unreachable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
- // MIR for `otherwise_t1` before UninhabitedEnumBranching
|
||||||
|
+ // MIR for `otherwise_t1` after UninhabitedEnumBranching
|
||||||
|
|
||||||
|
fn otherwise_t1() -> () {
|
||||||
|
let mut _0: ();
|
||||||
|
let _1: &str;
|
||||||
|
let mut _2: Test1;
|
||||||
|
let mut _3: isize;
|
||||||
|
let _4: &str;
|
||||||
|
let _5: &str;
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_1);
|
||||||
|
StorageLive(_2);
|
||||||
|
_2 = Test1::C;
|
||||||
|
_3 = discriminant(_2);
|
||||||
|
- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
|
||||||
|
+ switchInt(move _3) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
StorageLive(_5);
|
||||||
|
_5 = const "C";
|
||||||
|
_1 = &(*_5);
|
||||||
|
StorageDead(_5);
|
||||||
|
goto -> bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
_1 = const "A(Empty)";
|
||||||
|
goto -> bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
StorageLive(_4);
|
||||||
|
_4 = const "B(Empty)";
|
||||||
|
_1 = &(*_4);
|
||||||
|
StorageDead(_4);
|
||||||
|
goto -> bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb4: {
|
||||||
|
StorageDead(_2);
|
||||||
|
StorageDead(_1);
|
||||||
|
_0 = const ();
|
||||||
|
return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bb5: {
|
||||||
|
+ unreachable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
- // MIR for `otherwise_t2` before UninhabitedEnumBranching
|
||||||
|
+ // MIR for `otherwise_t2` after UninhabitedEnumBranching
|
||||||
|
|
||||||
|
fn otherwise_t2() -> () {
|
||||||
|
let mut _0: ();
|
||||||
|
let _1: &str;
|
||||||
|
let mut _2: Test2;
|
||||||
|
let mut _3: isize;
|
||||||
|
let _4: &str;
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_1);
|
||||||
|
StorageLive(_2);
|
||||||
|
_2 = Test2::D;
|
||||||
|
_3 = discriminant(_2);
|
||||||
|
- switchInt(move _3) -> [4: bb2, otherwise: bb1];
|
||||||
|
+ switchInt(move _3) -> [4: bb2, 5: bb1, otherwise: bb4];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
StorageLive(_4);
|
||||||
|
_4 = const "E";
|
||||||
|
_1 = &(*_4);
|
||||||
|
StorageDead(_4);
|
||||||
|
goto -> bb3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
_1 = const "D";
|
||||||
|
goto -> bb3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
StorageDead(_2);
|
||||||
|
StorageDead(_1);
|
||||||
|
_0 = const ();
|
||||||
|
return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bb4: {
|
||||||
|
+ unreachable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
- // MIR for `otherwise_t2` before UninhabitedEnumBranching
|
||||||
|
+ // MIR for `otherwise_t2` after UninhabitedEnumBranching
|
||||||
|
|
||||||
|
fn otherwise_t2() -> () {
|
||||||
|
let mut _0: ();
|
||||||
|
let _1: &str;
|
||||||
|
let mut _2: Test2;
|
||||||
|
let mut _3: isize;
|
||||||
|
let _4: &str;
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_1);
|
||||||
|
StorageLive(_2);
|
||||||
|
_2 = Test2::D;
|
||||||
|
_3 = discriminant(_2);
|
||||||
|
- switchInt(move _3) -> [4: bb2, otherwise: bb1];
|
||||||
|
+ switchInt(move _3) -> [4: bb2, 5: bb1, otherwise: bb4];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
StorageLive(_4);
|
||||||
|
_4 = const "E";
|
||||||
|
_1 = &(*_4);
|
||||||
|
StorageDead(_4);
|
||||||
|
goto -> bb3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
_1 = const "D";
|
||||||
|
goto -> bb3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
StorageDead(_2);
|
||||||
|
StorageDead(_1);
|
||||||
|
_0 = const ();
|
||||||
|
return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bb4: {
|
||||||
|
+ unreachable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
- // MIR for `otherwise_t3` before UninhabitedEnumBranching
|
||||||
|
+ // MIR for `otherwise_t3` after UninhabitedEnumBranching
|
||||||
|
|
||||||
|
fn otherwise_t3() -> () {
|
||||||
|
let mut _0: ();
|
||||||
|
let _1: &str;
|
||||||
|
let mut _2: Test3;
|
||||||
|
let mut _3: isize;
|
||||||
|
let _4: &str;
|
||||||
|
let _5: &str;
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_1);
|
||||||
|
StorageLive(_2);
|
||||||
|
_2 = Test3::C;
|
||||||
|
_3 = discriminant(_2);
|
||||||
|
- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
|
||||||
|
+ switchInt(move _3) -> [0: bb5, 1: bb5, otherwise: bb1];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
StorageLive(_5);
|
||||||
|
_5 = const "C";
|
||||||
|
_1 = &(*_5);
|
||||||
|
StorageDead(_5);
|
||||||
|
goto -> bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
_1 = const "A(Empty)";
|
||||||
|
goto -> bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
StorageLive(_4);
|
||||||
|
_4 = const "B(Empty)";
|
||||||
|
_1 = &(*_4);
|
||||||
|
StorageDead(_4);
|
||||||
|
goto -> bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb4: {
|
||||||
|
StorageDead(_2);
|
||||||
|
StorageDead(_1);
|
||||||
|
_0 = const ();
|
||||||
|
return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bb5: {
|
||||||
|
+ unreachable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
- // MIR for `otherwise_t3` before UninhabitedEnumBranching
|
||||||
|
+ // MIR for `otherwise_t3` after UninhabitedEnumBranching
|
||||||
|
|
||||||
|
fn otherwise_t3() -> () {
|
||||||
|
let mut _0: ();
|
||||||
|
let _1: &str;
|
||||||
|
let mut _2: Test3;
|
||||||
|
let mut _3: isize;
|
||||||
|
let _4: &str;
|
||||||
|
let _5: &str;
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_1);
|
||||||
|
StorageLive(_2);
|
||||||
|
_2 = Test3::C;
|
||||||
|
_3 = discriminant(_2);
|
||||||
|
- switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
|
||||||
|
+ switchInt(move _3) -> [0: bb5, 1: bb5, otherwise: bb1];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
StorageLive(_5);
|
||||||
|
_5 = const "C";
|
||||||
|
_1 = &(*_5);
|
||||||
|
StorageDead(_5);
|
||||||
|
goto -> bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
_1 = const "A(Empty)";
|
||||||
|
goto -> bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
StorageLive(_4);
|
||||||
|
_4 = const "B(Empty)";
|
||||||
|
_1 = &(*_4);
|
||||||
|
StorageDead(_4);
|
||||||
|
goto -> bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb4: {
|
||||||
|
StorageDead(_2);
|
||||||
|
StorageDead(_1);
|
||||||
|
_0 = const ();
|
||||||
|
return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bb5: {
|
||||||
|
+ unreachable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
- // MIR for `otherwise_t4` before UninhabitedEnumBranching
|
||||||
|
+ // MIR for `otherwise_t4` after UninhabitedEnumBranching
|
||||||
|
|
||||||
|
fn otherwise_t4() -> () {
|
||||||
|
let mut _0: ();
|
||||||
|
let _1: &str;
|
||||||
|
let mut _2: Test4;
|
||||||
|
let mut _3: isize;
|
||||||
|
let _4: &str;
|
||||||
|
let _5: &str;
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_1);
|
||||||
|
StorageLive(_2);
|
||||||
|
_2 = Test4::C;
|
||||||
|
_3 = discriminant(_2);
|
||||||
|
switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
StorageLive(_5);
|
||||||
|
_5 = const "CD";
|
||||||
|
_1 = &(*_5);
|
||||||
|
StorageDead(_5);
|
||||||
|
goto -> bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
_1 = const "A(i32)";
|
||||||
|
goto -> bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
StorageLive(_4);
|
||||||
|
_4 = const "B(i32)";
|
||||||
|
_1 = &(*_4);
|
||||||
|
StorageDead(_4);
|
||||||
|
goto -> bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb4: {
|
||||||
|
StorageDead(_2);
|
||||||
|
StorageDead(_1);
|
||||||
|
_0 = const ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
- // MIR for `otherwise_t4` before UninhabitedEnumBranching
|
||||||
|
+ // MIR for `otherwise_t4` after UninhabitedEnumBranching
|
||||||
|
|
||||||
|
fn otherwise_t4() -> () {
|
||||||
|
let mut _0: ();
|
||||||
|
let _1: &str;
|
||||||
|
let mut _2: Test4;
|
||||||
|
let mut _3: isize;
|
||||||
|
let _4: &str;
|
||||||
|
let _5: &str;
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_1);
|
||||||
|
StorageLive(_2);
|
||||||
|
_2 = Test4::C;
|
||||||
|
_3 = discriminant(_2);
|
||||||
|
switchInt(move _3) -> [0: bb2, 1: bb3, otherwise: bb1];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
StorageLive(_5);
|
||||||
|
_5 = const "CD";
|
||||||
|
_1 = &(*_5);
|
||||||
|
StorageDead(_5);
|
||||||
|
goto -> bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
_1 = const "A(i32)";
|
||||||
|
goto -> bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
StorageLive(_4);
|
||||||
|
_4 = const "B(i32)";
|
||||||
|
_1 = &(*_4);
|
||||||
|
StorageDead(_4);
|
||||||
|
goto -> bb4;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb4: {
|
||||||
|
StorageDead(_2);
|
||||||
|
StorageDead(_1);
|
||||||
|
_0 = const ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
- // MIR for `otherwise_t4_uninhabited_default` before UninhabitedEnumBranching
|
||||||
|
+ // MIR for `otherwise_t4_uninhabited_default` after UninhabitedEnumBranching
|
||||||
|
|
||||||
|
fn otherwise_t4_uninhabited_default() -> () {
|
||||||
|
let mut _0: ();
|
||||||
|
let _1: &str;
|
||||||
|
let mut _2: Test4;
|
||||||
|
let mut _3: isize;
|
||||||
|
let _4: &str;
|
||||||
|
let _5: &str;
|
||||||
|
let _6: &str;
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_1);
|
||||||
|
StorageLive(_2);
|
||||||
|
_2 = Test4::C;
|
||||||
|
_3 = discriminant(_2);
|
||||||
|
- switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1];
|
||||||
|
+ switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: bb6];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
StorageLive(_6);
|
||||||
|
_6 = const "D";
|
||||||
|
_1 = &(*_6);
|
||||||
|
StorageDead(_6);
|
||||||
|
goto -> bb5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
_1 = const "A(i32)";
|
||||||
|
goto -> bb5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
StorageLive(_4);
|
||||||
|
_4 = const "B(i32)";
|
||||||
|
_1 = &(*_4);
|
||||||
|
StorageDead(_4);
|
||||||
|
goto -> bb5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb4: {
|
||||||
|
StorageLive(_5);
|
||||||
|
_5 = const "C";
|
||||||
|
_1 = &(*_5);
|
||||||
|
StorageDead(_5);
|
||||||
|
goto -> bb5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb5: {
|
||||||
|
StorageDead(_2);
|
||||||
|
StorageDead(_1);
|
||||||
|
_0 = const ();
|
||||||
|
return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bb6: {
|
||||||
|
+ unreachable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
- // MIR for `otherwise_t4_uninhabited_default` before UninhabitedEnumBranching
|
||||||
|
+ // MIR for `otherwise_t4_uninhabited_default` after UninhabitedEnumBranching
|
||||||
|
|
||||||
|
fn otherwise_t4_uninhabited_default() -> () {
|
||||||
|
let mut _0: ();
|
||||||
|
let _1: &str;
|
||||||
|
let mut _2: Test4;
|
||||||
|
let mut _3: isize;
|
||||||
|
let _4: &str;
|
||||||
|
let _5: &str;
|
||||||
|
let _6: &str;
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_1);
|
||||||
|
StorageLive(_2);
|
||||||
|
_2 = Test4::C;
|
||||||
|
_3 = discriminant(_2);
|
||||||
|
- switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1];
|
||||||
|
+ switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: bb6];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
StorageLive(_6);
|
||||||
|
_6 = const "D";
|
||||||
|
_1 = &(*_6);
|
||||||
|
StorageDead(_6);
|
||||||
|
goto -> bb5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
_1 = const "A(i32)";
|
||||||
|
goto -> bb5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
StorageLive(_4);
|
||||||
|
_4 = const "B(i32)";
|
||||||
|
_1 = &(*_4);
|
||||||
|
StorageDead(_4);
|
||||||
|
goto -> bb5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb4: {
|
||||||
|
StorageLive(_5);
|
||||||
|
_5 = const "C";
|
||||||
|
_1 = &(*_5);
|
||||||
|
StorageDead(_5);
|
||||||
|
goto -> bb5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb5: {
|
||||||
|
StorageDead(_2);
|
||||||
|
StorageDead(_1);
|
||||||
|
_0 = const ();
|
||||||
|
return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bb6: {
|
||||||
|
+ unreachable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
- // MIR for `otherwise_t4_uninhabited_default_2` before UninhabitedEnumBranching
|
||||||
|
+ // MIR for `otherwise_t4_uninhabited_default_2` after UninhabitedEnumBranching
|
||||||
|
|
||||||
|
fn otherwise_t4_uninhabited_default_2() -> () {
|
||||||
|
let mut _0: ();
|
||||||
|
let _1: &str;
|
||||||
|
let mut _2: Test4;
|
||||||
|
let mut _3: isize;
|
||||||
|
let _4: &str;
|
||||||
|
let _5: &str;
|
||||||
|
let _6: &str;
|
||||||
|
let _7: &str;
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_1);
|
||||||
|
StorageLive(_2);
|
||||||
|
_2 = Test4::C;
|
||||||
|
_3 = discriminant(_2);
|
||||||
|
- switchInt(move _3) -> [0: bb1, 1: bb5, 2: bb6, otherwise: bb2];
|
||||||
|
+ switchInt(move _3) -> [0: bb1, 1: bb5, 2: bb6, 3: bb2, otherwise: bb8];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
switchInt(((_2 as A).0: i32)) -> [1: bb3, 2: bb4, otherwise: bb2];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
StorageLive(_7);
|
||||||
|
_7 = const "A(other)D";
|
||||||
|
_1 = &(*_7);
|
||||||
|
StorageDead(_7);
|
||||||
|
goto -> bb7;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
_1 = const "A(1)";
|
||||||
|
goto -> bb7;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb4: {
|
||||||
|
StorageLive(_4);
|
||||||
|
_4 = const "A(2)";
|
||||||
|
_1 = &(*_4);
|
||||||
|
StorageDead(_4);
|
||||||
|
goto -> bb7;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb5: {
|
||||||
|
StorageLive(_5);
|
||||||
|
_5 = const "B(i32)";
|
||||||
|
_1 = &(*_5);
|
||||||
|
StorageDead(_5);
|
||||||
|
goto -> bb7;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb6: {
|
||||||
|
StorageLive(_6);
|
||||||
|
_6 = const "C";
|
||||||
|
_1 = &(*_6);
|
||||||
|
StorageDead(_6);
|
||||||
|
goto -> bb7;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb7: {
|
||||||
|
StorageDead(_2);
|
||||||
|
StorageDead(_1);
|
||||||
|
_0 = const ();
|
||||||
|
return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bb8: {
|
||||||
|
+ unreachable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
- // MIR for `otherwise_t4_uninhabited_default_2` before UninhabitedEnumBranching
|
||||||
|
+ // MIR for `otherwise_t4_uninhabited_default_2` after UninhabitedEnumBranching
|
||||||
|
|
||||||
|
fn otherwise_t4_uninhabited_default_2() -> () {
|
||||||
|
let mut _0: ();
|
||||||
|
let _1: &str;
|
||||||
|
let mut _2: Test4;
|
||||||
|
let mut _3: isize;
|
||||||
|
let _4: &str;
|
||||||
|
let _5: &str;
|
||||||
|
let _6: &str;
|
||||||
|
let _7: &str;
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_1);
|
||||||
|
StorageLive(_2);
|
||||||
|
_2 = Test4::C;
|
||||||
|
_3 = discriminant(_2);
|
||||||
|
- switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, otherwise: bb1];
|
||||||
|
+ switchInt(move _3) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: bb8];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
StorageLive(_7);
|
||||||
|
_7 = const "A(other)D";
|
||||||
|
_1 = &(*_7);
|
||||||
|
StorageDead(_7);
|
||||||
|
goto -> bb7;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
switchInt(((_2 as A).0: i32)) -> [1: bb3, 2: bb4, otherwise: bb1];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
_1 = const "A(1)";
|
||||||
|
goto -> bb7;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb4: {
|
||||||
|
StorageLive(_4);
|
||||||
|
_4 = const "A(2)";
|
||||||
|
_1 = &(*_4);
|
||||||
|
StorageDead(_4);
|
||||||
|
goto -> bb7;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb5: {
|
||||||
|
StorageLive(_5);
|
||||||
|
_5 = const "B(i32)";
|
||||||
|
_1 = &(*_5);
|
||||||
|
StorageDead(_5);
|
||||||
|
goto -> bb7;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb6: {
|
||||||
|
StorageLive(_6);
|
||||||
|
_6 = const "C";
|
||||||
|
_1 = &(*_6);
|
||||||
|
StorageDead(_6);
|
||||||
|
goto -> bb7;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb7: {
|
||||||
|
StorageDead(_2);
|
||||||
|
StorageDead(_1);
|
||||||
|
_0 = const ();
|
||||||
|
return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bb8: {
|
||||||
|
+ unreachable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
- // MIR for `otherwise_t5_uninhabited_default` before UninhabitedEnumBranching
|
||||||
|
+ // MIR for `otherwise_t5_uninhabited_default` after UninhabitedEnumBranching
|
||||||
|
|
||||||
|
fn otherwise_t5_uninhabited_default() -> () {
|
||||||
|
let mut _0: ();
|
||||||
|
let _1: &str;
|
||||||
|
let mut _2: Test5<T>;
|
||||||
|
let mut _3: isize;
|
||||||
|
let _4: &str;
|
||||||
|
let _5: &str;
|
||||||
|
let _6: &str;
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_1);
|
||||||
|
StorageLive(_2);
|
||||||
|
_2 = Test5::<T>::C;
|
||||||
|
_3 = discriminant(_2);
|
||||||
|
switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
StorageLive(_6);
|
||||||
|
_6 = const "D";
|
||||||
|
_1 = &(*_6);
|
||||||
|
StorageDead(_6);
|
||||||
|
goto -> bb5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
_1 = const "A(T)";
|
||||||
|
goto -> bb5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
StorageLive(_4);
|
||||||
|
_4 = const "B(T)";
|
||||||
|
_1 = &(*_4);
|
||||||
|
StorageDead(_4);
|
||||||
|
goto -> bb5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb4: {
|
||||||
|
StorageLive(_5);
|
||||||
|
_5 = const "C";
|
||||||
|
_1 = &(*_5);
|
||||||
|
StorageDead(_5);
|
||||||
|
goto -> bb5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb5: {
|
||||||
|
drop(_2) -> [return: bb6, unwind unreachable];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb6: {
|
||||||
|
StorageDead(_2);
|
||||||
|
StorageDead(_1);
|
||||||
|
_0 = const ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
- // MIR for `otherwise_t5_uninhabited_default` before UninhabitedEnumBranching
|
||||||
|
+ // MIR for `otherwise_t5_uninhabited_default` after UninhabitedEnumBranching
|
||||||
|
|
||||||
|
fn otherwise_t5_uninhabited_default() -> () {
|
||||||
|
let mut _0: ();
|
||||||
|
let _1: &str;
|
||||||
|
let mut _2: Test5<T>;
|
||||||
|
let mut _3: isize;
|
||||||
|
let _4: &str;
|
||||||
|
let _5: &str;
|
||||||
|
let _6: &str;
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_1);
|
||||||
|
StorageLive(_2);
|
||||||
|
_2 = Test5::<T>::C;
|
||||||
|
_3 = discriminant(_2);
|
||||||
|
switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
StorageLive(_6);
|
||||||
|
_6 = const "D";
|
||||||
|
_1 = &(*_6);
|
||||||
|
StorageDead(_6);
|
||||||
|
goto -> bb5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
_1 = const "A(T)";
|
||||||
|
goto -> bb5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
StorageLive(_4);
|
||||||
|
_4 = const "B(T)";
|
||||||
|
_1 = &(*_4);
|
||||||
|
StorageDead(_4);
|
||||||
|
goto -> bb5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb4: {
|
||||||
|
StorageLive(_5);
|
||||||
|
_5 = const "C";
|
||||||
|
_1 = &(*_5);
|
||||||
|
StorageDead(_5);
|
||||||
|
goto -> bb5;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb5: {
|
||||||
|
drop(_2) -> [return: bb6, unwind: bb7];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb6: {
|
||||||
|
StorageDead(_2);
|
||||||
|
StorageDead(_1);
|
||||||
|
_0 = const ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb7 (cleanup): {
|
||||||
|
resume;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,20 @@ enum Test3 {
|
||||||
D,
|
D,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Test4 {
|
||||||
|
A(i32),
|
||||||
|
B(i32),
|
||||||
|
C,
|
||||||
|
D,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Test5<T> {
|
||||||
|
A(T),
|
||||||
|
B(T),
|
||||||
|
C,
|
||||||
|
D,
|
||||||
|
}
|
||||||
|
|
||||||
struct Plop {
|
struct Plop {
|
||||||
xx: u32,
|
xx: u32,
|
||||||
test3: Test3,
|
test3: Test3,
|
||||||
|
@ -57,6 +71,112 @@ fn custom_discriminant() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EMIT_MIR uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.diff
|
||||||
|
fn otherwise_t1() {
|
||||||
|
// CHECK-LABEL: fn otherwise_t1(
|
||||||
|
// CHECK: [[discr:_.*]] = discriminant(
|
||||||
|
// CHECK: switchInt(move [[discr]]) -> [0: bb5, 1: bb5, 2: bb1, otherwise: bb5];
|
||||||
|
// CHECK: bb5: {
|
||||||
|
// CHECK-NEXT: unreachable;
|
||||||
|
match Test1::C {
|
||||||
|
Test1::A(_) => "A(Empty)",
|
||||||
|
Test1::B(_) => "B(Empty)",
|
||||||
|
_ => "C",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// EMIT_MIR uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.diff
|
||||||
|
fn otherwise_t2() {
|
||||||
|
// CHECK-LABEL: fn otherwise_t2(
|
||||||
|
// CHECK: [[discr:_.*]] = discriminant(
|
||||||
|
// CHECK: switchInt(move [[discr]]) -> [4: bb2, 5: bb1, otherwise: bb4];
|
||||||
|
// CHECK: bb4: {
|
||||||
|
// CHECK-NEXT: unreachable;
|
||||||
|
match Test2::D {
|
||||||
|
Test2::D => "D",
|
||||||
|
_ => "E",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// EMIT_MIR uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.diff
|
||||||
|
fn otherwise_t3() {
|
||||||
|
// CHECK-LABEL: fn otherwise_t3(
|
||||||
|
// CHECK: [[discr:_.*]] = discriminant(
|
||||||
|
// CHECK: switchInt(move [[discr]]) -> [0: bb5, 1: bb5, otherwise: bb1];
|
||||||
|
// CHECK: bb1: {
|
||||||
|
// CHECK-NOT: unreachable;
|
||||||
|
// CHECK: }
|
||||||
|
// CHECK: bb5: {
|
||||||
|
// CHECK-NEXT: unreachable;
|
||||||
|
match Test3::C {
|
||||||
|
Test3::A(_) => "A(Empty)",
|
||||||
|
Test3::B(_) => "B(Empty)",
|
||||||
|
_ => "C",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// EMIT_MIR uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.diff
|
||||||
|
fn otherwise_t4_uninhabited_default() {
|
||||||
|
// CHECK-LABEL: fn otherwise_t4_uninhabited_default(
|
||||||
|
// CHECK: [[discr:_.*]] = discriminant(
|
||||||
|
// CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb3, 2: bb4, 3: bb1, otherwise: bb6];
|
||||||
|
// CHECK: bb6: {
|
||||||
|
// CHECK-NEXT: unreachable;
|
||||||
|
match Test4::C {
|
||||||
|
Test4::A(_) => "A(i32)",
|
||||||
|
Test4::B(_) => "B(i32)",
|
||||||
|
Test4::C => "C",
|
||||||
|
_ => "D",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// EMIT_MIR uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.diff
|
||||||
|
fn otherwise_t4_uninhabited_default_2() {
|
||||||
|
// CHECK-LABEL: fn otherwise_t4_uninhabited_default_2(
|
||||||
|
// CHECK: [[discr:_.*]] = discriminant(
|
||||||
|
// CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb5, 2: bb6, 3: bb1, otherwise: bb8];
|
||||||
|
// CHECK: bb8: {
|
||||||
|
// CHECK-NEXT: unreachable;
|
||||||
|
match Test4::C {
|
||||||
|
Test4::A(1) => "A(1)",
|
||||||
|
Test4::A(2) => "A(2)",
|
||||||
|
Test4::B(_) => "B(i32)",
|
||||||
|
Test4::C => "C",
|
||||||
|
_ => "A(other)D",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// EMIT_MIR uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.diff
|
||||||
|
fn otherwise_t4() {
|
||||||
|
// CHECK-LABEL: fn otherwise_t4(
|
||||||
|
// CHECK: [[discr:_.*]] = discriminant(
|
||||||
|
// CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb3, otherwise: bb1];
|
||||||
|
// CHECK: bb1: {
|
||||||
|
// CHECK-NOT: unreachable;
|
||||||
|
// CHECK: }
|
||||||
|
match Test4::C {
|
||||||
|
Test4::A(_) => "A(i32)",
|
||||||
|
Test4::B(_) => "B(i32)",
|
||||||
|
_ => "CD",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// EMIT_MIR uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.diff
|
||||||
|
fn otherwise_t5_uninhabited_default<T>() {
|
||||||
|
// CHECK-LABEL: fn otherwise_t5_uninhabited_default(
|
||||||
|
// CHECK: [[discr:_.*]] = discriminant(
|
||||||
|
// CHECK: switchInt(move [[discr]]) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1];
|
||||||
|
// CHECK: bb1: {
|
||||||
|
// CHECK-NOT: unreachable;
|
||||||
|
// CHECK: }
|
||||||
|
match Test5::<T>::C {
|
||||||
|
Test5::A(_) => "A(T)",
|
||||||
|
Test5::B(_) => "B(T)",
|
||||||
|
Test5::C => "C",
|
||||||
|
_ => "D",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// EMIT_MIR uninhabited_enum_branching.byref.UninhabitedEnumBranching.diff
|
// EMIT_MIR uninhabited_enum_branching.byref.UninhabitedEnumBranching.diff
|
||||||
fn byref() {
|
fn byref() {
|
||||||
// CHECK-LABEL: fn byref(
|
// CHECK-LABEL: fn byref(
|
||||||
|
@ -87,5 +207,12 @@ fn byref() {
|
||||||
fn main() {
|
fn main() {
|
||||||
simple();
|
simple();
|
||||||
custom_discriminant();
|
custom_discriminant();
|
||||||
|
otherwise_t1();
|
||||||
|
otherwise_t2();
|
||||||
|
otherwise_t3();
|
||||||
|
otherwise_t4_uninhabited_default();
|
||||||
|
otherwise_t4_uninhabited_default_2();
|
||||||
|
otherwise_t4();
|
||||||
|
otherwise_t5_uninhabited_default::<i32>();
|
||||||
byref();
|
byref();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
bb0: {
|
bb0: {
|
||||||
_2 = discriminant(_1);
|
_2 = discriminant(_1);
|
||||||
- switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1];
|
- switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1];
|
||||||
+ switchInt(move _2) -> [0: bb5, 1: bb3, otherwise: bb1];
|
+ switchInt(move _2) -> [0: bb5, 1: bb3, 2: bb1, otherwise: bb5];
|
||||||
}
|
}
|
||||||
|
|
||||||
bb1: {
|
bb1: {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue