Skip to content

Commit 007fae1

Browse files
committed
fix(manual_find_map and manual_filter_map): check clone method
1 parent 39231b4 commit 007fae1

File tree

7 files changed

+122
-3
lines changed

7 files changed

+122
-3
lines changed

clippy_lints/src/methods/filter_map.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,15 @@ pub(super) fn check<'tcx>(
155155
}
156156
false
157157
};
158-
if SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(filter_arg, map_arg);
158+
159+
if match map_arg.kind {
160+
ExprKind::MethodCall(clone, [original_arg], _) => {
161+
clone.ident.name == sym::clone
162+
&& SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(filter_arg, original_arg)
163+
},
164+
_ => SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(filter_arg, map_arg)
165+
};
166+
159167
then {
160168
let span = filter_span.with_hi(expr.span.hi());
161169
let (filter_name, lint) = if is_find {

tests/ui/manual_filter_map.fixed

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,25 @@ fn to_opt<T>(_: T) -> Option<T> {
3535
fn to_res<T>(_: T) -> Result<T, ()> {
3636
unimplemented!()
3737
}
38+
39+
struct OptionFoo {
40+
field: Option<String>,
41+
}
42+
43+
struct ResultFoo {
44+
field: Result<String, ()>,
45+
}
46+
47+
fn issue_8920() {
48+
let vec = vec![OptionFoo {
49+
field: Some(String::from("str")),
50+
}];
51+
let _ = vec
52+
.iter()
53+
.filter_map(|f| f.field.clone());
54+
55+
let vec = vec![ResultFoo {
56+
field: Ok(String::from("str")),
57+
}];
58+
let _ = vec.iter().filter_map(|f| f.field.clone().ok());
59+
}

tests/ui/manual_filter_map.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,26 @@ fn to_opt<T>(_: T) -> Option<T> {
3535
fn to_res<T>(_: T) -> Result<T, ()> {
3636
unimplemented!()
3737
}
38+
39+
struct OptionFoo {
40+
field: Option<String>,
41+
}
42+
43+
struct ResultFoo {
44+
field: Result<String, ()>,
45+
}
46+
47+
fn issue_8920() {
48+
let vec = vec![OptionFoo {
49+
field: Some(String::from("str")),
50+
}];
51+
let _ = vec
52+
.iter()
53+
.filter(|f| f.field.is_some())
54+
.map(|f| f.field.clone().unwrap());
55+
56+
let vec = vec![ResultFoo {
57+
field: Ok(String::from("str")),
58+
}];
59+
let _ = vec.iter().filter(|f| f.field.is_ok()).map(|f| f.field.clone().unwrap());
60+
}

tests/ui/manual_filter_map.stderr

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,19 @@ error: `filter(..).map(..)` can be simplified as `filter_map(..)`
1818
LL | let _ = (0..).filter(|&n| to_res(n).is_ok()).map(|a| to_res(a).unwrap_or(1));
1919
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter_map(|a| to_res(a).ok())`
2020

21-
error: aborting due to 3 previous errors
21+
error: `filter(..).map(..)` can be simplified as `filter_map(..)`
22+
--> $DIR/manual_filter_map.rs:53:10
23+
|
24+
LL | .filter(|f| f.field.is_some())
25+
| __________^
26+
LL | | .map(|f| f.field.clone().unwrap());
27+
| |__________________________________________^ help: try: `filter_map(|f| f.field.clone())`
28+
29+
error: `filter(..).map(..)` can be simplified as `filter_map(..)`
30+
--> $DIR/manual_filter_map.rs:59:24
31+
|
32+
LL | let _ = vec.iter().filter(|f| f.field.is_ok()).map(|f| f.field.clone().unwrap());
33+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter_map(|f| f.field.clone().ok())`
34+
35+
error: aborting due to 5 previous errors
2236

tests/ui/manual_find_map.fixed

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,23 @@ fn to_opt<T>(_: T) -> Option<T> {
3535
fn to_res<T>(_: T) -> Result<T, ()> {
3636
unimplemented!()
3737
}
38+
39+
struct OptionFoo {
40+
field: Option<String>,
41+
}
42+
43+
struct ResultFoo {
44+
field: Result<String, ()>,
45+
}
46+
47+
fn issue_8920() {
48+
let vec = vec![OptionFoo {
49+
field: Some(String::from("str")),
50+
}];
51+
let _ = vec.iter().find_map(|f| f.field.clone());
52+
53+
let vec = vec![ResultFoo {
54+
field: Ok(String::from("str")),
55+
}];
56+
let _ = vec.iter().find_map(|f| f.field.clone().ok());
57+
}

tests/ui/manual_find_map.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,23 @@ fn to_opt<T>(_: T) -> Option<T> {
3535
fn to_res<T>(_: T) -> Result<T, ()> {
3636
unimplemented!()
3737
}
38+
39+
struct OptionFoo {
40+
field: Option<String>,
41+
}
42+
43+
struct ResultFoo {
44+
field: Result<String, ()>,
45+
}
46+
47+
fn issue_8920() {
48+
let vec = vec![OptionFoo {
49+
field: Some(String::from("str")),
50+
}];
51+
let _ = vec.iter().find(|f| f.field.is_some()).map(|f| f.field.clone().unwrap());
52+
53+
let vec = vec![ResultFoo {
54+
field: Ok(String::from("str")),
55+
}];
56+
let _ = vec.iter().find(|f| f.field.is_ok()).map(|f| f.field.clone().unwrap());
57+
}

tests/ui/manual_find_map.stderr

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,17 @@ error: `find(..).map(..)` can be simplified as `find_map(..)`
1818
LL | let _ = (0..).find(|&n| to_res(n).is_ok()).map(|a| to_res(a).unwrap_or(1));
1919
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|a| to_res(a).ok())`
2020

21-
error: aborting due to 3 previous errors
21+
error: `find(..).map(..)` can be simplified as `find_map(..)`
22+
--> $DIR/manual_find_map.rs:51:24
23+
|
24+
LL | let _ = vec.iter().find(|f| f.field.is_some()).map(|f| f.field.clone().unwrap());
25+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|f| f.field.clone())`
26+
27+
error: `find(..).map(..)` can be simplified as `find_map(..)`
28+
--> $DIR/manual_find_map.rs:56:24
29+
|
30+
LL | let _ = vec.iter().find(|f| f.field.is_ok()).map(|f| f.field.clone().unwrap());
31+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|f| f.field.clone().ok())`
32+
33+
error: aborting due to 5 previous errors
2234

0 commit comments

Comments
 (0)