diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 570ae66d595..3009aa3a64e 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1497,11 +1497,20 @@ impl<'tcx> LateLintPass<'tcx> for Methods { if cx.access_levels.is_exported(impl_item.hir_id) { // check missing trait implementations for &(method_name, n_args, fn_header, self_kind, out_type, trait_name) in &TRAIT_METHODS { + let no_lifetime_params = || { + impl_item.generics.params.iter().filter(|p| match p.kind { + hir::GenericParamKind::Lifetime { .. } => true, + _ => false, + }).count() == 0 + }; if name == method_name && sig.decl.inputs.len() == n_args && out_type.matches(cx, &sig.decl.output) && self_kind.matches(cx, self_ty, first_arg_ty) && - fn_header_equals(*fn_header, sig.header) { + fn_header_equals(*fn_header, sig.header) && + // ignore methods with lifetime params, risk of false positive + no_lifetime_params() + { span_lint(cx, SHOULD_IMPLEMENT_TRAIT, impl_item.span, &format!( "defining a method called `{}` on this type; consider implementing \ the `{}` trait or choosing a less ambiguous name", name, trait_name)); diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 7880cf36415..3b267b0dab2 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -10,6 +10,7 @@ clippy::non_ascii_literal, clippy::new_without_default, clippy::needless_pass_by_value, + clippy::needless_lifetimes, clippy::print_stdout, clippy::must_use_candidate, clippy::use_self, @@ -82,6 +83,10 @@ impl T { fn new(self) -> Self { unimplemented!(); } + + pub fn next<'b>(&'b mut self) -> Option<&'b mut T> { + unimplemented!(); + } } pub struct T1; diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 01cf487ac14..9b8ecaed692 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,5 +1,5 @@ error: defining a method called `add` on this type; consider implementing the `std::ops::Add` trait or choosing a less ambiguous name - --> $DIR/methods.rs:39:5 + --> $DIR/methods.rs:40:5 | LL | / pub fn add(self, other: T) -> T { LL | | self @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::should-implement-trait` implied by `-D warnings` error: methods called `new` usually return `Self` - --> $DIR/methods.rs:169:5 + --> $DIR/methods.rs:174:5 | LL | / fn new() -> i32 { LL | | 0 @@ -19,7 +19,7 @@ LL | | } = note: `-D clippy::new-ret-no-self` implied by `-D warnings` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:188:13 + --> $DIR/methods.rs:193:13 | LL | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | let _ = v.iter().filter(|&x| *x < 0).next(); = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:191:13 + --> $DIR/methods.rs:196:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ @@ -38,7 +38,7 @@ LL | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:208:22 + --> $DIR/methods.rs:213:22 | LL | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x < 0)` @@ -46,25 +46,25 @@ LL | let _ = v.iter().find(|&x| *x < 0).is_some(); = note: `-D clippy::search-is-some` implied by `-D warnings` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:209:20 + --> $DIR/methods.rs:214:20 | LL | let _ = (0..1).find(|x| **y == *x).is_some(); // one dereference less | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| **y == x)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:210:20 + --> $DIR/methods.rs:215:20 | LL | let _ = (0..1).find(|x| *x == 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| x == 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:211:22 + --> $DIR/methods.rs:216:22 | LL | let _ = v.iter().find(|x| **x == 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x == 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:214:13 + --> $DIR/methods.rs:219:13 | LL | let _ = v.iter().find(|&x| { | _____________^ @@ -74,13 +74,13 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:220:22 + --> $DIR/methods.rs:225:22 | LL | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:223:13 + --> $DIR/methods.rs:228:13 | LL | let _ = v.iter().position(|&x| { | _____________^ @@ -90,13 +90,13 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:229:22 + --> $DIR/methods.rs:234:22 | LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:232:13 + --> $DIR/methods.rs:237:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^