diff options
| author | kyoto7250 <50972773+kyoto7250@users.noreply.github.com> | 2022-06-02 00:57:08 +0900 |
|---|---|---|
| committer | kyoto7250 <50972773+kyoto7250@users.noreply.github.com> | 2022-06-02 09:54:14 +0900 |
| commit | 007fae10ed8c8fa51b396bcc02071fe792f2c288 (patch) | |
| tree | d5736bf47d5a61562153a6d5f02d1a4395593d86 | |
| parent | 39231b4b503955626c1ccf965b8328ac67c523bb (diff) | |
| download | rust-007fae10ed8c8fa51b396bcc02071fe792f2c288.tar.gz rust-007fae10ed8c8fa51b396bcc02071fe792f2c288.zip | |
fix(manual_find_map and manual_filter_map): check clone method
| -rw-r--r-- | clippy_lints/src/methods/filter_map.rs | 10 | ||||
| -rw-r--r-- | tests/ui/manual_filter_map.fixed | 22 | ||||
| -rw-r--r-- | tests/ui/manual_filter_map.rs | 23 | ||||
| -rw-r--r-- | tests/ui/manual_filter_map.stderr | 16 | ||||
| -rw-r--r-- | tests/ui/manual_find_map.fixed | 20 | ||||
| -rw-r--r-- | tests/ui/manual_find_map.rs | 20 | ||||
| -rw-r--r-- | tests/ui/manual_find_map.stderr | 14 |
7 files changed, 122 insertions, 3 deletions
diff --git a/clippy_lints/src/methods/filter_map.rs b/clippy_lints/src/methods/filter_map.rs index 558cb6bd64e..04ca295dc69 100644 --- a/clippy_lints/src/methods/filter_map.rs +++ b/clippy_lints/src/methods/filter_map.rs @@ -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 { diff --git a/tests/ui/manual_filter_map.fixed b/tests/ui/manual_filter_map.fixed index fc8f58f8ea5..c88a4f43de2 100644 --- a/tests/ui/manual_filter_map.fixed +++ b/tests/ui/manual_filter_map.fixed @@ -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()); +} diff --git a/tests/ui/manual_filter_map.rs b/tests/ui/manual_filter_map.rs index 3af4bbee3bf..bb859ebe315 100644 --- a/tests/ui/manual_filter_map.rs +++ b/tests/ui/manual_filter_map.rs @@ -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()); +} diff --git a/tests/ui/manual_filter_map.stderr b/tests/ui/manual_filter_map.stderr index 4d4e2d5c12f..a78343e882f 100644 --- a/tests/ui/manual_filter_map.stderr +++ b/tests/ui/manual_filter_map.stderr @@ -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 diff --git a/tests/ui/manual_find_map.fixed b/tests/ui/manual_find_map.fixed index 95e97c4fd1f..d78d72d8e8f 100644 --- a/tests/ui/manual_find_map.fixed +++ b/tests/ui/manual_find_map.fixed @@ -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()); +} diff --git a/tests/ui/manual_find_map.rs b/tests/ui/manual_find_map.rs index cd3c82e3b25..74e8e52ed16 100644 --- a/tests/ui/manual_find_map.rs +++ b/tests/ui/manual_find_map.rs @@ -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()); +} diff --git a/tests/ui/manual_find_map.stderr b/tests/ui/manual_find_map.stderr index 9e7f798df45..0b1465a8422 100644 --- a/tests/ui/manual_find_map.stderr +++ b/tests/ui/manual_find_map.stderr @@ -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 |
