@@ -64,6 +64,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
64
64
tcx,
65
65
param_env,
66
66
mir_phase,
67
+ unwind_edge_count : 0 ,
67
68
reachable_blocks : traversal:: reachable_as_bitset ( body) ,
68
69
storage_liveness,
69
70
place_cache : Vec :: new ( ) ,
@@ -80,6 +81,7 @@ struct TypeChecker<'a, 'tcx> {
80
81
tcx : TyCtxt < ' tcx > ,
81
82
param_env : ParamEnv < ' tcx > ,
82
83
mir_phase : MirPhase ,
84
+ unwind_edge_count : usize ,
83
85
reachable_blocks : BitSet < BasicBlock > ,
84
86
storage_liveness : ResultsCursor < ' a , ' tcx , MaybeStorageLive < ' static > > ,
85
87
place_cache : Vec < PlaceRef < ' tcx > > ,
@@ -104,7 +106,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
104
106
) ;
105
107
}
106
108
107
- fn check_edge ( & self , location : Location , bb : BasicBlock , edge_kind : EdgeKind ) {
109
+ fn check_edge ( & mut self , location : Location , bb : BasicBlock , edge_kind : EdgeKind ) {
108
110
if bb == START_BLOCK {
109
111
self . fail ( location, "start block must not have predecessors" )
110
112
}
@@ -113,10 +115,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
113
115
match ( src. is_cleanup , bb. is_cleanup , edge_kind) {
114
116
// Non-cleanup blocks can jump to non-cleanup blocks along non-unwind edges
115
117
( false , false , EdgeKind :: Normal )
116
- // Non-cleanup blocks can jump to cleanup blocks along unwind edges
117
- | ( false , true , EdgeKind :: Unwind )
118
118
// Cleanup blocks can jump to cleanup blocks along non-unwind edges
119
119
| ( true , true , EdgeKind :: Normal ) => { }
120
+ // Non-cleanup blocks can jump to cleanup blocks along unwind edges
121
+ ( false , true , EdgeKind :: Unwind ) => {
122
+ self . unwind_edge_count += 1 ;
123
+ }
120
124
// All other jumps are invalid
121
125
_ => {
122
126
self . fail (
@@ -137,6 +141,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
137
141
}
138
142
139
143
fn check_cleanup_control_flow ( & self ) {
144
+ if self . unwind_edge_count <= 1 {
145
+ return ;
146
+ }
140
147
let doms = self . body . basic_blocks . dominators ( ) ;
141
148
let mut post_contract_node = FxHashMap :: default ( ) ;
142
149
// Reusing the allocation across invocations of the closure
@@ -196,7 +203,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
196
203
stack. clear ( ) ;
197
204
stack. insert ( bb) ;
198
205
loop {
199
- let Some ( parent ) = parent[ bb] . take ( ) else {
206
+ let Some ( parent) = parent[ bb] . take ( ) else {
200
207
break
201
208
} ;
202
209
let no_cycle = stack. insert ( parent) ;
0 commit comments