Skip to content

Commit 73bad36

Browse files
committed
Auto merge of rust-lang#13548 - wowinter13:unnecessary_filter_map_filter_map_some, r=llogiq
fix: remove unnecessary filter_map usages fixes rust-lang/rust-clippy#12556 (Fixed version of rust-lang/rust-clippy#12766) changelog: [unnecessary_filter_map]: filter map improvements
2 parents 12ca363 + ad002ea commit 73bad36

File tree

5 files changed

+92
-44
lines changed

5 files changed

+92
-44
lines changed

clippy_lints/src/methods/unnecessary_filter_map.rs

+26-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
use super::utils::clone_or_copy_needed;
2-
use clippy_utils::diagnostics::span_lint;
2+
use clippy_utils::diagnostics::span_lint_and_sugg;
33
use clippy_utils::ty::is_copy;
44
use clippy_utils::usage::mutated_variables;
55
use clippy_utils::visitors::{Descend, for_each_expr_without_closures};
6-
use clippy_utils::{is_res_lang_ctor, is_trait_method, path_res, path_to_local_id};
6+
use clippy_utils::{MaybePath, is_res_lang_ctor, is_trait_method, path_res, path_to_local_id};
77
use core::ops::ControlFlow;
8+
use rustc_errors::Applicability;
89
use rustc_hir as hir;
910
use rustc_hir::LangItem::{OptionNone, OptionSome};
1011
use rustc_lint::LateContext;
12+
use rustc_middle::query::Key;
1113
use rustc_middle::ty;
1214
use rustc_span::sym;
1315

@@ -36,9 +38,25 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a
3638
ControlFlow::Continue(Descend::Yes)
3739
}
3840
});
39-
4041
let in_ty = cx.typeck_results().node_type(body.params[0].hir_id);
4142
let sugg = if !found_filtering {
43+
// Check if the closure is .filter_map(|x| Some(x))
44+
if name == "filter_map"
45+
&& let hir::ExprKind::Call(expr, args) = body.value.kind
46+
&& is_res_lang_ctor(cx, path_res(cx, expr), OptionSome)
47+
&& arg_id.ty_def_id() == args[0].hir_id().ty_def_id()
48+
&& let hir::ExprKind::Path(_) = args[0].kind
49+
{
50+
span_lint_and_sugg(
51+
cx,
52+
UNNECESSARY_FILTER_MAP,
53+
expr.span,
54+
format!("{name} is unnecessary"),
55+
"try removing the filter_map",
56+
String::new(),
57+
Applicability::MaybeIncorrect,
58+
);
59+
}
4260
if name == "filter_map" { "map" } else { "map(..).next()" }
4361
} else if !found_mapping && !mutates_arg && (!clone_or_copy_needed || is_copy(cx, in_ty)) {
4462
match cx.typeck_results().expr_ty(body.value).kind() {
@@ -52,15 +70,18 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a
5270
} else {
5371
return;
5472
};
55-
span_lint(
73+
span_lint_and_sugg(
5674
cx,
5775
if name == "filter_map" {
5876
UNNECESSARY_FILTER_MAP
5977
} else {
6078
UNNECESSARY_FIND_MAP
6179
},
6280
expr.span,
63-
format!("this `.{name}` can be written more simply using `.{sugg}`"),
81+
format!("this `.{name}` can be written more simply"),
82+
"try instead",
83+
sugg.to_string(),
84+
Applicability::MaybeIncorrect,
6485
);
6586
}
6687
}

tests/ui/unnecessary_filter_map.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
1+
//@no-rustfix
12
#![allow(dead_code)]
23

34
fn main() {
45
let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None });
5-
//~^ ERROR: this `.filter_map` can be written more simply using `.filter`
6+
//~^ ERROR: this `.filter_map` can be written more simply
67
//~| NOTE: `-D clippy::unnecessary-filter-map` implied by `-D warnings`
78
let _ = (0..4).filter_map(|x| {
8-
//~^ ERROR: this `.filter_map` can be written more simply using `.filter`
9+
//~^ ERROR: this `.filter_map` can be written more simply
910
if x > 1 {
1011
return Some(x);
1112
};
1213
None
1314
});
1415
let _ = (0..4).filter_map(|x| match x {
15-
//~^ ERROR: this `.filter_map` can be written more simply using `.filter`
16+
//~^ ERROR: this `.filter_map` can be written more simply
1617
0 | 1 => None,
1718
_ => Some(x),
1819
});
1920

2021
let _ = (0..4).filter_map(|x| Some(x + 1));
21-
//~^ ERROR: this `.filter_map` can be written more simply using `.map`
22+
//~^ ERROR: this `.filter_map` can be written more simply
2223

2324
let _ = (0..4).filter_map(i32::checked_abs);
25+
26+
let _ = (0..4).filter_map(Some);
27+
28+
let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x));
2429
}
2530

2631
fn filter_map_none_changes_item_type() -> impl Iterator<Item = bool> {
+37-16
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
error: this `.filter_map` can be written more simply using `.filter`
2-
--> tests/ui/unnecessary_filter_map.rs:4:13
1+
error: this `.filter_map` can be written more simply
2+
--> tests/ui/unnecessary_filter_map.rs:5:13
33
|
44
LL | let _ = (0..4).filter_map(|x| if x > 1 { Some(x) } else { None });
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `filter`
66
|
77
= note: `-D clippy::unnecessary-filter-map` implied by `-D warnings`
88
= help: to override `-D warnings` add `#[allow(clippy::unnecessary_filter_map)]`
99

10-
error: this `.filter_map` can be written more simply using `.filter`
11-
--> tests/ui/unnecessary_filter_map.rs:7:13
10+
error: this `.filter_map` can be written more simply
11+
--> tests/ui/unnecessary_filter_map.rs:8:13
1212
|
1313
LL | let _ = (0..4).filter_map(|x| {
1414
| _____________^
@@ -18,30 +18,51 @@ LL | | return Some(x);
1818
LL | | };
1919
LL | | None
2020
LL | | });
21-
| |______^
21+
| |______^ help: try instead: `filter`
2222

23-
error: this `.filter_map` can be written more simply using `.filter`
24-
--> tests/ui/unnecessary_filter_map.rs:14:13
23+
error: this `.filter_map` can be written more simply
24+
--> tests/ui/unnecessary_filter_map.rs:15:13
2525
|
2626
LL | let _ = (0..4).filter_map(|x| match x {
2727
| _____________^
2828
LL | |
2929
LL | | 0 | 1 => None,
3030
LL | | _ => Some(x),
3131
LL | | });
32-
| |______^
32+
| |______^ help: try instead: `filter`
3333

34-
error: this `.filter_map` can be written more simply using `.map`
35-
--> tests/ui/unnecessary_filter_map.rs:20:13
34+
error: this `.filter_map` can be written more simply
35+
--> tests/ui/unnecessary_filter_map.rs:21:13
3636
|
3737
LL | let _ = (0..4).filter_map(|x| Some(x + 1));
38-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
38+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `map`
3939

40-
error: this `.filter_map` can be written more simply using `.filter`
41-
--> tests/ui/unnecessary_filter_map.rs:160:14
40+
error: redundant closure
41+
--> tests/ui/unnecessary_filter_map.rs:28:57
42+
|
43+
LL | let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x));
44+
| ^^^^^^^^^^^ help: replace the closure with the function itself: `Some`
45+
|
46+
= note: `-D clippy::redundant-closure` implied by `-D warnings`
47+
= help: to override `-D warnings` add `#[allow(clippy::redundant_closure)]`
48+
49+
error: filter_map is unnecessary
50+
--> tests/ui/unnecessary_filter_map.rs:28:61
51+
|
52+
LL | let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x));
53+
| ^^^^ help: try removing the filter_map
54+
55+
error: this `.filter_map` can be written more simply
56+
--> tests/ui/unnecessary_filter_map.rs:28:13
57+
|
58+
LL | let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x));
59+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `map`
60+
61+
error: this `.filter_map` can be written more simply
62+
--> tests/ui/unnecessary_filter_map.rs:165:14
4263
|
4364
LL | let _x = std::iter::once(1).filter_map(|n| (n > 1).then_some(n));
44-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
65+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `filter`
4566

46-
error: aborting due to 5 previous errors
67+
error: aborting due to 8 previous errors
4768

tests/ui/unnecessary_find_map.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
1+
//@no-rustfix
12
#![allow(dead_code)]
23

34
fn main() {
45
let _ = (0..4).find_map(|x| if x > 1 { Some(x) } else { None });
5-
//~^ ERROR: this `.find_map` can be written more simply using `.find`
6+
//~^ ERROR: this `.find_map` can be written more simply
67
//~| NOTE: `-D clippy::unnecessary-find-map` implied by `-D warnings`
78
let _ = (0..4).find_map(|x| {
8-
//~^ ERROR: this `.find_map` can be written more simply using `.find`
9+
//~^ ERROR: this `.find_map` can be written more simply
910
if x > 1 {
1011
return Some(x);
1112
};
1213
None
1314
});
1415
let _ = (0..4).find_map(|x| match x {
15-
//~^ ERROR: this `.find_map` can be written more simply using `.find`
16+
//~^ ERROR: this `.find_map` can be written more simply
1617
0 | 1 => None,
1718
_ => Some(x),
1819
});
1920

2021
let _ = (0..4).find_map(|x| Some(x + 1));
21-
//~^ ERROR: this `.find_map` can be written more simply using `.map(..).next()`
22+
//~^ ERROR: this `.find_map` can be written more simply
2223

2324
let _ = (0..4).find_map(i32::checked_abs);
2425
}

tests/ui/unnecessary_find_map.stderr

+15-15
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
error: this `.find_map` can be written more simply using `.find`
2-
--> tests/ui/unnecessary_find_map.rs:4:13
1+
error: this `.find_map` can be written more simply
2+
--> tests/ui/unnecessary_find_map.rs:5:13
33
|
44
LL | let _ = (0..4).find_map(|x| if x > 1 { Some(x) } else { None });
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `find`
66
|
77
= note: `-D clippy::unnecessary-find-map` implied by `-D warnings`
88
= help: to override `-D warnings` add `#[allow(clippy::unnecessary_find_map)]`
99

10-
error: this `.find_map` can be written more simply using `.find`
11-
--> tests/ui/unnecessary_find_map.rs:7:13
10+
error: this `.find_map` can be written more simply
11+
--> tests/ui/unnecessary_find_map.rs:8:13
1212
|
1313
LL | let _ = (0..4).find_map(|x| {
1414
| _____________^
@@ -18,30 +18,30 @@ LL | | return Some(x);
1818
LL | | };
1919
LL | | None
2020
LL | | });
21-
| |______^
21+
| |______^ help: try instead: `find`
2222

23-
error: this `.find_map` can be written more simply using `.find`
24-
--> tests/ui/unnecessary_find_map.rs:14:13
23+
error: this `.find_map` can be written more simply
24+
--> tests/ui/unnecessary_find_map.rs:15:13
2525
|
2626
LL | let _ = (0..4).find_map(|x| match x {
2727
| _____________^
2828
LL | |
2929
LL | | 0 | 1 => None,
3030
LL | | _ => Some(x),
3131
LL | | });
32-
| |______^
32+
| |______^ help: try instead: `find`
3333

34-
error: this `.find_map` can be written more simply using `.map(..).next()`
35-
--> tests/ui/unnecessary_find_map.rs:20:13
34+
error: this `.find_map` can be written more simply
35+
--> tests/ui/unnecessary_find_map.rs:21:13
3636
|
3737
LL | let _ = (0..4).find_map(|x| Some(x + 1));
38-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
38+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `map(..).next()`
3939

40-
error: this `.find_map` can be written more simply using `.find`
41-
--> tests/ui/unnecessary_find_map.rs:32:14
40+
error: this `.find_map` can be written more simply
41+
--> tests/ui/unnecessary_find_map.rs:33:14
4242
|
4343
LL | let _x = std::iter::once(1).find_map(|n| (n > 1).then_some(n));
44-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
44+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try instead: `find`
4545

4646
error: aborting due to 5 previous errors
4747

0 commit comments

Comments
 (0)