about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-08-11 10:58:13 +0000
committerbors <bors@rust-lang.org>2023-08-11 10:58:13 +0000
commit1e8fdf492808a25d78a97e1242b835ace9924e4d (patch)
treec6c1a0fe00d63070f911e4420addbbf72beff1e7
parent8703661a9a06e32e90a4622c1fb1305ebe50088c (diff)
parenta5f62bdfcdf826c1b03603e9a5bc3a052db853c2 (diff)
downloadrust-1e8fdf492808a25d78a97e1242b835ace9924e4d.tar.gz
rust-1e8fdf492808a25d78a97e1242b835ace9924e4d.zip
Auto merge of #11320 - max-niederman:redundant_locals_shadow_mutated, r=Alexendoo
redundant_locals: fix FPs on mutated shadows

Fixes #11290.

When a mutable binding is shadowed by
a mutable binding of the same name in a different scope, mutations in that scope have different meaning.
This PR fixes spurious `redundant_locals` emissions on such locals.

cc `@Centri3,` `@flip1995`

changelog: [`redundant_locals`]: fix false positives on mutated shadows
-rw-r--r--clippy_lints/src/redundant_locals.rs11
-rw-r--r--tests/ui/redundant_locals.rs9
-rw-r--r--tests/ui/redundant_locals.stderr22
3 files changed, 31 insertions, 11 deletions
diff --git a/clippy_lints/src/redundant_locals.rs b/clippy_lints/src/redundant_locals.rs
index 1271cf38538..a1ebba6a6a8 100644
--- a/clippy_lints/src/redundant_locals.rs
+++ b/clippy_lints/src/redundant_locals.rs
@@ -1,6 +1,7 @@
 use clippy_utils::diagnostics::span_lint_and_help;
 use clippy_utils::is_from_proc_macro;
 use clippy_utils::ty::needs_ordered_drop;
+use rustc_ast::Mutability;
 use rustc_hir::def::Res;
 use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, HirId, Local, Node, Pat, PatKind, QPath};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -62,6 +63,8 @@ impl<'tcx> LateLintPass<'tcx> for RedundantLocals {
             if let Node::Pat(binding_pat) = cx.tcx.hir().get(binding_id);
             // the previous binding has the same mutability
             if find_binding(binding_pat, ident).unwrap().1 == mutability;
+            // the local does not change the effect of assignments to the binding. see #11290
+            if !affects_assignments(cx, mutability, binding_id, local.hir_id);
             // the local does not affect the code's drop behavior
             if !affects_drop_behavior(cx, binding_id, local.hir_id, expr);
             // the local is user-controlled
@@ -94,6 +97,14 @@ fn find_binding(pat: &Pat<'_>, name: Ident) -> Option<BindingAnnotation> {
     ret
 }
 
+/// Check if a rebinding of a local changes the effect of assignments to the binding.
+fn affects_assignments(cx: &LateContext<'_>, mutability: Mutability, bind: HirId, rebind: HirId) -> bool {
+    let hir = cx.tcx.hir();
+
+    // the binding is mutable and the rebinding is in a different scope than the original binding
+    mutability == Mutability::Mut && hir.get_enclosing_scope(bind) != hir.get_enclosing_scope(rebind)
+}
+
 /// Check if a rebinding of a local affects the code's drop behavior.
 fn affects_drop_behavior<'tcx>(cx: &LateContext<'tcx>, bind: HirId, rebind: HirId, rebind_expr: &Expr<'tcx>) -> bool {
     let hir = cx.tcx.hir();
diff --git a/tests/ui/redundant_locals.rs b/tests/ui/redundant_locals.rs
index e74c78a50b6..80af38f47b8 100644
--- a/tests/ui/redundant_locals.rs
+++ b/tests/ui/redundant_locals.rs
@@ -27,6 +27,15 @@ fn downgraded_mutability() {
     let x = x;
 }
 
+// see #11290
+fn shadow_mutation() {
+    let mut x = 1;
+    {
+        let mut x = x;
+        x = 2;
+    }
+}
+
 fn coercion(par: &mut i32) {
     let par: &i32 = par;
 
diff --git a/tests/ui/redundant_locals.stderr b/tests/ui/redundant_locals.stderr
index df07dd2f453..587de057524 100644
--- a/tests/ui/redundant_locals.stderr
+++ b/tests/ui/redundant_locals.stderr
@@ -20,7 +20,7 @@ LL |     let mut x = x;
    = help: remove the redefinition of `x`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:37:14
+  --> $DIR/redundant_locals.rs:46:14
    |
 LL | fn parameter(x: i32) {
    |              ^
@@ -30,7 +30,7 @@ LL |     let x = x;
    = help: remove the redefinition of `x`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:42:9
+  --> $DIR/redundant_locals.rs:51:9
    |
 LL |     let x = 1;
    |         ^
@@ -40,7 +40,7 @@ LL |     let x = x;
    = help: remove the redefinition of `x`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:43:9
+  --> $DIR/redundant_locals.rs:52:9
    |
 LL |     let x = x;
    |         ^
@@ -50,7 +50,7 @@ LL |     let x = x;
    = help: remove the redefinition of `x`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:44:9
+  --> $DIR/redundant_locals.rs:53:9
    |
 LL |     let x = x;
    |         ^
@@ -60,7 +60,7 @@ LL |     let x = x;
    = help: remove the redefinition of `x`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:45:9
+  --> $DIR/redundant_locals.rs:54:9
    |
 LL |     let x = x;
    |         ^
@@ -70,7 +70,7 @@ LL |     let x = x;
    = help: remove the redefinition of `x`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:50:9
+  --> $DIR/redundant_locals.rs:59:9
    |
 LL |     let a = 1;
    |         ^
@@ -81,7 +81,7 @@ LL |     let a = a;
    = help: remove the redefinition of `a`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:51:9
+  --> $DIR/redundant_locals.rs:60:9
    |
 LL |     let b = 2;
    |         ^
@@ -92,7 +92,7 @@ LL |     let b = b;
    = help: remove the redefinition of `b`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:58:13
+  --> $DIR/redundant_locals.rs:67:13
    |
 LL |         let x = 1;
    |             ^
@@ -102,7 +102,7 @@ LL |         let x = x;
    = help: remove the redefinition of `x`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:65:13
+  --> $DIR/redundant_locals.rs:74:13
    |
 LL |         let x = 1;
    |             ^
@@ -112,7 +112,7 @@ LL |         let x = x;
    = help: remove the redefinition of `x`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:68:6
+  --> $DIR/redundant_locals.rs:77:6
    |
 LL |     |x: i32| {
    |      ^
@@ -122,7 +122,7 @@ LL |         let x = x;
    = help: remove the redefinition of `x`
 
 error: redundant redefinition of a binding
-  --> $DIR/redundant_locals.rs:85:9
+  --> $DIR/redundant_locals.rs:94:9
    |
 LL |     let x = 1;
    |         ^