@@ -3,7 +3,7 @@ use rustc_data_structures::graph::iterate::{
33 NodeStatus , TriColorDepthFirstSearch , TriColorVisitor ,
44} ;
55use 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 } ;
77use rustc_middle:: ty:: { self , Instance , TyCtxt } ;
88use rustc_middle:: ty:: { GenericArg , GenericArgs } ;
99use rustc_session:: lint:: builtin:: UNCONDITIONAL_RECURSION ;
@@ -57,6 +57,13 @@ struct Search<'mir, 'tcx> {
5757}
5858
5959impl < ' 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+
6067 /// Returns `true` if `func` refers to the function we are searching in.
6168 fn is_recursive_call ( & self , func : & Operand < ' tcx > , args : & [ Operand < ' tcx > ] ) -> bool {
6269 let Search { tcx, body, trait_args, .. } = * self ;
@@ -138,25 +145,21 @@ impl<'mir, 'tcx> TriColorVisitor<BasicBlocks<'tcx>> for Search<'mir, 'tcx> {
138145 fn node_settled ( & mut self , bb : BasicBlock ) -> ControlFlow < Self :: BreakVal > {
139146 // When we examine a node for the last time, remember it if it is a recursive call.
140147 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 ) ;
145150 }
146151
147152 ControlFlow :: Continue ( ( ) )
148153 }
149154
150155 fn ignore_edge ( & mut self , bb : BasicBlock , target : BasicBlock ) -> bool {
151156 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 ) {
155160 return true ;
156161 }
157- // Don't traverse successors of recursive calls or false CFG edges.
158162 match & terminator. kind {
159- TerminatorKind :: Call { func, args, .. } => self . is_recursive_call ( func, args) ,
160163 TerminatorKind :: FalseEdge { imaginary_target, .. } => imaginary_target == & target,
161164 _ => false ,
162165 }
0 commit comments