From d67628e053db3235b9d4d406e4b47113b51a1fad Mon Sep 17 00:00:00 2001 From: Kyle Stachowicz Date: Mon, 14 May 2018 23:32:21 -0700 Subject: [PATCH] Add lint checks for unused loop labels --- src/librustc_lint/lib.rs | 4 +- src/librustc_lint/unused.rs | 63 ++++++++++++++++++++++ src/librustc_mir/interpret/eval_context.rs | 2 +- src/test/ui/lint/unused_loop_label.rs | 55 +++++++++++++++++++ src/test/ui/lint/unused_loop_label.stderr | 32 +++++++++++ src/test/ui/lint/unused_loop_label.stdout | 0 6 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/lint/unused_loop_label.rs create mode 100644 src/test/ui/lint/unused_loop_label.stderr create mode 100644 src/test/ui/lint/unused_loop_label.stdout diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 0ae133640fad..19e0bbd83053 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -110,6 +110,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { add_early_builtin_with_new!(sess, DeprecatedAttr, + UnusedLoopLabel, ); add_builtin!(sess, @@ -177,7 +178,8 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { UNUSED_DOC_COMMENT, UNUSED_EXTERN_CRATES, UNUSED_FEATURES, - UNUSED_PARENS); + UNUSED_PARENS, + UNUSED_LOOP_LABEL); add_lint_group!(sess, "rust_2018_idioms", diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 845c964b986d..38c5a36067c4 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -25,6 +25,8 @@ use syntax_pos::Span; use rustc::hir; +use std::vec; + declare_lint! { pub UNUSED_MUST_USE, Warn, @@ -464,3 +466,64 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAllocation { } } } + +declare_lint! { + pub(super) UNUSED_LOOP_LABEL, + Warn, + "warns on unused labels for loops" +} + +#[derive(Clone)] +pub struct UnusedLoopLabel(pub vec::Vec); + +impl UnusedLoopLabel { + pub fn new() -> Self { + UnusedLoopLabel(vec![]) + } +} + +impl LintPass for UnusedLoopLabel { + fn get_lints(&self) -> LintArray { + lint_array!(UNUSED_LOOP_LABEL) + } +} + +impl EarlyLintPass for UnusedLoopLabel { + fn check_expr(&mut self, _: &EarlyContext, expr: &ast::Expr) { + match expr.node { + ast::ExprKind::While(_, _, Some(ref label)) + | ast::ExprKind::WhileLet(_, _, _, Some(ref label)) + | ast::ExprKind::ForLoop(_, _, _, Some(ref label)) + | ast::ExprKind::Loop(_, Some(ref label)) => { + self.0.push(*label); + } + ast::ExprKind::Break(Some(ref label), _) | ast::ExprKind::Continue(Some(ref label)) => { + 'remove_used_label: for i in (0..self.0.len()).rev() { + if self.0.get(i).unwrap().ident.name == label.ident.name { + self.0.remove(i); + break 'remove_used_label; + } + } + } + _ => {} + } + } + + fn check_expr_post(&mut self, ctxt: &EarlyContext, expr: &ast::Expr) { + match expr.node { + ast::ExprKind::While(_, _, Some(ref label)) + | ast::ExprKind::WhileLet(_, _, _, Some(ref label)) + | ast::ExprKind::ForLoop(_, _, _, Some(ref label)) + | ast::ExprKind::Loop(_, Some(ref label)) => if !self.0.is_empty() { + { + let unused_label = self.0.last().unwrap(); + if label.ident.name == unused_label.ident.name { + ctxt.span_lint(UNUSED_LOOP_LABEL, label.ident.span, "unused loop label"); + } + } + self.0.pop(); + }, + _ => {} + } + } +} diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 03137619edaf..7b6cee96a875 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -1705,7 +1705,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M let mut trace_text = "\n\nAn error occurred in miri:\n".to_string(); backtrace.resolve(); write!(trace_text, "backtrace frames: {}\n", backtrace.frames().len()).unwrap(); - 'frames: for (i, frame) in backtrace.frames().iter().enumerate() { + for (i, frame) in backtrace.frames().iter().enumerate() { if frame.symbols().is_empty() { write!(trace_text, "{}: no symbols\n", i).unwrap(); } diff --git a/src/test/ui/lint/unused_loop_label.rs b/src/test/ui/lint/unused_loop_label.rs new file mode 100644 index 000000000000..b3142cd86337 --- /dev/null +++ b/src/test/ui/lint/unused_loop_label.rs @@ -0,0 +1,55 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// The output should warn when a loop label is not used. However, it +// should also deal with the edge cases where a label is shadowed, +// within nested loops + +// compile-pass +// compile-flags: -W unused_loop_label + +fn main() { + 'unused_while_label: while 0 == 0 { + //~^ WARN unused loop label + } + + let opt = Some(0); + 'unused_while_let_label: while let Some(_) = opt { + //~^ WARN unused loop label + } + + 'unused_for_label: for _ in 0..10 { + //~^ WARN unused loop label + } + + 'used_loop_label: loop { + break 'used_loop_label; + } + + 'used_loop_label_outer: loop { + 'used_loop_label_inner: loop { + break 'used_loop_label_inner; + } + break 'used_loop_label_outer; + } + + 'unused_loop_label_outer: loop { + 'unused_loop_label_inner: loop { + //~^ WARN unused loop label + break 'unused_loop_label_outer; + } + } + + // This is diverging, so put it at the end so we don't get unreachable_code errors everywhere + // else + 'unused_loop_label: loop { + //~^ WARN unused loop label + } +} diff --git a/src/test/ui/lint/unused_loop_label.stderr b/src/test/ui/lint/unused_loop_label.stderr new file mode 100644 index 000000000000..4804c268975f --- /dev/null +++ b/src/test/ui/lint/unused_loop_label.stderr @@ -0,0 +1,32 @@ +warning: unused loop label + --> $DIR/unused_loop_label.rs:19:5 + | +LL | 'unused_while_label: while 0 == 0 { + | ^^^^^^^^^^^^^^^^^^^ + | + = note: requested on the command line with `-W unused-loop-label` + +warning: unused loop label + --> $DIR/unused_loop_label.rs:24:5 + | +LL | 'unused_while_let_label: while let Some(_) = opt { + | ^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused loop label + --> $DIR/unused_loop_label.rs:28:5 + | +LL | 'unused_for_label: for _ in 0..10 { + | ^^^^^^^^^^^^^^^^^ + +warning: unused loop label + --> $DIR/unused_loop_label.rs:44:9 + | +LL | 'unused_loop_label_inner: loop { + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused loop label + --> $DIR/unused_loop_label.rs:52:5 + | +LL | 'unused_loop_label: loop { + | ^^^^^^^^^^^^^^^^^^ + diff --git a/src/test/ui/lint/unused_loop_label.stdout b/src/test/ui/lint/unused_loop_label.stdout new file mode 100644 index 000000000000..e69de29bb2d1