about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/methods/iter_kv_map.rs22
-rw-r--r--tests/ui/iter_kv_map.fixed35
-rw-r--r--tests/ui/iter_kv_map.rs39
-rw-r--r--tests/ui/iter_kv_map.stderr114
4 files changed, 175 insertions, 35 deletions
diff --git a/clippy_lints/src/methods/iter_kv_map.rs b/clippy_lints/src/methods/iter_kv_map.rs
index 2244ebfb129..c87f5daab6f 100644
--- a/clippy_lints/src/methods/iter_kv_map.rs
+++ b/clippy_lints/src/methods/iter_kv_map.rs
@@ -6,7 +6,7 @@ use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::sugg;
 use clippy_utils::ty::is_type_diagnostic_item;
 use clippy_utils::visitors::is_local_used;
-use rustc_hir::{BindingAnnotation, Body, BorrowKind, Expr, ExprKind, Mutability, Pat, PatKind};
+use rustc_hir::{BindingAnnotation, Body, BorrowKind, ByRef, Expr, ExprKind, Mutability, Pat, PatKind};
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::ty;
 use rustc_span::sym;
@@ -30,9 +30,9 @@ pub(super) fn check<'tcx>(
         if let Body {params: [p], value: body_expr, generator_kind: _ } = cx.tcx.hir().body(c.body);
         if let PatKind::Tuple([key_pat, val_pat], _) = p.pat.kind;
 
-        let (replacement_kind, binded_ident) = match (&key_pat.kind, &val_pat.kind) {
-            (key, PatKind::Binding(_, _, value, _)) if pat_is_wild(cx, key, m_arg) => ("value", value),
-            (PatKind::Binding(_, _, key, _), value) if pat_is_wild(cx, value, m_arg) => ("key", key),
+        let (replacement_kind, annotation, bound_ident) = match (&key_pat.kind, &val_pat.kind) {
+            (key, PatKind::Binding(ann, _, value, _)) if pat_is_wild(cx, key, m_arg) => ("value", ann, value),
+            (PatKind::Binding(ann, _, key, _), value) if pat_is_wild(cx, value, m_arg) => ("key", ann, key),
             _ => return,
         };
 
@@ -47,7 +47,7 @@ pub(super) fn check<'tcx>(
             if_chain! {
                 if let ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body_expr.kind;
                 if let [local_ident] = path.segments;
-                if local_ident.ident.as_str() == binded_ident.as_str();
+                if local_ident.ident.as_str() == bound_ident.as_str();
 
                 then {
                     span_lint_and_sugg(
@@ -60,13 +60,23 @@ pub(super) fn check<'tcx>(
                         applicability,
                     );
                 } else {
+                    let ref_annotation = if annotation.0 == ByRef::Yes {
+                        "ref "
+                    } else {
+                        ""
+                    };
+                    let mut_annotation = if annotation.1 == Mutability::Mut {
+                        "mut "
+                    } else {
+                        ""
+                    };
                     span_lint_and_sugg(
                         cx,
                         ITER_KV_MAP,
                         expr.span,
                         &format!("iterating on a map's {replacement_kind}s"),
                         "try",
-                        format!("{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{binded_ident}| {})",
+                        format!("{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{ref_annotation}{mut_annotation}{bound_ident}| {})",
                             snippet_with_applicability(cx, body_expr.span, "/* body */", &mut applicability)),
                         applicability,
                     );
diff --git a/tests/ui/iter_kv_map.fixed b/tests/ui/iter_kv_map.fixed
index 83fee04080f..f2a4c284cb1 100644
--- a/tests/ui/iter_kv_map.fixed
+++ b/tests/ui/iter_kv_map.fixed
@@ -1,14 +1,15 @@
 // run-rustfix
 
 #![warn(clippy::iter_kv_map)]
-#![allow(clippy::redundant_clone)]
-#![allow(clippy::suspicious_map)]
-#![allow(clippy::map_identity)]
+#![allow(unused_mut, clippy::redundant_clone, clippy::suspicious_map, clippy::map_identity)]
 
 use std::collections::{BTreeMap, HashMap};
 
 fn main() {
     let get_key = |(key, _val)| key;
+    fn ref_acceptor(v: &u32) -> u32 {
+        *v
+    }
 
     let map: HashMap<u32, u32> = HashMap::new();
 
@@ -36,6 +37,20 @@ fn main() {
     let _ = map.keys().map(|key| key * 9).count();
     let _ = map.values().map(|value| value * 17).count();
 
+    // Preserve the ref in the fix.
+    let _ = map.clone().into_values().map(|ref val| ref_acceptor(val)).count();
+
+    // Preserve the mut in the fix.
+    let _ = map
+        .clone().into_values().map(|mut val| {
+            val += 2;
+            val
+        })
+        .count();
+
+    // Don't let a mut interfere.
+    let _ = map.clone().into_values().count();
+
     let map: BTreeMap<u32, u32> = BTreeMap::new();
 
     let _ = map.keys().collect::<Vec<_>>();
@@ -61,4 +76,18 @@ fn main() {
     // Lint
     let _ = map.keys().map(|key| key * 9).count();
     let _ = map.values().map(|value| value * 17).count();
+
+    // Preserve the ref in the fix.
+    let _ = map.clone().into_values().map(|ref val| ref_acceptor(val)).count();
+
+    // Preserve the mut in the fix.
+    let _ = map
+        .clone().into_values().map(|mut val| {
+            val += 2;
+            val
+        })
+        .count();
+
+    // Don't let a mut interfere.
+    let _ = map.clone().into_values().count();
 }
diff --git a/tests/ui/iter_kv_map.rs b/tests/ui/iter_kv_map.rs
index 7a1f1fb0198..ad6564df408 100644
--- a/tests/ui/iter_kv_map.rs
+++ b/tests/ui/iter_kv_map.rs
@@ -1,14 +1,15 @@
 // run-rustfix
 
 #![warn(clippy::iter_kv_map)]
-#![allow(clippy::redundant_clone)]
-#![allow(clippy::suspicious_map)]
-#![allow(clippy::map_identity)]
+#![allow(unused_mut, clippy::redundant_clone, clippy::suspicious_map, clippy::map_identity)]
 
 use std::collections::{BTreeMap, HashMap};
 
 fn main() {
     let get_key = |(key, _val)| key;
+    fn ref_acceptor(v: &u32) -> u32 {
+        *v
+    }
 
     let map: HashMap<u32, u32> = HashMap::new();
 
@@ -36,6 +37,22 @@ fn main() {
     let _ = map.iter().map(|(key, _value)| key * 9).count();
     let _ = map.iter().map(|(_key, value)| value * 17).count();
 
+    // Preserve the ref in the fix.
+    let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count();
+
+    // Preserve the mut in the fix.
+    let _ = map
+        .clone()
+        .into_iter()
+        .map(|(_, mut val)| {
+            val += 2;
+            val
+        })
+        .count();
+
+    // Don't let a mut interfere.
+    let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
+
     let map: BTreeMap<u32, u32> = BTreeMap::new();
 
     let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
@@ -61,4 +78,20 @@ fn main() {
     // Lint
     let _ = map.iter().map(|(key, _value)| key * 9).count();
     let _ = map.iter().map(|(_key, value)| value * 17).count();
+
+    // Preserve the ref in the fix.
+    let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count();
+
+    // Preserve the mut in the fix.
+    let _ = map
+        .clone()
+        .into_iter()
+        .map(|(_, mut val)| {
+            val += 2;
+            val
+        })
+        .count();
+
+    // Don't let a mut interfere.
+    let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
 }
diff --git a/tests/ui/iter_kv_map.stderr b/tests/ui/iter_kv_map.stderr
index 9b9b04c97d8..e00da223b4d 100644
--- a/tests/ui/iter_kv_map.stderr
+++ b/tests/ui/iter_kv_map.stderr
@@ -1,5 +1,5 @@
 error: iterating on a map's keys
-  --> $DIR/iter_kv_map.rs:15:13
+  --> $DIR/iter_kv_map.rs:16:13
    |
 LL |     let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
@@ -7,130 +7,198 @@ LL |     let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
    = note: `-D clippy::iter-kv-map` implied by `-D warnings`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:16:13
+  --> $DIR/iter_kv_map.rs:17:13
    |
 LL |     let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:17:13
+  --> $DIR/iter_kv_map.rs:18:13
    |
 LL |     let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)`
 
 error: iterating on a map's keys
-  --> $DIR/iter_kv_map.rs:19:13
+  --> $DIR/iter_kv_map.rs:20:13
    |
 LL |     let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()`
 
 error: iterating on a map's keys
-  --> $DIR/iter_kv_map.rs:20:13
+  --> $DIR/iter_kv_map.rs:21:13
    |
 LL |     let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:22:13
+  --> $DIR/iter_kv_map.rs:23:13
    |
 LL |     let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:23:13
+  --> $DIR/iter_kv_map.rs:24:13
    |
 LL |     let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:25:13
+  --> $DIR/iter_kv_map.rs:26:13
    |
 LL |     let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()`
 
 error: iterating on a map's keys
-  --> $DIR/iter_kv_map.rs:26:13
+  --> $DIR/iter_kv_map.rs:27:13
    |
 LL |     let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
 
 error: iterating on a map's keys
-  --> $DIR/iter_kv_map.rs:36:13
+  --> $DIR/iter_kv_map.rs:37:13
    |
 LL |     let _ = map.iter().map(|(key, _value)| key * 9).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:37:13
+  --> $DIR/iter_kv_map.rs:38:13
    |
 LL |     let _ = map.iter().map(|(_key, value)| value * 17).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)`
 
-error: iterating on a map's keys
+error: iterating on a map's values
   --> $DIR/iter_kv_map.rs:41:13
    |
+LL |     let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|ref val| ref_acceptor(val))`
+
+error: iterating on a map's values
+  --> $DIR/iter_kv_map.rs:44:13
+   |
+LL |       let _ = map
+   |  _____________^
+LL | |         .clone()
+LL | |         .into_iter()
+LL | |         .map(|(_, mut val)| {
+LL | |             val += 2;
+LL | |             val
+LL | |         })
+   | |__________^
+   |
+help: try
+   |
+LL ~     let _ = map
+LL +         .clone().into_values().map(|mut val| {
+LL +             val += 2;
+LL +             val
+LL +         })
+   |
+
+error: iterating on a map's values
+  --> $DIR/iter_kv_map.rs:54:13
+   |
+LL |     let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
+
+error: iterating on a map's keys
+  --> $DIR/iter_kv_map.rs:58:13
+   |
 LL |     let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:42:13
+  --> $DIR/iter_kv_map.rs:59:13
    |
 LL |     let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:43:13
+  --> $DIR/iter_kv_map.rs:60:13
    |
 LL |     let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)`
 
 error: iterating on a map's keys
-  --> $DIR/iter_kv_map.rs:45:13
+  --> $DIR/iter_kv_map.rs:62:13
    |
 LL |     let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()`
 
 error: iterating on a map's keys
-  --> $DIR/iter_kv_map.rs:46:13
+  --> $DIR/iter_kv_map.rs:63:13
    |
 LL |     let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:48:13
+  --> $DIR/iter_kv_map.rs:65:13
    |
 LL |     let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:49:13
+  --> $DIR/iter_kv_map.rs:66:13
    |
 LL |     let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:51:13
+  --> $DIR/iter_kv_map.rs:68:13
    |
 LL |     let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()`
 
 error: iterating on a map's keys
-  --> $DIR/iter_kv_map.rs:52:13
+  --> $DIR/iter_kv_map.rs:69:13
    |
 LL |     let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
 
 error: iterating on a map's keys
-  --> $DIR/iter_kv_map.rs:62:13
+  --> $DIR/iter_kv_map.rs:79:13
    |
 LL |     let _ = map.iter().map(|(key, _value)| key * 9).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)`
 
 error: iterating on a map's values
-  --> $DIR/iter_kv_map.rs:63:13
+  --> $DIR/iter_kv_map.rs:80:13
    |
 LL |     let _ = map.iter().map(|(_key, value)| value * 17).count();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)`
 
-error: aborting due to 22 previous errors
+error: iterating on a map's values
+  --> $DIR/iter_kv_map.rs:83:13
+   |
+LL |     let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|ref val| ref_acceptor(val))`
+
+error: iterating on a map's values
+  --> $DIR/iter_kv_map.rs:86:13
+   |
+LL |       let _ = map
+   |  _____________^
+LL | |         .clone()
+LL | |         .into_iter()
+LL | |         .map(|(_, mut val)| {
+LL | |             val += 2;
+LL | |             val
+LL | |         })
+   | |__________^
+   |
+help: try
+   |
+LL ~     let _ = map
+LL +         .clone().into_values().map(|mut val| {
+LL +             val += 2;
+LL +             val
+LL +         })
+   |
+
+error: iterating on a map's values
+  --> $DIR/iter_kv_map.rs:96:13
+   |
+LL |     let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
+
+error: aborting due to 28 previous errors