about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-04-30 15:08:27 +0000
committerbors <bors@rust-lang.org>2021-04-30 15:08:27 +0000
commita300b0e66ce819833c4de4439ea3044a4c89eda3 (patch)
treeb2d1f7727897bb8bd95d8716ce053ac6ac4a8425
parent5e49c4bd67d69131265cb414a29d5489a9eb35a1 (diff)
parent63425de77db7f4dee55cfceeed7e174bfe986b0d (diff)
downloadrust-a300b0e66ce819833c4de4439ea3044a4c89eda3.tar.gz
rust-a300b0e66ce819833c4de4439ea3044a4c89eda3.zip
Auto merge of #7144 - rust-lang:while_immutable_mut_cond, r=flip1995
while_immutable_cond: check condition for mutation

This fixes #6689 by also checking the bindings mutated in the condition, whereas it was previously only checked in the loop body.

---

changelog: Fix FP in [`while_immutable_cond`] where mutation in the loop variable wasn't picked up.
-rw-r--r--clippy_lints/src/loops/while_immutable_condition.rs13
-rw-r--r--tests/ui/infinite_loop.rs12
2 files changed, 20 insertions, 5 deletions
diff --git a/clippy_lints/src/loops/while_immutable_condition.rs b/clippy_lints/src/loops/while_immutable_condition.rs
index de267cc77d2..55404b87ec9 100644
--- a/clippy_lints/src/loops/while_immutable_condition.rs
+++ b/clippy_lints/src/loops/while_immutable_condition.rs
@@ -28,11 +28,14 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, cond: &'tcx Expr<'_>, expr: &'
         return;
     }
     let used_in_condition = &var_visitor.ids;
-    let no_cond_variable_mutated = if let Some(used_mutably) = mutated_variables(expr, cx) {
-        used_in_condition.is_disjoint(&used_mutably)
-    } else {
-        return;
-    };
+    let mutated_in_body = mutated_variables(expr, cx);
+    let mutated_in_condition = mutated_variables(cond, cx);
+    let no_cond_variable_mutated =
+        if let (Some(used_mutably_body), Some(used_mutably_cond)) = (mutated_in_body, mutated_in_condition) {
+            used_in_condition.is_disjoint(&used_mutably_body) && used_in_condition.is_disjoint(&used_mutably_cond)
+        } else {
+            return;
+        };
     let mutable_static_in_cond = var_visitor.def_ids.iter().any(|(_, v)| *v);
 
     let mut has_break_or_return_visitor = HasBreakOrReturnVisitor {
diff --git a/tests/ui/infinite_loop.rs b/tests/ui/infinite_loop.rs
index 72591f12baf..3d8fb8507e5 100644
--- a/tests/ui/infinite_loop.rs
+++ b/tests/ui/infinite_loop.rs
@@ -192,11 +192,23 @@ fn while_loop_with_break_and_return() {
     }
 }
 
+fn immutable_condition_false_positive(mut n: u64) -> u32 {
+    let mut count = 0;
+    while {
+        n >>= 1;
+        n != 0
+    } {
+        count += 1;
+    }
+    count
+}
+
 fn main() {
     immutable_condition();
     unused_var();
     used_immutable();
     internally_mutable();
+    immutable_condition_false_positive(5);
 
     let mut c = Counter { count: 0 };
     c.inc_n(5);