Skip to content

Commit 31a89ea

Browse files
authored
Fix for_kv_map FN when using iter and iter_mut (#16830)
Closes #16822 changelog: [`for_kv_map`] fix FN when using `iter` and `iter_mut`
2 parents 0c71cf8 + 4351f2a commit 31a89ea

4 files changed

Lines changed: 107 additions & 6 deletions

File tree

clippy_lints/src/loops/for_kv_map.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,20 @@ pub(super) fn check<'tcx>(
2323
&& pat.len() == 2
2424
{
2525
let arg_span = arg.span;
26-
let (new_pat_span, kind, ty, mutbl) = match *cx.typeck_results().expr_ty(arg).kind() {
26+
let (arg, arg_ty) = match arg.kind {
27+
// `for x in &expr` or `for x in &mut expr`
28+
ExprKind::AddrOf(BorrowKind::Ref, _, expr) => (expr, cx.typeck_results().expr_ty(arg)),
29+
// `for x in receiver.iter()` or `for x in receiver.iter_mut()`
30+
ExprKind::MethodCall(path, receiver, [], ..)
31+
if path.ident.name == sym::iter || path.ident.name == sym::iter_mut =>
32+
{
33+
// Use `expr_ty_adjusted` because `.iter()` / `.iter_mut()` may introduce auto deferences
34+
(receiver, cx.typeck_results().expr_ty_adjusted(receiver))
35+
},
36+
_ => (arg, cx.typeck_results().expr_ty(arg)),
37+
};
38+
39+
let (new_pat_span, kind, ty, mutbl) = match *arg_ty.kind() {
2740
ty::Ref(_, ty, mutbl) => match (&pat[0].kind, &pat[1].kind) {
2841
(key, _) if pat_is_wild(cx, key, body) => (pat[1].span, "value", ty, mutbl),
2942
(_, value) if pat_is_wild(cx, value, body) => (pat[0].span, "key", ty, Mutability::Not),
@@ -35,10 +48,6 @@ pub(super) fn check<'tcx>(
3548
Mutability::Not => "",
3649
Mutability::Mut => "_mut",
3750
};
38-
let arg = match arg.kind {
39-
ExprKind::AddrOf(BorrowKind::Ref, _, expr) => expr,
40-
_ => arg,
41-
};
4251

4352
if matches!(ty.opt_diag_name(cx), Some(sym::HashMap | sym::BTreeMap))
4453
&& let Some(arg_span) = walk_span_to_context(arg_span, span.ctxt())

tests/ui/for_kv_map.fixed

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,25 @@ fn wrongly_unmangled_macros() {
8686
let _v = v;
8787
}
8888
}
89+
90+
fn issue16822(mut x: HashMap<usize, usize>) {
91+
for v in x.values() {
92+
//~^ for_kv_map
93+
println!("{}", v);
94+
}
95+
96+
for v in x.values_mut() {
97+
//~^ for_kv_map
98+
*v += 1;
99+
}
100+
101+
for k in x.keys() {
102+
//~^ for_kv_map
103+
println!("{}", k);
104+
}
105+
106+
for k in x.keys() {
107+
//~^ for_kv_map
108+
println!("{}", k);
109+
}
110+
}

tests/ui/for_kv_map.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,25 @@ fn wrongly_unmangled_macros() {
8686
let _v = v;
8787
}
8888
}
89+
90+
fn issue16822(mut x: HashMap<usize, usize>) {
91+
for (_, v) in x.iter() {
92+
//~^ for_kv_map
93+
println!("{}", v);
94+
}
95+
96+
for (_, v) in x.iter_mut() {
97+
//~^ for_kv_map
98+
*v += 1;
99+
}
100+
101+
for (k, _) in x.iter() {
102+
//~^ for_kv_map
103+
println!("{}", k);
104+
}
105+
106+
for (k, _) in x.iter_mut() {
107+
//~^ for_kv_map
108+
println!("{}", k);
109+
}
110+
}

tests/ui/for_kv_map.stderr

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,5 +84,53 @@ LL - for (_, v) in test_map!(wrapped) {
8484
LL + for v in test_map!(wrapped).values() {
8585
|
8686

87-
error: aborting due to 7 previous errors
87+
error: you seem to want to iterate on a map's values
88+
--> tests/ui/for_kv_map.rs:91:19
89+
|
90+
LL | for (_, v) in x.iter() {
91+
| ^^^^^^^^
92+
|
93+
help: use the corresponding method
94+
|
95+
LL - for (_, v) in x.iter() {
96+
LL + for v in x.values() {
97+
|
98+
99+
error: you seem to want to iterate on a map's values
100+
--> tests/ui/for_kv_map.rs:96:19
101+
|
102+
LL | for (_, v) in x.iter_mut() {
103+
| ^^^^^^^^^^^^
104+
|
105+
help: use the corresponding method
106+
|
107+
LL - for (_, v) in x.iter_mut() {
108+
LL + for v in x.values_mut() {
109+
|
110+
111+
error: you seem to want to iterate on a map's keys
112+
--> tests/ui/for_kv_map.rs:101:19
113+
|
114+
LL | for (k, _) in x.iter() {
115+
| ^^^^^^^^
116+
|
117+
help: use the corresponding method
118+
|
119+
LL - for (k, _) in x.iter() {
120+
LL + for k in x.keys() {
121+
|
122+
123+
error: you seem to want to iterate on a map's keys
124+
--> tests/ui/for_kv_map.rs:106:19
125+
|
126+
LL | for (k, _) in x.iter_mut() {
127+
| ^^^^^^^^^^^^
128+
|
129+
help: use the corresponding method
130+
|
131+
LL - for (k, _) in x.iter_mut() {
132+
LL + for k in x.keys() {
133+
|
134+
135+
error: aborting due to 11 previous errors
88136

0 commit comments

Comments
 (0)