Auto merge of #13512 - samueltardieu:issue-13511, r=xFrednet
`infinite_loop`: continuing an outer loop leaves the inner loop changelog: [`infinite_loop`]: detect a `continue` targeting an outer loop Fix #13511
This commit is contained in:
commit
d9c8d976cb
@ -42,6 +42,7 @@ pub(super) fn check<'tcx>(
|
||||
let mut loop_visitor = LoopVisitor {
|
||||
cx,
|
||||
label,
|
||||
inner_labels: label.into_iter().collect(),
|
||||
is_finite: false,
|
||||
loop_depth: 0,
|
||||
};
|
||||
@ -93,6 +94,7 @@ fn get_parent_fn_ret_ty<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> Option
|
||||
struct LoopVisitor<'hir, 'tcx> {
|
||||
cx: &'hir LateContext<'tcx>,
|
||||
label: Option<Label>,
|
||||
inner_labels: Vec<Label>,
|
||||
loop_depth: usize,
|
||||
is_finite: bool,
|
||||
}
|
||||
@ -108,11 +110,24 @@ fn visit_expr(&mut self, ex: &'hir Expr<'_>) {
|
||||
self.is_finite = true;
|
||||
}
|
||||
},
|
||||
ExprKind::Continue(hir::Destination { label, .. }) => {
|
||||
// Check whether we are leaving this loop by continuing into an outer loop
|
||||
// whose label we did not encounter.
|
||||
if label.is_some_and(|label| !self.inner_labels.contains(&label)) {
|
||||
self.is_finite = true;
|
||||
}
|
||||
},
|
||||
ExprKind::Ret(..) => self.is_finite = true,
|
||||
ExprKind::Loop(..) => {
|
||||
ExprKind::Loop(_, label, _, _) => {
|
||||
if let Some(label) = label {
|
||||
self.inner_labels.push(*label);
|
||||
}
|
||||
self.loop_depth += 1;
|
||||
walk_expr(self, ex);
|
||||
self.loop_depth -= 1;
|
||||
if label.is_some() {
|
||||
self.inner_labels.pop();
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
// Calls to a function that never return
|
||||
|
@ -390,4 +390,42 @@ fn span_inside_fn() {
|
||||
}
|
||||
}
|
||||
|
||||
fn continue_outer() {
|
||||
// Should not lint (issue #13511)
|
||||
let mut count = 0;
|
||||
'outer: loop {
|
||||
if count != 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
loop {
|
||||
count += 1;
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
|
||||
// This should lint as we continue the loop itself
|
||||
'infinite: loop {
|
||||
//~^ ERROR: infinite loop detected
|
||||
loop {
|
||||
continue 'infinite;
|
||||
}
|
||||
}
|
||||
// This should lint as we continue an inner loop
|
||||
loop {
|
||||
//~^ ERROR: infinite loop detected
|
||||
'inner: loop {
|
||||
loop {
|
||||
continue 'inner;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This should lint as we continue the loop itself
|
||||
loop {
|
||||
//~^ ERROR: infinite loop detected
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -255,5 +255,67 @@ LL | | })
|
||||
|
|
||||
= help: if this is not intended, try adding a `break` or `return` condition in the loop
|
||||
|
||||
error: aborting due to 17 previous errors
|
||||
error: infinite loop detected
|
||||
--> tests/ui/infinite_loops.rs:408:5
|
||||
|
|
||||
LL | / 'infinite: loop {
|
||||
LL | |
|
||||
LL | | loop {
|
||||
LL | | continue 'infinite;
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
help: if this is intentional, consider specifying `!` as function return
|
||||
|
|
||||
LL | fn continue_outer() -> ! {
|
||||
| ++++
|
||||
|
||||
error: infinite loop detected
|
||||
--> tests/ui/infinite_loops.rs:415:5
|
||||
|
|
||||
LL | / loop {
|
||||
LL | |
|
||||
LL | | 'inner: loop {
|
||||
LL | | loop {
|
||||
... |
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
help: if this is intentional, consider specifying `!` as function return
|
||||
|
|
||||
LL | fn continue_outer() -> ! {
|
||||
| ++++
|
||||
|
||||
error: infinite loop detected
|
||||
--> tests/ui/infinite_loops.rs:417:9
|
||||
|
|
||||
LL | / 'inner: loop {
|
||||
LL | | loop {
|
||||
LL | | continue 'inner;
|
||||
LL | | }
|
||||
LL | | }
|
||||
| |_________^
|
||||
|
|
||||
help: if this is intentional, consider specifying `!` as function return
|
||||
|
|
||||
LL | fn continue_outer() -> ! {
|
||||
| ++++
|
||||
|
||||
error: infinite loop detected
|
||||
--> tests/ui/infinite_loops.rs:425:5
|
||||
|
|
||||
LL | / loop {
|
||||
LL | |
|
||||
LL | | continue;
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
help: if this is intentional, consider specifying `!` as function return
|
||||
|
|
||||
LL | fn continue_outer() -> ! {
|
||||
| ++++
|
||||
|
||||
error: aborting due to 21 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user