@@ -3,7 +3,7 @@ use rustc_data_structures::graph::iterate::{
3
3
NodeStatus , TriColorDepthFirstSearch , TriColorVisitor ,
4
4
} ;
5
5
use rustc_hir:: def:: DefKind ;
6
- use rustc_middle:: mir:: { self , BasicBlock , BasicBlocks , Body , Operand , TerminatorKind } ;
6
+ use rustc_middle:: mir:: { self , BasicBlock , BasicBlocks , Body , Operand , Terminator , TerminatorKind } ;
7
7
use rustc_middle:: ty:: { self , Instance , TyCtxt } ;
8
8
use rustc_middle:: ty:: { GenericArg , GenericArgs } ;
9
9
use rustc_session:: lint:: builtin:: UNCONDITIONAL_RECURSION ;
@@ -57,6 +57,13 @@ struct Search<'mir, 'tcx> {
57
57
}
58
58
59
59
impl < ' mir , ' tcx > Search < ' mir , ' tcx > {
60
+ fn is_recursive_terminator ( & self , terminator : & Terminator < ' tcx > ) -> bool {
61
+ match & terminator. kind {
62
+ TerminatorKind :: Call { func, args, .. } => self . is_recursive_call ( func, args) ,
63
+ _ => false ,
64
+ }
65
+ }
66
+
60
67
/// Returns `true` if `func` refers to the function we are searching in.
61
68
fn is_recursive_call ( & self , func : & Operand < ' tcx > , args : & [ Operand < ' tcx > ] ) -> bool {
62
69
let Search { tcx, body, trait_args, .. } = * self ;
@@ -138,25 +145,21 @@ impl<'mir, 'tcx> TriColorVisitor<BasicBlocks<'tcx>> for Search<'mir, 'tcx> {
138
145
fn node_settled ( & mut self , bb : BasicBlock ) -> ControlFlow < Self :: BreakVal > {
139
146
// When we examine a node for the last time, remember it if it is a recursive call.
140
147
let terminator = self . body [ bb] . terminator ( ) ;
141
- if let TerminatorKind :: Call { func, args, .. } = & terminator. kind {
142
- if self . is_recursive_call ( func, args) {
143
- self . reachable_recursive_calls . push ( terminator. source_info . span ) ;
144
- }
148
+ if self . is_recursive_terminator ( terminator) {
149
+ self . reachable_recursive_calls . push ( terminator. source_info . span ) ;
145
150
}
146
151
147
152
ControlFlow :: Continue ( ( ) )
148
153
}
149
154
150
155
fn ignore_edge ( & mut self , bb : BasicBlock , target : BasicBlock ) -> bool {
151
156
let terminator = self . body [ bb] . terminator ( ) ;
152
- if terminator. unwind ( ) == Some ( & mir:: UnwindAction :: Cleanup ( target) )
153
- && terminator. successors ( ) . count ( ) > 1
154
- {
157
+ let ignore_unwind = terminator. unwind ( ) == Some ( & mir:: UnwindAction :: Cleanup ( target) )
158
+ && terminator. successors ( ) . count ( ) > 1 ;
159
+ if ignore_unwind || self . is_recursive_terminator ( terminator ) {
155
160
return true ;
156
161
}
157
- // Don't traverse successors of recursive calls or false CFG edges.
158
162
match & terminator. kind {
159
- TerminatorKind :: Call { func, args, .. } => self . is_recursive_call ( func, args) ,
160
163
TerminatorKind :: FalseEdge { imaginary_target, .. } => imaginary_target == & target,
161
164
_ => false ,
162
165
}
0 commit comments