From 730299b8a325a8ea75d651859cb9fa9c5b671845 Mon Sep 17 00:00:00 2001 From: DianQK Date: Fri, 26 Jan 2024 18:33:00 +0800 Subject: [PATCH 1/3] Regenerate `uninhabited_enum_branching.rs` --- ...UninhabitedEnumBranching.panic-abort.diff} | 0 ...UninhabitedEnumBranching.panic-unwind.diff | 119 ++++++++++++++++++ ...UninhabitedEnumBranching.panic-abort.diff} | 0 ...UninhabitedEnumBranching.panic-unwind.diff | 48 +++++++ tests/mir-opt/uninhabited_enum_branching.rs | 2 + ...UninhabitedEnumBranching.panic-abort.diff} | 0 ...UninhabitedEnumBranching.panic-unwind.diff | 57 +++++++++ 7 files changed, 226 insertions(+) rename tests/mir-opt/{uninhabited_enum_branching.byref.UninhabitedEnumBranching.diff => uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-abort.diff} (100%) create mode 100644 tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff rename tests/mir-opt/{uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.diff => uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-abort.diff} (100%) create mode 100644 tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff rename tests/mir-opt/{uninhabited_enum_branching.simple.UninhabitedEnumBranching.diff => uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-abort.diff} (100%) create mode 100644 tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff diff --git a/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-abort.diff similarity index 100% rename from tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.diff rename to tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-abort.diff diff --git a/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff new file mode 100644 index 0000000000000..7919450cdc52a --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.byref.UninhabitedEnumBranching.panic-unwind.diff @@ -0,0 +1,119 @@ +- // MIR for `byref` before UninhabitedEnumBranching ++ // MIR for `byref` after UninhabitedEnumBranching + + fn byref() -> () { + let mut _0: (); + let _1: Plop; + let mut _2: Test3; + let _3: &str; + let mut _4: &Test3; + let mut _5: isize; + let _6: &str; + let _7: &str; + let _8: &str; + let _9: &str; + let mut _10: isize; + let _11: &str; + let _12: &str; + let _13: &str; + scope 1 { + debug plop => _1; + } + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test3::C; + _1 = Plop { xx: const 51_u32, test3: move _2 }; + StorageDead(_2); + StorageLive(_3); + StorageLive(_4); + _4 = &(_1.1: Test3); + _5 = discriminant((*_4)); +- switchInt(move _5) -> [0: bb3, 1: bb4, 2: bb5, 3: bb1, otherwise: bb2]; ++ switchInt(move _5) -> [0: bb12, 1: bb12, 2: bb5, 3: bb1, otherwise: bb12]; + } + + bb1: { + StorageLive(_8); + _8 = const "D"; + _3 = &(*_8); + StorageDead(_8); + goto -> bb6; + } + + bb2: { + unreachable; + } + + bb3: { + _3 = const "A(Empty)"; + goto -> bb6; + } + + bb4: { + StorageLive(_6); + _6 = const "B(Empty)"; + _3 = &(*_6); + StorageDead(_6); + goto -> bb6; + } + + bb5: { + StorageLive(_7); + _7 = const "C"; + _3 = &(*_7); + StorageDead(_7); + goto -> bb6; + } + + bb6: { + StorageDead(_4); + StorageDead(_3); + StorageLive(_9); + _10 = discriminant((_1.1: Test3)); +- switchInt(move _10) -> [0: bb8, 1: bb9, 2: bb10, 3: bb7, otherwise: bb2]; ++ switchInt(move _10) -> [0: bb12, 1: bb12, 2: bb10, 3: bb7, otherwise: bb12]; + } + + bb7: { + StorageLive(_13); + _13 = const "D"; + _9 = &(*_13); + StorageDead(_13); + goto -> bb11; + } + + bb8: { + _9 = const "A(Empty)"; + goto -> bb11; + } + + bb9: { + StorageLive(_11); + _11 = const "B(Empty)"; + _9 = &(*_11); + StorageDead(_11); + goto -> bb11; + } + + bb10: { + StorageLive(_12); + _12 = const "C"; + _9 = &(*_12); + StorageDead(_12); + goto -> bb11; + } + + bb11: { + StorageDead(_9); + _0 = const (); + StorageDead(_1); + return; ++ } ++ ++ bb12: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-abort.diff similarity index 100% rename from tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.diff rename to tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-abort.diff diff --git a/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff new file mode 100644 index 0000000000000..5e15298a78c12 --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.custom_discriminant.UninhabitedEnumBranching.panic-unwind.diff @@ -0,0 +1,48 @@ +- // MIR for `custom_discriminant` before UninhabitedEnumBranching ++ // MIR for `custom_discriminant` after UninhabitedEnumBranching + + fn custom_discriminant() -> () { + 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: bb3, 5: bb1, otherwise: bb2]; ++ switchInt(move _3) -> [4: bb3, 5: bb1, otherwise: bb5]; + } + + bb1: { + StorageLive(_4); + _4 = const "E"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb4; + } + + bb2: { + unreachable; + } + + bb3: { + _1 = const "D"; + goto -> bb4; + } + + bb4: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb5: { ++ unreachable; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.rs b/tests/mir-opt/uninhabited_enum_branching.rs index 60389117b1614..4c55547ef2ce0 100644 --- a/tests/mir-opt/uninhabited_enum_branching.rs +++ b/tests/mir-opt/uninhabited_enum_branching.rs @@ -1,4 +1,6 @@ // unit-test: UninhabitedEnumBranching +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY + enum Empty {} // test matching an enum with uninhabited variants diff --git a/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-abort.diff similarity index 100% rename from tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.diff rename to tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-abort.diff diff --git a/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff new file mode 100644 index 0000000000000..410db79802edc --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.simple.UninhabitedEnumBranching.panic-unwind.diff @@ -0,0 +1,57 @@ +- // MIR for `simple` before UninhabitedEnumBranching ++ // MIR for `simple` after UninhabitedEnumBranching + + fn simple() -> () { + 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: bb3, 1: bb4, 2: bb1, otherwise: bb2]; ++ switchInt(move _3) -> [0: bb6, 1: bb6, 2: bb1, otherwise: bb6]; + } + + bb1: { + StorageLive(_5); + _5 = const "C"; + _1 = &(*_5); + StorageDead(_5); + goto -> bb5; + } + + bb2: { + unreachable; + } + + bb3: { + _1 = const "A(Empty)"; + goto -> bb5; + } + + bb4: { + StorageLive(_4); + _4 = const "B(Empty)"; + _1 = &(*_4); + StorageDead(_4); + goto -> bb5; + } + + bb5: { + StorageDead(_2); + StorageDead(_1); + _0 = const (); + return; ++ } ++ ++ bb6: { ++ unreachable; + } + } + From df9681bbbe7693e9803ff046da5dfccba1e5f940 Mon Sep 17 00:00:00 2001 From: DianQK Date: Tue, 23 Jan 2024 10:55:51 +0800 Subject: [PATCH 2/3] Replace the default branch with an unreachable branch If it is the last variant --- compiler/rustc_middle/src/mir/terminator.rs | 11 ++ .../src/uninhabited_enum_branching.rs | 22 ++- .../enum/uninhabited_enum_default_branch.rs | 24 ++++ ...to_exponential_common.GVN.panic-abort.diff | 6 +- ...o_exponential_common.GVN.panic-unwind.diff | 6 +- ....foo.SimplifyLocals-final.panic-abort.diff | 6 +- ...foo.SimplifyLocals-final.panic-unwind.diff | 6 +- ....UninhabitedEnumBranching.panic-abort.diff | 53 ++++++++ ...UninhabitedEnumBranching.panic-unwind.diff | 53 ++++++++ ....UninhabitedEnumBranching.panic-abort.diff | 44 ++++++ ...UninhabitedEnumBranching.panic-unwind.diff | 44 ++++++ ....UninhabitedEnumBranching.panic-abort.diff | 53 ++++++++ ...UninhabitedEnumBranching.panic-unwind.diff | 53 ++++++++ ....UninhabitedEnumBranching.panic-abort.diff | 48 +++++++ ...UninhabitedEnumBranching.panic-unwind.diff | 48 +++++++ ....UninhabitedEnumBranching.panic-abort.diff | 62 +++++++++ ...UninhabitedEnumBranching.panic-unwind.diff | 62 +++++++++ ....UninhabitedEnumBranching.panic-abort.diff | 75 +++++++++++ ...UninhabitedEnumBranching.panic-unwind.diff | 75 +++++++++++ ....UninhabitedEnumBranching.panic-abort.diff | 61 +++++++++ ...UninhabitedEnumBranching.panic-unwind.diff | 65 +++++++++ tests/mir-opt/uninhabited_enum_branching.rs | 127 ++++++++++++++++++ ..._fallthrough.UninhabitedEnumBranching.diff | 2 +- 23 files changed, 995 insertions(+), 11 deletions(-) create mode 100644 tests/codegen/enum/uninhabited_enum_default_branch.rs create mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff create mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff create mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff create mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff create mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff create mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff create mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff create mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff create mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff create mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff create mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff create mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff create mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff create mode 100644 tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index fdbbf468ecea2..ed29c2d30273f 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -74,6 +74,17 @@ impl SwitchTargets { 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()) } + + /// 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> { diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs index e68d37f4c701e..dbe9ba08d7c55 100644 --- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs @@ -78,6 +78,7 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { trace!("UninhabitedEnumBranching starting for {:?}", body.source); 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() { 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), ); - let allowed_variants = if let Ok(layout) = layout { + let mut allowed_variants = if let Ok(layout) = layout { variant_discriminants(&layout, discriminant_ty, tcx) } else { continue; @@ -103,20 +104,29 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { let terminator = bb_data.terminator(); let TerminatorKind::SwitchInt { targets, .. } = &terminator.kind else { bug!() }; - let mut reachable_count = 0; for (index, (val, _)) in targets.iter().enumerate() { - if allowed_variants.contains(&val) { - reachable_count += 1; - } else { + if !allowed_variants.remove(&val) { removable_switchs.push((bb, index)); } } - if reachable_count == allowed_variants.len() { + if allowed_variants.is_empty() { removable_switchs.push((bb, targets.iter().count())); + } else if allowed_variants.len() == 1 { + #[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() { return; } diff --git a/tests/codegen/enum/uninhabited_enum_default_branch.rs b/tests/codegen/enum/uninhabited_enum_default_branch.rs new file mode 100644 index 0000000000000..0fada2e788643 --- /dev/null +++ b/tests/codegen/enum/uninhabited_enum_default_branch.rs @@ -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: [[OR_COND:%.*]] = icmp ult i32 [[TMP1]], 70 +// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 153 +// CHECK-NEXT: [[SPEC_SELECT:%.*]] = or i1 [[OR_COND]], [[TMP2]] +// CHECK-NEXT: ret i1 [[SPEC_SELECT]] +#[no_mangle] +pub fn foo(x: Int) -> bool { + (x >= A && x <= B) + || x == C +} diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff index 080478ea88419..bd346af6d16e4 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff @@ -69,7 +69,7 @@ StorageLive(_6); _6 = ((*_1).4: std::option::Option); _7 = discriminant(_6); - switchInt(move _7) -> [1: bb4, otherwise: bb6]; + switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9]; } bb4: { @@ -135,5 +135,9 @@ StorageDead(_6); return; } + + bb9: { + unreachable; + } } diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff index ff8933fca8b2c..422cbeaa224ea 100644 --- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff +++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff @@ -69,7 +69,7 @@ StorageLive(_6); _6 = ((*_1).4: std::option::Option); _7 = discriminant(_6); - switchInt(move _7) -> [1: bb4, otherwise: bb6]; + switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9]; } bb4: { @@ -135,5 +135,9 @@ StorageDead(_6); return; } + + bb9: { + unreachable; + } } diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff index 1566d7197acd8..3108b7d3e13d7 100644 --- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff +++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff @@ -23,7 +23,7 @@ StorageDead(_3); StorageDead(_2); _5 = discriminant((_1.0: std::option::Option)); - switchInt(move _5) -> [1: bb1, otherwise: bb3]; + switchInt(move _5) -> [1: bb1, 0: bb3, otherwise: bb5]; } bb1: { @@ -46,5 +46,9 @@ StorageDead(_1); return; } + + bb5: { + unreachable; + } } diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff index ba5262b0ee143..3ef3be198ede3 100644 --- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff +++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff @@ -23,7 +23,7 @@ StorageDead(_3); StorageDead(_2); _5 = discriminant((_1.0: std::option::Option)); - switchInt(move _5) -> [1: bb1, otherwise: bb3]; + switchInt(move _5) -> [1: bb1, 0: bb3, otherwise: bb5]; } bb1: { @@ -46,5 +46,9 @@ StorageDead(_1); return; } + + bb5: { + unreachable; + } } diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff new file mode 100644 index 0000000000000..383fde4d787b9 --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-abort.diff @@ -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; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff new file mode 100644 index 0000000000000..383fde4d787b9 --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t1.UninhabitedEnumBranching.panic-unwind.diff @@ -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; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff new file mode 100644 index 0000000000000..3a2dc19db71cd --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-abort.diff @@ -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; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff new file mode 100644 index 0000000000000..3a2dc19db71cd --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t2.UninhabitedEnumBranching.panic-unwind.diff @@ -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; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff new file mode 100644 index 0000000000000..5dc1e2b73f6a4 --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-abort.diff @@ -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; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff new file mode 100644 index 0000000000000..5dc1e2b73f6a4 --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t3.UninhabitedEnumBranching.panic-unwind.diff @@ -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; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff new file mode 100644 index 0000000000000..1352dda49715b --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-abort.diff @@ -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; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff new file mode 100644 index 0000000000000..1352dda49715b --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4.UninhabitedEnumBranching.panic-unwind.diff @@ -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; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff new file mode 100644 index 0000000000000..40dd961fbac4d --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff @@ -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; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff new file mode 100644 index 0000000000000..40dd961fbac4d --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff @@ -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; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff new file mode 100644 index 0000000000000..de6944ee423c6 --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-abort.diff @@ -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; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff new file mode 100644 index 0000000000000..de6944ee423c6 --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t4_uninhabited_default_2.UninhabitedEnumBranching.panic-unwind.diff @@ -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; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff new file mode 100644 index 0000000000000..aaede2dd92438 --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff @@ -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; + let mut _3: isize; + let _4: &str; + let _5: &str; + let _6: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test5::::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; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff new file mode 100644 index 0000000000000..edaaa0db588b0 --- /dev/null +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff @@ -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; + let mut _3: isize; + let _4: &str; + let _5: &str; + let _6: &str; + + bb0: { + StorageLive(_1); + StorageLive(_2); + _2 = Test5::::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; + } + } + diff --git a/tests/mir-opt/uninhabited_enum_branching.rs b/tests/mir-opt/uninhabited_enum_branching.rs index 4c55547ef2ce0..866db31f05130 100644 --- a/tests/mir-opt/uninhabited_enum_branching.rs +++ b/tests/mir-opt/uninhabited_enum_branching.rs @@ -25,6 +25,20 @@ enum Test3 { D, } +enum Test4 { + A(i32), + B(i32), + C, + D, +} + +enum Test5 { + A(T), + B(T), + C, + D, +} + struct Plop { xx: u32, 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: bb1, 1: bb5, 2: bb6, 3: bb2, 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() { + // 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::::C { + Test5::A(_) => "A(T)", + Test5::B(_) => "B(T)", + Test5::C => "C", + _ => "D", + }; +} + // EMIT_MIR uninhabited_enum_branching.byref.UninhabitedEnumBranching.diff fn byref() { // CHECK-LABEL: fn byref( @@ -87,5 +207,12 @@ fn byref() { fn main() { simple(); custom_discriminant(); + otherwise_t1(); + otherwise_t2(); + otherwise_t3(); + otherwise_t4_uninhabited_default(); + otherwise_t4_uninhabited_default_2(); + otherwise_t4(); + otherwise_t5_uninhabited_default::(); byref(); } diff --git a/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff b/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff index 79948139f888d..28a8c251d956a 100644 --- a/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff +++ b/tests/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff @@ -9,7 +9,7 @@ bb0: { _2 = discriminant(_1); - 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: { From a3341df158ba5ced015ba2bb6d048d24855156a9 Mon Sep 17 00:00:00 2001 From: DianQK Date: Wed, 24 Jan 2024 20:47:39 +0800 Subject: [PATCH 3/3] Get all variants to eliminate the default branching if we cannot get the layout of type --- .../src/uninhabited_enum_branching.rs | 6 ++ ..._to_digit.PreCodegen.after.panic-abort.mir | 60 ++++++++++++------- ...to_digit.PreCodegen.after.panic-unwind.mir | 60 ++++++++++++------- ...cked_ops.step_forward.PreCodegen.after.mir | 56 +---------------- ....foo.SimplifyLocals-final.panic-abort.diff | 2 +- ...foo.SimplifyLocals-final.panic-unwind.diff | 2 +- ....UninhabitedEnumBranching.panic-abort.diff | 9 ++- ...UninhabitedEnumBranching.panic-unwind.diff | 9 ++- tests/mir-opt/uninhabited_enum_branching.rs | 16 ++--- 9 files changed, 107 insertions(+), 113 deletions(-) diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs index dbe9ba08d7c55..e4723e8d74af4 100644 --- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs @@ -95,6 +95,12 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { let mut allowed_variants = if let Ok(layout) = layout { variant_discriminants(&layout, discriminant_ty, tcx) + } else if let Some(variant_range) = discriminant_ty.variant_range(tcx) { + variant_range + .map(|variant| { + discriminant_ty.discriminant_for_variant(tcx, variant).unwrap().val + }) + .collect() } else { continue; }; diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir index f7be8b75db7b8..ea400ac9b2998 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir @@ -3,7 +3,8 @@ fn num_to_digit(_1: char) -> u32 { debug num => _1; let mut _0: u32; - let mut _5: std::option::Option; + let mut _5: bool; + let mut _6: std::option::Option; scope 1 (inlined char::methods::::is_digit) { debug self => _1; debug radix => const 8_u32; @@ -15,15 +16,16 @@ fn num_to_digit(_1: char) -> u32 { } } scope 3 (inlined #[track_caller] Option::::unwrap) { - debug self => _5; - let mut _6: isize; - let mut _7: !; + debug self => _6; + let mut _7: isize; + let mut _8: !; scope 4 { debug val => _0; } } bb0: { + StorageLive(_5); StorageLive(_3); StorageLive(_2); _2 = char::methods::::to_digit(_1, const 8_u32) -> [return: bb1, unwind unreachable]; @@ -33,45 +35,59 @@ fn num_to_digit(_1: char) -> u32 { _3 = &_2; StorageLive(_4); _4 = discriminant(_2); - StorageDead(_3); - StorageDead(_2); - switchInt(move _4) -> [1: bb2, otherwise: bb7]; + switchInt(move _4) -> [1: bb2, 0: bb3, otherwise: bb11]; } bb2: { - StorageDead(_4); - StorageLive(_5); - _5 = char::methods::::to_digit(move _1, const 8_u32) -> [return: bb3, unwind unreachable]; + _5 = const true; + goto -> bb4; } bb3: { - StorageLive(_6); - _6 = discriminant(_5); - switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb6]; + _5 = const false; + goto -> bb4; } bb4: { - _7 = option::unwrap_failed() -> unwind unreachable; + StorageDead(_4); + StorageDead(_3); + StorageDead(_2); + switchInt(move _5) -> [0: bb5, otherwise: bb6]; } bb5: { - _0 = move ((_5 as Some).0: u32); - StorageDead(_6); - StorageDead(_5); - goto -> bb8; + _0 = const 0_u32; + goto -> bb10; } bb6: { - unreachable; + StorageLive(_6); + _6 = char::methods::::to_digit(move _1, const 8_u32) -> [return: bb7, unwind unreachable]; } bb7: { - StorageDead(_4); - _0 = const 0_u32; - goto -> bb8; + StorageLive(_7); + _7 = discriminant(_6); + switchInt(move _7) -> [0: bb8, 1: bb9, otherwise: bb11]; } bb8: { + _8 = option::unwrap_failed() -> unwind unreachable; + } + + bb9: { + _0 = move ((_6 as Some).0: u32); + StorageDead(_7); + StorageDead(_6); + goto -> bb10; + } + + bb10: { + StorageDead(_5); return; } + + bb11: { + unreachable; + } } diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir index e76fe992ac7d3..ca7dd89e5589a 100644 --- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir @@ -3,7 +3,8 @@ fn num_to_digit(_1: char) -> u32 { debug num => _1; let mut _0: u32; - let mut _5: std::option::Option; + let mut _5: bool; + let mut _6: std::option::Option; scope 1 (inlined char::methods::::is_digit) { debug self => _1; debug radix => const 8_u32; @@ -15,15 +16,16 @@ fn num_to_digit(_1: char) -> u32 { } } scope 3 (inlined #[track_caller] Option::::unwrap) { - debug self => _5; - let mut _6: isize; - let mut _7: !; + debug self => _6; + let mut _7: isize; + let mut _8: !; scope 4 { debug val => _0; } } bb0: { + StorageLive(_5); StorageLive(_3); StorageLive(_2); _2 = char::methods::::to_digit(_1, const 8_u32) -> [return: bb1, unwind continue]; @@ -33,45 +35,59 @@ fn num_to_digit(_1: char) -> u32 { _3 = &_2; StorageLive(_4); _4 = discriminant(_2); - StorageDead(_3); - StorageDead(_2); - switchInt(move _4) -> [1: bb2, otherwise: bb7]; + switchInt(move _4) -> [1: bb2, 0: bb3, otherwise: bb11]; } bb2: { - StorageDead(_4); - StorageLive(_5); - _5 = char::methods::::to_digit(move _1, const 8_u32) -> [return: bb3, unwind continue]; + _5 = const true; + goto -> bb4; } bb3: { - StorageLive(_6); - _6 = discriminant(_5); - switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb6]; + _5 = const false; + goto -> bb4; } bb4: { - _7 = option::unwrap_failed() -> unwind continue; + StorageDead(_4); + StorageDead(_3); + StorageDead(_2); + switchInt(move _5) -> [0: bb5, otherwise: bb6]; } bb5: { - _0 = move ((_5 as Some).0: u32); - StorageDead(_6); - StorageDead(_5); - goto -> bb8; + _0 = const 0_u32; + goto -> bb10; } bb6: { - unreachable; + StorageLive(_6); + _6 = char::methods::::to_digit(move _1, const 8_u32) -> [return: bb7, unwind continue]; } bb7: { - StorageDead(_4); - _0 = const 0_u32; - goto -> bb8; + StorageLive(_7); + _7 = discriminant(_6); + switchInt(move _7) -> [0: bb8, 1: bb9, otherwise: bb11]; } bb8: { + _8 = option::unwrap_failed() -> unwind continue; + } + + bb9: { + _0 = move ((_6 as Some).0: u32); + StorageDead(_7); + StorageDead(_6); + goto -> bb10; + } + + bb10: { + StorageDead(_5); return; } + + bb11: { + unreachable; + } } diff --git a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir index cf7feef00514a..f1d0da28b4ef1 100644 --- a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir @@ -4,66 +4,12 @@ fn step_forward(_1: u32, _2: usize) -> u32 { debug x => _1; debug n => _2; let mut _0: u32; - scope 1 (inlined ::forward) { - debug start => _1; - debug n => _2; - let _3: std::option::Option; - let mut _4: &std::option::Option; - let mut _7: bool; - let mut _8: u32; - scope 2 { - } - scope 3 (inlined Option::::is_none) { - debug self => _4; - let mut _6: bool; - scope 4 (inlined Option::::is_some) { - debug self => _4; - let mut _5: isize; - } - } - scope 5 (inlined core::num::::wrapping_add) { - debug self => _1; - debug rhs => _8; - } - } bb0: { - StorageLive(_7); - StorageLive(_4); - StorageLive(_3); - _3 = ::forward_checked(_1, _2) -> [return: bb1, unwind continue]; + _0 = ::forward(move _1, move _2) -> [return: bb1, unwind continue]; } bb1: { - _4 = &_3; - StorageLive(_6); - StorageLive(_5); - _5 = discriminant(_3); - _6 = Eq(_5, const 1_isize); - StorageDead(_5); - _7 = Not(move _6); - StorageDead(_6); - switchInt(move _7) -> [0: bb2, otherwise: bb3]; - } - - bb2: { - StorageDead(_3); - StorageDead(_4); - goto -> bb4; - } - - bb3: { - StorageDead(_3); - StorageDead(_4); - assert(!const true, "attempt to compute `{} + {}`, which would overflow", const _, const 1_u32) -> [success: bb4, unwind continue]; - } - - bb4: { - StorageDead(_7); - StorageLive(_8); - _8 = _2 as u32 (IntToInt); - _0 = Add(_1, _8); - StorageDead(_8); return; } } diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff index 3108b7d3e13d7..c520a159f47b2 100644 --- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff +++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-abort.diff @@ -28,7 +28,7 @@ bb1: { _4 = discriminant((_1.1: std::option::Option)); - switchInt(move _4) -> [0: bb2, otherwise: bb3]; + switchInt(move _4) -> [0: bb2, 1: bb3, otherwise: bb5]; } bb2: { diff --git a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff index 3ef3be198ede3..686581591fc4e 100644 --- a/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff +++ b/tests/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.panic-unwind.diff @@ -28,7 +28,7 @@ bb1: { _4 = discriminant((_1.1: std::option::Option)); - switchInt(move _4) -> [0: bb2, otherwise: bb3]; + switchInt(move _4) -> [0: bb2, 1: bb3, otherwise: bb5]; } bb2: { diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff index aaede2dd92438..8180428a6f459 100644 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-abort.diff @@ -5,7 +5,7 @@ let mut _0: (); let _1: &str; let mut _2: Test5; - let mut _3: isize; + let mut _3: i8; let _4: &str; let _5: &str; let _6: &str; @@ -15,7 +15,8 @@ StorageLive(_2); _2 = Test5::::C; _3 = discriminant(_2); - switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1]; +- switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, otherwise: bb1]; ++ switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: bb7]; } bb1: { @@ -56,6 +57,10 @@ StorageDead(_1); _0 = const (); return; ++ } ++ ++ bb7: { ++ unreachable; } } diff --git a/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff index edaaa0db588b0..b13d5816aed9d 100644 --- a/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff +++ b/tests/mir-opt/uninhabited_enum_branching.otherwise_t5_uninhabited_default.UninhabitedEnumBranching.panic-unwind.diff @@ -5,7 +5,7 @@ let mut _0: (); let _1: &str; let mut _2: Test5; - let mut _3: isize; + let mut _3: i8; let _4: &str; let _5: &str; let _6: &str; @@ -15,7 +15,8 @@ StorageLive(_2); _2 = Test5::::C; _3 = discriminant(_2); - switchInt(move _3) -> [0: bb2, 1: bb3, 2: bb4, otherwise: bb1]; +- switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, otherwise: bb1]; ++ switchInt(move _3) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: bb8]; } bb1: { @@ -60,6 +61,10 @@ bb7 (cleanup): { resume; ++ } ++ ++ bb8: { ++ unreachable; } } diff --git a/tests/mir-opt/uninhabited_enum_branching.rs b/tests/mir-opt/uninhabited_enum_branching.rs index 866db31f05130..aa606acee44d1 100644 --- a/tests/mir-opt/uninhabited_enum_branching.rs +++ b/tests/mir-opt/uninhabited_enum_branching.rs @@ -32,11 +32,12 @@ enum Test4 { D, } +#[repr(i8)] enum Test5 { - A(T), - B(T), - C, - D, + A(T) = -1, + B(T) = 0, + C = 5, + D = 3, } struct Plop { @@ -165,10 +166,9 @@ fn otherwise_t4() { fn otherwise_t5_uninhabited_default() { // 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: } + // CHECK: switchInt(move [[discr]]) -> [255: bb2, 0: bb3, 5: bb4, 3: bb1, otherwise: [[unreachable:bb.*]]]; + // CHECK: [[unreachable]]: { + // CHECK-NEXT: unreachable; match Test5::::C { Test5::A(_) => "A(T)", Test5::B(_) => "B(T)",