From e9f56f949d2d1c11f1331151323beb8e85181c29 Mon Sep 17 00:00:00 2001 From: dswij Date: Fri, 13 Aug 2021 14:34:33 +0800 Subject: [PATCH 1/2] Add false positive test for iterator method --- tests/ui/auxiliary/option_helpers.rs | 9 +++++++++ tests/ui/methods.rs | 5 ++++- 2 files changed, 13 insertions(+), 1 deletion(-) 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() { From 91b598a8e484da328325ece3400e8612b6f854df Mon Sep 17 00:00:00 2001 From: dswij Date: Fri, 13 Aug 2021 14:36:40 +0800 Subject: [PATCH 2/2] Fix false positive on `filter_next` --- clippy_lints/src/methods/filter_next.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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, "..");