diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index d6430cf291b..acc7b11e346 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -565,6 +565,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { && lhs_constructor.ident.name == "Some" && (pat_args.is_empty() || !is_refutable(cx, &pat_args[0]) + && !is_used_inside(cx, iter_expr, &arms[0].body) && !is_iterator_used_after_while_let(cx, iter_expr) && !is_nested(cx, expr, &method_args[0])) { @@ -1888,6 +1889,19 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> { } } +fn is_used_inside<'a, 'tcx: 'a>(cx: &'a LateContext<'a, 'tcx>, expr: &'tcx Expr, container: &'tcx Expr) -> bool { + let def_id = match var_def_id(cx, expr) { + Some(id) => id, + None => return false, + }; + if let Some(used_mutably) = mutated_variables(container, cx) { + if used_mutably.contains(&def_id) { + return true; + } + } + false +} + fn is_iterator_used_after_while_let<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, iter_expr: &'tcx Expr) -> bool { let def_id = match var_def_id(cx, iter_expr) { Some(id) => id, diff --git a/tests/ui/while_loop.rs b/tests/ui/while_loop.rs index 283a2d43c04..8c3bf1cc674 100644 --- a/tests/ui/while_loop.rs +++ b/tests/ui/while_loop.rs @@ -216,4 +216,14 @@ fn refutable() { while let Some(..) = values.iter().next() { values.remove(&1); } + + // Issue 3670 + { + let array = [Some(0), None, Some(1)]; + let mut iter = array.iter(); + + while let Some(elem) = iter.next() { + let _ = elem.or_else(|| *iter.next()?); + } + } }