Skip to content

Commit a773276

Browse files
author
Michael Wright
committed
Fix bad while_let_on_iterator suggestion.
Don't suggest a `for` loop if the iterator is used inside the `while` loop. Closes #3670
1 parent 235f960 commit a773276

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

Diff for: clippy_lints/src/loops.rs

+14
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
565565
&& lhs_constructor.ident.name == "Some"
566566
&& (pat_args.is_empty()
567567
|| !is_refutable(cx, &pat_args[0])
568+
&& !is_used_inside(cx, iter_expr, &arms[0].body)
568569
&& !is_iterator_used_after_while_let(cx, iter_expr)
569570
&& !is_nested(cx, expr, &method_args[0]))
570571
{
@@ -1888,6 +1889,19 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
18881889
}
18891890
}
18901891

1892+
fn is_used_inside<'a, 'tcx: 'a>(cx: &'a LateContext<'a, 'tcx>, expr: &'tcx Expr, container: &'tcx Expr) -> bool {
1893+
let def_id = match var_def_id(cx, expr) {
1894+
Some(id) => id,
1895+
None => return false,
1896+
};
1897+
if let Some(used_mutably) = mutated_variables(container, cx) {
1898+
if used_mutably.contains(&def_id) {
1899+
return true;
1900+
}
1901+
}
1902+
false
1903+
}
1904+
18911905
fn is_iterator_used_after_while_let<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, iter_expr: &'tcx Expr) -> bool {
18921906
let def_id = match var_def_id(cx, iter_expr) {
18931907
Some(id) => id,

Diff for: tests/ui/while_loop.rs

+10
Original file line numberDiff line numberDiff line change
@@ -216,4 +216,14 @@ fn refutable() {
216216
while let Some(..) = values.iter().next() {
217217
values.remove(&1);
218218
}
219+
220+
// Issue 3670
221+
{
222+
let array = [Some(0), None, Some(1)];
223+
let mut iter = array.iter();
224+
225+
while let Some(elem) = iter.next() {
226+
let _ = elem.or_else(|| *iter.next()?);
227+
}
228+
}
219229
}

0 commit comments

Comments
 (0)