mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-23 13:13:34 +00:00
Fix check of immutable condition in closure
This commit is contained in:
parent
b01b0083ba
commit
d458f22d89
2 changed files with 30 additions and 1 deletions
|
@ -2150,8 +2150,20 @@ fn check_infinite_loop<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, cond: &'tcx Expr, b
|
|||
return;
|
||||
}
|
||||
|
||||
if mut_var_visitor.ids.is_empty() {
|
||||
span_lint(
|
||||
cx,
|
||||
WHILE_IMMUTABLE_CONDITION,
|
||||
cond.span,
|
||||
"all variables in condition are immutable. This either leads to an infinite or to a never running loop.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
let mut delegate = MutVarsDelegate {
|
||||
used_mutably: mut_var_visitor.ids,
|
||||
skip: false,
|
||||
};
|
||||
let def_id = def_id::DefId::local(block.hir_id.owner);
|
||||
let region_scope_tree = &cx.tcx.region_scope_tree(def_id);
|
||||
|
@ -2194,7 +2206,10 @@ impl<'a, 'tcx> VarCollectorVisitor<'a, 'tcx> {
|
|||
impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> {
|
||||
fn visit_expr(&mut self, ex: &'tcx Expr) {
|
||||
match ex.node {
|
||||
ExprPath(_) => self.insert_def_id(ex),
|
||||
ExprPath(_) => if let Some(node_id) = check_for_mutability(self.cx, ex) {
|
||||
self.ids.insert(node_id, false);
|
||||
},
|
||||
|
||||
// If there is any fuction/method call… we just stop analysis
|
||||
ExprCall(..) | ExprMethodCall(..) => self.skip = true,
|
||||
|
||||
|
@ -2211,6 +2226,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> {
|
|||
|
||||
struct MutVarsDelegate {
|
||||
used_mutably: HashMap<NodeId, bool>,
|
||||
skip: bool,
|
||||
}
|
||||
|
||||
impl<'tcx> MutVarsDelegate {
|
||||
|
@ -2220,6 +2236,7 @@ impl<'tcx> MutVarsDelegate {
|
|||
if let Some(used) = self.used_mutably.get_mut(&id) {
|
||||
*used = true;
|
||||
},
|
||||
Categorization::Upvar(_) => skip = true,
|
||||
Categorization::Deref(ref cmt, _) => self.update(&cmt.cat, sp),
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
|
||||
|
||||
|
||||
fn fn_val(i: i32) -> i32 { unimplemented!() }
|
||||
fn fn_constref(i: &i32) -> i32 { unimplemented!() }
|
||||
fn fn_mutref(i: &mut i32) { unimplemented!() }
|
||||
fn fooi() -> i32 { unimplemented!() }
|
||||
fn foob() -> bool { unimplemented!() }
|
||||
|
||||
#[allow(many_single_char_names)]
|
||||
fn immutable_condition() {
|
||||
// Should warn when all vars mentionned are immutable
|
||||
let y = 0;
|
||||
|
@ -43,6 +47,14 @@ fn immutable_condition() {
|
|||
println!("OK - Fn call results may vary");
|
||||
}
|
||||
|
||||
let mut a = 0;
|
||||
let mut c = move || {
|
||||
while a < 5 {
|
||||
a += 1;
|
||||
println!("OK - a is mutable");
|
||||
}
|
||||
};
|
||||
c();
|
||||
}
|
||||
|
||||
fn unused_var() {
|
||||
|
|
Loading…
Reference in a new issue