Skip to content

Commit eed34b8

Browse files
committed
Add is_recursive_terminator() helper for unconditional_recursion lint
1 parent f92d669 commit eed34b8

File tree

1 file changed

+13
-10
lines changed

1 file changed

+13
-10
lines changed

Diff for: compiler/rustc_mir_build/src/lints.rs

+13-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc_data_structures::graph::iterate::{
33
NodeStatus, TriColorDepthFirstSearch, TriColorVisitor,
44
};
55
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};
77
use rustc_middle::ty::{self, Instance, TyCtxt};
88
use rustc_middle::ty::{GenericArg, GenericArgs};
99
use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION;
@@ -57,6 +57,13 @@ struct Search<'mir, 'tcx> {
5757
}
5858

5959
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+
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

Comments
 (0)