Skip to content

Commit 1788f7b

Browse files
authored
Merge pull request #1847 from Manishearth/nested_while_let
don't lint while_let_on_iterator on nested loops
2 parents b8ecdc1 + 01a4a1d commit 1788f7b

File tree

3 files changed

+27
-4
lines changed

3 files changed

+27
-4
lines changed

clippy_lints/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
251251
reg.register_late_lint_pass(box shadow::Pass);
252252
reg.register_late_lint_pass(box types::LetPass);
253253
reg.register_late_lint_pass(box types::UnitCmp);
254-
reg.register_late_lint_pass(box loops::Pass);
254+
reg.register_late_lint_pass(box loops::Pass::default());
255255
reg.register_late_lint_pass(box lifetimes::LifetimePass);
256256
reg.register_late_lint_pass(box entry::HashMapLint);
257257
reg.register_late_lint_pass(box ranges::StepByZero);

clippy_lints/src/loops.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,10 @@ declare_lint! {
304304
"any loop that will always `break` or `return`"
305305
}
306306

307-
#[derive(Copy, Clone)]
308-
pub struct Pass;
307+
#[derive(Copy, Clone, Default)]
308+
pub struct Pass {
309+
loop_count : usize,
310+
}
309311

310312
impl LintPass for Pass {
311313
fn get_lints(&self) -> LintArray {
@@ -327,6 +329,13 @@ impl LintPass for Pass {
327329
}
328330

329331
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
332+
fn check_expr_post(&mut self, _: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
333+
match expr.node {
334+
ExprWhile(..) | ExprLoop(..) => { self.loop_count -= 1; }
335+
_ => ()
336+
}
337+
}
338+
330339
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
331340
if let Some((pat, arg, body)) = higher::for_loop(expr) {
332341
check_for_loop(cx, pat, arg, body, expr);
@@ -336,6 +345,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
336345
match expr.node {
337346
ExprWhile(_, ref block, _) |
338347
ExprLoop(ref block, _, _) => {
348+
self.loop_count += 1;
339349
if never_loop(block, &expr.id) {
340350
span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops");
341351
}
@@ -398,7 +408,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
398408
&ExprMethodCall(method_name, _, ref method_args)) = (pat, &match_expr.node) {
399409
let iter_expr = &method_args[0];
400410
let lhs_constructor = last_path_segment(qpath);
401-
if method_name.node == "next" && match_trait_method(cx, match_expr, &paths::ITERATOR) &&
411+
if self.loop_count < 2 && method_name.node == "next" &&
412+
match_trait_method(cx, match_expr, &paths::ITERATOR) &&
402413
lhs_constructor.name == "Some" && !is_refutable(cx, &pat_args[0]) &&
403414
!is_iterator_used_after_while_let(cx, iter_expr) {
404415
let iterator = snippet(cx, method_args[0].span, "_");

clippy_tests/examples/while_loop.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,4 +165,16 @@ fn refutable() {
165165
for &(1, 2, 3) in b {}
166166
for &Option::None in b.next() {}
167167
// */
168+
169+
let mut y = a.iter();
170+
loop { // x is reused, so don't lint here
171+
while let Some(v) = y.next() {
172+
}
173+
}
174+
175+
let mut y = a.iter();
176+
for _ in 0..2 {
177+
while let Some(v) = y.next() {
178+
}
179+
}
168180
}

0 commit comments

Comments
 (0)