]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_mir_build/src/lints.rs
Ignore unwinding edges when checking for unconditional recursion
[rust.git] / compiler / rustc_mir_build / src / lints.rs
index e4c2d2dce67c7d3883b5614c3e23599a74626e59..b21ca6028a221510c20d5a2be8f4bb4507996ef7 100644 (file)
@@ -11,9 +11,8 @@
 
 crate fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
     let def_id = body.source.def_id().expect_local();
-    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
 
-    if let Some(fn_kind) = tcx.hir().get(hir_id).fn_kind() {
+    if let Some(fn_kind) = tcx.hir().get_by_def_id(def_id).fn_kind() {
         if let FnKind::Closure = fn_kind {
             // closures can't recur, so they don't matter.
             return;
@@ -34,6 +33,9 @@
         if let Some(NonRecursive) = TriColorDepthFirstSearch::new(&body).run_from_start(&mut vis) {
             return;
         }
+        if vis.reachable_recursive_calls.is_empty() {
+            return;
+        }
 
         vis.reachable_recursive_calls.sort();
 
@@ -149,13 +151,14 @@ fn node_settled(&mut self, bb: BasicBlock) -> ControlFlow<Self::BreakVal> {
     }
 
     fn ignore_edge(&mut self, bb: BasicBlock, target: BasicBlock) -> bool {
+        let terminator = self.body[bb].terminator();
+        if terminator.unwind() == Some(&Some(target)) && terminator.successors().count() > 1 {
+            return true;
+        }
         // 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::FalseUnwind { unwind: Some(imaginary_target), .. }
-            | TerminatorKind::FalseEdge { imaginary_target, .. } => imaginary_target == target,
-
+            TerminatorKind::FalseEdge { imaginary_target, .. } => imaginary_target == target,
             _ => false,
         }
     }