fix(manual_find_map and manual_filter_map): check clone method

This commit is contained in:
kyoto7250 2022-06-02 00:57:08 +09:00
parent 39231b4b50
commit 007fae10ed
7 changed files with 122 additions and 3 deletions

View File

@ -155,7 +155,15 @@ pub(super) fn check<'tcx>(
}
false
};
if SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(filter_arg, map_arg);
if match map_arg.kind {
ExprKind::MethodCall(clone, [original_arg], _) => {
clone.ident.name == sym::clone
&& SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(filter_arg, original_arg)
},
_ => SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(filter_arg, map_arg)
};
then {
let span = filter_span.with_hi(expr.span.hi());
let (filter_name, lint) = if is_find {

View File

@ -35,3 +35,25 @@ fn to_opt<T>(_: T) -> Option<T> {
fn to_res<T>(_: T) -> Result<T, ()> {
unimplemented!()
}
struct OptionFoo {
field: Option<String>,
}
struct ResultFoo {
field: Result<String, ()>,
}
fn issue_8920() {
let vec = vec![OptionFoo {
field: Some(String::from("str")),
}];
let _ = vec
.iter()
.filter_map(|f| f.field.clone());
let vec = vec![ResultFoo {
field: Ok(String::from("str")),
}];
let _ = vec.iter().filter_map(|f| f.field.clone().ok());
}

View File

@ -35,3 +35,26 @@ fn to_opt<T>(_: T) -> Option<T> {
fn to_res<T>(_: T) -> Result<T, ()> {
unimplemented!()
}
struct OptionFoo {
field: Option<String>,
}
struct ResultFoo {
field: Result<String, ()>,
}
fn issue_8920() {
let vec = vec![OptionFoo {
field: Some(String::from("str")),
}];
let _ = vec
.iter()
.filter(|f| f.field.is_some())
.map(|f| f.field.clone().unwrap());
let vec = vec![ResultFoo {
field: Ok(String::from("str")),
}];
let _ = vec.iter().filter(|f| f.field.is_ok()).map(|f| f.field.clone().unwrap());
}

View File

@ -18,5 +18,19 @@ error: `filter(..).map(..)` can be simplified as `filter_map(..)`
LL | let _ = (0..).filter(|&n| to_res(n).is_ok()).map(|a| to_res(a).unwrap_or(1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter_map(|a| to_res(a).ok())`
error: aborting due to 3 previous errors
error: `filter(..).map(..)` can be simplified as `filter_map(..)`
--> $DIR/manual_filter_map.rs:53:10
|
LL | .filter(|f| f.field.is_some())
| __________^
LL | | .map(|f| f.field.clone().unwrap());
| |__________________________________________^ help: try: `filter_map(|f| f.field.clone())`
error: `filter(..).map(..)` can be simplified as `filter_map(..)`
--> $DIR/manual_filter_map.rs:59:24
|
LL | let _ = vec.iter().filter(|f| f.field.is_ok()).map(|f| f.field.clone().unwrap());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `filter_map(|f| f.field.clone().ok())`
error: aborting due to 5 previous errors

View File

@ -35,3 +35,23 @@ fn to_opt<T>(_: T) -> Option<T> {
fn to_res<T>(_: T) -> Result<T, ()> {
unimplemented!()
}
struct OptionFoo {
field: Option<String>,
}
struct ResultFoo {
field: Result<String, ()>,
}
fn issue_8920() {
let vec = vec![OptionFoo {
field: Some(String::from("str")),
}];
let _ = vec.iter().find_map(|f| f.field.clone());
let vec = vec![ResultFoo {
field: Ok(String::from("str")),
}];
let _ = vec.iter().find_map(|f| f.field.clone().ok());
}

View File

@ -35,3 +35,23 @@ fn to_opt<T>(_: T) -> Option<T> {
fn to_res<T>(_: T) -> Result<T, ()> {
unimplemented!()
}
struct OptionFoo {
field: Option<String>,
}
struct ResultFoo {
field: Result<String, ()>,
}
fn issue_8920() {
let vec = vec![OptionFoo {
field: Some(String::from("str")),
}];
let _ = vec.iter().find(|f| f.field.is_some()).map(|f| f.field.clone().unwrap());
let vec = vec![ResultFoo {
field: Ok(String::from("str")),
}];
let _ = vec.iter().find(|f| f.field.is_ok()).map(|f| f.field.clone().unwrap());
}

View File

@ -18,5 +18,17 @@ error: `find(..).map(..)` can be simplified as `find_map(..)`
LL | let _ = (0..).find(|&n| to_res(n).is_ok()).map(|a| to_res(a).unwrap_or(1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|a| to_res(a).ok())`
error: aborting due to 3 previous errors
error: `find(..).map(..)` can be simplified as `find_map(..)`
--> $DIR/manual_find_map.rs:51:24
|
LL | let _ = vec.iter().find(|f| f.field.is_some()).map(|f| f.field.clone().unwrap());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|f| f.field.clone())`
error: `find(..).map(..)` can be simplified as `find_map(..)`
--> $DIR/manual_find_map.rs:56:24
|
LL | let _ = vec.iter().find(|f| f.field.is_ok()).map(|f| f.field.clone().unwrap());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `find_map(|f| f.field.clone().ok())`
error: aborting due to 5 previous errors