use rustc::lint::*;
use rustc::hir;
-use rustc::hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn};
+use rustc::hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor};
use std::collections::HashMap;
use syntax::ast;
use syntax::codemap::Span;
-use syntax::symbol::InternedString;
-use utils::{in_macro, span_lint};
+use syntax::symbol::LocalInternedString;
+use crate::utils::{in_macro, span_lint};
/// **What it does:** Checks for unused labels.
///
/// if i > 4 { continue }
/// }
/// ```
-declare_lint! {
+declare_clippy_lint! {
pub UNUSED_LABEL,
- Warn,
+ complexity,
"unused labels"
}
pub struct UnusedLabel;
-#[derive(Default)]
-struct UnusedLabelVisitor {
- labels: HashMap<InternedString, Span>,
-}
-
-impl UnusedLabelVisitor {
- pub fn new() -> UnusedLabelVisitor {
- ::std::default::Default::default()
- }
+struct UnusedLabelVisitor<'a, 'tcx: 'a> {
+ labels: HashMap<LocalInternedString, Span>,
+ cx: &'a LateContext<'a, 'tcx>,
}
impl LintPass for UnusedLabel {
}
}
-impl LateLintPass for UnusedLabel {
- fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, body: &hir::Expr, span: Span, fn_id: ast::NodeId) {
- if in_macro(cx, span) {
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedLabel {
+ fn check_fn(
+ &mut self,
+ cx: &LateContext<'a, 'tcx>,
+ kind: FnKind<'tcx>,
+ decl: &'tcx hir::FnDecl,
+ body: &'tcx hir::Body,
+ span: Span,
+ fn_id: ast::NodeId,
+ ) {
+ if in_macro(span) {
return;
}
- let mut v = UnusedLabelVisitor::new();
- walk_fn(&mut v, kind, decl, body, span, fn_id);
+ let mut v = UnusedLabelVisitor {
+ cx,
+ labels: HashMap::new(),
+ };
+ walk_fn(&mut v, kind, decl, body.id(), span, fn_id);
for (label, span) in v.labels {
span_lint(cx, UNUSED_LABEL, span, &format!("unused label `{}`", label));
}
}
-impl<'v> Visitor<'v> for UnusedLabelVisitor {
- fn visit_expr(&mut self, expr: &hir::Expr) {
+impl<'a, 'tcx: 'a> Visitor<'tcx> for UnusedLabelVisitor<'a, 'tcx> {
+ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
match expr.node {
- hir::ExprBreak(Some(label), _) |
- hir::ExprAgain(Some(label)) => {
- self.labels.remove(&label.name.as_str());
- }
- hir::ExprLoop(_, Some(label), _) |
- hir::ExprWhile(_, _, Some(label)) => {
- self.labels.insert(label.node.as_str(), expr.span);
- }
+ hir::ExprBreak(destination, _) | hir::ExprContinue(destination) => if let Some(label) = destination.label {
+ self.labels.remove(&label.ident.as_str());
+ },
+ hir::ExprLoop(_, Some(label), _) | hir::ExprWhile(_, _, Some(label)) => {
+ self.labels.insert(label.ident.as_str(), expr.span);
+ },
_ => (),
}
walk_expr(self, expr);
}
+ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+ NestedVisitorMap::All(&self.cx.tcx.hir)
+ }
}