Skip to content

Commit 45dc16f

Browse files
committed
fix check_infinite_loop by checking for break or return inside loop body
1 parent 42f32a0 commit 45dc16f

File tree

3 files changed

+64
-12
lines changed

3 files changed

+64
-12
lines changed

clippy_lints/src/loops.rs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2358,17 +2358,50 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, e
23582358
return;
23592359
};
23602360
let mutable_static_in_cond = var_visitor.def_ids.iter().any(|(_, v)| *v);
2361-
if no_cond_variable_mutated && !mutable_static_in_cond {
2361+
2362+
let mut has_break_or_return_visitor = HasBreakOrReturnVisitor {
2363+
has_break_or_return: false,
2364+
};
2365+
walk_expr(&mut has_break_or_return_visitor, expr);
2366+
let has_break_or_return = has_break_or_return_visitor.has_break_or_return;
2367+
2368+
if no_cond_variable_mutated && !mutable_static_in_cond && !has_break_or_return {
23622369
span_lint(
23632370
cx,
23642371
WHILE_IMMUTABLE_CONDITION,
23652372
cond.span,
2366-
"Variable in the condition are not mutated in the loop body. \
2367-
This either leads to an infinite or to a never running loop.",
2373+
"variables in the condition are not mutated in the loop body. \
2374+
This may lead to an infinite or to a never running loop",
23682375
);
23692376
}
23702377
}
23712378

2379+
struct HasBreakOrReturnVisitor {
2380+
has_break_or_return: bool,
2381+
}
2382+
2383+
impl<'a, 'tcx> Visitor<'tcx> for HasBreakOrReturnVisitor {
2384+
fn visit_expr(&mut self, expr: &'tcx Expr) {
2385+
if self.has_break_or_return {
2386+
return;
2387+
}
2388+
2389+
match expr.kind {
2390+
ExprKind::Ret(_) | ExprKind::Break(_, _) => {
2391+
self.has_break_or_return = true;
2392+
return;
2393+
},
2394+
_ => {},
2395+
}
2396+
2397+
walk_expr(self, expr);
2398+
}
2399+
2400+
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
2401+
NestedVisitorMap::None
2402+
}
2403+
}
2404+
23722405
/// Collects the set of variables in an expression
23732406
/// Stops analysis if a function call is found
23742407
/// Note: In some cases such as `self`, there are no mutable annotation,

tests/ui/infinite_loop.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,23 @@ impl Counter {
177177
}
178178
}
179179

180+
fn while_loop_with_break_and_return() {
181+
let y = 0;
182+
while y < 10 {
183+
if y == 0 {
184+
break;
185+
}
186+
println!("OK - loop contains break");
187+
}
188+
189+
while y < 10 {
190+
if y == 0 {
191+
return;
192+
}
193+
println!("OK - loop contains return");
194+
}
195+
}
196+
180197
fn main() {
181198
immutable_condition();
182199
unused_var();
@@ -186,4 +203,6 @@ fn main() {
186203
let mut c = Counter { count: 0 };
187204
c.inc_n(5);
188205
c.print_n(2);
206+
207+
while_loop_with_break_and_return();
189208
}

tests/ui/infinite_loop.stderr

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,54 @@
1-
error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop.
1+
error: variables in the condition are not mutated in the loop body. This may lead to an infinite or to a never running loop
22
--> $DIR/infinite_loop.rs:23:11
33
|
44
LL | while y < 10 {
55
| ^^^^^^
66
|
77
= note: `#[deny(clippy::while_immutable_condition)]` on by default
88

9-
error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop.
9+
error: variables in the condition are not mutated in the loop body. This may lead to an infinite or to a never running loop
1010
--> $DIR/infinite_loop.rs:28:11
1111
|
1212
LL | while y < 10 && x < 3 {
1313
| ^^^^^^^^^^^^^^^
1414

15-
error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop.
15+
error: variables in the condition are not mutated in the loop body. This may lead to an infinite or to a never running loop
1616
--> $DIR/infinite_loop.rs:35:11
1717
|
1818
LL | while !cond {
1919
| ^^^^^
2020

21-
error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop.
21+
error: variables in the condition are not mutated in the loop body. This may lead to an infinite or to a never running loop
2222
--> $DIR/infinite_loop.rs:79:11
2323
|
2424
LL | while i < 3 {
2525
| ^^^^^
2626

27-
error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop.
27+
error: variables in the condition are not mutated in the loop body. This may lead to an infinite or to a never running loop
2828
--> $DIR/infinite_loop.rs:84:11
2929
|
3030
LL | while i < 3 && j > 0 {
3131
| ^^^^^^^^^^^^^^
3232

33-
error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop.
33+
error: variables in the condition are not mutated in the loop body. This may lead to an infinite or to a never running loop
3434
--> $DIR/infinite_loop.rs:88:11
3535
|
3636
LL | while i < 3 {
3737
| ^^^^^
3838

39-
error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop.
39+
error: variables in the condition are not mutated in the loop body. This may lead to an infinite or to a never running loop
4040
--> $DIR/infinite_loop.rs:103:11
4141
|
4242
LL | while i < 3 {
4343
| ^^^^^
4444

45-
error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop.
45+
error: variables in the condition are not mutated in the loop body. This may lead to an infinite or to a never running loop
4646
--> $DIR/infinite_loop.rs:108:11
4747
|
4848
LL | while i < 3 {
4949
| ^^^^^
5050

51-
error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop.
51+
error: variables in the condition are not mutated in the loop body. This may lead to an infinite or to a never running loop
5252
--> $DIR/infinite_loop.rs:174:15
5353
|
5454
LL | while self.count < n {

0 commit comments

Comments
 (0)