@@ -4,7 +4,8 @@ use crate::MirPass;
44use rustc_data_structures:: fx:: FxHashSet ;
55use rustc_middle:: mir:: patch:: MirPatch ;
66use rustc_middle:: mir:: {
7- BasicBlockData , Body , Local , Operand , Rvalue , StatementKind , TerminatorKind ,
7+ BasicBlock , BasicBlockData , BasicBlocks , Body , Local , Operand , Rvalue , StatementKind ,
8+ TerminatorKind ,
89} ;
910use rustc_middle:: ty:: layout:: TyAndLayout ;
1011use rustc_middle:: ty:: { Ty , TyCtxt } ;
@@ -118,9 +119,28 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
118119 unreachable_targets. push ( index) ;
119120 }
120121 }
121-
122- let replace_otherwise_to_unreachable = allowed_variants. len ( ) <= 1
123- && !body. basic_blocks [ targets. otherwise ( ) ] . is_empty_unreachable ( ) ;
122+ let otherwise_is_empty_unreachable =
123+ body. basic_blocks [ targets. otherwise ( ) ] . is_empty_unreachable ( ) ;
124+ // After resolving https://github.com/llvm/llvm-project/issues/78578,
125+ // we can remove the limit on the number of successors.
126+ fn check_successors ( basic_blocks : & BasicBlocks < ' _ > , bb : BasicBlock ) -> bool {
127+ let mut successors = basic_blocks[ bb] . terminator ( ) . successors ( ) ;
128+ let Some ( first_successor) = successors. next ( ) else { return true } ;
129+ if successors. next ( ) . is_some ( ) {
130+ return true ;
131+ }
132+ if let TerminatorKind :: SwitchInt { .. } =
133+ & basic_blocks[ first_successor] . terminator ( ) . kind
134+ {
135+ return false ;
136+ } ;
137+ true
138+ }
139+ let otherwise_is_last_variant = !otherwise_is_empty_unreachable
140+ && allowed_variants. len ( ) == 1
141+ && check_successors ( & body. basic_blocks , targets. otherwise ( ) ) ;
142+ let replace_otherwise_to_unreachable = otherwise_is_last_variant
143+ || !otherwise_is_empty_unreachable && allowed_variants. is_empty ( ) ;
124144
125145 if unreachable_targets. is_empty ( ) && !replace_otherwise_to_unreachable {
126146 continue ;
@@ -129,7 +149,6 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
129149 let unreachable_block = patch. unreachable_no_cleanup_block ( ) ;
130150 let mut targets = targets. clone ( ) ;
131151 if replace_otherwise_to_unreachable {
132- let otherwise_is_last_variant = !allowed_variants. is_empty ( ) ;
133152 if otherwise_is_last_variant {
134153 #[ allow( rustc:: potential_query_instability) ]
135154 let last_variant = * allowed_variants. iter ( ) . next ( ) . unwrap ( ) ;
0 commit comments