Merge pull request #1847 from Manishearth/nested_while_let

don't lint while_let_on_iterator on nested loops
This commit is contained in:
Oliver Schneider
2017-07-04 16:05:24 +02:00
committed by GitHub
3 changed files with 27 additions and 4 deletions

View File

@@ -251,7 +251,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
reg.register_late_lint_pass(box shadow::Pass); reg.register_late_lint_pass(box shadow::Pass);
reg.register_late_lint_pass(box types::LetPass); reg.register_late_lint_pass(box types::LetPass);
reg.register_late_lint_pass(box types::UnitCmp); reg.register_late_lint_pass(box types::UnitCmp);
reg.register_late_lint_pass(box loops::Pass); reg.register_late_lint_pass(box loops::Pass::default());
reg.register_late_lint_pass(box lifetimes::LifetimePass); reg.register_late_lint_pass(box lifetimes::LifetimePass);
reg.register_late_lint_pass(box entry::HashMapLint); reg.register_late_lint_pass(box entry::HashMapLint);
reg.register_late_lint_pass(box ranges::StepByZero); reg.register_late_lint_pass(box ranges::StepByZero);

View File

@@ -304,8 +304,10 @@ declare_lint! {
"any loop that will always `break` or `return`" "any loop that will always `break` or `return`"
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone, Default)]
pub struct Pass; pub struct Pass {
loop_count : usize,
}
impl LintPass for Pass { impl LintPass for Pass {
fn get_lints(&self) -> LintArray { fn get_lints(&self) -> LintArray {
@@ -327,6 +329,13 @@ impl LintPass for Pass {
} }
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
fn check_expr_post(&mut self, _: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
match expr.node {
ExprWhile(..) | ExprLoop(..) => { self.loop_count -= 1; }
_ => ()
}
}
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let Some((pat, arg, body)) = higher::for_loop(expr) { if let Some((pat, arg, body)) = higher::for_loop(expr) {
check_for_loop(cx, pat, arg, body, expr); check_for_loop(cx, pat, arg, body, expr);
@@ -336,6 +345,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
match expr.node { match expr.node {
ExprWhile(_, ref block, _) | ExprWhile(_, ref block, _) |
ExprLoop(ref block, _, _) => { ExprLoop(ref block, _, _) => {
self.loop_count += 1;
if never_loop(block, &expr.id) { if never_loop(block, &expr.id) {
span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops"); span_lint(cx, NEVER_LOOP, expr.span, "this loop never actually loops");
} }
@@ -398,7 +408,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
&ExprMethodCall(method_name, _, ref method_args)) = (pat, &match_expr.node) { &ExprMethodCall(method_name, _, ref method_args)) = (pat, &match_expr.node) {
let iter_expr = &method_args[0]; let iter_expr = &method_args[0];
let lhs_constructor = last_path_segment(qpath); let lhs_constructor = last_path_segment(qpath);
if method_name.node == "next" && match_trait_method(cx, match_expr, &paths::ITERATOR) && if self.loop_count < 2 && method_name.node == "next" &&
match_trait_method(cx, match_expr, &paths::ITERATOR) &&
lhs_constructor.name == "Some" && !is_refutable(cx, &pat_args[0]) && lhs_constructor.name == "Some" && !is_refutable(cx, &pat_args[0]) &&
!is_iterator_used_after_while_let(cx, iter_expr) { !is_iterator_used_after_while_let(cx, iter_expr) {
let iterator = snippet(cx, method_args[0].span, "_"); let iterator = snippet(cx, method_args[0].span, "_");

View File

@@ -165,4 +165,16 @@ fn refutable() {
for &(1, 2, 3) in b {} for &(1, 2, 3) in b {}
for &Option::None in b.next() {} for &Option::None in b.next() {}
// */ // */
let mut y = a.iter();
loop { // x is reused, so don't lint here
while let Some(v) = y.next() {
}
}
let mut y = a.iter();
for _ in 0..2 {
while let Some(v) = y.next() {
}
}
} }