diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index dade1f4eb26fa..3f1a1ed48a147 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -36,15 +36,15 @@ use util::nodemap::FnvHashMap; use std::cell::RefCell; use std::cmp; use std::mem; -use syntax::ast_util::IdVisitingOperation; +use syntax::ast_util::{self, IdVisitingOperation}; use syntax::attr::{self, AttrMetaMethods}; use syntax::codemap::Span; use syntax::parse::token::InternedString; use syntax::ast; use rustc_front::hir; -use rustc_front::visit::{self, Visitor, FnKind}; use rustc_front::util; -use syntax::visit::Visitor as SyntaxVisitor; +use rustc_front::visit as hir_visit; +use syntax::visit as ast_visit; use syntax::diagnostic; /// Information about the registered lints. @@ -248,8 +248,8 @@ impl LintStore { } } -/// Context for lint checking. -pub struct Context<'a, 'tcx: 'a> { +/// Context for lint checking after type checking. +pub struct LateContext<'a, 'tcx: 'a> { /// Type context we're checking in. pub tcx: &'a ty::ctxt<'tcx>, @@ -272,15 +272,35 @@ pub struct Context<'a, 'tcx: 'a> { node_levels: RefCell>, } +pub type Context<'a, 'tcx: 'a> = LateContext<'a, 'tcx>; + +/// Context for lint checking of the AST, after expansion, before lowering to +/// HIR. +pub struct EarlyContext<'a> { + /// Type context we're checking in. + pub sess: &'a Session, + + /// The crate being checked. + pub krate: &'a ast::Crate, + + /// The store of registered lints. + lints: LintStore, + + /// When recursing into an attributed node of the ast which modifies lint + /// levels, this stack keeps track of the previous lint levels of whatever + /// was modified. + level_stack: Vec<(LintId, LevelSource)>, +} + /// Convenience macro for calling a `LintPass` method on every pass in the context. macro_rules! run_lints { ($cx:expr, $f:ident, $($args:expr),*) => ({ // Move the vector of passes out of `$cx` so that we can // iterate over it mutably while passing `$cx` to the methods. - let mut passes = $cx.lints.passes.take().unwrap(); + let mut passes = $cx.mut_lints().passes.take().unwrap(); for obj in &mut passes { obj.$f($cx, $($args),*); } - $cx.lints.passes = Some(passes); + $cx.mut_lints().passes = Some(passes); }) } /// Parse the lint attributes into a vector, with `Err`s for malformed lint @@ -364,65 +384,50 @@ pub fn raw_emit_lint(sess: &Session, lint: &'static Lint, } } -impl<'a, 'tcx> Context<'a, 'tcx> { - fn new(tcx: &'a ty::ctxt<'tcx>, - krate: &'a hir::Crate, - exported_items: &'a ExportedItems) -> Context<'a, 'tcx> { - // We want to own the lint store, so move it out of the session. - let lint_store = mem::replace(&mut *tcx.sess.lint_store.borrow_mut(), - LintStore::new()); - - Context { - tcx: tcx, - krate: krate, - exported_items: exported_items, - lints: lint_store, - level_stack: vec![], - node_levels: RefCell::new(FnvHashMap()), - } - } - - /// Get the overall compiler `Session` object. - pub fn sess(&'a self) -> &'a Session { - &self.tcx.sess - } +pub trait LintContext: Sized { + fn sess(&self) -> &Session; + fn lints(&self) -> &LintStore; + fn mut_lints(&mut self) -> &mut LintStore; + fn level_stack(&mut self) -> &mut Vec<(LintId, LevelSource)>; + fn enter_attrs(&mut self, attrs: &[hir::Attribute]); + fn exit_attrs(&mut self, attrs: &[hir::Attribute]); /// Get the level of `lint` at the current position of the lint /// traversal. - pub fn current_level(&self, lint: &'static Lint) -> Level { - self.lints.levels.get(&LintId::of(lint)).map_or(Allow, |&(lvl, _)| lvl) + fn current_level(&self, lint: &'static Lint) -> Level { + self.lints().levels.get(&LintId::of(lint)).map_or(Allow, |&(lvl, _)| lvl) } fn lookup_and_emit(&self, lint: &'static Lint, span: Option, msg: &str) { - let (level, src) = match self.lints.levels.get(&LintId::of(lint)) { + let (level, src) = match self.lints().levels.get(&LintId::of(lint)) { None => return, Some(&(Warn, src)) => { let lint_id = LintId::of(builtin::WARNINGS); - (self.lints.get_level_source(lint_id).0, src) + (self.lints().get_level_source(lint_id).0, src) } Some(&pair) => pair, }; - raw_emit_lint(&self.tcx.sess, lint, (level, src), span, msg); - } - - /// Emit a lint at the appropriate level, with no associated span. - pub fn lint(&self, lint: &'static Lint, msg: &str) { - self.lookup_and_emit(lint, None, msg); + raw_emit_lint(&self.sess(), lint, (level, src), span, msg); } /// Emit a lint at the appropriate level, for a particular span. - pub fn span_lint(&self, lint: &'static Lint, span: Span, msg: &str) { + fn span_lint(&self, lint: &'static Lint, span: Span, msg: &str) { self.lookup_and_emit(lint, Some(span), msg); } + /// Emit a lint at the appropriate level, with no associated span. + fn lint(&self, lint: &'static Lint, msg: &str) { + self.lookup_and_emit(lint, None, msg); + } + /// Merge the lints specified by any lint attributes into the /// current lint context, call the provided function, then reset the /// lints in effect to their previous state. fn with_lint_attrs(&mut self, attrs: &[ast::Attribute], - f: F) where - F: FnOnce(&mut Context), + f: F) + where F: FnOnce(&mut Self), { // Parse all of the lint attributes, and then add them all to the // current dictionary of lint information. Along the way, keep a history @@ -433,15 +438,15 @@ impl<'a, 'tcx> Context<'a, 'tcx> { for result in gather_attrs(attrs) { let v = match result { Err(span) => { - span_err!(self.tcx.sess, span, E0452, + span_err!(self.sess(), span, E0452, "malformed lint attribute"); continue; } Ok((lint_name, level, span)) => { - match self.lints.find_lint(&lint_name, &self.tcx.sess, Some(span)) { + match self.lints().find_lint(&lint_name, &self.sess(), Some(span)) { Ok(lint_id) => vec![(lint_id, level, span)], Err(FindLintError::NotFound) => { - match self.lints.lint_groups.get(&lint_name[..]) { + match self.lints().lint_groups.get(&lint_name[..]) { Some(&(ref v, _)) => v.iter() .map(|lint_id: &LintId| (*lint_id, level, span)) @@ -460,35 +465,90 @@ impl<'a, 'tcx> Context<'a, 'tcx> { }; for (lint_id, level, span) in v { - let now = self.lints.get_level_source(lint_id).0; + let now = self.lints().get_level_source(lint_id).0; if now == Forbid && level != Forbid { let lint_name = lint_id.as_str(); - span_err!(self.tcx.sess, span, E0453, + span_err!(self.sess(), span, E0453, "{}({}) overruled by outer forbid({})", level.as_str(), lint_name, lint_name); } else if now != level { - let src = self.lints.get_level_source(lint_id).1; - self.level_stack.push((lint_id, (now, src))); + let src = self.lints().get_level_source(lint_id).1; + self.level_stack().push((lint_id, (now, src))); pushed += 1; - self.lints.set_level(lint_id, (level, Node(span))); + self.mut_lints().set_level(lint_id, (level, Node(span))); } } } - run_lints!(self, enter_lint_attrs, attrs); + self.enter_attrs(attrs); f(self); - run_lints!(self, exit_lint_attrs, attrs); + self.exit_attrs(attrs); // rollback for _ in 0..pushed { - let (lint, lvlsrc) = self.level_stack.pop().unwrap(); - self.lints.set_level(lint, lvlsrc); + let (lint, lvlsrc) = self.level_stack().pop().unwrap(); + self.mut_lints().set_level(lint, lvlsrc); + } + } + + fn with_ast_lint_attrs(&mut self, + attrs: &[ast::Attribute], + f: F) + where F: FnOnce(&mut Self), + { + self.with_lint_attrs(&lower_attrs(attrs), f) + } +} + + +impl<'a> EarlyContext<'a> { + fn new(sess: &'a Session, + krate: &'a ast::Crate) -> EarlyContext<'a> { + // We want to own the lint store, so move it out of the session. + let lint_store = mem::replace(&mut *sess.lint_store.borrow_mut(), + LintStore::new()); + + EarlyContext { + sess: sess, + krate: krate, + lints: lint_store, + level_stack: vec![], } } - fn visit_ids(&mut self, f: F) where - F: FnOnce(&mut util::IdVisitor) + fn visit_ids(&mut self, f: F) + where F: FnOnce(&mut ast_util::IdVisitor) + { + let mut v = ast_util::IdVisitor { + operation: self, + pass_through_items: false, + visited_outermost: false, + }; + f(&mut v); + } +} + +impl<'a, 'tcx> LateContext<'a, 'tcx> { + fn new(tcx: &'a ty::ctxt<'tcx>, + krate: &'a hir::Crate, + exported_items: &'a ExportedItems) -> LateContext<'a, 'tcx> { + // We want to own the lint store, so move it out of the session. + let lint_store = mem::replace(&mut *tcx.sess.lint_store.borrow_mut(), + LintStore::new()); + + LateContext { + tcx: tcx, + krate: krate, + exported_items: exported_items, + lints: lint_store, + level_stack: vec![], + node_levels: RefCell::new(FnvHashMap()), + } + } + + fn visit_ids(&mut self, f: F) + where F: FnOnce(&mut util::IdVisitor) { let mut v = util::IdVisitor { operation: self, @@ -499,41 +559,95 @@ impl<'a, 'tcx> Context<'a, 'tcx> { } } -impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { +impl<'a, 'tcx> LintContext for LateContext<'a, 'tcx> { + /// Get the overall compiler `Session` object. + fn sess(&self) -> &Session { + &self.tcx.sess + } + + fn lints(&self) -> &LintStore { + &self.lints + } + + fn mut_lints(&mut self) -> &mut LintStore { + &mut self.lints + } + + fn level_stack(&mut self) -> &mut Vec<(LintId, LevelSource)> { + &mut self.level_stack + } + + fn enter_attrs(&mut self, attrs: &[hir::Attribute]) { + run_lints!(self, enter_lint_attrs, attrs); + } + + fn exit_attrs(&mut self, attrs: &[hir::Attribute]) { + run_lints!(self, exit_lint_attrs, attrs); + } +} + +impl<'a> LintContext for EarlyContext<'a> { + /// Get the overall compiler `Session` object. + fn sess(&self) -> &Session { + &self.sess + } + + fn lints(&self) -> &LintStore { + &self.lints + } + + fn mut_lints(&mut self) -> &mut LintStore { + &mut self.lints + } + + fn level_stack(&mut self) -> &mut Vec<(LintId, LevelSource)> { + &mut self.level_stack + } + + fn enter_attrs(&mut self, attrs: &[hir::Attribute]) { + run_lints!(self, ast_enter_lint_attrs, attrs); + } + + fn exit_attrs(&mut self, attrs: &[hir::Attribute]) { + run_lints!(self, ast_exit_lint_attrs, attrs); + } +} + +impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> { fn visit_item(&mut self, it: &hir::Item) { self.with_lint_attrs(&it.attrs, |cx| { run_lints!(cx, check_item, it); cx.visit_ids(|v| v.visit_item(it)); - visit::walk_item(cx, it); + hir_visit::walk_item(cx, it); }) } fn visit_foreign_item(&mut self, it: &hir::ForeignItem) { self.with_lint_attrs(&it.attrs, |cx| { run_lints!(cx, check_foreign_item, it); - visit::walk_foreign_item(cx, it); + hir_visit::walk_foreign_item(cx, it); }) } fn visit_pat(&mut self, p: &hir::Pat) { run_lints!(self, check_pat, p); - visit::walk_pat(self, p); + hir_visit::walk_pat(self, p); } fn visit_expr(&mut self, e: &hir::Expr) { run_lints!(self, check_expr, e); - visit::walk_expr(self, e); + hir_visit::walk_expr(self, e); } fn visit_stmt(&mut self, s: &hir::Stmt) { run_lints!(self, check_stmt, s); - visit::walk_stmt(self, s); + hir_visit::walk_stmt(self, s); } - fn visit_fn(&mut self, fk: FnKind<'v>, decl: &'v hir::FnDecl, + fn visit_fn(&mut self, fk: hir_visit::FnKind<'v>, decl: &'v hir::FnDecl, body: &'v hir::Block, span: Span, id: ast::NodeId) { run_lints!(self, check_fn, fk, decl, body, span, id); - visit::walk_fn(self, fk, decl, body, span); + hir_visit::walk_fn(self, fk, decl, body, span); } fn visit_struct_def(&mut self, @@ -542,28 +656,28 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { g: &hir::Generics, id: ast::NodeId) { run_lints!(self, check_struct_def, s, ident, g, id); - visit::walk_struct_def(self, s); + hir_visit::walk_struct_def(self, s); run_lints!(self, check_struct_def_post, s, ident, g, id); } fn visit_struct_field(&mut self, s: &hir::StructField) { self.with_lint_attrs(&s.node.attrs, |cx| { run_lints!(cx, check_struct_field, s); - visit::walk_struct_field(cx, s); + hir_visit::walk_struct_field(cx, s); }) } fn visit_variant(&mut self, v: &hir::Variant, g: &hir::Generics) { self.with_lint_attrs(&v.node.attrs, |cx| { run_lints!(cx, check_variant, v, g); - visit::walk_variant(cx, v, g); + hir_visit::walk_variant(cx, v, g); run_lints!(cx, check_variant_post, v, g); }) } fn visit_ty(&mut self, t: &hir::Ty) { run_lints!(self, check_ty, t); - visit::walk_ty(self, t); + hir_visit::walk_ty(self, t); } fn visit_ident(&mut self, sp: Span, id: ast::Ident) { @@ -572,27 +686,27 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { fn visit_mod(&mut self, m: &hir::Mod, s: Span, n: ast::NodeId) { run_lints!(self, check_mod, m, s, n); - visit::walk_mod(self, m); + hir_visit::walk_mod(self, m); } fn visit_local(&mut self, l: &hir::Local) { run_lints!(self, check_local, l); - visit::walk_local(self, l); + hir_visit::walk_local(self, l); } fn visit_block(&mut self, b: &hir::Block) { run_lints!(self, check_block, b); - visit::walk_block(self, b); + hir_visit::walk_block(self, b); } fn visit_arm(&mut self, a: &hir::Arm) { run_lints!(self, check_arm, a); - visit::walk_arm(self, a); + hir_visit::walk_arm(self, a); } fn visit_decl(&mut self, d: &hir::Decl) { run_lints!(self, check_decl, d); - visit::walk_decl(self, d); + hir_visit::walk_decl(self, d); } fn visit_expr_post(&mut self, e: &hir::Expr) { @@ -601,14 +715,14 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { fn visit_generics(&mut self, g: &hir::Generics) { run_lints!(self, check_generics, g); - visit::walk_generics(self, g); + hir_visit::walk_generics(self, g); } fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) { self.with_lint_attrs(&trait_item.attrs, |cx| { run_lints!(cx, check_trait_item, trait_item); cx.visit_ids(|v| v.visit_trait_item(trait_item)); - visit::walk_trait_item(cx, trait_item); + hir_visit::walk_trait_item(cx, trait_item); }); } @@ -616,7 +730,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { self.with_lint_attrs(&impl_item.attrs, |cx| { run_lints!(cx, check_impl_item, impl_item); cx.visit_ids(|v| v.visit_impl_item(impl_item)); - visit::walk_impl_item(cx, impl_item); + hir_visit::walk_impl_item(cx, impl_item); }); } @@ -634,12 +748,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { fn visit_explicit_self(&mut self, es: &hir::ExplicitSelf) { run_lints!(self, check_explicit_self, es); - visit::walk_explicit_self(self, es); + hir_visit::walk_explicit_self(self, es); } fn visit_path(&mut self, p: &hir::Path, id: ast::NodeId) { run_lints!(self, check_path, p, id); - visit::walk_path(self, p); + hir_visit::walk_path(self, p); } fn visit_attribute(&mut self, attr: &ast::Attribute) { @@ -647,10 +761,170 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { } } +impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> { + fn visit_item(&mut self, it: &ast::Item) { + self.with_ast_lint_attrs(&it.attrs, |cx| { + run_lints!(cx, check_ast_item, it); + cx.visit_ids(|v| v.visit_item(it)); + ast_visit::walk_item(cx, it); + }) + } + + fn visit_foreign_item(&mut self, it: &ast::ForeignItem) { + self.with_ast_lint_attrs(&it.attrs, |cx| { + run_lints!(cx, check_ast_foreign_item, it); + ast_visit::walk_foreign_item(cx, it); + }) + } + + fn visit_pat(&mut self, p: &ast::Pat) { + run_lints!(self, check_ast_pat, p); + ast_visit::walk_pat(self, p); + } + + fn visit_expr(&mut self, e: &ast::Expr) { + run_lints!(self, check_ast_expr, e); + ast_visit::walk_expr(self, e); + } + + fn visit_stmt(&mut self, s: &ast::Stmt) { + run_lints!(self, check_ast_stmt, s); + ast_visit::walk_stmt(self, s); + } + + fn visit_fn(&mut self, fk: ast_visit::FnKind<'v>, decl: &'v ast::FnDecl, + body: &'v ast::Block, span: Span, id: ast::NodeId) { + run_lints!(self, check_ast_fn, fk, decl, body, span, id); + ast_visit::walk_fn(self, fk, decl, body, span); + } + + fn visit_struct_def(&mut self, + s: &ast::StructDef, + ident: ast::Ident, + g: &ast::Generics, + id: ast::NodeId) { + run_lints!(self, check_ast_struct_def, s, ident, g, id); + ast_visit::walk_struct_def(self, s); + run_lints!(self, check_ast_struct_def_post, s, ident, g, id); + } + + fn visit_struct_field(&mut self, s: &ast::StructField) { + self.with_ast_lint_attrs(&s.node.attrs, |cx| { + run_lints!(cx, check_ast_struct_field, s); + ast_visit::walk_struct_field(cx, s); + }) + } + + fn visit_variant(&mut self, v: &ast::Variant, g: &ast::Generics) { + self.with_ast_lint_attrs(&v.node.attrs, |cx| { + run_lints!(cx, check_ast_variant, v, g); + ast_visit::walk_variant(cx, v, g); + run_lints!(cx, check_ast_variant_post, v, g); + }) + } + + fn visit_ty(&mut self, t: &ast::Ty) { + run_lints!(self, check_ast_ty, t); + ast_visit::walk_ty(self, t); + } + + fn visit_ident(&mut self, sp: Span, id: ast::Ident) { + run_lints!(self, check_ast_ident, sp, id); + } + + fn visit_mod(&mut self, m: &ast::Mod, s: Span, n: ast::NodeId) { + run_lints!(self, check_ast_mod, m, s, n); + ast_visit::walk_mod(self, m); + } + + fn visit_local(&mut self, l: &ast::Local) { + run_lints!(self, check_ast_local, l); + ast_visit::walk_local(self, l); + } + + fn visit_block(&mut self, b: &ast::Block) { + run_lints!(self, check_ast_block, b); + ast_visit::walk_block(self, b); + } + + fn visit_arm(&mut self, a: &ast::Arm) { + run_lints!(self, check_ast_arm, a); + ast_visit::walk_arm(self, a); + } + + fn visit_decl(&mut self, d: &ast::Decl) { + run_lints!(self, check_ast_decl, d); + ast_visit::walk_decl(self, d); + } + + fn visit_expr_post(&mut self, e: &ast::Expr) { + run_lints!(self, check_ast_expr_post, e); + } + + fn visit_generics(&mut self, g: &ast::Generics) { + run_lints!(self, check_ast_generics, g); + ast_visit::walk_generics(self, g); + } + + fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) { + self.with_ast_lint_attrs(&trait_item.attrs, |cx| { + run_lints!(cx, check_ast_trait_item, trait_item); + cx.visit_ids(|v| v.visit_trait_item(trait_item)); + ast_visit::walk_trait_item(cx, trait_item); + }); + } + + fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) { + self.with_ast_lint_attrs(&impl_item.attrs, |cx| { + run_lints!(cx, check_ast_impl_item, impl_item); + cx.visit_ids(|v| v.visit_impl_item(impl_item)); + ast_visit::walk_impl_item(cx, impl_item); + }); + } + + fn visit_opt_lifetime_ref(&mut self, sp: Span, lt: &Option) { + run_lints!(self, check_ast_opt_lifetime_ref, sp, lt); + } + + fn visit_lifetime_ref(&mut self, lt: &ast::Lifetime) { + run_lints!(self, check_ast_lifetime_ref, lt); + } + + fn visit_lifetime_def(&mut self, lt: &ast::LifetimeDef) { + run_lints!(self, check_ast_lifetime_def, lt); + } + + fn visit_explicit_self(&mut self, es: &ast::ExplicitSelf) { + run_lints!(self, check_ast_explicit_self, es); + ast_visit::walk_explicit_self(self, es); + } + + fn visit_path(&mut self, p: &ast::Path, id: ast::NodeId) { + run_lints!(self, check_ast_path, p, id); + ast_visit::walk_path(self, p); + } + + fn visit_attribute(&mut self, attr: &ast::Attribute) { + run_lints!(self, check_ast_attribute, attr); + } +} + // Output any lints that were previously added to the session. -impl<'a, 'tcx> IdVisitingOperation for Context<'a, 'tcx> { +impl<'a, 'tcx> IdVisitingOperation for LateContext<'a, 'tcx> { + fn visit_id(&mut self, id: ast::NodeId) { + match self.sess().lints.borrow_mut().remove(&id) { + None => {} + Some(lints) => { + for (lint_id, span, msg) in lints { + self.span_lint(lint_id.lint, span, &msg[..]) + } + } + } + } +} +impl<'a> IdVisitingOperation for EarlyContext<'a> { fn visit_id(&mut self, id: ast::NodeId) { - match self.tcx.sess.lints.borrow_mut().remove(&id) { + match self.sess.lints.borrow_mut().remove(&id) { None => {} Some(lints) => { for (lint_id, span, msg) in lints { @@ -661,7 +935,7 @@ impl<'a, 'tcx> IdVisitingOperation for Context<'a, 'tcx> { } } -// This lint pass is defined here because it touches parts of the `Context` +// This lint pass is defined here because it touches parts of the `LateContext` // that we don't want to expose. It records the lint level at certain AST // nodes, so that the variant size difference check in trans can call // `raw_emit_lint`. @@ -673,7 +947,7 @@ impl LintPass for GatherNodeLevels { lint_array!() } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { hir::ItemEnum(..) => { let lint_id = LintId::of(builtin::VARIANT_SIZE_DIFFERENCES); @@ -698,21 +972,21 @@ pub fn check_crate(tcx: &ty::ctxt, krate: &hir::Crate, exported_items: &ExportedItems) { - let mut cx = Context::new(tcx, krate, exported_items); + let mut cx = LateContext::new(tcx, krate, exported_items); // Visit the whole crate. cx.with_lint_attrs(&krate.attrs, |cx| { cx.visit_id(ast::CRATE_NODE_ID); cx.visit_ids(|v| { v.visited_outermost = true; - visit::walk_crate(v, krate); + hir_visit::walk_crate(v, krate); }); // since the root module isn't visited as an item (because it isn't an // item), warn for it here. run_lints!(cx, check_crate, krate); - visit::walk_crate(cx, krate); + hir_visit::walk_crate(cx, krate); }); // If we missed any lints added to the session, then there's a bug somewhere @@ -727,3 +1001,35 @@ pub fn check_crate(tcx: &ty::ctxt, *tcx.node_lint_levels.borrow_mut() = cx.node_levels.into_inner(); } + +pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) { + let mut cx = EarlyContext::new(sess, krate); + + // Visit the whole crate. + cx.with_ast_lint_attrs(&krate.attrs, |cx| { + cx.visit_id(ast::CRATE_NODE_ID); + cx.visit_ids(|v| { + v.visited_outermost = true; + ast_visit::walk_crate(v, krate); + }); + + // since the root module isn't visited as an item (because it isn't an + // item), warn for it here. + run_lints!(cx, check_ast_crate, krate); + + ast_visit::walk_crate(cx, krate); + }); + + // Put the lint store back in the session. + mem::replace(&mut *sess.lint_store.borrow_mut(), cx.lints); + + // If we missed any lints added to the session, then there's a bug somewhere + // in the iteration code. + for (_, v) in sess.lints.borrow().iter() { + for &(lint, span, ref msg) in v { + sess.span_bug(span, + &format!("unprocessed lint {}: {}", + lint.as_str(), *msg)) + } + } +} diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 11a1852ed2509..d30f8f3c53ad2 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -35,10 +35,12 @@ use std::hash; use std::ascii::AsciiExt; use syntax::codemap::Span; use rustc_front::visit::FnKind; +use syntax::visit as ast_visit; use syntax::ast; use rustc_front::hir; -pub use lint::context::{Context, LintStore, raw_emit_lint, check_crate, gather_attrs, +pub use lint::context::{LateContext, EarlyContext, Context, LintContext, LintStore, + raw_emit_lint, check_crate, check_ast_crate, gather_attrs, GatherNodeLevels}; /// Specification of a single lint. @@ -126,46 +128,92 @@ pub trait LintPass { /// `Lint`, make it a private `static` item in its own module. fn get_lints(&self) -> LintArray; - fn check_crate(&mut self, _: &Context, _: &hir::Crate) { } - fn check_ident(&mut self, _: &Context, _: Span, _: ast::Ident) { } - fn check_mod(&mut self, _: &Context, _: &hir::Mod, _: Span, _: ast::NodeId) { } - fn check_foreign_item(&mut self, _: &Context, _: &hir::ForeignItem) { } - fn check_item(&mut self, _: &Context, _: &hir::Item) { } - fn check_local(&mut self, _: &Context, _: &hir::Local) { } - fn check_block(&mut self, _: &Context, _: &hir::Block) { } - fn check_stmt(&mut self, _: &Context, _: &hir::Stmt) { } - fn check_arm(&mut self, _: &Context, _: &hir::Arm) { } - fn check_pat(&mut self, _: &Context, _: &hir::Pat) { } - fn check_decl(&mut self, _: &Context, _: &hir::Decl) { } - fn check_expr(&mut self, _: &Context, _: &hir::Expr) { } - fn check_expr_post(&mut self, _: &Context, _: &hir::Expr) { } - fn check_ty(&mut self, _: &Context, _: &hir::Ty) { } - fn check_generics(&mut self, _: &Context, _: &hir::Generics) { } - fn check_fn(&mut self, _: &Context, + fn check_ident(&mut self, _: &LateContext, _: Span, _: ast::Ident) { } + fn check_crate(&mut self, _: &LateContext, _: &hir::Crate) { } + fn check_mod(&mut self, _: &LateContext, _: &hir::Mod, _: Span, _: ast::NodeId) { } + fn check_foreign_item(&mut self, _: &LateContext, _: &hir::ForeignItem) { } + fn check_item(&mut self, _: &LateContext, _: &hir::Item) { } + fn check_local(&mut self, _: &LateContext, _: &hir::Local) { } + fn check_block(&mut self, _: &LateContext, _: &hir::Block) { } + fn check_stmt(&mut self, _: &LateContext, _: &hir::Stmt) { } + fn check_arm(&mut self, _: &LateContext, _: &hir::Arm) { } + fn check_pat(&mut self, _: &LateContext, _: &hir::Pat) { } + fn check_decl(&mut self, _: &LateContext, _: &hir::Decl) { } + fn check_expr(&mut self, _: &LateContext, _: &hir::Expr) { } + fn check_expr_post(&mut self, _: &LateContext, _: &hir::Expr) { } + fn check_ty(&mut self, _: &LateContext, _: &hir::Ty) { } + fn check_generics(&mut self, _: &LateContext, _: &hir::Generics) { } + fn check_fn(&mut self, _: &LateContext, _: FnKind, _: &hir::FnDecl, _: &hir::Block, _: Span, _: ast::NodeId) { } - fn check_trait_item(&mut self, _: &Context, _: &hir::TraitItem) { } - fn check_impl_item(&mut self, _: &Context, _: &hir::ImplItem) { } - fn check_struct_def(&mut self, _: &Context, + fn check_trait_item(&mut self, _: &LateContext, _: &hir::TraitItem) { } + fn check_impl_item(&mut self, _: &LateContext, _: &hir::ImplItem) { } + fn check_struct_def(&mut self, _: &LateContext, _: &hir::StructDef, _: ast::Ident, _: &hir::Generics, _: ast::NodeId) { } - fn check_struct_def_post(&mut self, _: &Context, + fn check_struct_def_post(&mut self, _: &LateContext, _: &hir::StructDef, _: ast::Ident, _: &hir::Generics, _: ast::NodeId) { } - fn check_struct_field(&mut self, _: &Context, _: &hir::StructField) { } - fn check_variant(&mut self, _: &Context, _: &hir::Variant, _: &hir::Generics) { } - fn check_variant_post(&mut self, _: &Context, _: &hir::Variant, _: &hir::Generics) { } - fn check_opt_lifetime_ref(&mut self, _: &Context, _: Span, _: &Option) { } - fn check_lifetime_ref(&mut self, _: &Context, _: &hir::Lifetime) { } - fn check_lifetime_def(&mut self, _: &Context, _: &hir::LifetimeDef) { } - fn check_explicit_self(&mut self, _: &Context, _: &hir::ExplicitSelf) { } - fn check_mac(&mut self, _: &Context, _: &ast::Mac) { } - fn check_path(&mut self, _: &Context, _: &hir::Path, _: ast::NodeId) { } - fn check_attribute(&mut self, _: &Context, _: &ast::Attribute) { } + fn check_struct_field(&mut self, _: &LateContext, _: &hir::StructField) { } + fn check_variant(&mut self, _: &LateContext, _: &hir::Variant, _: &hir::Generics) { } + fn check_variant_post(&mut self, _: &LateContext, _: &hir::Variant, _: &hir::Generics) { } + fn check_opt_lifetime_ref(&mut self, _: &LateContext, _: Span, _: &Option) { } + fn check_lifetime_ref(&mut self, _: &LateContext, _: &hir::Lifetime) { } + fn check_lifetime_def(&mut self, _: &LateContext, _: &hir::LifetimeDef) { } + fn check_explicit_self(&mut self, _: &LateContext, _: &hir::ExplicitSelf) { } + // Note that you shouldn't implement both check_mac and check_ast_mac, + // because then your lint will be called twice. Prefer check_ast_mac. + fn check_mac(&mut self, _: &LateContext, _: &ast::Mac) { } + fn check_path(&mut self, _: &LateContext, _: &hir::Path, _: ast::NodeId) { } + fn check_attribute(&mut self, _: &LateContext, _: &ast::Attribute) { } + + fn check_ast_ident(&mut self, _: &EarlyContext, _: Span, _: ast::Ident) { } + fn check_ast_crate(&mut self, _: &EarlyContext, _: &ast::Crate) { } + fn check_ast_mod(&mut self, _: &EarlyContext, _: &ast::Mod, _: Span, _: ast::NodeId) { } + fn check_ast_foreign_item(&mut self, _: &EarlyContext, _: &ast::ForeignItem) { } + fn check_ast_item(&mut self, _: &EarlyContext, _: &ast::Item) { } + fn check_ast_local(&mut self, _: &EarlyContext, _: &ast::Local) { } + fn check_ast_block(&mut self, _: &EarlyContext, _: &ast::Block) { } + fn check_ast_stmt(&mut self, _: &EarlyContext, _: &ast::Stmt) { } + fn check_ast_arm(&mut self, _: &EarlyContext, _: &ast::Arm) { } + fn check_ast_pat(&mut self, _: &EarlyContext, _: &ast::Pat) { } + fn check_ast_decl(&mut self, _: &EarlyContext, _: &ast::Decl) { } + fn check_ast_expr(&mut self, _: &EarlyContext, _: &ast::Expr) { } + fn check_ast_expr_post(&mut self, _: &EarlyContext, _: &ast::Expr) { } + fn check_ast_ty(&mut self, _: &EarlyContext, _: &ast::Ty) { } + fn check_ast_generics(&mut self, _: &EarlyContext, _: &ast::Generics) { } + fn check_ast_fn(&mut self, _: &EarlyContext, + _: ast_visit::FnKind, _: &ast::FnDecl, _: &ast::Block, _: Span, _: ast::NodeId) { } + fn check_ast_trait_item(&mut self, _: &EarlyContext, _: &ast::TraitItem) { } + fn check_ast_impl_item(&mut self, _: &EarlyContext, _: &ast::ImplItem) { } + fn check_ast_struct_def(&mut self, _: &EarlyContext, + _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { } + fn check_ast_struct_def_post(&mut self, _: &EarlyContext, + _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { } + fn check_ast_struct_field(&mut self, _: &EarlyContext, _: &ast::StructField) { } + fn check_ast_variant(&mut self, _: &EarlyContext, _: &ast::Variant, _: &ast::Generics) { } + fn check_ast_variant_post(&mut self, _: &EarlyContext, _: &ast::Variant, _: &ast::Generics) { } + fn check_ast_opt_lifetime_ref(&mut self, + _: &EarlyContext, + _: Span, + _: &Option) { } + fn check_ast_lifetime_ref(&mut self, _: &EarlyContext, _: &ast::Lifetime) { } + fn check_ast_lifetime_def(&mut self, _: &EarlyContext, _: &ast::LifetimeDef) { } + fn check_ast_explicit_self(&mut self, _: &EarlyContext, _: &ast::ExplicitSelf) { } + fn check_ast_mac(&mut self, _: &EarlyContext, _: &ast::Mac) { } + fn check_ast_path(&mut self, _: &EarlyContext, _: &ast::Path, _: ast::NodeId) { } + fn check_ast_attribute(&mut self, _: &EarlyContext, _: &ast::Attribute) { } /// Called when entering a syntax node that can have lint attributes such /// as `#[allow(...)]`. Called with *all* the attributes of that node. - fn enter_lint_attrs(&mut self, _: &Context, _: &[ast::Attribute]) { } + fn enter_lint_attrs(&mut self, _: &LateContext, _: &[ast::Attribute]) { } /// Counterpart to `enter_lint_attrs`. - fn exit_lint_attrs(&mut self, _: &Context, _: &[ast::Attribute]) { } + fn exit_lint_attrs(&mut self, _: &LateContext, _: &[ast::Attribute]) { } + + /// Called when entering a syntax node that can have lint attributes such + /// as `#[allow(...)]`. Called with *all* the attributes of that node. + fn ast_enter_lint_attrs(&mut self, _: &EarlyContext, _: &[ast::Attribute]) { } + + /// Counterpart to `ast_enter_lint_attrs`. + fn ast_exit_lint_attrs(&mut self, _: &EarlyContext, _: &[ast::Attribute]) { } } /// A lint pass boxed up as a trait object. diff --git a/src/librustc/plugin/registry.rs b/src/librustc/plugin/registry.rs index e79721b4347a6..ca7ce2308a1cb 100644 --- a/src/librustc/plugin/registry.rs +++ b/src/librustc/plugin/registry.rs @@ -89,7 +89,6 @@ impl<'a> Registry<'a> { /// Register a syntax extension of any kind. /// /// This is the most general hook into `libsyntax`'s expansion behavior. - #[allow(deprecated)] pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension) { self.syntax_exts.push((name, match extension { NormalTT(ext, _, allow_internal_unstable) => { diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index f3038624ac107..4ec13ba35993d 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -132,7 +132,6 @@ pub fn compile_input(sess: Session, phase_3_run_analysis_passes(sess, ast_map, - &expanded_crate, &arenas, id, control.make_glob_map, @@ -598,6 +597,10 @@ pub fn phase_2_configure_and_expand(sess: &Session, sess.abort_if_errors(); }); + time(time_passes, "early lint checks", || { + lint::check_ast_crate(sess, &krate) + }); + Some(krate) } @@ -641,7 +644,6 @@ pub fn make_map<'ast>(sess: &Session, /// structures carrying the results of the analysis. pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session, ast_map: front::map::Map<'tcx>, - ast_crate: &ast::Crate, arenas: &'tcx ty::CtxtArenas<'tcx>, name: String, make_glob_map: resolve::MakeGlobMap, @@ -765,7 +767,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session, &tcx.sess, lib_features_used)); time(time_passes, "lint checking", || - lint::check_crate(tcx, &lower_crate(ast_crate), &exported_items)); + lint::check_crate(tcx, krate, &exported_items)); // The above three passes generate errors w/o aborting tcx.sess.abort_if_errors(); diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index dc36a4ab93c6a..75b57341d48df 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -157,7 +157,6 @@ impl PpSourceMode { fn call_with_pp_support_hir<'tcx, A, B, F>(&self, sess: Session, ast_map: &hir_map::Map<'tcx>, - ast_crate: &ast::Crate, arenas: &'tcx ty::CtxtArenas<'tcx>, id: String, payload: B, @@ -180,7 +179,6 @@ impl PpSourceMode { PpmTyped => { driver::phase_3_run_analysis_passes(sess, ast_map.clone(), - ast_crate, arenas, id, resolve::MakeGlobMap::No, @@ -715,7 +713,7 @@ pub fn pretty_print_input(sess: Session, (PpmHir(s), None) => { let out: &mut Write = &mut out; s.call_with_pp_support_hir( - sess, &ast_map.unwrap(), &krate, &arenas, id, box out, |annotation, out, krate| { + sess, &ast_map.unwrap(), &arenas, id, box out, |annotation, out, krate| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); pprust_hir::print_crate(sess.codemap(), @@ -733,7 +731,6 @@ pub fn pretty_print_input(sess: Session, let out: &mut Write = &mut out; s.call_with_pp_support_hir(sess, &ast_map.unwrap(), - &krate, &arenas, id, (out,uii), @@ -782,7 +779,6 @@ pub fn pretty_print_input(sess: Session, let variants = gather_flowgraph_variants(&sess); driver::phase_3_run_analysis_passes(sess, ast_map, - &krate, &arenas, id, resolve::MakeGlobMap::No, diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 816b84f3d46b1..c092049258c9b 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -38,7 +38,7 @@ use middle::const_eval::{eval_const_expr_partial, ConstVal}; use middle::const_eval::EvalHint::ExprTypeChecked; use rustc::front::map as hir_map; use util::nodemap::{FnvHashMap, FnvHashSet, NodeSet}; -use lint::{Level, Context, LintPass, LintArray, Lint}; +use lint::{Level, LateContext, LintContext, LintPass, LintArray, Lint}; use std::collections::HashSet; use std::collections::hash_map::Entry::{Occupied, Vacant}; @@ -73,7 +73,7 @@ impl LintPass for WhileTrue { lint_array!(WHILE_TRUE) } - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { + fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { if let hir::ExprWhile(ref cond, _, _) = e.node { if let hir::ExprLit(ref lit) = cond.node { if let ast::LitBool(true) = lit.node { @@ -122,7 +122,7 @@ impl LintPass for TypeLimits { lint_array!(UNUSED_COMPARISONS, OVERFLOWING_LITERALS, EXCEEDING_BITSHIFTS) } - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { + fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { match e.node { hir::ExprUnary(hir::UnNeg, ref expr) => { match expr.node { @@ -377,7 +377,7 @@ impl LintPass for TypeLimits { } } - fn check_unsigned_negation_feature(cx: &Context, span: Span) { + fn check_unsigned_negation_feature(cx: &LateContext, span: Span) { if !cx.sess().features.borrow().negate_unsigned { // FIXME(#27141): change this to syntax::feature_gate::emit_feature_err… cx.sess().span_warn(span, @@ -398,7 +398,7 @@ declare_lint! { } struct ImproperCTypesVisitor<'a, 'tcx: 'a> { - cx: &'a Context<'a, 'tcx> + cx: &'a LateContext<'a, 'tcx> } enum FfiResult { @@ -703,13 +703,13 @@ impl LintPass for ImproperCTypes { lint_array!(IMPROPER_CTYPES) } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { - fn check_ty(cx: &Context, ty: &hir::Ty) { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { + fn check_ty(cx: &LateContext, ty: &hir::Ty) { let mut vis = ImproperCTypesVisitor { cx: cx }; vis.visit_ty(ty); } - fn check_foreign_fn(cx: &Context, decl: &hir::FnDecl) { + fn check_foreign_fn(cx: &LateContext, decl: &hir::FnDecl) { for input in &decl.inputs { check_ty(cx, &*input.ty); } @@ -747,7 +747,7 @@ declare_lint! { pub struct BoxPointers; impl BoxPointers { - fn check_heap_type<'a, 'tcx>(&self, cx: &Context<'a, 'tcx>, + fn check_heap_type<'a, 'tcx>(&self, cx: &LateContext<'a, 'tcx>, span: Span, ty: Ty<'tcx>) { for leaf_ty in ty.walk() { if let ty::TyBox(_) = leaf_ty.sty { @@ -763,7 +763,7 @@ impl LintPass for BoxPointers { lint_array!(BOX_POINTERS) } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { hir::ItemFn(..) | hir::ItemTy(..) | @@ -786,7 +786,7 @@ impl LintPass for BoxPointers { } } - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { + fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { let ty = cx.tcx.node_id_to_type(e.id); self.check_heap_type(cx, e.span, ty); } @@ -799,7 +799,7 @@ declare_lint! { } struct RawPtrDeriveVisitor<'a, 'tcx: 'a> { - cx: &'a Context<'a, 'tcx> + cx: &'a LateContext<'a, 'tcx> } impl<'a, 'tcx, 'v> Visitor<'v> for RawPtrDeriveVisitor<'a, 'tcx> { @@ -832,7 +832,7 @@ impl LintPass for RawPointerDerive { lint_array!(RAW_POINTER_DERIVE) } - fn check_item(&mut self, cx: &Context, item: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { if !attr::contains_name(&item.attrs, "automatically_derived") { return; } @@ -888,7 +888,7 @@ impl LintPass for UnusedAttributes { lint_array!(UNUSED_ATTRIBUTES) } - fn check_attribute(&mut self, cx: &Context, attr: &ast::Attribute) { + fn check_attribute(&mut self, cx: &LateContext, attr: &ast::Attribute) { // Note that check_name() marks the attribute as used if it matches. for &(ref name, ty, _) in KNOWN_ATTRIBUTES { match ty { @@ -948,7 +948,7 @@ impl LintPass for PathStatements { lint_array!(PATH_STATEMENTS) } - fn check_stmt(&mut self, cx: &Context, s: &hir::Stmt) { + fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { match s.node { hir::StmtSemi(ref expr, _) => { match expr.node { @@ -982,7 +982,7 @@ impl LintPass for UnusedResults { lint_array!(UNUSED_MUST_USE, UNUSED_RESULTS) } - fn check_stmt(&mut self, cx: &Context, s: &hir::Stmt) { + fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { let expr = match s.node { hir::StmtSemi(ref expr, _) => &**expr, _ => return @@ -1015,7 +1015,7 @@ impl LintPass for UnusedResults { cx.span_lint(UNUSED_RESULTS, s.span, "unused result"); } - fn check_must_use(cx: &Context, attrs: &[ast::Attribute], sp: Span) -> bool { + fn check_must_use(cx: &LateContext, attrs: &[ast::Attribute], sp: Span) -> bool { for attr in attrs { if attr.check_name("must_use") { let mut msg = "unused result which must be used".to_string(); @@ -1046,7 +1046,7 @@ declare_lint! { pub struct NonCamelCaseTypes; impl NonCamelCaseTypes { - fn check_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) { + fn check_case(&self, cx: &LateContext, sort: &str, ident: ast::Ident, span: Span) { fn is_camel_case(ident: ast::Ident) -> bool { let ident = ident.name.as_str(); if ident.is_empty() { @@ -1088,7 +1088,7 @@ impl LintPass for NonCamelCaseTypes { lint_array!(NON_CAMEL_CASE_TYPES) } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { let extern_repr_count = it.attrs.iter().filter(|attr| { attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr).iter() .any(|r| r == &attr::ReprExtern) @@ -1119,7 +1119,7 @@ impl LintPass for NonCamelCaseTypes { } } - fn check_generics(&mut self, cx: &Context, it: &hir::Generics) { + fn check_generics(&mut self, cx: &LateContext, it: &hir::Generics) { for gen in it.ty_params.iter() { self.check_case(cx, "type parameter", gen.ident, gen.span); } @@ -1127,21 +1127,21 @@ impl LintPass for NonCamelCaseTypes { } #[derive(PartialEq)] -enum MethodContext { +enum MethodLateContext { TraitDefaultImpl, TraitImpl, PlainImpl } -fn method_context(cx: &Context, id: ast::NodeId, span: Span) -> MethodContext { +fn method_context(cx: &LateContext, id: ast::NodeId, span: Span) -> MethodLateContext { match cx.tcx.impl_or_trait_items.borrow().get(&DefId::local(id)) { None => cx.sess().span_bug(span, "missing method descriptor?!"), Some(item) => match item.container() { - ty::TraitContainer(..) => MethodContext::TraitDefaultImpl, + ty::TraitContainer(..) => MethodLateContext::TraitDefaultImpl, ty::ImplContainer(cid) => { match cx.tcx.impl_trait_ref(cid) { - Some(_) => MethodContext::TraitImpl, - None => MethodContext::PlainImpl + Some(_) => MethodLateContext::TraitImpl, + None => MethodLateContext::PlainImpl } } } @@ -1190,7 +1190,7 @@ impl NonSnakeCase { words.join("_") } - fn check_snake_case(&self, cx: &Context, sort: &str, name: &str, span: Option) { + fn check_snake_case(&self, cx: &LateContext, sort: &str, name: &str, span: Option) { fn is_snake_case(ident: &str) -> bool { if ident.is_empty() { return true; @@ -1234,7 +1234,7 @@ impl LintPass for NonSnakeCase { lint_array!(NON_SNAKE_CASE) } - fn check_crate(&mut self, cx: &Context, cr: &hir::Crate) { + fn check_crate(&mut self, cx: &LateContext, cr: &hir::Crate) { let attr_crate_name = cr.attrs.iter().find(|at| at.check_name("crate_name")) .and_then(|at| at.value_str().map(|s| (at, s))); if let Some(ref name) = cx.tcx.sess.opts.crate_name { @@ -1244,15 +1244,15 @@ impl LintPass for NonSnakeCase { } } - fn check_fn(&mut self, cx: &Context, + fn check_fn(&mut self, cx: &LateContext, fk: FnKind, _: &hir::FnDecl, _: &hir::Block, span: Span, id: ast::NodeId) { match fk { FnKind::Method(ident, _, _) => match method_context(cx, id, span) { - MethodContext::PlainImpl => { + MethodLateContext::PlainImpl => { self.check_snake_case(cx, "method", &ident.name.as_str(), Some(span)) }, - MethodContext::TraitDefaultImpl => { + MethodLateContext::TraitDefaultImpl => { self.check_snake_case(cx, "trait method", &ident.name.as_str(), Some(span)) }, _ => (), @@ -1264,25 +1264,25 @@ impl LintPass for NonSnakeCase { } } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { if let hir::ItemMod(_) = it.node { self.check_snake_case(cx, "module", &it.ident.name.as_str(), Some(it.span)); } } - fn check_trait_item(&mut self, cx: &Context, trait_item: &hir::TraitItem) { + fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) { if let hir::MethodTraitItem(_, None) = trait_item.node { self.check_snake_case(cx, "trait method", &trait_item.ident.name.as_str(), Some(trait_item.span)); } } - fn check_lifetime_def(&mut self, cx: &Context, t: &hir::LifetimeDef) { + fn check_lifetime_def(&mut self, cx: &LateContext, t: &hir::LifetimeDef) { self.check_snake_case(cx, "lifetime", &t.lifetime.name.as_str(), Some(t.lifetime.span)); } - fn check_pat(&mut self, cx: &Context, p: &hir::Pat) { + fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) { if let &hir::PatIdent(_, ref path1, _) = &p.node { let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def()); if let Some(def::DefLocal(_)) = def { @@ -1291,7 +1291,7 @@ impl LintPass for NonSnakeCase { } } - fn check_struct_def(&mut self, cx: &Context, s: &hir::StructDef, + fn check_struct_def(&mut self, cx: &LateContext, s: &hir::StructDef, _: ast::Ident, _: &hir::Generics, _: ast::NodeId) { for sf in &s.fields { if let hir::StructField_ { kind: hir::NamedField(ident, _), .. } = sf.node { @@ -1312,7 +1312,7 @@ declare_lint! { pub struct NonUpperCaseGlobals; impl NonUpperCaseGlobals { - fn check_upper_case(cx: &Context, sort: &str, ident: ast::Ident, span: Span) { + fn check_upper_case(cx: &LateContext, sort: &str, ident: ast::Ident, span: Span) { let s = ident.name.as_str(); if s.chars().any(|c| c.is_lowercase()) { @@ -1335,7 +1335,7 @@ impl LintPass for NonUpperCaseGlobals { lint_array!(NON_UPPER_CASE_GLOBALS) } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { // only check static constants hir::ItemStatic(_, hir::MutImmutable, _) => { @@ -1348,7 +1348,7 @@ impl LintPass for NonUpperCaseGlobals { } } - fn check_trait_item(&mut self, cx: &Context, ti: &hir::TraitItem) { + fn check_trait_item(&mut self, cx: &LateContext, ti: &hir::TraitItem) { match ti.node { hir::ConstTraitItem(..) => { NonUpperCaseGlobals::check_upper_case(cx, "associated constant", @@ -1358,7 +1358,7 @@ impl LintPass for NonUpperCaseGlobals { } } - fn check_impl_item(&mut self, cx: &Context, ii: &hir::ImplItem) { + fn check_impl_item(&mut self, cx: &LateContext, ii: &hir::ImplItem) { match ii.node { hir::ConstImplItem(..) => { NonUpperCaseGlobals::check_upper_case(cx, "associated constant", @@ -1368,7 +1368,7 @@ impl LintPass for NonUpperCaseGlobals { } } - fn check_pat(&mut self, cx: &Context, p: &hir::Pat) { + fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) { // Lint for constants that look like binding identifiers (#7526) match (&p.node, cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def())) { (&hir::PatIdent(_, ref path1, _), Some(def::DefConst(..))) => { @@ -1390,7 +1390,7 @@ declare_lint! { pub struct UnusedParens; impl UnusedParens { - fn check_unused_parens_core(&self, cx: &Context, value: &hir::Expr, msg: &str, + fn check_unused_parens_core(&self, cx: &LateContext, value: &hir::Expr, msg: &str, struct_lit_needs_parens: bool) { if let hir::ExprParen(ref inner) = value.node { let necessary = struct_lit_needs_parens && contains_exterior_struct_lit(&**inner); @@ -1441,7 +1441,7 @@ impl LintPass for UnusedParens { lint_array!(UNUSED_PARENS) } - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { + fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { let (value, msg, struct_lit_needs_parens) = match e.node { hir::ExprIf(ref cond, _, _) => (cond, "`if` condition", true), hir::ExprWhile(ref cond, _, _) => (cond, "`while` condition", true), @@ -1459,7 +1459,7 @@ impl LintPass for UnusedParens { self.check_unused_parens_core(cx, &**value, msg, struct_lit_needs_parens); } - fn check_stmt(&mut self, cx: &Context, s: &hir::Stmt) { + fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { let (value, msg) = match s.node { hir::StmtDecl(ref decl, _) => match decl.node { hir::DeclLocal(ref local) => match local.init { @@ -1488,7 +1488,7 @@ impl LintPass for UnusedImportBraces { lint_array!(UNUSED_IMPORT_BRACES) } - fn check_item(&mut self, cx: &Context, item: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { if let hir::ItemUse(ref view_path) = item.node { if let hir::ViewPathList(_, ref items) = view_path.node { if items.len() == 1 { @@ -1518,7 +1518,7 @@ impl LintPass for NonShorthandFieldPatterns { lint_array!(NON_SHORTHAND_FIELD_PATTERNS) } - fn check_pat(&mut self, cx: &Context, pat: &hir::Pat) { + fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) { let def_map = cx.tcx.def_map.borrow(); if let hir::PatStruct(_, ref v, _) = pat.node { let field_pats = v.iter().filter(|fieldpat| { @@ -1557,7 +1557,7 @@ impl LintPass for UnusedUnsafe { lint_array!(UNUSED_UNSAFE) } - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { + fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { if let hir::ExprBlock(ref blk) = e.node { // Don't warn about generated blocks, that'll just pollute the output. if blk.rules == hir::UnsafeBlock(hir::UserProvided) && @@ -1582,7 +1582,7 @@ impl LintPass for UnsafeCode { lint_array!(UNSAFE_CODE) } - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { + fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { if let hir::ExprBlock(ref blk) = e.node { // Don't warn about generated blocks, that'll just pollute the output. if blk.rules == hir::UnsafeBlock(hir::UserProvided) { @@ -1591,7 +1591,7 @@ impl LintPass for UnsafeCode { } } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { hir::ItemTrait(hir::Unsafety::Unsafe, _, _, _) => cx.span_lint(UNSAFE_CODE, it.span, "declaration of an `unsafe` trait"), @@ -1603,7 +1603,7 @@ impl LintPass for UnsafeCode { } } - fn check_fn(&mut self, cx: &Context, fk: FnKind, _: &hir::FnDecl, + fn check_fn(&mut self, cx: &LateContext, fk: FnKind, _: &hir::FnDecl, _: &hir::Block, span: Span, _: ast::NodeId) { match fk { FnKind::ItemFn(_, _, hir::Unsafety::Unsafe, _, _, _) => @@ -1619,7 +1619,7 @@ impl LintPass for UnsafeCode { } } - fn check_trait_item(&mut self, cx: &Context, trait_item: &hir::TraitItem) { + fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) { if let hir::MethodTraitItem(ref sig, None) = trait_item.node { if sig.unsafety == hir::Unsafety::Unsafe { cx.span_lint(UNSAFE_CODE, trait_item.span, @@ -1639,7 +1639,7 @@ declare_lint! { pub struct UnusedMut; impl UnusedMut { - fn check_unused_mut_pat(&self, cx: &Context, pats: &[P]) { + fn check_unused_mut_pat(&self, cx: &LateContext, pats: &[P]) { // collect all mutable pattern and group their NodeIDs by their Identifier to // avoid false warnings in match arms with multiple patterns @@ -1673,7 +1673,7 @@ impl LintPass for UnusedMut { lint_array!(UNUSED_MUT) } - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { + fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { if let hir::ExprMatch(_, ref arms, _) = e.node { for a in arms { self.check_unused_mut_pat(cx, &a.pats) @@ -1681,7 +1681,7 @@ impl LintPass for UnusedMut { } } - fn check_stmt(&mut self, cx: &Context, s: &hir::Stmt) { + fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { if let hir::StmtDecl(ref d, _) = s.node { if let hir::DeclLocal(ref l) = d.node { self.check_unused_mut_pat(cx, slice::ref_slice(&l.pat)); @@ -1689,7 +1689,7 @@ impl LintPass for UnusedMut { } } - fn check_fn(&mut self, cx: &Context, + fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &hir::FnDecl, _: &hir::Block, _: Span, _: ast::NodeId) { for a in &decl.inputs { @@ -1712,7 +1712,7 @@ impl LintPass for UnusedAllocation { lint_array!(UNUSED_ALLOCATION) } - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { + fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { match e.node { hir::ExprUnary(hir::UnUniq, _) => (), _ => return @@ -1774,7 +1774,7 @@ impl MissingDoc { } fn check_missing_docs_attrs(&self, - cx: &Context, + cx: &LateContext, id: Option, attrs: &[ast::Attribute], sp: Span, @@ -1817,7 +1817,7 @@ impl LintPass for MissingDoc { lint_array!(MISSING_DOCS) } - fn enter_lint_attrs(&mut self, _: &Context, attrs: &[ast::Attribute]) { + fn enter_lint_attrs(&mut self, _: &LateContext, attrs: &[ast::Attribute]) { let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| { attr.check_name("doc") && match attr.meta_item_list() { None => false, @@ -1827,26 +1827,26 @@ impl LintPass for MissingDoc { self.doc_hidden_stack.push(doc_hidden); } - fn exit_lint_attrs(&mut self, _: &Context, _: &[ast::Attribute]) { + fn exit_lint_attrs(&mut self, _: &LateContext, _: &[ast::Attribute]) { self.doc_hidden_stack.pop().expect("empty doc_hidden_stack"); } - fn check_struct_def(&mut self, _: &Context, _: &hir::StructDef, + fn check_struct_def(&mut self, _: &LateContext, _: &hir::StructDef, _: ast::Ident, _: &hir::Generics, id: ast::NodeId) { self.struct_def_stack.push(id); } - fn check_struct_def_post(&mut self, _: &Context, _: &hir::StructDef, + fn check_struct_def_post(&mut self, _: &LateContext, _: &hir::StructDef, _: ast::Ident, _: &hir::Generics, id: ast::NodeId) { let popped = self.struct_def_stack.pop().expect("empty struct_def_stack"); assert!(popped == id); } - fn check_crate(&mut self, cx: &Context, krate: &hir::Crate) { + fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) { self.check_missing_docs_attrs(cx, None, &krate.attrs, krate.span, "crate"); } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { let desc = match it.node { hir::ItemFn(..) => "a function", hir::ItemMod(..) => "a module", @@ -1886,7 +1886,7 @@ impl LintPass for MissingDoc { self.check_missing_docs_attrs(cx, Some(it.id), &it.attrs, it.span, desc); } - fn check_trait_item(&mut self, cx: &Context, trait_item: &hir::TraitItem) { + fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) { if self.private_traits.contains(&trait_item.id) { return } let desc = match trait_item.node { @@ -1900,9 +1900,9 @@ impl LintPass for MissingDoc { trait_item.span, desc); } - fn check_impl_item(&mut self, cx: &Context, impl_item: &hir::ImplItem) { + fn check_impl_item(&mut self, cx: &LateContext, impl_item: &hir::ImplItem) { // If the method is an impl for a trait, don't doc. - if method_context(cx, impl_item.id, impl_item.span) == MethodContext::TraitImpl { + if method_context(cx, impl_item.id, impl_item.span) == MethodLateContext::TraitImpl { return; } @@ -1916,7 +1916,7 @@ impl LintPass for MissingDoc { impl_item.span, desc); } - fn check_struct_field(&mut self, cx: &Context, sf: &hir::StructField) { + fn check_struct_field(&mut self, cx: &LateContext, sf: &hir::StructField) { if let hir::NamedField(_, vis) = sf.node.kind { if vis == hir::Public || self.in_variant { let cur_struct_def = *self.struct_def_stack.last() @@ -1928,13 +1928,13 @@ impl LintPass for MissingDoc { } } - fn check_variant(&mut self, cx: &Context, v: &hir::Variant, _: &hir::Generics) { + fn check_variant(&mut self, cx: &LateContext, v: &hir::Variant, _: &hir::Generics) { self.check_missing_docs_attrs(cx, Some(v.node.id), &v.node.attrs, v.span, "a variant"); assert!(!self.in_variant); self.in_variant = true; } - fn check_variant_post(&mut self, _: &Context, _: &hir::Variant, _: &hir::Generics) { + fn check_variant_post(&mut self, _: &LateContext, _: &hir::Variant, _: &hir::Generics) { assert!(self.in_variant); self.in_variant = false; } @@ -1954,7 +1954,7 @@ impl LintPass for MissingCopyImplementations { lint_array!(MISSING_COPY_IMPLEMENTATIONS) } - fn check_item(&mut self, cx: &Context, item: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { if !cx.exported_items.contains(&item.id) { return; } @@ -2016,7 +2016,7 @@ impl LintPass for MissingDebugImplementations { lint_array!(MISSING_DEBUG_IMPLEMENTATIONS) } - fn check_item(&mut self, cx: &Context, item: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { if !cx.exported_items.contains(&item.id) { return; } @@ -2066,7 +2066,7 @@ declare_lint! { pub struct Stability; impl Stability { - fn lint(&self, cx: &Context, _id: DefId, + fn lint(&self, cx: &LateContext, _id: DefId, span: Span, stability: &Option<&attr::Stability>) { // Deprecated attributes apply in-crate and cross-crate. let (lint, label) = match *stability { @@ -2077,7 +2077,7 @@ impl Stability { output(cx, span, stability, lint, label); - fn output(cx: &Context, span: Span, stability: &Option<&attr::Stability>, + fn output(cx: &LateContext, span: Span, stability: &Option<&attr::Stability>, lint: &'static Lint, label: &'static str) { let msg = match *stability { Some(&attr::Stability { reason: Some(ref s), .. }) => { @@ -2110,28 +2110,28 @@ impl LintPass for Stability { lint_array!(DEPRECATED) } - fn check_item(&mut self, cx: &Context, item: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { stability::check_item(cx.tcx, item, false, &mut |id, sp, stab| self.lint(cx, id, sp, &stab.map(|s| hir_to_ast_stability(s)).as_ref())); } - fn check_expr(&mut self, cx: &Context, e: &hir::Expr) { + fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { stability::check_expr(cx.tcx, e, &mut |id, sp, stab| self.lint(cx, id, sp, &stab.map(|s| hir_to_ast_stability(s)).as_ref())); } - fn check_path(&mut self, cx: &Context, path: &hir::Path, id: ast::NodeId) { + fn check_path(&mut self, cx: &LateContext, path: &hir::Path, id: ast::NodeId) { stability::check_path(cx.tcx, path, id, &mut |id, sp, stab| self.lint(cx, id, sp, &stab.map(|s| hir_to_ast_stability(s)).as_ref())); } - fn check_pat(&mut self, cx: &Context, pat: &hir::Pat) { + fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) { stability::check_pat(cx.tcx, pat, &mut |id, sp, stab| self.lint(cx, id, sp, @@ -2154,7 +2154,7 @@ impl LintPass for UnconditionalRecursion { lint_array![UNCONDITIONAL_RECURSION] } - fn check_fn(&mut self, cx: &Context, fn_kind: FnKind, _: &hir::FnDecl, + fn check_fn(&mut self, cx: &LateContext, fn_kind: FnKind, _: &hir::FnDecl, blk: &hir::Block, sp: Span, id: ast::NodeId) { type F = for<'tcx> fn(&ty::ctxt<'tcx>, ast::NodeId, ast::NodeId, ast::Ident, ast::NodeId) -> bool; @@ -2401,7 +2401,7 @@ impl LintPass for PluginAsLibrary { lint_array![PLUGIN_AS_LIBRARY] } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { if cx.sess().plugin_registrar_fn.get().is_some() { // We're compiling a plugin; it's fine to link other plugins. return; @@ -2457,7 +2457,7 @@ impl LintPass for InvalidNoMangleItems { NO_MANGLE_CONST_ITEMS) } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { hir::ItemFn(..) => { if attr::contains_name(&it.attrs, "no_mangle") && @@ -2503,7 +2503,7 @@ impl LintPass for MutableTransmutes { lint_array!(MUTABLE_TRANSMUTES) } - fn check_expr(&mut self, cx: &Context, expr: &hir::Expr) { + fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) { use syntax::abi::RustIntrinsic; let msg = "mutating transmuted &mut T from &T may cause undefined behavior,\ @@ -2518,7 +2518,7 @@ impl LintPass for MutableTransmutes { _ => () } - fn get_transmute_from_to<'a, 'tcx>(cx: &Context<'a, 'tcx>, expr: &hir::Expr) + fn get_transmute_from_to<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr) -> Option<(&'tcx ty::TypeVariants<'tcx>, &'tcx ty::TypeVariants<'tcx>)> { match expr.node { hir::ExprPath(..) => (), @@ -2542,7 +2542,7 @@ impl LintPass for MutableTransmutes { None } - fn def_id_is_transmute(cx: &Context, def_id: DefId) -> bool { + fn def_id_is_transmute(cx: &LateContext, def_id: DefId) -> bool { match cx.tcx.lookup_item_type(def_id).ty.sty { ty::TyBareFn(_, ref bfty) if bfty.abi == RustIntrinsic => (), _ => return false @@ -2569,7 +2569,8 @@ impl LintPass for UnstableFeatures { fn get_lints(&self) -> LintArray { lint_array!(UNSTABLE_FEATURES) } - fn check_attribute(&mut self, ctx: &Context, attr: &ast::Attribute) { + + fn check_attribute(&mut self, ctx: &LateContext, attr: &ast::Attribute) { if attr::contains_name(&[attr.node.value.clone()], "feature") { if let Some(items) = attr.node.value.meta_item_list() { for item in items { @@ -2595,7 +2596,7 @@ impl LintPass for DropWithReprExtern { fn get_lints(&self) -> LintArray { lint_array!(DROP_WITH_REPR_EXTERN) } - fn check_crate(&mut self, ctx: &Context, _: &hir::Crate) { + fn check_crate(&mut self, ctx: &LateContext, _: &hir::Crate) { for dtor_did in ctx.tcx.destructors.borrow().iter() { let (drop_impl_did, dtor_self_type) = if dtor_did.is_local() { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 63468dd55f8a9..d7238c827ab57 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -141,7 +141,6 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec, externs: Externs, driver::phase_3_run_analysis_passes(sess, hir_map, - &krate, &arenas, name, resolve::MakeGlobMap::No,