Skip to content

Commit bef6f41

Browse files
committed
also suggest in the multi-line case
This used to be a workaround for a rustc diagnostics issue which has since been resolved
1 parent 537443b commit bef6f41

6 files changed

Lines changed: 98 additions & 82 deletions

File tree

clippy_lints/src/methods/filter_next.rs

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -41,40 +41,32 @@ pub(super) fn check(
4141
expr.span,
4242
format!("called `filter(..).{next_method}()` on an `{required_trait}`"),
4343
|diag| {
44-
let sugg_msg = format!("use `.{find_method}(..)` instead");
45-
4644
let mut app = Applicability::MachineApplicable;
47-
// add note if not multi-line
4845
let filter_snippet = snippet_with_applicability(cx, filter_arg.span, "..", &mut app);
49-
if filter_snippet.lines().count() <= 1 {
50-
let iter_snippet = snippet_with_applicability(cx, recv.span, "..", &mut app);
51-
let pat = if let Some(id) = path_to_local_with_projections(recv)
52-
&& let Node::Pat(pat) = cx.tcx.hir_node(id)
53-
&& let PatKind::Binding(BindingMode(_, Mutability::Not), _, ident, _) = pat.kind
54-
{
55-
app = Applicability::Unspecified;
56-
Some((pat.span, ident))
57-
} else {
58-
None
59-
};
60-
61-
diag.span_suggestion_verbose(
62-
expr.span,
63-
sugg_msg,
64-
format!("{iter_snippet}.{find_method}({filter_snippet})"),
65-
app,
66-
);
46+
let iter_snippet = snippet_with_applicability(cx, recv.span, "..", &mut app);
6747

68-
if let Some((pat_span, ident)) = pat {
69-
diag.span_help(
70-
pat_span,
71-
format!(
72-
"you will also need to make `{ident}` mutable, because `{find_method}` takes `&mut self`"
73-
),
74-
);
75-
}
48+
let pat = if let Some(id) = path_to_local_with_projections(recv)
49+
&& let Node::Pat(pat) = cx.tcx.hir_node(id)
50+
&& let PatKind::Binding(BindingMode(_, Mutability::Not), _, ident, _) = pat.kind
51+
{
52+
app = Applicability::Unspecified;
53+
Some((pat.span, ident))
7654
} else {
77-
diag.help(sugg_msg);
55+
None
56+
};
57+
58+
diag.span_suggestion_verbose(
59+
expr.span,
60+
format!("use `.{find_method}(..)` instead"),
61+
format!("{iter_snippet}.{find_method}({filter_snippet})"),
62+
app,
63+
);
64+
65+
if let Some((pat_span, ident)) = pat {
66+
diag.span_help(
67+
pat_span,
68+
format!("you will also need to make `{ident}` mutable, because `{find_method}` takes `&mut self`"),
69+
);
7870
}
7971
},
8072
);

tests/ui/filter_next.fixed

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,19 @@ fn filter_next() {
1919
let _ = v.iter().rfind(|&x| *x < 0);
2020
//~^ filter_next
2121

22+
// Multi-line case.
23+
#[rustfmt::skip]
24+
let _ = v.iter().find(|&x| {
25+
//~^ filter_next
26+
*x < 0
27+
});
28+
29+
#[rustfmt::skip]
30+
let _ = v.iter().rfind(|&x| {
31+
//~^ filter_next
32+
*x < 0
33+
});
34+
2235
// Check that we don't lint if the caller is not an `Iterator`.
2336
let foo = IteratorFalsePositives { foo: 0 };
2437
let _ = foo.filter().next();

tests/ui/filter_next.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,21 @@ fn filter_next() {
1919
let _ = v.iter().filter(|&x| *x < 0).next_back();
2020
//~^ filter_next
2121

22+
// Multi-line case.
23+
#[rustfmt::skip]
24+
let _ = v.iter().filter(|&x| {
25+
//~^ filter_next
26+
*x < 0
27+
}
28+
).next();
29+
30+
#[rustfmt::skip]
31+
let _ = v.iter().filter(|&x| {
32+
//~^ filter_next
33+
*x < 0
34+
}
35+
).next_back();
36+
2237
// Check that we don't lint if the caller is not an `Iterator`.
2338
let foo = IteratorFalsePositives { foo: 0 };
2439
let _ = foo.filter().next();

tests/ui/filter_next.stderr

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,46 @@ LL - let _ = v.iter().filter(|&x| *x < 0).next_back();
2424
LL + let _ = v.iter().rfind(|&x| *x < 0);
2525
|
2626

27+
error: called `filter(..).next()` on an `Iterator`
28+
--> tests/ui/filter_next.rs:24:13
29+
|
30+
LL | let _ = v.iter().filter(|&x| {
31+
| _____________^
32+
LL | |
33+
LL | | *x < 0
34+
LL | | }
35+
LL | | ).next();
36+
| |___________________________^
37+
|
38+
help: use `.find(..)` instead
39+
|
40+
LL ~ let _ = v.iter().find(|&x| {
41+
LL +
42+
LL + *x < 0
43+
LL ~ });
44+
|
45+
46+
error: called `filter(..).next_back()` on an `DoubleEndedIterator`
47+
--> tests/ui/filter_next.rs:31:13
48+
|
49+
LL | let _ = v.iter().filter(|&x| {
50+
| _____________^
51+
LL | |
52+
LL | | *x < 0
53+
LL | | }
54+
LL | | ).next_back();
55+
| |________________________________^
56+
|
57+
help: use `.rfind(..)` instead
58+
|
59+
LL ~ let _ = v.iter().rfind(|&x| {
60+
LL +
61+
LL + *x < 0
62+
LL ~ });
63+
|
64+
2765
error: called `filter(..).next_back()` on an `DoubleEndedIterator`
28-
--> tests/ui/filter_next.rs:43:13
66+
--> tests/ui/filter_next.rs:58:13
2967
|
3068
LL | let _ = vec![1].into_iter().filter(|&x| x < 0).next_back();
3169
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -36,5 +74,5 @@ LL - let _ = vec![1].into_iter().filter(|&x| x < 0).next_back();
3674
LL + let _ = vec![1].into_iter().rfind(|&x| x < 0);
3775
|
3876

39-
error: aborting due to 3 previous errors
77+
error: aborting due to 5 previous errors
4078

tests/ui/filter_next_unfixable.rs

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,7 @@
11
//@no-rustfix
22
#![warn(clippy::filter_next)]
33

4-
#[rustfmt::skip]
5-
fn main() {
6-
let v = [3, 2, 1, 0, -1, -2, -3];
7-
8-
// Multi-line case -- only a note is emitted
9-
let _ = v.iter().filter(|&x| {
10-
//~^ filter_next
11-
*x < 0
12-
}
13-
).next();
14-
15-
let _ = v.iter().filter(|&x| {
16-
//~^ filter_next
17-
*x < 0
18-
}
19-
).next_back();
20-
}
4+
fn main() {}
215

226
// The fixed version doesn't compile, as `iter` isn't `mut`.
237
// We do emit a note suggesting adding it, but not an autofix
Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,30 @@
11
error: called `filter(..).next()` on an `Iterator`
2-
--> tests/ui/filter_next_unfixable.rs:9:13
3-
|
4-
LL | let _ = v.iter().filter(|&x| {
5-
| _____________^
6-
LL | |
7-
LL | | *x < 0
8-
LL | | }
9-
LL | | ).next();
10-
| |___________________________^
11-
|
12-
= help: use `.find(..)` instead
13-
= note: `-D clippy::filter-next` implied by `-D warnings`
14-
= help: to override `-D warnings` add `#[allow(clippy::filter_next)]`
15-
16-
error: called `filter(..).next_back()` on an `DoubleEndedIterator`
17-
--> tests/ui/filter_next_unfixable.rs:15:13
18-
|
19-
LL | let _ = v.iter().filter(|&x| {
20-
| _____________^
21-
LL | |
22-
LL | | *x < 0
23-
LL | | }
24-
LL | | ).next_back();
25-
| |________________________________^
26-
|
27-
= help: use `.rfind(..)` instead
28-
29-
error: called `filter(..).next()` on an `Iterator`
30-
--> tests/ui/filter_next_unfixable.rs:27:17
2+
--> tests/ui/filter_next_unfixable.rs:11:17
313
|
324
LL | let _ = iter.filter(|_| true).next();
335
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
346
|
357
help: you will also need to make `iter` mutable, because `find` takes `&mut self`
36-
--> tests/ui/filter_next_unfixable.rs:26:13
8+
--> tests/ui/filter_next_unfixable.rs:10:13
379
|
3810
LL | let iter = (0..10);
3911
| ^^^^
12+
= note: `-D clippy::filter-next` implied by `-D warnings`
13+
= help: to override `-D warnings` add `#[allow(clippy::filter_next)]`
4014
help: use `.find(..)` instead
4115
|
4216
LL - let _ = iter.filter(|_| true).next();
4317
LL + let _ = iter.find(|_| true);
4418
|
4519

4620
error: called `filter(..).next_back()` on an `DoubleEndedIterator`
47-
--> tests/ui/filter_next_unfixable.rs:32:17
21+
--> tests/ui/filter_next_unfixable.rs:16:17
4822
|
4923
LL | let _ = iter.filter(|_| true).next_back();
5024
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5125
|
5226
help: you will also need to make `iter` mutable, because `rfind` takes `&mut self`
53-
--> tests/ui/filter_next_unfixable.rs:31:13
27+
--> tests/ui/filter_next_unfixable.rs:15:13
5428
|
5529
LL | let iter = (0..10);
5630
| ^^^^
@@ -60,5 +34,5 @@ LL - let _ = iter.filter(|_| true).next_back();
6034
LL + let _ = iter.rfind(|_| true);
6135
|
6236

63-
error: aborting due to 4 previous errors
37+
error: aborting due to 2 previous errors
6438

0 commit comments

Comments
 (0)