Skip to content

Commit 2342e6e

Browse files
committed
fix check_infinite_loop by checking for break or return inside loop body
1 parent 180f870 commit 2342e6e

File tree

3 files changed

+64
-12
lines changed

3 files changed

+64
-12
lines changed

clippy_lints/src/loops.rs

+36-3
Original file line numberDiff line numberDiff line change
@@ -2367,17 +2367,50 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, e
23672367
return;
23682368
};
23692369
let mutable_static_in_cond = var_visitor.def_ids.iter().any(|(_, v)| *v);
2370-
if no_cond_variable_mutated && !mutable_static_in_cond {
2370+
2371+
let mut has_break_or_return_visitor = HasBreakOrReturnVisitor {
2372+
has_break_or_return: false,
2373+
};
2374+
walk_expr(&mut has_break_or_return_visitor, expr);
2375+
let has_break_or_return = has_break_or_return_visitor.has_break_or_return;
2376+
2377+
if no_cond_variable_mutated && !mutable_static_in_cond && !has_break_or_return {
23712378
span_lint(
23722379
cx,
23732380
WHILE_IMMUTABLE_CONDITION,
23742381
cond.span,
2375-
"Variable in the condition are not mutated in the loop body. \
2376-
This either leads to an infinite or to a never running loop.",
2382+
"variables in the condition are not mutated in the loop body. \
2383+
This may lead to an infinite or to a never running loop",
23772384
);
23782385
}
23792386
}
23802387

2388+
struct HasBreakOrReturnVisitor {
2389+
has_break_or_return: bool,
2390+
}
2391+
2392+
impl<'a, 'tcx> Visitor<'tcx> for HasBreakOrReturnVisitor {
2393+
fn visit_expr(&mut self, expr: &'tcx Expr) {
2394+
if self.has_break_or_return {
2395+
return;
2396+
}
2397+
2398+
match expr.kind {
2399+
ExprKind::Ret(_) | ExprKind::Break(_, _) => {
2400+
self.has_break_or_return = true;
2401+
return;
2402+
},
2403+
_ => {},
2404+
}
2405+
2406+
walk_expr(self, expr);
2407+
}
2408+
2409+
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
2410+
NestedVisitorMap::None
2411+
}
2412+
}
2413+
23812414
/// Collects the set of variables in an expression
23822415
/// Stops analysis if a function call is found
23832416
/// Note: In some cases such as `self`, there are no mutable annotation,

tests/ui/infinite_loop.rs

+19
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

+9-9
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)