Skip to content

Commit c24784e

Browse files
committed
Auto merge of rust-lang#11757 - matthri:iter-kv-map-msrv-fix, r=Alexendoo
Fix iter_kv_map false positive into_keys and into_values suggestion fixes: rust-lang#11752 changelog: [`iter_kv_map`]: fix false positive: Don't suggest `into_keys()` and `into_values()` if the MSRV is to low
2 parents a72730e + a20f61b commit c24784e

File tree

8 files changed

+156
-3
lines changed

8 files changed

+156
-3
lines changed

book/src/lint_configuration.md

+1
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio
150150
* [`tuple_array_conversions`](https://rust-lang.github.io/rust-clippy/master/index.html#tuple_array_conversions)
151151
* [`manual_try_fold`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold)
152152
* [`manual_hash_one`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_hash_one)
153+
* [`iter_kv_map`](https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map)
153154

154155

155156
## `cognitive-complexity-threshold`

clippy_config/src/conf.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ define_Conf! {
249249
///
250250
/// Suppress lints whenever the suggested change would cause breakage for other crates.
251251
(avoid_breaking_exported_api: bool = true),
252-
/// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE.
252+
/// Lint: MANUAL_SPLIT_ONCE, MANUAL_STR_REPEAT, CLONED_INSTEAD_OF_COPIED, REDUNDANT_FIELD_NAMES, OPTION_MAP_UNWRAP_OR, REDUNDANT_STATIC_LIFETIMES, FILTER_MAP_NEXT, CHECKED_CONVERSIONS, MANUAL_RANGE_CONTAINS, USE_SELF, MEM_REPLACE_WITH_DEFAULT, MANUAL_NON_EXHAUSTIVE, OPTION_AS_REF_DEREF, MAP_UNWRAP_OR, MATCH_LIKE_MATCHES_MACRO, MANUAL_STRIP, MISSING_CONST_FOR_FN, UNNESTED_OR_PATTERNS, FROM_OVER_INTO, PTR_AS_PTR, IF_THEN_SOME_ELSE_NONE, APPROX_CONSTANT, DEPRECATED_CFG_ATTR, INDEX_REFUTABLE_SLICE, MAP_CLONE, BORROW_AS_PTR, MANUAL_BITS, ERR_EXPECT, CAST_ABS_TO_UNSIGNED, UNINLINED_FORMAT_ARGS, MANUAL_CLAMP, MANUAL_LET_ELSE, UNCHECKED_DURATION_SUBTRACTION, COLLAPSIBLE_STR_REPLACE, SEEK_FROM_CURRENT, SEEK_REWIND, UNNECESSARY_LAZY_EVALUATIONS, TRANSMUTE_PTR_TO_REF, ALMOST_COMPLETE_RANGE, NEEDLESS_BORROW, DERIVABLE_IMPLS, MANUAL_IS_ASCII_CHECK, MANUAL_REM_EUCLID, MANUAL_RETAIN, TYPE_REPETITION_IN_BOUNDS, TUPLE_ARRAY_CONVERSIONS, MANUAL_TRY_FOLD, MANUAL_HASH_ONE, ITER_KV_MAP.
253253
///
254254
/// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml`
255255
#[default_text = ""]

clippy_config/src/msrvs.rs

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ msrv_aliases! {
2323
1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE }
2424
1,58,0 { FORMAT_ARGS_CAPTURE, PATTERN_TRAIT_CHAR_ARRAY }
2525
1,55,0 { SEEK_REWIND }
26+
1,54,0 { INTO_KEYS }
2627
1,53,0 { OR_PATTERNS, MANUAL_BITS, BTREE_MAP_RETAIN, BTREE_SET_RETAIN, ARRAY_INTO_ITERATOR }
2728
1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST }
2829
1,51,0 { BORROW_AS_PTR, SEEK_FROM_CURRENT, UNSIGNED_ABS }

clippy_lints/src/methods/iter_kv_map.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![allow(unused_imports)]
22

33
use super::ITER_KV_MAP;
4+
use clippy_config::msrvs::{self, Msrv};
45
use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_sugg, span_lint_and_then};
56
use clippy_utils::source::{snippet, snippet_with_applicability};
67
use clippy_utils::ty::is_type_diagnostic_item;
@@ -21,7 +22,11 @@ pub(super) fn check<'tcx>(
2122
expr: &'tcx Expr<'tcx>, // .iter().map(|(_, v_| v))
2223
recv: &'tcx Expr<'tcx>, // hashmap
2324
m_arg: &'tcx Expr<'tcx>, // |(_, v)| v
25+
msrv: &Msrv,
2426
) {
27+
if map_type == "into_iter" && !msrv.meets(msrvs::INTO_KEYS) {
28+
return;
29+
}
2530
if !expr.span.from_expansion()
2631
&& let ExprKind::Closure(c) = m_arg.kind
2732
&& let Body {

clippy_lints/src/methods/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4301,7 +4301,7 @@ impl Methods {
43014301
map_clone::check(cx, expr, recv, m_arg, &self.msrv);
43024302
match method_call(recv) {
43034303
Some((map_name @ ("iter" | "into_iter"), recv2, _, _, _)) => {
4304-
iter_kv_map::check(cx, map_name, expr, recv2, m_arg);
4304+
iter_kv_map::check(cx, map_name, expr, recv2, m_arg, &self.msrv);
43054305
},
43064306
Some(("cloned", recv2, [], _, _)) => iter_overeager_cloned::check(
43074307
cx,

tests/ui/iter_kv_map.fixed

+43
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,46 @@ fn main() {
8989
// Don't let a mut interfere.
9090
let _ = map.clone().into_values().count();
9191
}
92+
93+
#[clippy::msrv = "1.53"]
94+
fn msrv_1_53() {
95+
let map: HashMap<u32, u32> = HashMap::new();
96+
97+
// Don't lint because into_iter is not supported
98+
let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
99+
let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
100+
101+
let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
102+
let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
103+
104+
// Lint
105+
let _ = map.keys().collect::<Vec<_>>();
106+
//~^ ERROR: iterating on a map's keys
107+
let _ = map.values().collect::<Vec<_>>();
108+
//~^ ERROR: iterating on a map's values
109+
let _ = map.values().map(|v| v + 2).collect::<Vec<_>>();
110+
//~^ ERROR: iterating on a map's values
111+
}
112+
113+
#[clippy::msrv = "1.54"]
114+
fn msrv_1_54() {
115+
// Lint all
116+
let map: HashMap<u32, u32> = HashMap::new();
117+
118+
let _ = map.clone().into_keys().collect::<Vec<_>>();
119+
//~^ ERROR: iterating on a map's keys
120+
let _ = map.clone().into_keys().map(|key| key + 2).collect::<Vec<_>>();
121+
//~^ ERROR: iterating on a map's keys
122+
123+
let _ = map.clone().into_values().collect::<Vec<_>>();
124+
//~^ ERROR: iterating on a map's values
125+
let _ = map.clone().into_values().map(|val| val + 2).collect::<Vec<_>>();
126+
//~^ ERROR: iterating on a map's values
127+
128+
let _ = map.keys().collect::<Vec<_>>();
129+
//~^ ERROR: iterating on a map's keys
130+
let _ = map.values().collect::<Vec<_>>();
131+
//~^ ERROR: iterating on a map's values
132+
let _ = map.values().map(|v| v + 2).collect::<Vec<_>>();
133+
//~^ ERROR: iterating on a map's values
134+
}

tests/ui/iter_kv_map.rs

+43
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,46 @@ fn main() {
9393
// Don't let a mut interfere.
9494
let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
9595
}
96+
97+
#[clippy::msrv = "1.53"]
98+
fn msrv_1_53() {
99+
let map: HashMap<u32, u32> = HashMap::new();
100+
101+
// Don't lint because into_iter is not supported
102+
let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
103+
let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
104+
105+
let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
106+
let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
107+
108+
// Lint
109+
let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
110+
//~^ ERROR: iterating on a map's keys
111+
let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
112+
//~^ ERROR: iterating on a map's values
113+
let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
114+
//~^ ERROR: iterating on a map's values
115+
}
116+
117+
#[clippy::msrv = "1.54"]
118+
fn msrv_1_54() {
119+
// Lint all
120+
let map: HashMap<u32, u32> = HashMap::new();
121+
122+
let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
123+
//~^ ERROR: iterating on a map's keys
124+
let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
125+
//~^ ERROR: iterating on a map's keys
126+
127+
let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
128+
//~^ ERROR: iterating on a map's values
129+
let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
130+
//~^ ERROR: iterating on a map's values
131+
132+
let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
133+
//~^ ERROR: iterating on a map's keys
134+
let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
135+
//~^ ERROR: iterating on a map's values
136+
let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
137+
//~^ ERROR: iterating on a map's values
138+
}

tests/ui/iter_kv_map.stderr

+61-1
Original file line numberDiff line numberDiff line change
@@ -201,5 +201,65 @@ error: iterating on a map's values
201201
LL | let _ = map.clone().into_iter().map(|(_, mut val)| val).count();
202202
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
203203

204-
error: aborting due to 28 previous errors
204+
error: iterating on a map's keys
205+
--> $DIR/iter_kv_map.rs:109:13
206+
|
207+
LL | let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
208+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
209+
210+
error: iterating on a map's values
211+
--> $DIR/iter_kv_map.rs:111:13
212+
|
213+
LL | let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
214+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
215+
216+
error: iterating on a map's values
217+
--> $DIR/iter_kv_map.rs:113:13
218+
|
219+
LL | let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
220+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)`
221+
222+
error: iterating on a map's keys
223+
--> $DIR/iter_kv_map.rs:122:13
224+
|
225+
LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
226+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()`
227+
228+
error: iterating on a map's keys
229+
--> $DIR/iter_kv_map.rs:124:13
230+
|
231+
LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
232+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)`
233+
234+
error: iterating on a map's values
235+
--> $DIR/iter_kv_map.rs:127:13
236+
|
237+
LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
238+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
239+
240+
error: iterating on a map's values
241+
--> $DIR/iter_kv_map.rs:129:13
242+
|
243+
LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
244+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)`
245+
246+
error: iterating on a map's keys
247+
--> $DIR/iter_kv_map.rs:132:13
248+
|
249+
LL | let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
250+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
251+
252+
error: iterating on a map's values
253+
--> $DIR/iter_kv_map.rs:134:13
254+
|
255+
LL | let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
256+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
257+
258+
error: iterating on a map's values
259+
--> $DIR/iter_kv_map.rs:136:13
260+
|
261+
LL | let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
262+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)`
263+
264+
error: aborting due to 38 previous errors
205265

0 commit comments

Comments
 (0)