diff --git a/clippy_lints/src/methods/filter_next.rs b/clippy_lints/src/methods/filter_next.rs index 172714f6b01c6..bcf8d93b602ef 100644 --- a/clippy_lints/src/methods/filter_next.rs +++ b/clippy_lints/src/methods/filter_next.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; -use clippy_utils::is_trait_method; use clippy_utils::source::snippet; +use clippy_utils::ty::implements_trait; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -16,7 +16,10 @@ pub(super) fn check<'tcx>( filter_arg: &'tcx hir::Expr<'_>, ) { // lint if caller of `.filter().next()` is an Iterator - if is_trait_method(cx, expr, sym::Iterator) { + let recv_impls_iterator = cx.tcx.get_diagnostic_item(sym::Iterator).map_or(false, |id| { + implements_trait(cx, cx.typeck_results().expr_ty(recv), id, &[]) + }); + if recv_impls_iterator { let msg = "called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling \ `.find(..)` instead"; let filter_snippet = snippet(cx, filter_arg.span, ".."); diff --git a/tests/ui/auxiliary/option_helpers.rs b/tests/ui/auxiliary/option_helpers.rs index 7dc3f4ebd4d46..86a637ce3093c 100644 --- a/tests/ui/auxiliary/option_helpers.rs +++ b/tests/ui/auxiliary/option_helpers.rs @@ -53,3 +53,12 @@ impl IteratorFalsePositives { self.foo as usize } } + +#[derive(Copy, Clone)] +pub struct IteratorMethodFalsePositives; + +impl IteratorMethodFalsePositives { + pub fn filter(&self, _s: i32) -> std::vec::IntoIter { + unimplemented!(); + } +} diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 513d930e05687..c441b35b99203 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -32,7 +32,7 @@ use std::ops::Mul; use std::rc::{self, Rc}; use std::sync::{self, Arc}; -use option_helpers::IteratorFalsePositives; +use option_helpers::{IteratorFalsePositives, IteratorMethodFalsePositives}; struct Lt<'a> { foo: &'a u32, @@ -131,6 +131,9 @@ fn filter_next() { // Check that we don't lint if the caller is not an `Iterator`. let foo = IteratorFalsePositives { foo: 0 }; let _ = foo.filter().next(); + + let foo = IteratorMethodFalsePositives {}; + let _ = foo.filter(42).next(); } fn main() {