about summary refs log tree commit diff
path: root/compiler/rustc_mir_build/src/lints.rs
diff options
context:
space:
mode:
authorTomasz Miąsko <tomasz.miasko@gmail.com>2022-01-27 00:00:00 +0000
committerTomasz Miąsko <tomasz.miasko@gmail.com>2022-01-29 23:00:54 +0100
commit35b5daaaf8ab7675c940687c0898fb4d0300c850 (patch)
tree067a518fec04b7925f80e11f3cb9ab65ed88b171 /compiler/rustc_mir_build/src/lints.rs
parenta00e130dae74a213338e2b095ec855156d8f3d8a (diff)
downloadrust-35b5daaaf8ab7675c940687c0898fb4d0300c850.tar.gz
rust-35b5daaaf8ab7675c940687c0898fb4d0300c850.zip
Check the number of arguments first in `is_recursive_call`
Diffstat (limited to 'compiler/rustc_mir_build/src/lints.rs')
-rw-r--r--compiler/rustc_mir_build/src/lints.rs14
1 files changed, 10 insertions, 4 deletions
diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs
index b21ca6028a2..bccff379873 100644
--- a/compiler/rustc_mir_build/src/lints.rs
+++ b/compiler/rustc_mir_build/src/lints.rs
@@ -66,8 +66,14 @@ struct Search<'mir, 'tcx> {
 
 impl<'mir, 'tcx> Search<'mir, 'tcx> {
     /// Returns `true` if `func` refers to the function we are searching in.
-    fn is_recursive_call(&self, func: &Operand<'tcx>) -> bool {
+    fn is_recursive_call(&self, func: &Operand<'tcx>, args: &[Operand<'tcx>]) -> bool {
         let Search { tcx, body, trait_substs, .. } = *self;
+        // Resolving function type to a specific instance that is being called is expensive.  To
+        // avoid the cost we check the number of arguments first, which is sufficient to reject
+        // most of calls as non-recursive.
+        if args.len() != body.arg_count {
+            return false;
+        }
         let caller = body.source.def_id();
         let param_env = tcx.param_env(caller);
 
@@ -141,8 +147,8 @@ impl<'mir, 'tcx> TriColorVisitor<&'mir Body<'tcx>> for Search<'mir, 'tcx> {
     fn node_settled(&mut self, bb: BasicBlock) -> ControlFlow<Self::BreakVal> {
         // When we examine a node for the last time, remember it if it is a recursive call.
         let terminator = self.body[bb].terminator();
-        if let TerminatorKind::Call { func, .. } = &terminator.kind {
-            if self.is_recursive_call(func) {
+        if let TerminatorKind::Call { func, args, .. } = &terminator.kind {
+            if self.is_recursive_call(func, args) {
                 self.reachable_recursive_calls.push(terminator.source_info.span);
             }
         }
@@ -157,7 +163,7 @@ impl<'mir, 'tcx> TriColorVisitor<&'mir Body<'tcx>> for Search<'mir, 'tcx> {
         }
         // Don't traverse successors of recursive calls or false CFG edges.
         match self.body[bb].terminator().kind {
-            TerminatorKind::Call { ref func, .. } => self.is_recursive_call(func),
+            TerminatorKind::Call { ref func, ref args, .. } => self.is_recursive_call(func, args),
             TerminatorKind::FalseEdge { imaginary_target, .. } => imaginary_target == target,
             _ => false,
         }