Make the iter_kv_map lint handle ref/mut annotations.

For the degenerate (`map(|(k, _)| k)`/`map(|(_, v)| v)`) cases a mut annotation is superfluous and a ref annotation won't compile, so no additional handling is required. For cases where the `map` call must be preserved ref/mut annotations should also be presereved so that the map body continues to work as expected.
This commit is contained in:
Kyle Huey 2023-01-04 13:32:34 -08:00
parent 0bca8dd254
commit d0c1605d51
4 changed files with 174 additions and 34 deletions

View File

@ -6,7 +6,7 @@
use clippy_utils::sugg; use clippy_utils::sugg;
use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::visitors::is_local_used; 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_lint::{LateContext, LintContext};
use rustc_middle::ty; use rustc_middle::ty;
use rustc_span::sym; 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 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; if let PatKind::Tuple([key_pat, val_pat], _) = p.pat.kind;
let (replacement_kind, binded_ident) = match (&key_pat.kind, &val_pat.kind) { let (replacement_kind, annotation, binded_ident) = match (&key_pat.kind, &val_pat.kind) {
(key, PatKind::Binding(_, _, value, _)) if pat_is_wild(cx, key, m_arg) => ("value", value), (key, PatKind::Binding(ann, _, value, _)) if pat_is_wild(cx, key, m_arg) => ("value", ann, value),
(PatKind::Binding(_, _, key, _), value) if pat_is_wild(cx, value, m_arg) => ("key", key), (PatKind::Binding(ann, _, key, _), value) if pat_is_wild(cx, value, m_arg) => ("key", ann, key),
_ => return, _ => return,
}; };
@ -60,13 +60,23 @@ pub(super) fn check<'tcx>(
applicability, applicability,
); );
} else { } 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( span_lint_and_sugg(
cx, cx,
ITER_KV_MAP, ITER_KV_MAP,
expr.span, expr.span,
&format!("iterating on a map's {replacement_kind}s"), &format!("iterating on a map's {replacement_kind}s"),
"try", "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}{binded_ident}| {})",
snippet_with_applicability(cx, body_expr.span, "/* body */", &mut applicability)), snippet_with_applicability(cx, body_expr.span, "/* body */", &mut applicability)),
applicability, applicability,
); );

View File

@ -1,14 +1,15 @@
// run-rustfix // run-rustfix
#![warn(clippy::iter_kv_map)] #![warn(clippy::iter_kv_map)]
#![allow(clippy::redundant_clone)] #![allow(unused_mut, clippy::redundant_clone, clippy::suspicious_map, clippy::map_identity)]
#![allow(clippy::suspicious_map)]
#![allow(clippy::map_identity)]
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap};
fn main() { fn main() {
let get_key = |(key, _val)| key; let get_key = |(key, _val)| key;
fn ref_acceptor(v: &u32) -> u32 {
*v
}
let map: HashMap<u32, u32> = HashMap::new(); let map: HashMap<u32, u32> = HashMap::new();
@ -36,6 +37,20 @@ fn main() {
let _ = map.keys().map(|key| key * 9).count(); let _ = map.keys().map(|key| key * 9).count();
let _ = map.values().map(|value| value * 17).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: BTreeMap<u32, u32> = BTreeMap::new();
let _ = map.keys().collect::<Vec<_>>(); let _ = map.keys().collect::<Vec<_>>();
@ -61,4 +76,18 @@ fn main() {
// Lint // Lint
let _ = map.keys().map(|key| key * 9).count(); let _ = map.keys().map(|key| key * 9).count();
let _ = map.values().map(|value| value * 17).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();
} }

View File

@ -1,14 +1,15 @@
// run-rustfix // run-rustfix
#![warn(clippy::iter_kv_map)] #![warn(clippy::iter_kv_map)]
#![allow(clippy::redundant_clone)] #![allow(unused_mut, clippy::redundant_clone, clippy::suspicious_map, clippy::map_identity)]
#![allow(clippy::suspicious_map)]
#![allow(clippy::map_identity)]
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap};
fn main() { fn main() {
let get_key = |(key, _val)| key; let get_key = |(key, _val)| key;
fn ref_acceptor(v: &u32) -> u32 {
*v
}
let map: HashMap<u32, u32> = HashMap::new(); 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)| key * 9).count();
let _ = map.iter().map(|(_key, value)| value * 17).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: BTreeMap<u32, u32> = BTreeMap::new();
let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>(); let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
@ -61,4 +78,20 @@ fn main() {
// Lint // Lint
let _ = map.iter().map(|(key, _value)| key * 9).count(); let _ = map.iter().map(|(key, _value)| key * 9).count();
let _ = map.iter().map(|(_key, value)| value * 17).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();
} }

View File

@ -1,5 +1,5 @@
error: iterating on a map's keys 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<_>>(); LL | let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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` = note: `-D clippy::iter-kv-map` implied by `-D warnings`
error: iterating on a map's values 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<_>>(); LL | let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
error: iterating on a map's 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<_>>(); LL | let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)`
error: iterating on a map's keys 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<_>>(); LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()`
error: iterating on a map's 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<_>>(); LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)`
error: iterating on a map's values 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<_>>(); LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
error: iterating on a map's 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<_>>(); LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)`
error: iterating on a map's values 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<_>>(); LL | let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()`
error: iterating on a map's keys 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(); LL | let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
error: iterating on a map's 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(); LL | let _ = map.iter().map(|(key, _value)| key * 9).count();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)`
error: iterating on a map's values 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(); LL | let _ = map.iter().map(|(_key, value)| value * 17).count();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 --> $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<_>>(); LL | let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
error: iterating on a map's values 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<_>>(); LL | let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
error: iterating on a map's 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<_>>(); LL | let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)`
error: iterating on a map's keys 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<_>>(); LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()`
error: iterating on a map's 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<_>>(); LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)`
error: iterating on a map's values 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<_>>(); LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
error: iterating on a map's 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<_>>(); LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)`
error: iterating on a map's values 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<_>>(); LL | let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()`
error: iterating on a map's keys 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(); LL | let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
error: iterating on a map's 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(); LL | let _ = map.iter().map(|(key, _value)| key * 9).count();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)`
error: iterating on a map's values 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(); LL | let _ = map.iter().map(|(_key, value)| value * 17).count();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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