Skip to content

Commit 721ac28

Browse files
committed
fix: filter_map_bool_then suggest wrongly when contain return
1 parent 221ae5f commit 721ac28

File tree

3 files changed

+120
-9
lines changed

3 files changed

+120
-9
lines changed

clippy_lints/src/methods/filter_map_bool_then.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use super::FILTER_MAP_BOOL_THEN;
2-
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use clippy_utils::diagnostics::span_lint_and_then;
33
use clippy_utils::source::SpanRangeExt;
44
use clippy_utils::ty::is_copy;
5-
use clippy_utils::{is_from_proc_macro, is_trait_method, peel_blocks};
5+
use clippy_utils::{contains_return, is_from_proc_macro, is_trait_method, peel_blocks};
66
use rustc_errors::Applicability;
77
use rustc_hir::{Expr, ExprKind};
88
use rustc_lint::{LateContext, LintContext};
@@ -44,17 +44,26 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: &
4444
&& let Some(filter) = recv.span.get_source_text(cx)
4545
&& let Some(map) = then_body.span.get_source_text(cx)
4646
{
47-
span_lint_and_sugg(
47+
span_lint_and_then(
4848
cx,
4949
FILTER_MAP_BOOL_THEN,
5050
call_span,
5151
"usage of `bool::then` in `filter_map`",
52-
"use `filter` then `map` instead",
53-
format!(
54-
"filter(|&{param_snippet}| {derefs}{filter}).map(|{param_snippet}| {map})",
55-
derefs = "*".repeat(needed_derefs)
56-
),
57-
Applicability::MachineApplicable,
52+
|diag| {
53+
if contains_return(recv) {
54+
diag.help("consider using `filter` then `map` instead");
55+
} else {
56+
diag.span_suggestion(
57+
call_span,
58+
"use `filter` then `map` instead",
59+
format!(
60+
"filter(|&{param_snippet}| {derefs}{filter}).map(|{param_snippet}| {map})",
61+
derefs = "*".repeat(needed_derefs)
62+
),
63+
Applicability::MachineApplicable,
64+
);
65+
}
66+
},
5867
);
5968
}
6069
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#![allow(clippy::question_mark, unused)]
2+
#![warn(clippy::filter_map_bool_then)]
3+
//@no-rustfix
4+
5+
mod issue14368 {
6+
7+
fn do_something(_: ()) -> bool {
8+
true
9+
}
10+
11+
fn option_with_early_return(x: &[Option<bool>]) {
12+
let _ = x.iter().filter_map(|&x| x?.then(|| do_something(())));
13+
//~^ filter_map_bool_then
14+
let _ = x
15+
.iter()
16+
.filter_map(|&x| if let Some(x) = x { x } else { return None }.then(|| do_something(())));
17+
//~^ filter_map_bool_then
18+
let _ = x.iter().filter_map(|&x| {
19+
//~^ filter_map_bool_then
20+
match x {
21+
Some(x) => x,
22+
None => return None,
23+
}
24+
.then(|| do_something(()))
25+
});
26+
}
27+
28+
#[derive(Copy, Clone)]
29+
enum Foo {
30+
One(bool),
31+
Two,
32+
Three(Option<i32>),
33+
}
34+
35+
fn nested_type_with_early_return(x: &[Foo]) {
36+
let _ = x.iter().filter_map(|&x| {
37+
//~^ filter_map_bool_then
38+
match x {
39+
Foo::One(x) => x,
40+
Foo::Two => return None,
41+
Foo::Three(inner) => {
42+
if inner? == 0 {
43+
return Some(false);
44+
} else {
45+
true
46+
}
47+
},
48+
}
49+
.then(|| do_something(()))
50+
});
51+
}
52+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
error: usage of `bool::then` in `filter_map`
2+
--> tests/ui/filter_map_bool_then_unfixable.rs:12:26
3+
|
4+
LL | let _ = x.iter().filter_map(|&x| x?.then(|| do_something(())));
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: consider using `filter` then `map` instead
8+
= note: `-D clippy::filter-map-bool-then` implied by `-D warnings`
9+
= help: to override `-D warnings` add `#[allow(clippy::filter_map_bool_then)]`
10+
11+
error: usage of `bool::then` in `filter_map`
12+
--> tests/ui/filter_map_bool_then_unfixable.rs:16:14
13+
|
14+
LL | .filter_map(|&x| if let Some(x) = x { x } else { return None }.then(|| do_something(())));
15+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
16+
|
17+
= help: consider using `filter` then `map` instead
18+
19+
error: usage of `bool::then` in `filter_map`
20+
--> tests/ui/filter_map_bool_then_unfixable.rs:18:26
21+
|
22+
LL | let _ = x.iter().filter_map(|&x| {
23+
| __________________________^
24+
LL | |
25+
LL | | match x {
26+
LL | | Some(x) => x,
27+
... |
28+
LL | | .then(|| do_something(()))
29+
LL | | });
30+
| |__________^
31+
|
32+
= help: consider using `filter` then `map` instead
33+
34+
error: usage of `bool::then` in `filter_map`
35+
--> tests/ui/filter_map_bool_then_unfixable.rs:36:26
36+
|
37+
LL | let _ = x.iter().filter_map(|&x| {
38+
| __________________________^
39+
LL | |
40+
LL | | match x {
41+
LL | | Foo::One(x) => x,
42+
... |
43+
LL | | .then(|| do_something(()))
44+
LL | | });
45+
| |__________^
46+
|
47+
= help: consider using `filter` then `map` instead
48+
49+
error: aborting due to 4 previous errors
50+

0 commit comments

Comments
 (0)