diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index d348aaa899e..b21ca6028a2 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -33,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(); @@ -148,13 +151,14 @@ fn node_settled(&mut self, bb: BasicBlock) -> ControlFlow { } 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, } } diff --git a/src/test/ui/lint/lint-unconditional-recursion.rs b/src/test/ui/lint/lint-unconditional-recursion.rs index d2a0329585b..ad052d36f20 100644 --- a/src/test/ui/lint/lint-unconditional-recursion.rs +++ b/src/test/ui/lint/lint-unconditional-recursion.rs @@ -149,4 +149,46 @@ pub fn panics(x: bool) { } } +pub fn unreachable1() { + panic!(); + unreachable1(); // WARN unreachable statement +} + +pub fn unreachable2() { + loop {} + unreachable2(); // WARN unreachable statement +} + +pub fn drop_and_replace(mut a: Option) { //~ ERROR function cannot return without recursing + a = None; + drop_and_replace(a); +} + +// Calls are assumed to return normally. +pub fn call() -> String { //~ ERROR function cannot return without recursing + let s = String::new(); + call(); + s +} + +// Arithmetic operations are assumed not to overflow. +pub fn overflow_check(a: i32, b: i32) { //~ ERROR function cannot return without recursing + let _ = a + b; + overflow_check(a, b); +} + +pub struct Point { + pub x: f32, + pub y: f32, +} + +impl Default for Point { + fn default() -> Self { //~ ERROR function cannot return without recursing + Point { + x: Default::default(), + ..Default::default() + } + } +} + fn main() {} diff --git a/src/test/ui/lint/lint-unconditional-recursion.stderr b/src/test/ui/lint/lint-unconditional-recursion.stderr index fb884e31299..c11b73f41ca 100644 --- a/src/test/ui/lint/lint-unconditional-recursion.stderr +++ b/src/test/ui/lint/lint-unconditional-recursion.stderr @@ -153,5 +153,49 @@ LL | self.as_ref() | = help: a `loop` may express intention better if this is on purpose -error: aborting due to 14 previous errors +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:162:1 + | +LL | pub fn drop_and_replace(mut a: Option) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | a = None; +LL | drop_and_replace(a); + | ------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:168:1 + | +LL | pub fn call() -> String { + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | let s = String::new(); +LL | call(); + | ------ recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:175:1 + | +LL | pub fn overflow_check(a: i32, b: i32) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | let _ = a + b; +LL | overflow_check(a, b); + | -------------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: function cannot return without recursing + --> $DIR/lint-unconditional-recursion.rs:186:5 + | +LL | fn default() -> Self { + | ^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +... +LL | ..Default::default() + | ------------------ recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +error: aborting due to 18 previous errors diff --git a/src/test/ui/recursion/issue-83150.rs b/src/test/ui/recursion/issue-83150.rs index 650ad22d206..dc25004f89b 100644 --- a/src/test/ui/recursion/issue-83150.rs +++ b/src/test/ui/recursion/issue-83150.rs @@ -6,6 +6,6 @@ fn main() { func(&mut iter) } -fn func>(iter: &mut T) { +fn func>(iter: &mut T) { //~ WARN function cannot return without recursing func(&mut iter.map(|x| x + 1)) } diff --git a/src/test/ui/recursion/issue-83150.stderr b/src/test/ui/recursion/issue-83150.stderr index d45bfc3ca55..4c8469be626 100644 --- a/src/test/ui/recursion/issue-83150.stderr +++ b/src/test/ui/recursion/issue-83150.stderr @@ -1,8 +1,19 @@ +warning: function cannot return without recursing + --> $DIR/issue-83150.rs:9:1 + | +LL | fn func>(iter: &mut T) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | func(&mut iter.map(|x| x + 1)) + | ------------------------------ recursive call site + | + = note: `#[warn(unconditional_recursion)]` on by default + = help: a `loop` may express intention better if this is on purpose + error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>: Iterator` | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`) = note: required because of the requirements on the impl of `Iterator` for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>, [closure@$DIR/issue-83150.rs:10:24: 10:33]>` -error: aborting due to previous error +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0275`.