Skip to content

Commit d458f22

Browse files
committed
Fix check of immutable condition in closure
1 parent b01b008 commit d458f22

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

clippy_lints/src/loops.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2150,8 +2150,20 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, b
21502150
return;
21512151
}
21522152

2153+
if mut_var_visitor.ids.is_empty() {
2154+
span_lint(
2155+
cx,
2156+
WHILE_IMMUTABLE_CONDITION,
2157+
cond.span,
2158+
"all variables in condition are immutable. This either leads to an infinite or to a never running loop.",
2159+
);
2160+
return;
2161+
}
2162+
2163+
21532164
let mut delegate = MutVarsDelegate {
21542165
used_mutably: mut_var_visitor.ids,
2166+
skip: false,
21552167
};
21562168
let def_id = def_id::DefId::local(block.hir_id.owner);
21572169
let region_scope_tree = &cx.tcx.region_scope_tree(def_id);
@@ -2194,7 +2206,10 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> {
21942206
impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> {
21952207
fn visit_expr(&mut self, ex: &'tcx Expr) {
21962208
match ex.node {
2197-
ExprPath(_) => self.insert_def_id(ex),
2209+
ExprPath(_) => if let Some(node_id) = check_for_mutability(self.cx, ex) {
2210+
self.ids.insert(node_id, false);
2211+
},
2212+
21982213
// If there is any fuction/method call… we just stop analysis
21992214
ExprCall(..) | ExprMethodCall(..) => self.skip = true,
22002215

@@ -2211,6 +2226,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> {
22112226

22122227
struct MutVarsDelegate {
22132228
used_mutably: HashMap<NodeId, bool>,
2229+
skip: bool,
22142230
}
22152231

22162232
impl<'tcx> MutVarsDelegate {
@@ -2220,6 +2236,7 @@ impl<'tcx> MutVarsDelegate {
22202236
if let Some(used) = self.used_mutably.get_mut(&id) {
22212237
*used = true;
22222238
},
2239+
Categorization::Upvar(_) => skip = true,
22232240
Categorization::Deref(ref cmt, _) => self.update(&cmt.cat, sp),
22242241
_ => {}
22252242
}

tests/ui/infinite_loop.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1+
2+
3+
14
fn fn_val(i: i32) -> i32 { unimplemented!() }
25
fn fn_constref(i: &i32) -> i32 { unimplemented!() }
36
fn fn_mutref(i: &mut i32) { unimplemented!() }
47
fn fooi() -> i32 { unimplemented!() }
58
fn foob() -> bool { unimplemented!() }
69

10+
#[allow(many_single_char_names)]
711
fn immutable_condition() {
812
// Should warn when all vars mentionned are immutable
913
let y = 0;
@@ -43,6 +47,14 @@ fn immutable_condition() {
4347
println!("OK - Fn call results may vary");
4448
}
4549

50+
let mut a = 0;
51+
let mut c = move || {
52+
while a < 5 {
53+
a += 1;
54+
println!("OK - a is mutable");
55+
}
56+
};
57+
c();
4658
}
4759

4860
fn unused_var() {

0 commit comments

Comments
 (0)