3 use rustc::hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn};
4 use std::collections::HashMap;
6 use syntax::codemap::Span;
7 use syntax::parse::token::InternedString;
8 use utils::{in_macro, span_lint};
10 /// **What it does:** This lint checks for unused labels.
12 /// **Why is this bad?** Maybe the label should be used in which case there is an error in the
13 /// code or it should be removed.
15 /// **Known problems:** Hopefully none.
19 /// fn unused_label() {
20 /// 'label: for i in 1..2 {
21 /// if i > 4 { continue }
30 pub struct UnusedLabel;
33 struct UnusedLabelVisitor {
34 labels: HashMap<InternedString, Span>,
37 impl UnusedLabelVisitor {
38 pub fn new() -> UnusedLabelVisitor {
39 ::std::default::Default::default()
43 impl LintPass for UnusedLabel {
44 fn get_lints(&self) -> LintArray {
45 lint_array!(UNUSED_LABEL)
49 impl LateLintPass for UnusedLabel {
50 fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, body: &hir::Block, span: Span, _: ast::NodeId) {
51 if in_macro(cx, span) {
55 let mut v = UnusedLabelVisitor::new();
56 walk_fn(&mut v, kind, decl, body, span);
58 for (label, span) in v.labels {
59 span_lint(cx, UNUSED_LABEL, span, &format!("unused label `{}`", label));
64 impl<'v> Visitor<'v> for UnusedLabelVisitor {
65 fn visit_expr(&mut self, expr: &hir::Expr) {
67 hir::ExprBreak(Some(label)) | hir::ExprAgain(Some(label)) => {
68 self.labels.remove(&label.node.as_str());
70 hir::ExprLoop(_, Some(label)) | hir::ExprWhile(_, _, Some(label)) => {
71 self.labels.insert(label.node.as_str(), expr.span);
76 walk_expr(self, expr);