From 9f629d1b7eb2b53897ae3b367c5ce75540a9519f Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sun, 14 Jun 2026 13:49:33 +0200 Subject: [PATCH 1/7] test: make the fixable file the default i.e. rename: - filter_map_next -> filter_map_next_unfixable - filter_map_next_fixable -> filter_map_next This is because having fixable lints is the common case --- ...xt_fixable.fixed => filter_map_next.fixed} | 0 tests/ui/filter_map_next.rs | 24 ++++++++++--------- tests/ui/filter_map_next.stderr | 18 +++++++------- tests/ui/filter_map_next_fixable.rs | 22 ----------------- tests/ui/filter_map_next_fixable.stderr | 17 ------------- tests/ui/filter_map_next_unfixable.rs | 20 ++++++++++++++++ tests/ui/filter_map_next_unfixable.stderr | 15 ++++++++++++ 7 files changed, 58 insertions(+), 58 deletions(-) rename tests/ui/{filter_map_next_fixable.fixed => filter_map_next.fixed} (100%) delete mode 100644 tests/ui/filter_map_next_fixable.rs delete mode 100644 tests/ui/filter_map_next_fixable.stderr create mode 100644 tests/ui/filter_map_next_unfixable.rs create mode 100644 tests/ui/filter_map_next_unfixable.stderr diff --git a/tests/ui/filter_map_next_fixable.fixed b/tests/ui/filter_map_next.fixed similarity index 100% rename from tests/ui/filter_map_next_fixable.fixed rename to tests/ui/filter_map_next.fixed diff --git a/tests/ui/filter_map_next.rs b/tests/ui/filter_map_next.rs index 5414e01c8700..3d686ef41d91 100644 --- a/tests/ui/filter_map_next.rs +++ b/tests/ui/filter_map_next.rs @@ -3,18 +3,20 @@ fn main() { let a = ["1", "lol", "3", "NaN", "5"]; - #[rustfmt::skip] - let _: Option = vec![1, 2, 3, 4, 5, 6] + let element: Option = a.iter().filter_map(|s| s.parse().ok()).next(); //~^ filter_map_next + assert_eq!(element, Some(1)); +} +#[clippy::msrv = "1.29"] +fn msrv_1_29() { + let a = ["1", "lol", "3", "NaN", "5"]; + let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); +} - .into_iter() - .filter_map(|x| { - if x == 2 { - Some(x * 2) - } else { - None - } - }) - .next(); +#[clippy::msrv = "1.30"] +fn msrv_1_30() { + let a = ["1", "lol", "3", "NaN", "5"]; + let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); + //~^ filter_map_next } diff --git a/tests/ui/filter_map_next.stderr b/tests/ui/filter_map_next.stderr index 974bb946d46a..9b51de0a0294 100644 --- a/tests/ui/filter_map_next.stderr +++ b/tests/ui/filter_map_next.stderr @@ -1,15 +1,17 @@ error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead - --> tests/ui/filter_map_next.rs:7:26 + --> tests/ui/filter_map_next.rs:6:32 | -LL | let _: Option = vec![1, 2, 3, 4, 5, 6] - | __________________________^ -... | -LL | | }) -LL | | .next(); - | |_______________^ +LL | let element: Option = a.iter().filter_map(|s| s.parse().ok()).next(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.iter().find_map(|s| s.parse().ok())` | = note: `-D clippy::filter-map-next` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::filter_map_next)]` -error: aborting due to 1 previous error +error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead + --> tests/ui/filter_map_next.rs:20:26 + | +LL | let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.iter().find_map(|s| s.parse().ok())` + +error: aborting due to 2 previous errors diff --git a/tests/ui/filter_map_next_fixable.rs b/tests/ui/filter_map_next_fixable.rs deleted file mode 100644 index 3d686ef41d91..000000000000 --- a/tests/ui/filter_map_next_fixable.rs +++ /dev/null @@ -1,22 +0,0 @@ -#![warn(clippy::filter_map_next)] - -fn main() { - let a = ["1", "lol", "3", "NaN", "5"]; - - let element: Option = a.iter().filter_map(|s| s.parse().ok()).next(); - //~^ filter_map_next - assert_eq!(element, Some(1)); -} - -#[clippy::msrv = "1.29"] -fn msrv_1_29() { - let a = ["1", "lol", "3", "NaN", "5"]; - let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); -} - -#[clippy::msrv = "1.30"] -fn msrv_1_30() { - let a = ["1", "lol", "3", "NaN", "5"]; - let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); - //~^ filter_map_next -} diff --git a/tests/ui/filter_map_next_fixable.stderr b/tests/ui/filter_map_next_fixable.stderr deleted file mode 100644 index 1002837732b8..000000000000 --- a/tests/ui/filter_map_next_fixable.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead - --> tests/ui/filter_map_next_fixable.rs:6:32 - | -LL | let element: Option = a.iter().filter_map(|s| s.parse().ok()).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.iter().find_map(|s| s.parse().ok())` - | - = note: `-D clippy::filter-map-next` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::filter_map_next)]` - -error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead - --> tests/ui/filter_map_next_fixable.rs:20:26 - | -LL | let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.iter().find_map(|s| s.parse().ok())` - -error: aborting due to 2 previous errors - diff --git a/tests/ui/filter_map_next_unfixable.rs b/tests/ui/filter_map_next_unfixable.rs new file mode 100644 index 000000000000..5414e01c8700 --- /dev/null +++ b/tests/ui/filter_map_next_unfixable.rs @@ -0,0 +1,20 @@ +#![warn(clippy::filter_map_next)] + +fn main() { + let a = ["1", "lol", "3", "NaN", "5"]; + + #[rustfmt::skip] + let _: Option = vec![1, 2, 3, 4, 5, 6] + //~^ filter_map_next + + + .into_iter() + .filter_map(|x| { + if x == 2 { + Some(x * 2) + } else { + None + } + }) + .next(); +} diff --git a/tests/ui/filter_map_next_unfixable.stderr b/tests/ui/filter_map_next_unfixable.stderr new file mode 100644 index 000000000000..39ce93a11cec --- /dev/null +++ b/tests/ui/filter_map_next_unfixable.stderr @@ -0,0 +1,15 @@ +error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead + --> tests/ui/filter_map_next_unfixable.rs:7:26 + | +LL | let _: Option = vec![1, 2, 3, 4, 5, 6] + | __________________________^ +... | +LL | | }) +LL | | .next(); + | |_______________^ + | + = note: `-D clippy::filter-map-next` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::filter_map_next)]` + +error: aborting due to 1 previous error + From 85139f72a3de73ef2f4d723a9285fead6c256a92 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sun, 14 Jun 2026 01:25:05 +0200 Subject: [PATCH 2/7] misc improvements --- clippy_lints/src/methods/filter_map_next.rs | 23 +++++++-------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/methods/filter_map_next.rs b/clippy_lints/src/methods/filter_map_next.rs index 698025d58e54..3787130564c3 100644 --- a/clippy_lints/src/methods/filter_map_next.rs +++ b/clippy_lints/src/methods/filter_map_next.rs @@ -3,29 +3,20 @@ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; use clippy_utils::source::snippet; use rustc_errors::Applicability; -use rustc_hir as hir; +use rustc_hir::Expr; use rustc_lint::LateContext; use rustc_span::sym; use super::FILTER_MAP_NEXT; -pub(super) fn check<'tcx>( - cx: &LateContext<'tcx>, - expr: &'tcx hir::Expr<'_>, - recv: &'tcx hir::Expr<'_>, - arg: &'tcx hir::Expr<'_>, - msrv: Msrv, -) { - if cx.ty_based_def(expr).opt_parent(cx).is_diag_item(cx, sym::Iterator) { - if !msrv.meets(cx, msrvs::ITERATOR_FIND_MAP) { - return; - } - - let msg = "called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling \ - `.find_map(..)` instead"; +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<'_>, msrv: Msrv) { + if cx.ty_based_def(expr).opt_parent(cx).is_diag_item(cx, sym::Iterator) && msrv.meets(cx, msrvs::ITERATOR_FIND_MAP) + { + let msg = "called `filter_map(..).next()` on an `Iterator`. \ + This is more succinctly expressed by calling `.find_map(..)` instead"; let filter_snippet = snippet(cx, arg.span, ".."); if filter_snippet.lines().count() <= 1 { - let iter_snippet = snippet(cx, recv.span, ".."); + let iter_snippet = snippet(cx, recv.span, "_"); span_lint_and_sugg( cx, FILTER_MAP_NEXT, From 4801dcfdc6e12b2b94fc479b491cb84c2e9f2f0e Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sun, 14 Jun 2026 13:42:37 +0200 Subject: [PATCH 3/7] wrap everything in `span_lint_and_then` separate commit to improve diffs --- clippy_lints/src/methods/filter_map_next.rs | 38 +++++++++++---------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/methods/filter_map_next.rs b/clippy_lints/src/methods/filter_map_next.rs index 3787130564c3..e108a201b04a 100644 --- a/clippy_lints/src/methods/filter_map_next.rs +++ b/clippy_lints/src/methods/filter_map_next.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; use clippy_utils::source::snippet; @@ -12,22 +12,24 @@ use super::FILTER_MAP_NEXT; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<'_>, msrv: Msrv) { if cx.ty_based_def(expr).opt_parent(cx).is_diag_item(cx, sym::Iterator) && msrv.meets(cx, msrvs::ITERATOR_FIND_MAP) { - let msg = "called `filter_map(..).next()` on an `Iterator`. \ - This is more succinctly expressed by calling `.find_map(..)` instead"; - let filter_snippet = snippet(cx, arg.span, ".."); - if filter_snippet.lines().count() <= 1 { - let iter_snippet = snippet(cx, recv.span, "_"); - span_lint_and_sugg( - cx, - FILTER_MAP_NEXT, - expr.span, - msg, - "try", - format!("{iter_snippet}.find_map({filter_snippet})"), - Applicability::MachineApplicable, - ); - } else { - span_lint(cx, FILTER_MAP_NEXT, expr.span, msg); - } + span_lint_and_then( + cx, + FILTER_MAP_NEXT, + expr.span, + "called `filter_map(..).next()` on an `Iterator`. \ + This is more succinctly expressed by calling `.find_map(..)` instead", + |diag| { + let filter_snippet = snippet(cx, arg.span, ".."); + if filter_snippet.lines().count() <= 1 { + let iter_snippet = snippet(cx, recv.span, "_"); + diag.span_suggestion( + expr.span, + "try", + format!("{iter_snippet}.find_map({filter_snippet})"), + Applicability::MachineApplicable, + ); + } + }, + ); } } From 9867fc2954f0bd4e9ebce2f0f7f0946d62221093 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sun, 14 Jun 2026 14:02:28 +0200 Subject: [PATCH 4/7] extract suggestion out of the main message 1. In the singe-line case, we switch to verbose suggestions, otherwise the suggestion line gets too long due to the longer message. 2. In the multi-line case, we use span-less help, otherwise the whole multiline span gets highlighted the second time. 3. Also make the suggestion message more concise. --- clippy_lints/src/methods/filter_map_next.rs | 11 +++++++---- tests/ui/filter_map_next.stderr | 19 +++++++++++++++---- tests/ui/filter_map_next_unfixable.stderr | 3 ++- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/methods/filter_map_next.rs b/clippy_lints/src/methods/filter_map_next.rs index e108a201b04a..571a5560eeec 100644 --- a/clippy_lints/src/methods/filter_map_next.rs +++ b/clippy_lints/src/methods/filter_map_next.rs @@ -16,18 +16,21 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: cx, FILTER_MAP_NEXT, expr.span, - "called `filter_map(..).next()` on an `Iterator`. \ - This is more succinctly expressed by calling `.find_map(..)` instead", + "called `filter_map(..).next()` on an `Iterator`", |diag| { + let sugg_msg = "use `.find_map(..)` instead"; + let filter_snippet = snippet(cx, arg.span, ".."); if filter_snippet.lines().count() <= 1 { let iter_snippet = snippet(cx, recv.span, "_"); - diag.span_suggestion( + diag.span_suggestion_verbose( expr.span, - "try", + sugg_msg, format!("{iter_snippet}.find_map({filter_snippet})"), Applicability::MachineApplicable, ); + } else { + diag.help(sugg_msg); } }, ); diff --git a/tests/ui/filter_map_next.stderr b/tests/ui/filter_map_next.stderr index 9b51de0a0294..76bbdc4ac75a 100644 --- a/tests/ui/filter_map_next.stderr +++ b/tests/ui/filter_map_next.stderr @@ -1,17 +1,28 @@ -error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead +error: called `filter_map(..).next()` on an `Iterator` --> tests/ui/filter_map_next.rs:6:32 | LL | let element: Option = a.iter().filter_map(|s| s.parse().ok()).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.iter().find_map(|s| s.parse().ok())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::filter-map-next` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::filter_map_next)]` +help: use `.find_map(..)` instead + | +LL - let element: Option = a.iter().filter_map(|s| s.parse().ok()).next(); +LL + let element: Option = a.iter().find_map(|s| s.parse().ok()); + | -error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead +error: called `filter_map(..).next()` on an `Iterator` --> tests/ui/filter_map_next.rs:20:26 | LL | let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.iter().find_map(|s| s.parse().ok())` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `.find_map(..)` instead + | +LL - let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); +LL + let _: Option = a.iter().find_map(|s| s.parse().ok()); + | error: aborting due to 2 previous errors diff --git a/tests/ui/filter_map_next_unfixable.stderr b/tests/ui/filter_map_next_unfixable.stderr index 39ce93a11cec..9ebedf7d8f77 100644 --- a/tests/ui/filter_map_next_unfixable.stderr +++ b/tests/ui/filter_map_next_unfixable.stderr @@ -1,4 +1,4 @@ -error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead +error: called `filter_map(..).next()` on an `Iterator` --> tests/ui/filter_map_next_unfixable.rs:7:26 | LL | let _: Option = vec![1, 2, 3, 4, 5, 6] @@ -8,6 +8,7 @@ LL | | }) LL | | .next(); | |_______________^ | + = help: use `.find_map(..)` instead = note: `-D clippy::filter-map-next` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::filter_map_next)]` From 271382534d3b953474615058720e1993429c7fbe Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sun, 14 Jun 2026 14:08:32 +0200 Subject: [PATCH 5/7] fix: respect reduced applicability --- clippy_lints/src/methods/filter_map_next.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/methods/filter_map_next.rs b/clippy_lints/src/methods/filter_map_next.rs index 571a5560eeec..a0f86e003a23 100644 --- a/clippy_lints/src/methods/filter_map_next.rs +++ b/clippy_lints/src/methods/filter_map_next.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::{MaybeDef, MaybeTypeckRes}; -use clippy_utils::source::snippet; +use clippy_utils::source::snippet_with_applicability; use rustc_errors::Applicability; use rustc_hir::Expr; use rustc_lint::LateContext; @@ -20,14 +20,15 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: |diag| { let sugg_msg = "use `.find_map(..)` instead"; - let filter_snippet = snippet(cx, arg.span, ".."); + let mut app = Applicability::MachineApplicable; + let filter_snippet = snippet_with_applicability(cx, arg.span, "..", &mut app); if filter_snippet.lines().count() <= 1 { - let iter_snippet = snippet(cx, recv.span, "_"); + let iter_snippet = snippet_with_applicability(cx, recv.span, "_", &mut app); diag.span_suggestion_verbose( expr.span, sugg_msg, format!("{iter_snippet}.find_map({filter_snippet})"), - Applicability::MachineApplicable, + app, ); } else { diag.help(sugg_msg); From 2be04b4afa319ac1b8f26f785bbf94c290e19352 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sun, 14 Jun 2026 13:54:37 +0200 Subject: [PATCH 6/7] also suggest in the multi-line case This used to be a workaround for a rustc diagnostics issue which has since been resolved --- clippy_lints/src/methods/filter_map_next.rs | 20 +++++--------- tests/ui/filter_map_next.fixed | 13 +++++++++ tests/ui/filter_map_next.rs | 15 +++++++++++ tests/ui/filter_map_next.stderr | 29 +++++++++++++++++++-- tests/ui/filter_map_next_unfixable.rs | 20 -------------- tests/ui/filter_map_next_unfixable.stderr | 16 ------------ 6 files changed, 62 insertions(+), 51 deletions(-) delete mode 100644 tests/ui/filter_map_next_unfixable.rs delete mode 100644 tests/ui/filter_map_next_unfixable.stderr diff --git a/clippy_lints/src/methods/filter_map_next.rs b/clippy_lints/src/methods/filter_map_next.rs index a0f86e003a23..9e55732830bc 100644 --- a/clippy_lints/src/methods/filter_map_next.rs +++ b/clippy_lints/src/methods/filter_map_next.rs @@ -18,21 +18,15 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: expr.span, "called `filter_map(..).next()` on an `Iterator`", |diag| { - let sugg_msg = "use `.find_map(..)` instead"; - let mut app = Applicability::MachineApplicable; + let iter_snippet = snippet_with_applicability(cx, recv.span, "_", &mut app); let filter_snippet = snippet_with_applicability(cx, arg.span, "..", &mut app); - if filter_snippet.lines().count() <= 1 { - let iter_snippet = snippet_with_applicability(cx, recv.span, "_", &mut app); - diag.span_suggestion_verbose( - expr.span, - sugg_msg, - format!("{iter_snippet}.find_map({filter_snippet})"), - app, - ); - } else { - diag.help(sugg_msg); - } + diag.span_suggestion_verbose( + expr.span, + "use `.find_map(..)` instead", + format!("{iter_snippet}.find_map({filter_snippet})"), + app, + ); }, ); } diff --git a/tests/ui/filter_map_next.fixed b/tests/ui/filter_map_next.fixed index 09c416041a4e..cd27501dbe5d 100644 --- a/tests/ui/filter_map_next.fixed +++ b/tests/ui/filter_map_next.fixed @@ -6,6 +6,19 @@ fn main() { let element: Option = a.iter().find_map(|s| s.parse().ok()); //~^ filter_map_next assert_eq!(element, Some(1)); + + #[rustfmt::skip] + let _: Option = vec![1, 2, 3, 4, 5, 6] + //~^ filter_map_next + + + .into_iter().find_map(|x| { + if x == 2 { + Some(x * 2) + } else { + None + } + }); } #[clippy::msrv = "1.29"] diff --git a/tests/ui/filter_map_next.rs b/tests/ui/filter_map_next.rs index 3d686ef41d91..e3e668689682 100644 --- a/tests/ui/filter_map_next.rs +++ b/tests/ui/filter_map_next.rs @@ -6,6 +6,21 @@ fn main() { let element: Option = a.iter().filter_map(|s| s.parse().ok()).next(); //~^ filter_map_next assert_eq!(element, Some(1)); + + #[rustfmt::skip] + let _: Option = vec![1, 2, 3, 4, 5, 6] + //~^ filter_map_next + + + .into_iter() + .filter_map(|x| { + if x == 2 { + Some(x * 2) + } else { + None + } + }) + .next(); } #[clippy::msrv = "1.29"] diff --git a/tests/ui/filter_map_next.stderr b/tests/ui/filter_map_next.stderr index 76bbdc4ac75a..e227600662aa 100644 --- a/tests/ui/filter_map_next.stderr +++ b/tests/ui/filter_map_next.stderr @@ -13,7 +13,32 @@ LL + let element: Option = a.iter().find_map(|s| s.parse().ok()); | error: called `filter_map(..).next()` on an `Iterator` - --> tests/ui/filter_map_next.rs:20:26 + --> tests/ui/filter_map_next.rs:11:26 + | +LL | let _: Option = vec![1, 2, 3, 4, 5, 6] + | __________________________^ +... | +LL | | }) +LL | | .next(); + | |_______________^ + | +help: use `.find_map(..)` instead + | +LL ~ let _: Option = vec![1, 2, 3, 4, 5, 6] +LL + +LL + +LL + +LL + .into_iter().find_map(|x| { +LL + if x == 2 { +LL + Some(x * 2) +LL + } else { +LL + None +LL + } +LL ~ }); + | + +error: called `filter_map(..).next()` on an `Iterator` + --> tests/ui/filter_map_next.rs:35:26 | LL | let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -24,5 +49,5 @@ LL - let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); LL + let _: Option = a.iter().find_map(|s| s.parse().ok()); | -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/filter_map_next_unfixable.rs b/tests/ui/filter_map_next_unfixable.rs deleted file mode 100644 index 5414e01c8700..000000000000 --- a/tests/ui/filter_map_next_unfixable.rs +++ /dev/null @@ -1,20 +0,0 @@ -#![warn(clippy::filter_map_next)] - -fn main() { - let a = ["1", "lol", "3", "NaN", "5"]; - - #[rustfmt::skip] - let _: Option = vec![1, 2, 3, 4, 5, 6] - //~^ filter_map_next - - - .into_iter() - .filter_map(|x| { - if x == 2 { - Some(x * 2) - } else { - None - } - }) - .next(); -} diff --git a/tests/ui/filter_map_next_unfixable.stderr b/tests/ui/filter_map_next_unfixable.stderr deleted file mode 100644 index 9ebedf7d8f77..000000000000 --- a/tests/ui/filter_map_next_unfixable.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: called `filter_map(..).next()` on an `Iterator` - --> tests/ui/filter_map_next_unfixable.rs:7:26 - | -LL | let _: Option = vec![1, 2, 3, 4, 5, 6] - | __________________________^ -... | -LL | | }) -LL | | .next(); - | |_______________^ - | - = help: use `.find_map(..)` instead - = note: `-D clippy::filter-map-next` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::filter_map_next)]` - -error: aborting due to 1 previous error - From 473f7cdc9d2fff64222dc29cb2a63fffabc83ffd Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 22 Jun 2026 12:31:17 +0200 Subject: [PATCH 7/7] add a test with comments --- tests/ui/filter_map_next.fixed | 8 ++++++++ tests/ui/filter_map_next.rs | 10 ++++++++++ tests/ui/filter_map_next.stderr | 27 +++++++++++++++++++++++++-- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/tests/ui/filter_map_next.fixed b/tests/ui/filter_map_next.fixed index cd27501dbe5d..cf2191515bea 100644 --- a/tests/ui/filter_map_next.fixed +++ b/tests/ui/filter_map_next.fixed @@ -19,6 +19,14 @@ fn main() { None } }); + + let element: Option = a + // very important comment -- don't delete! + .iter().find_map(|s| { + // another extremely important comment + s.parse().ok() + }); + //~^^^^^^^^ filter_map_next } #[clippy::msrv = "1.29"] diff --git a/tests/ui/filter_map_next.rs b/tests/ui/filter_map_next.rs index e3e668689682..684413bc03c5 100644 --- a/tests/ui/filter_map_next.rs +++ b/tests/ui/filter_map_next.rs @@ -21,6 +21,16 @@ fn main() { } }) .next(); + + let element: Option = a + // very important comment -- don't delete! + .iter() + .filter_map(|s| { + // another extremely important comment + s.parse().ok() + }) + .next(); + //~^^^^^^^^ filter_map_next } #[clippy::msrv = "1.29"] diff --git a/tests/ui/filter_map_next.stderr b/tests/ui/filter_map_next.stderr index e227600662aa..609b20679cf2 100644 --- a/tests/ui/filter_map_next.stderr +++ b/tests/ui/filter_map_next.stderr @@ -38,7 +38,30 @@ LL ~ }); | error: called `filter_map(..).next()` on an `Iterator` - --> tests/ui/filter_map_next.rs:35:26 + --> tests/ui/filter_map_next.rs:25:32 + | +LL | let element: Option = a + | ________________________________^ +LL | | // very important comment -- don't delete! +LL | | .iter() +LL | | .filter_map(|s| { +... | +LL | | }) +LL | | .next(); + | |_______________^ + | +help: use `.find_map(..)` instead + | +LL ~ let element: Option = a +LL + // very important comment -- don't delete! +LL + .iter().find_map(|s| { +LL + // another extremely important comment +LL + s.parse().ok() +LL ~ }); + | + +error: called `filter_map(..).next()` on an `Iterator` + --> tests/ui/filter_map_next.rs:45:26 | LL | let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,5 +72,5 @@ LL - let _: Option = a.iter().filter_map(|s| s.parse().ok()).next(); LL + let _: Option = a.iter().find_map(|s| s.parse().ok()); | -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors