Skip to content

Commit 44eb953

Browse files
committed
Auto merge of #5525 - flip1995:issue_1654, r=phansch
Don't trigger while_let_on_iterator when the iterator is recreated every iteration r? @phansch Fixes #1654 changelog: Fix false positive in [`while_let_on_iterator`]
2 parents a76bfd4 + a182622 commit 44eb953

File tree

4 files changed

+52
-15
lines changed

4 files changed

+52
-15
lines changed

clippy_lints/src/loops.rs

+11
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Loops {
566566
) = (pat, &match_expr.kind)
567567
{
568568
let iter_expr = &method_args[0];
569+
570+
// Don't lint when the iterator is recreated on every iteration
571+
if_chain! {
572+
if let ExprKind::MethodCall(..) | ExprKind::Call(..) = iter_expr.kind;
573+
if let Some(iter_def_id) = get_trait_def_id(cx, &paths::ITERATOR);
574+
if implements_trait(cx, cx.tables.expr_ty(iter_expr), iter_def_id, &[]);
575+
then {
576+
return;
577+
}
578+
}
579+
569580
let lhs_constructor = last_path_segment(qpath);
570581
if method_path.ident.name == sym!(next)
571582
&& match_trait_method(cx, match_expr, &paths::ITERATOR)

tests/ui/while_let_on_iterator.fixed

+20-4
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,7 @@ fn issue2965() {
119119
let mut values = HashSet::new();
120120
values.insert(1);
121121

122-
for _ in values.iter() {
123-
// FIXME(flip1995): Linting this with the following line uncommented is a FP, see #1654
124-
// values.remove(&1);
125-
}
122+
while let Some(..) = values.iter().next() {}
126123
}
127124

128125
fn issue3670() {
@@ -134,11 +131,30 @@ fn issue3670() {
134131
}
135132
}
136133

134+
fn issue1654() {
135+
// should not lint if the iterator is generated on every iteration
136+
use std::collections::HashSet;
137+
let mut values = HashSet::new();
138+
values.insert(1);
139+
140+
while let Some(..) = values.iter().next() {
141+
values.remove(&1);
142+
}
143+
144+
while let Some(..) = values.iter().map(|x| x + 1).next() {}
145+
146+
let chars = "Hello, World!".char_indices();
147+
while let Some((i, ch)) = chars.clone().next() {
148+
println!("{}: {}", i, ch);
149+
}
150+
}
151+
137152
fn main() {
138153
base();
139154
refutable();
140155
nested_loops();
141156
issue1121();
142157
issue2965();
143158
issue3670();
159+
issue1654();
144160
}

tests/ui/while_let_on_iterator.rs

+20-4
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,7 @@ fn issue2965() {
119119
let mut values = HashSet::new();
120120
values.insert(1);
121121

122-
while let Some(..) = values.iter().next() {
123-
// FIXME(flip1995): Linting this with the following line uncommented is a FP, see #1654
124-
// values.remove(&1);
125-
}
122+
while let Some(..) = values.iter().next() {}
126123
}
127124

128125
fn issue3670() {
@@ -134,11 +131,30 @@ fn issue3670() {
134131
}
135132
}
136133

134+
fn issue1654() {
135+
// should not lint if the iterator is generated on every iteration
136+
use std::collections::HashSet;
137+
let mut values = HashSet::new();
138+
values.insert(1);
139+
140+
while let Some(..) = values.iter().next() {
141+
values.remove(&1);
142+
}
143+
144+
while let Some(..) = values.iter().map(|x| x + 1).next() {}
145+
146+
let chars = "Hello, World!".char_indices();
147+
while let Some((i, ch)) = chars.clone().next() {
148+
println!("{}: {}", i, ch);
149+
}
150+
}
151+
137152
fn main() {
138153
base();
139154
refutable();
140155
nested_loops();
141156
issue1121();
142157
issue2965();
143158
issue3670();
159+
issue1654();
144160
}

tests/ui/while_let_on_iterator.stderr

+1-7
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,5 @@ error: this loop could be written as a `for` loop
2424
LL | while let Some(_) = y.next() {
2525
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in y`
2626

27-
error: this loop could be written as a `for` loop
28-
--> $DIR/while_let_on_iterator.rs:122:5
29-
|
30-
LL | while let Some(..) = values.iter().next() {
31-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in values.iter()`
32-
33-
error: aborting due to 5 previous errors
27+
error: aborting due to 4 previous errors
3428

0 commit comments

Comments
 (0)