From 76856e19ff3c7c699931d0acee8e61bc0dfec512 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 10 Sep 2015 16:40:59 +1200 Subject: [PATCH 1/6] Add an early lint pass for lints that operate on the AST There is a minor [breaking-change] for lint authors - some functions which were previously defined on `lint::Context` have moved to a trait - `LintContext`, you may need to import that trait to avoid name resolution errors. --- src/librustc/lint/context.rs | 476 ++++++++++++++++++++++++++------ src/librustc/lint/mod.rs | 114 +++++--- src/librustc/plugin/registry.rs | 1 - src/librustc_driver/driver.rs | 8 +- src/librustc_driver/pretty.rs | 6 +- src/librustc_lint/builtin.rs | 169 ++++++------ src/librustdoc/core.rs | 1 - 7 files changed, 563 insertions(+), 212 deletions(-) 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, From 70c6fb91938fb15c8814b47c402dc08b79108670 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 10 Sep 2015 16:49:15 +1200 Subject: [PATCH 2/6] Change the unused parens lint to operate on the AST --- src/librustc_lint/builtin.rs | 56 ++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index c092049258c9b..ba0d41240e13b 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, LateContext, LintContext, LintPass, LintArray, Lint}; +use lint::{Level, LateContext, EarlyContext, LintContext, LintPass, LintArray, Lint}; use std::collections::HashSet; use std::collections::hash_map::Entry::{Occupied, Vacant}; @@ -1390,9 +1390,9 @@ declare_lint! { pub struct UnusedParens; impl UnusedParens { - fn check_unused_parens_core(&self, cx: &LateContext, value: &hir::Expr, msg: &str, + fn check_unused_parens_core(&self, cx: &EarlyContext, value: &ast::Expr, msg: &str, struct_lit_needs_parens: bool) { - if let hir::ExprParen(ref inner) = value.node { + if let ast::ExprParen(ref inner) = value.node { let necessary = struct_lit_needs_parens && contains_exterior_struct_lit(&**inner); if !necessary { cx.span_lint(UNUSED_PARENS, value.span, @@ -1405,27 +1405,27 @@ impl UnusedParens { /// delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo /// == X { y: 1 }` and `X { y: 1 } == foo` all do, but `(X { /// y: 1 }) == foo` does not. - fn contains_exterior_struct_lit(value: &hir::Expr) -> bool { + fn contains_exterior_struct_lit(value: &ast::Expr) -> bool { match value.node { - hir::ExprStruct(..) => true, + ast::ExprStruct(..) => true, - hir::ExprAssign(ref lhs, ref rhs) | - hir::ExprAssignOp(_, ref lhs, ref rhs) | - hir::ExprBinary(_, ref lhs, ref rhs) => { + ast::ExprAssign(ref lhs, ref rhs) | + ast::ExprAssignOp(_, ref lhs, ref rhs) | + ast::ExprBinary(_, ref lhs, ref rhs) => { // X { y: 1 } + X { y: 2 } contains_exterior_struct_lit(&**lhs) || contains_exterior_struct_lit(&**rhs) } - hir::ExprUnary(_, ref x) | - hir::ExprCast(ref x, _) | - hir::ExprField(ref x, _) | - hir::ExprTupField(ref x, _) | - hir::ExprIndex(ref x, _) => { + ast::ExprUnary(_, ref x) | + ast::ExprCast(ref x, _) | + ast::ExprField(ref x, _) | + ast::ExprTupField(ref x, _) | + ast::ExprIndex(ref x, _) => { // &X { y: 1 }, X { y: 1 }.y contains_exterior_struct_lit(&**x) } - hir::ExprMethodCall(_, _, ref exprs) => { + ast::ExprMethodCall(_, _, ref exprs) => { // X { y: 1 }.bar(...) contains_exterior_struct_lit(&*exprs[0]) } @@ -1441,28 +1441,28 @@ impl LintPass for UnusedParens { lint_array!(UNUSED_PARENS) } - fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { + fn check_ast_expr(&mut self, cx: &EarlyContext, e: &ast::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), - hir::ExprMatch(ref head, _, source) => match source { - hir::MatchSource::Normal => (head, "`match` head expression", true), - hir::MatchSource::IfLetDesugar { .. } => (head, "`if let` head expression", true), - hir::MatchSource::WhileLetDesugar => (head, "`while let` head expression", true), - hir::MatchSource::ForLoopDesugar => (head, "`for` head expression", true), + ast::ExprIf(ref cond, _, _) => (cond, "`if` condition", true), + ast::ExprWhile(ref cond, _, _) => (cond, "`while` condition", true), + ast::ExprMatch(ref head, _, source) => match source { + ast::MatchSource::Normal => (head, "`match` head expression", true), + ast::MatchSource::IfLetDesugar { .. } => (head, "`if let` head expression", true), + ast::MatchSource::WhileLetDesugar => (head, "`while let` head expression", true), + ast::MatchSource::ForLoopDesugar => (head, "`for` head expression", true), }, - hir::ExprRet(Some(ref value)) => (value, "`return` value", false), - hir::ExprAssign(_, ref value) => (value, "assigned value", false), - hir::ExprAssignOp(_, _, ref value) => (value, "assigned value", false), + ast::ExprRet(Some(ref value)) => (value, "`return` value", false), + ast::ExprAssign(_, ref value) => (value, "assigned value", false), + ast::ExprAssignOp(_, _, ref value) => (value, "assigned value", false), _ => return }; self.check_unused_parens_core(cx, &**value, msg, struct_lit_needs_parens); } - fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { + fn check_ast_stmt(&mut self, cx: &EarlyContext, s: &ast::Stmt) { let (value, msg) = match s.node { - hir::StmtDecl(ref decl, _) => match decl.node { - hir::DeclLocal(ref local) => match local.init { + ast::StmtDecl(ref decl, _) => match decl.node { + ast::DeclLocal(ref local) => match local.init { Some(ref value) => (value, "assigned value"), None => return }, From d21bfff78cd949ce72be57d3528c4f6985190feb Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Thu, 10 Sep 2015 17:17:08 +1200 Subject: [PATCH 3/6] Remove hir::ExprParen --- src/librustc/middle/cfg/construct.rs | 1 - src/librustc/middle/check_const.rs | 2 -- src/librustc/middle/const_eval.rs | 1 - src/librustc/middle/expr_use_visitor.rs | 7 ------- src/librustc/middle/liveness.rs | 7 +++---- src/librustc/middle/mem_categorization.rs | 4 ---- src/librustc/middle/region.rs | 6 ++---- src/librustc_back/svh.rs | 2 -- src/librustc_front/fold.rs | 1 - src/librustc_front/hir.rs | 3 --- src/librustc_front/lowering.rs | 4 +++- src/librustc_front/print/pprust.rs | 5 ----- src/librustc_front/visit.rs | 3 --- src/librustc_lint/builtin.rs | 3 --- src/librustc_mir/build/expr/as_constant.rs | 3 --- src/librustc_mir/build/expr/as_lvalue.rs | 3 --- src/librustc_mir/build/expr/as_operand.rs | 14 ++++---------- src/librustc_mir/build/expr/as_rvalue.rs | 3 --- src/librustc_mir/build/expr/as_temp.rs | 14 ++++---------- src/librustc_mir/build/expr/category.rs | 4 +--- src/librustc_mir/build/expr/into.rs | 3 --- src/librustc_mir/hair.rs | 1 - src/librustc_mir/tcx/expr.rs | 2 -- src/librustc_trans/trans/consts.rs | 3 --- .../trans/debuginfo/create_scope_map.rs | 3 +-- src/librustc_trans/trans/expr.rs | 11 ----------- src/librustc_typeck/check/method/confirm.rs | 1 - src/librustc_typeck/check/mod.rs | 7 ------- 28 files changed, 18 insertions(+), 103 deletions(-) diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index 3f6385ad82cc4..60aebd9cd4226 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -354,7 +354,6 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { hir::ExprAddrOf(_, ref e) | hir::ExprCast(ref e, _) | hir::ExprUnary(_, ref e) | - hir::ExprParen(ref e) | hir::ExprField(ref e, _) | hir::ExprTupField(ref e, _) => { self.straightline(expr, pred, Some(&**e).into_iter()) diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index d0451026d27ac..7da2c8f1492df 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -678,7 +678,6 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, let mut callee = &**callee; loop { callee = match callee.node { - hir::ExprParen(ref inner) => &**inner, hir::ExprBlock(ref block) => match block.expr { Some(ref tail) => &**tail, None => break @@ -763,7 +762,6 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, hir::ExprField(..) | hir::ExprTupField(..) | hir::ExprVec(_) | - hir::ExprParen(..) | hir::ExprTup(..) => {} // Conditional control flow (possible to implement). diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 11be35a24f5f7..8f5cf36278d52 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -996,7 +996,6 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>, hir::ExprLit(ref lit) => { lit_to_const(&**lit, ety) } - hir::ExprParen(ref e) => try!(eval_const_expr_partial(tcx, &**e, ty_hint)), hir::ExprBlock(ref block) => { match block.expr { Some(ref expr) => try!(eval_const_expr_partial(tcx, &**expr, ty_hint)), diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index a8fed5eab16be..c067c9b4d6313 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -362,9 +362,6 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> { let cmt = return_if_err!(self.mc.cat_expr(expr)); self.delegate.borrow(expr.id, expr.span, cmt, r, bk, cause); - // Note: Unlike consume, we can ignore ExprParen. cat_expr - // already skips over them, and walk will uncover any - // attachments or whatever. self.walk_expr(expr) } @@ -378,10 +375,6 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> { self.walk_adjustment(expr); match expr.node { - hir::ExprParen(ref subexpr) => { - self.walk_expr(&**subexpr) - } - hir::ExprPath(..) => { } hir::ExprUnary(hir::UnDeref, ref base) => { // *base diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 561760b29f19e..9bb19bb37d8e4 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -495,7 +495,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) { hir::ExprAgain(_) | hir::ExprLit(_) | hir::ExprRet(..) | hir::ExprBlock(..) | hir::ExprAssign(..) | hir::ExprAssignOp(..) | hir::ExprStruct(..) | hir::ExprRepeat(..) | - hir::ExprParen(..) | hir::ExprInlineAsm(..) | hir::ExprBox(..) | + hir::ExprInlineAsm(..) | hir::ExprBox(..) | hir::ExprRange(..) => { visit::walk_expr(ir, expr); } @@ -1161,8 +1161,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprBox(None, ref e) | hir::ExprAddrOf(_, ref e) | hir::ExprCast(ref e, _) | - hir::ExprUnary(_, ref e) | - hir::ExprParen(ref e) => { + hir::ExprUnary(_, ref e) => { self.propagate_through_expr(&**e, succ) } @@ -1435,7 +1434,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) { hir::ExprCast(..) | hir::ExprUnary(..) | hir::ExprRet(..) | hir::ExprBreak(..) | hir::ExprAgain(..) | hir::ExprLit(_) | hir::ExprBlock(..) | hir::ExprAddrOf(..) | - hir::ExprStruct(..) | hir::ExprRepeat(..) | hir::ExprParen(..) | + hir::ExprStruct(..) | hir::ExprRepeat(..) | hir::ExprClosure(..) | hir::ExprPath(..) | hir::ExprBox(..) | hir::ExprRange(..) => { visit::walk_expr(this, expr); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index dd2f48d25b4b0..2078ee2c57b8f 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -519,10 +519,6 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> { self.cat_def(expr.id, expr.span, expr_ty, def) } - hir::ExprParen(ref e) => { - self.cat_expr(&**e) - } - hir::ExprAddrOf(..) | hir::ExprCall(..) | hir::ExprAssign(..) | hir::ExprAssignOp(..) | hir::ExprClosure(..) | hir::ExprRet(..) | diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index f08cbb4143851..c26982ff5ede1 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -997,8 +997,7 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &hir::Local) { hir::ExprUnary(hir::UnUniq, ref subexpr) => { record_rvalue_scope_if_borrow_expr(visitor, &**subexpr, blk_id); } - hir::ExprCast(ref subexpr, _) | - hir::ExprParen(ref subexpr) => { + hir::ExprCast(ref subexpr, _) => { record_rvalue_scope_if_borrow_expr(visitor, &**subexpr, blk_id) } hir::ExprBlock(ref block) => { @@ -1047,8 +1046,7 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &hir::Local) { hir::ExprUnary(hir::UnDeref, ref subexpr) | hir::ExprField(ref subexpr, _) | hir::ExprTupField(ref subexpr, _) | - hir::ExprIndex(ref subexpr, _) | - hir::ExprParen(ref subexpr) => { + hir::ExprIndex(ref subexpr, _) => { expr = &**subexpr; } _ => { diff --git a/src/librustc_back/svh.rs b/src/librustc_back/svh.rs index 36fc814234d7f..7134066d08ce7 100644 --- a/src/librustc_back/svh.rs +++ b/src/librustc_back/svh.rs @@ -249,7 +249,6 @@ mod svh_visitor { SawExprInlineAsm(&'a hir::InlineAsm), SawExprStruct, SawExprRepeat, - SawExprParen, } fn saw_expr<'a>(node: &'a Expr_) -> SawExprComponent<'a> { @@ -283,7 +282,6 @@ mod svh_visitor { ExprInlineAsm(ref asm) => SawExprInlineAsm(asm), ExprStruct(..) => SawExprStruct, ExprRepeat(..) => SawExprRepeat, - ExprParen(..) => SawExprParen, } } diff --git a/src/librustc_front/fold.rs b/src/librustc_front/fold.rs index 0ff972f830f01..0693092c04a40 100644 --- a/src/librustc_front/fold.rs +++ b/src/librustc_front/fold.rs @@ -1164,7 +1164,6 @@ pub fn noop_fold_expr(Expr {id, node, span}: Expr, folder: &mut T) -> fields.move_map(|x| folder.fold_field(x)), maybe_expr.map(|x| folder.fold_expr(x))) }, - ExprParen(ex) => ExprParen(folder.fold_expr(ex)) }, span: folder.new_span(span) } diff --git a/src/librustc_front/hir.rs b/src/librustc_front/hir.rs index f329aa49daabc..8bc8bda9e066c 100644 --- a/src/librustc_front/hir.rs +++ b/src/librustc_front/hir.rs @@ -703,9 +703,6 @@ pub enum Expr_ { /// For example, `[1u8; 5]`. The first expression is the element /// to be repeated; the second is the number of times to repeat it. ExprRepeat(P, P), - - /// No-op: used solely so we can pretty-print faithfully - ExprParen(P) } /// The explicit Self type in a "qualified path". The actual diff --git a/src/librustc_front/lowering.rs b/src/librustc_front/lowering.rs index 38f9ec2c8e6bc..4f5f892043b08 100644 --- a/src/librustc_front/lowering.rs +++ b/src/librustc_front/lowering.rs @@ -810,7 +810,9 @@ pub fn lower_expr(e: &Expr) -> P { fields.iter().map(|x| lower_field(x)).collect(), maybe_expr.as_ref().map(|x| lower_expr(x))) }, - ExprParen(ref ex) => hir::ExprParen(lower_expr(ex)), + ExprParen(ref ex) => { + return lower_expr(ex); + } ExprIfLet(..) | ExprWhileLet(..) | ExprForLoop(..) | diff --git a/src/librustc_front/print/pprust.rs b/src/librustc_front/print/pprust.rs index d8d85135dd8f5..d4a52a5ed8eb0 100644 --- a/src/librustc_front/print/pprust.rs +++ b/src/librustc_front/print/pprust.rs @@ -1556,11 +1556,6 @@ impl<'a> State<'a> { try!(self.pclose()); } - hir::ExprParen(ref e) => { - try!(self.popen()); - try!(self.print_expr(&**e)); - try!(self.pclose()); - } } try!(self.ann.post(self, NodeExpr(expr))); self.end() diff --git a/src/librustc_front/visit.rs b/src/librustc_front/visit.rs index 4a3e74fd3fef7..d9b4f37411420 100644 --- a/src/librustc_front/visit.rs +++ b/src/librustc_front/visit.rs @@ -814,9 +814,6 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { ExprRet(ref optional_expression) => { walk_expr_opt(visitor, optional_expression) } - ExprParen(ref subexpression) => { - visitor.visit_expr(&**subexpression) - } ExprInlineAsm(ref ia) => { for input in &ia.inputs { let (_, ref input) = *input; diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index ba0d41240e13b..556acf44b45d1 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -154,9 +154,6 @@ impl LintPass for TypeLimits { self.negated_expr_id = expr.id; } }, - hir::ExprParen(ref expr) if self.negated_expr_id == e.id => { - self.negated_expr_id = expr.id; - }, hir::ExprBinary(binop, ref l, ref r) => { if is_comparison(binop) && !check_limits(cx.tcx, binop, &**l, &**r) { cx.span_lint(UNUSED_COMPARISONS, e.span, diff --git a/src/librustc_mir/build/expr/as_constant.rs b/src/librustc_mir/build/expr/as_constant.rs index a6d06c447a4c0..5d20fe4bab4fd 100644 --- a/src/librustc_mir/build/expr/as_constant.rs +++ b/src/librustc_mir/build/expr/as_constant.rs @@ -33,9 +33,6 @@ impl Builder { ExprKind::Scope { extent: _, value } => { return this.as_constant(value); } - ExprKind::Paren { arg } => { - return this.as_constant(arg); - } ExprKind::Literal { literal } => { ConstantKind::Literal(literal) } diff --git a/src/librustc_mir/build/expr/as_lvalue.rs b/src/librustc_mir/build/expr/as_lvalue.rs index 0ceafcc9a6266..ffbb9781bdce5 100644 --- a/src/librustc_mir/build/expr/as_lvalue.rs +++ b/src/librustc_mir/build/expr/as_lvalue.rs @@ -43,9 +43,6 @@ impl Builder { this.as_lvalue(block, value) }) } - ExprKind::Paren { arg } => { - this.as_lvalue(block, arg) - } ExprKind::Field { lhs, name } => { let lvalue = unpack!(block = this.as_lvalue(block, lhs)); let lvalue = lvalue.field(name); diff --git a/src/librustc_mir/build/expr/as_operand.rs b/src/librustc_mir/build/expr/as_operand.rs index ee090571b7cc5..0b236f3a1dcc3 100644 --- a/src/librustc_mir/build/expr/as_operand.rs +++ b/src/librustc_mir/build/expr/as_operand.rs @@ -39,16 +39,10 @@ impl Builder { block, expr); let this = self; - match expr.kind { - ExprKind::Scope { extent, value } => { - return this.in_scope(extent, block, |this| { - this.as_operand(block, value) - }); - } - ExprKind::Paren { arg } => { - return this.as_operand(block, arg); - } - _ => { } + if let ExprKind::Scope { extent, value } = expr.kind { + return this.in_scope(extent, block, |this| { + this.as_operand(block, value) + }); } let category = Category::of(&expr.kind).unwrap(); diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index e4d3ad21503ed..d03028ffea675 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -46,9 +46,6 @@ impl Builder { this.as_rvalue(block, value) }) } - ExprKind::Paren { arg } => { - this.as_rvalue(block, arg) - } ExprKind::InlineAsm { asm } => { block.and(Rvalue::InlineAsm(asm)) } diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index 50f04e0177b0b..cb652c8a5945e 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -37,16 +37,10 @@ impl Builder { block, expr); let this = self; - match expr.kind { - ExprKind::Scope { extent, value } => { - return this.in_scope(extent, block, |this| { - this.as_temp(block, value) - }); - } - ExprKind::Paren { arg } => { - return this.as_temp(block, arg); - } - _ => { } + if let ExprKind::Scope { extent, value } = expr.kind { + return this.in_scope(extent, block, |this| { + this.as_temp(block, value) + }); } let expr_ty = expr.ty.clone(); diff --git a/src/librustc_mir/build/expr/category.rs b/src/librustc_mir/build/expr/category.rs index 1f9928acdc81b..9cab2976b2c61 100644 --- a/src/librustc_mir/build/expr/category.rs +++ b/src/librustc_mir/build/expr/category.rs @@ -43,9 +43,7 @@ pub enum RvalueFunc { impl Category { pub fn of(ek: &ExprKind) -> Option { match *ek { - ExprKind::Scope { .. } | - ExprKind::Paren { .. } => - None, + ExprKind::Scope { .. } => None, ExprKind::Field { .. } | ExprKind::Deref { .. } | diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index b409903ad7eb5..72e505f2b6edd 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -40,9 +40,6 @@ impl Builder { this.into(destination, block, value) }) } - ExprKind::Paren { arg } => { - this.into(destination, block, arg) - } ExprKind::Block { body: ast_block } => { this.ast_block(destination, block, ast_block) } diff --git a/src/librustc_mir/hair.rs b/src/librustc_mir/hair.rs index c63a034833712..f1450522dd83e 100644 --- a/src/librustc_mir/hair.rs +++ b/src/librustc_mir/hair.rs @@ -171,7 +171,6 @@ pub struct Expr { #[derive(Clone, Debug)] pub enum ExprKind { Scope { extent: H::CodeExtent, value: ExprRef }, - Paren { arg: ExprRef }, // ugh. should be able to remove this! Box { place: Option>, value: ExprRef }, Call { fun: ExprRef, args: Vec> }, Deref { arg: ExprRef }, // NOT overloaded! diff --git a/src/librustc_mir/tcx/expr.rs b/src/librustc_mir/tcx/expr.rs index 350253c5b533a..7e68993b1309b 100644 --- a/src/librustc_mir/tcx/expr.rs +++ b/src/librustc_mir/tcx/expr.rs @@ -267,8 +267,6 @@ impl<'a,'tcx:'a> Mirror> for &'tcx hir::Expr { // Now comes the rote stuff: - hir::ExprParen(ref p) => - ExprKind::Paren { arg: p.to_ref() }, hir::ExprRepeat(ref v, ref c) => ExprKind::Repeat { value: v.to_ref(), count: c.to_ref() }, hir::ExprRet(ref v) => diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 0f06e3cbfa422..1d0c5137eceaa 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -703,7 +703,6 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let mut cur = sub; loop { match cur.node { - hir::ExprParen(ref sub) => cur = sub, hir::ExprBlock(ref blk) => { if let Some(ref sub) = blk.expr { cur = sub; @@ -830,7 +829,6 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let mut callee = &**callee; loop { callee = match callee.node { - hir::ExprParen(ref inner) => &**inner, hir::ExprBlock(ref block) => match block.expr { Some(ref tail) => &**tail, None => break, @@ -870,7 +868,6 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, const_fn_call(cx, MethodCallKey(method_call), method_did, &arg_vals, param_substs) }, - hir::ExprParen(ref e) => const_expr(cx, &**e, param_substs, fn_args).0, hir::ExprBlock(ref block) => { match block.expr { Some(ref expr) => const_expr(cx, &**expr, param_substs, fn_args).0, diff --git a/src/librustc_trans/trans/debuginfo/create_scope_map.rs b/src/librustc_trans/trans/debuginfo/create_scope_map.rs index ca616b5622a64..828086800499a 100644 --- a/src/librustc_trans/trans/debuginfo/create_scope_map.rs +++ b/src/librustc_trans/trans/debuginfo/create_scope_map.rs @@ -322,8 +322,7 @@ fn walk_expr(cx: &CrateContext, hir::ExprCast(ref sub_exp, _) | hir::ExprAddrOf(_, ref sub_exp) | hir::ExprField(ref sub_exp, _) | - hir::ExprTupField(ref sub_exp, _) | - hir::ExprParen(ref sub_exp) => + hir::ExprTupField(ref sub_exp, _) => walk_expr(cx, &**sub_exp, scope_stack, scope_map), hir::ExprBox(ref place, ref sub_expr) => { diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 55c833b7686d8..d8397b3c01766 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -630,9 +630,6 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let _icx = push_ctxt("trans_datum_unadjusted"); match expr.node { - hir::ExprParen(ref e) => { - trans(bcx, &**e) - } hir::ExprPath(..) => { trans_def(bcx, expr, bcx.def(expr.id)) } @@ -934,9 +931,6 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, debuginfo::set_source_location(bcx.fcx, expr.id, expr.span); match expr.node { - hir::ExprParen(ref e) => { - trans_into(bcx, &**e, Ignore) - } hir::ExprBreak(label_opt) => { controlflow::trans_break(bcx, expr, label_opt.map(|l| l.node)) } @@ -1050,9 +1044,6 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, debuginfo::set_source_location(bcx.fcx, expr.id, expr.span); match expr.node { - hir::ExprParen(ref e) => { - trans_into(bcx, &**e, dest) - } hir::ExprPath(..) => { trans_def_dps_unadjusted(bcx, expr, bcx.def(expr.id), dest) } @@ -2750,7 +2741,5 @@ fn expr_kind(tcx: &ty::ctxt, expr: &hir::Expr) -> ExprKind { ExprKind::RvalueDps } } - - hir::ExprParen(ref e) => expr_kind(tcx, &**e), } } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 572ba7a848713..abdcbf099a57a 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -468,7 +468,6 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { loop { let last = exprs[exprs.len() - 1]; match last.node { - hir::ExprParen(ref expr) | hir::ExprField(ref expr, _) | hir::ExprTupField(ref expr, _) | hir::ExprIndex(ref expr, _) | diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 51eee67df96ec..e5dbfdf176739 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3444,13 +3444,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, } fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); } - hir::ExprParen(ref a) => { - check_expr_with_expectation_and_lvalue_pref(fcx, - &**a, - expected, - lvalue_pref); - fcx.write_ty(id, fcx.expr_ty(&**a)); - } hir::ExprAssign(ref lhs, ref rhs) => { check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue); From c1084a3ada125b83c03c40b1f304f2f34abf0da0 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 11 Sep 2015 20:15:58 +1200 Subject: [PATCH 4/6] Changes to tests --- src/librustc/lint/context.rs | 4 ++-- src/librustc_driver/driver.rs | 7 +++---- src/test/auxiliary/lint_for_crate.rs | 2 +- src/test/auxiliary/lint_group_plugin_test.rs | 2 +- src/test/auxiliary/lint_plugin_test.rs | 8 ++++---- src/test/compile-fail/autoderef-full-lval.rs | 1 - src/test/compile-fail/borrow-tuple-fields.rs | 1 - src/test/compile-fail/cast-as-bool.rs | 2 +- src/test/compile-fail/dropck_arr_cycle_checked.rs | 1 - src/test/compile-fail/dropck_tarena_cycle_checked.rs | 2 -- src/test/compile-fail/dropck_tarena_unsound_drop.rs | 2 -- src/test/compile-fail/dropck_vec_cycle_checked.rs | 1 - src/test/compile-fail/for-loop-hygiene.rs | 2 -- src/test/compile-fail/issue-17283.rs | 2 ++ src/test/compile-fail/issue-23729.rs | 2 +- src/test/compile-fail/lint-visible-private-types.rs | 1 - src/test/compile-fail/loop-does-not-diverge.rs | 2 +- src/test/compile-fail/variance-trait-bounds.rs | 1 - src/test/compile-fail/variance-types.rs | 1 - .../compile-fail/vec-must-not-hide-type-from-dropck.rs | 1 - src/test/pretty/issue-4264.pp | 7 +++---- src/test/run-make/execution-engine/test.rs | 2 +- 22 files changed, 20 insertions(+), 34 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 3f1a1ed48a147..7004dac3d4f40 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -505,10 +505,10 @@ pub trait LintContext: Sized { 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. + // We want to own the lint store, so move it out of the session. Remember + // to put it back later... let lint_store = mem::replace(&mut *sess.lint_store.borrow_mut(), LintStore::new()); - EarlyContext { sess: sess, krate: krate, diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 4ec13ba35993d..ff2780918f7bd 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -129,6 +129,9 @@ pub fn compile_input(sess: Session, &ast_map.krate(), &id[..])); + time(sess.time_passes(), "early lint checks", || { + lint::check_ast_crate(&sess, &expanded_crate) + }); phase_3_run_analysis_passes(sess, ast_map, @@ -597,10 +600,6 @@ 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) } diff --git a/src/test/auxiliary/lint_for_crate.rs b/src/test/auxiliary/lint_for_crate.rs index 4c9c7f443c290..927b3e1cba988 100644 --- a/src/test/auxiliary/lint_for_crate.rs +++ b/src/test/auxiliary/lint_for_crate.rs @@ -17,7 +17,7 @@ extern crate rustc_front; extern crate syntax; -use rustc::lint::{Context, LintPass, LintPassObject, LintArray}; +use rustc::lint::{Context, LintContext, LintPass, LintPassObject, LintArray}; use rustc::plugin::Registry; use rustc_front::hir; use syntax::attr; diff --git a/src/test/auxiliary/lint_group_plugin_test.rs b/src/test/auxiliary/lint_group_plugin_test.rs index adc194fa45486..45393913578e5 100644 --- a/src/test/auxiliary/lint_group_plugin_test.rs +++ b/src/test/auxiliary/lint_group_plugin_test.rs @@ -20,7 +20,7 @@ extern crate rustc_front; extern crate rustc; use rustc_front::hir; -use rustc::lint::{Context, LintPass, LintPassObject, LintArray}; +use rustc::lint::{Context, LintContext, LintPass, LintPassObject, LintArray}; use rustc::plugin::Registry; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); diff --git a/src/test/auxiliary/lint_plugin_test.rs b/src/test/auxiliary/lint_plugin_test.rs index e6f91db230009..0dedd78abee05 100644 --- a/src/test/auxiliary/lint_plugin_test.rs +++ b/src/test/auxiliary/lint_plugin_test.rs @@ -13,15 +13,15 @@ #![feature(plugin_registrar)] #![feature(box_syntax, rustc_private)] -extern crate rustc_front; +extern crate syntax; // Load rustc as a plugin to get macros #[macro_use] extern crate rustc; -use rustc::lint::{Context, LintPass, LintPassObject, LintArray}; +use rustc::lint::{EarlyContext, LintContext, LintPass, LintPassObject, LintArray}; use rustc::plugin::Registry; -use rustc_front::hir; +use syntax::ast; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); struct Pass; @@ -31,7 +31,7 @@ impl LintPass for Pass { lint_array!(TEST_LINT) } - fn check_item(&mut self, cx: &Context, it: &hir::Item) { + fn check_ast_item(&mut self, cx: &EarlyContext, it: &ast::Item) { if it.ident.name == "lintme" { cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"); } diff --git a/src/test/compile-fail/autoderef-full-lval.rs b/src/test/compile-fail/autoderef-full-lval.rs index 2c5749e0d5d39..0d666a4920038 100644 --- a/src/test/compile-fail/autoderef-full-lval.rs +++ b/src/test/compile-fail/autoderef-full-lval.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unknown_features)] #![feature(box_syntax)] struct clam { diff --git a/src/test/compile-fail/borrow-tuple-fields.rs b/src/test/compile-fail/borrow-tuple-fields.rs index b1abbad525356..f3417fafe9037 100644 --- a/src/test/compile-fail/borrow-tuple-fields.rs +++ b/src/test/compile-fail/borrow-tuple-fields.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(unknown_features)] #![feature(box_syntax)] struct Foo(Box, isize); diff --git a/src/test/compile-fail/cast-as-bool.rs b/src/test/compile-fail/cast-as-bool.rs index 92cbbaa1cb442..52a4950022d1e 100644 --- a/src/test/compile-fail/cast-as-bool.rs +++ b/src/test/compile-fail/cast-as-bool.rs @@ -9,7 +9,7 @@ // except according to those terms. fn main() { - let u = (5 as bool); + let u = 5 as bool; //~^ ERROR cannot cast as `bool` //~^^ HELP compare with zero instead } diff --git a/src/test/compile-fail/dropck_arr_cycle_checked.rs b/src/test/compile-fail/dropck_arr_cycle_checked.rs index 19f790ddc9071..9cfeaca6dfadf 100644 --- a/src/test/compile-fail/dropck_arr_cycle_checked.rs +++ b/src/test/compile-fail/dropck_arr_cycle_checked.rs @@ -19,7 +19,6 @@ use std::cell::Cell; use id::Id; mod s { - #![allow(unstable)] use std::sync::atomic::{AtomicUsize, Ordering}; static S_COUNT: AtomicUsize = AtomicUsize::new(0); diff --git a/src/test/compile-fail/dropck_tarena_cycle_checked.rs b/src/test/compile-fail/dropck_tarena_cycle_checked.rs index 584e5eabf0cd8..d36293a484d4e 100644 --- a/src/test/compile-fail/dropck_tarena_cycle_checked.rs +++ b/src/test/compile-fail/dropck_tarena_cycle_checked.rs @@ -16,7 +16,6 @@ // which is a reduction of this code to more directly show the reason // for the error message we see here.) -#![allow(unstable)] #![feature(const_fn)] extern crate arena; @@ -26,7 +25,6 @@ use std::cell::Cell; use id::Id; mod s { - #![allow(unstable)] use std::sync::atomic::{AtomicUsize, Ordering}; static S_COUNT: AtomicUsize = AtomicUsize::new(0); diff --git a/src/test/compile-fail/dropck_tarena_unsound_drop.rs b/src/test/compile-fail/dropck_tarena_unsound_drop.rs index 7a204e6143eef..600c794109ccf 100644 --- a/src/test/compile-fail/dropck_tarena_unsound_drop.rs +++ b/src/test/compile-fail/dropck_tarena_unsound_drop.rs @@ -19,8 +19,6 @@ // (Also compare against dropck_tarena_cycle_checked.rs, from which // this was reduced to better understand its error message.) -#![allow(unstable)] - extern crate arena; use arena::TypedArena; diff --git a/src/test/compile-fail/dropck_vec_cycle_checked.rs b/src/test/compile-fail/dropck_vec_cycle_checked.rs index bc33ff8399aa5..caf25e68d568c 100644 --- a/src/test/compile-fail/dropck_vec_cycle_checked.rs +++ b/src/test/compile-fail/dropck_vec_cycle_checked.rs @@ -18,7 +18,6 @@ use std::cell::Cell; use id::Id; mod s { - #![allow(unstable)] use std::sync::atomic::{AtomicUsize, Ordering}; static S_COUNT: AtomicUsize = AtomicUsize::new(0); diff --git a/src/test/compile-fail/for-loop-hygiene.rs b/src/test/compile-fail/for-loop-hygiene.rs index ff6f848ab598d..f06882875fd9b 100644 --- a/src/test/compile-fail/for-loop-hygiene.rs +++ b/src/test/compile-fail/for-loop-hygiene.rs @@ -11,8 +11,6 @@ // for-loops are expanded in the front end, and use an `iter` ident in their expansion. Check that // `iter` is not accessible inside the for loop. -#![allow(unstable)] - fn main() { for _ in 0..10 { iter.next(); //~ error: unresolved name `iter` diff --git a/src/test/compile-fail/issue-17283.rs b/src/test/compile-fail/issue-17283.rs index a481fec6bf968..c7d6443663241 100644 --- a/src/test/compile-fail/issue-17283.rs +++ b/src/test/compile-fail/issue-17283.rs @@ -11,6 +11,8 @@ // Test that the parser does not attempt to parse struct literals // within assignments in if expressions. +#![allow(unused_parens)] + struct Foo { foo: usize } diff --git a/src/test/compile-fail/issue-23729.rs b/src/test/compile-fail/issue-23729.rs index 3d77d171acebf..f98cf6575d6ec 100644 --- a/src/test/compile-fail/issue-23729.rs +++ b/src/test/compile-fail/issue-23729.rs @@ -26,7 +26,7 @@ fn main() { self.pos += 1; Some(next_val) } else { - let next_val = (self.mem[0] + self.mem[1]); + let next_val = self.mem[0] + self.mem[1]; self.mem[0] = self.mem[1]; self.mem[1] = next_val; Some(next_val) diff --git a/src/test/compile-fail/lint-visible-private-types.rs b/src/test/compile-fail/lint-visible-private-types.rs index c6dc3b70bef37..d34738282eb26 100644 --- a/src/test/compile-fail/lint-visible-private-types.rs +++ b/src/test/compile-fail/lint-visible-private-types.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![deny(visible_private_types)] #![allow(dead_code)] #![crate_type="lib"] diff --git a/src/test/compile-fail/loop-does-not-diverge.rs b/src/test/compile-fail/loop-does-not-diverge.rs index 12de4a714efc5..cd320ba148aba 100644 --- a/src/test/compile-fail/loop-does-not-diverge.rs +++ b/src/test/compile-fail/loop-does-not-diverge.rs @@ -18,5 +18,5 @@ fn forever() -> ! { } fn main() { - if (1 == 2) { forever(); } + if 1 == 2 { forever(); } } diff --git a/src/test/compile-fail/variance-trait-bounds.rs b/src/test/compile-fail/variance-trait-bounds.rs index 222d8338aa2c4..b6f197987bab1 100644 --- a/src/test/compile-fail/variance-trait-bounds.rs +++ b/src/test/compile-fail/variance-trait-bounds.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![deny(bivariance)] #![allow(dead_code)] #![feature(rustc_attrs)] diff --git a/src/test/compile-fail/variance-types.rs b/src/test/compile-fail/variance-types.rs index e407ebe345a5b..2fd8bf20c7997 100644 --- a/src/test/compile-fail/variance-types.rs +++ b/src/test/compile-fail/variance-types.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![deny(bivariance)] #![allow(dead_code)] #![feature(rustc_attrs)] diff --git a/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs b/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs index 375289596841d..c8f4326bb2824 100644 --- a/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs +++ b/src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs @@ -29,7 +29,6 @@ use std::cell::Cell; use id::Id; mod s { - #![allow(unstable)] use std::sync::atomic::{AtomicUsize, Ordering}; static S_COUNT: AtomicUsize = AtomicUsize::new(0); diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index 6398c76d0a351..835f7fc96c63f 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -27,10 +27,9 @@ let _: [(); (1 as usize)] = ([(() as ())] as [(); 1]); let _ = - (((&((([(1 as i32), (2 as i32), (3 as i32)] as [i32; 3])) as [i32; 3]) - as &[i32; 3]) as *const _ as *const [i32; 3]) as - *const [i32; (3 as usize)] as *const [i32; 3]); - + (((&([(1 as i32), (2 as i32), (3 as i32)] as [i32; 3]) as &[i32; 3]) + as *const _ as *const [i32; 3]) as *const [i32; (3 as usize)] as + *const [i32; 3]); diff --git a/src/test/run-make/execution-engine/test.rs b/src/test/run-make/execution-engine/test.rs index a7c6f5225a652..6fc12d3a75078 100644 --- a/src/test/run-make/execution-engine/test.rs +++ b/src/test/run-make/execution-engine/test.rs @@ -228,7 +228,7 @@ fn compile_program(input: &str, sysroot: PathBuf) let ast_map = driver::make_map(&sess, &mut hir_forest); driver::phase_3_run_analysis_passes( - sess, ast_map, &krate, &arenas, id, MakeGlobMap::No, |tcx, analysis| { + sess, ast_map, &arenas, id, MakeGlobMap::No, |tcx, analysis| { let trans = driver::phase_4_translate_to_llvm(tcx, analysis); From a642d853aa29f8ec8486e736be551cf77f34e219 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 15 Sep 2015 11:35:25 +1200 Subject: [PATCH 5/6] Change to a multi-trait approach [breaking-change] for lint authors You must now implement LateLintPass or EarlyLintPass as well as LintPass and use either register_late_lint_pass or register_early_lint_pass, rather than register_lint_pass. --- src/librustc/lint/builtin.rs | 4 +- src/librustc/lint/context.rs | 167 +++++++++++-------- src/librustc/lint/mod.rs | 106 ++++++------ src/librustc/plugin/registry.rs | 18 +- src/librustc_driver/driver.rs | 9 +- src/librustc_lint/builtin.rs | 64 ++++++- src/librustc_lint/lib.rs | 19 ++- src/test/auxiliary/lint_for_crate.rs | 8 +- src/test/auxiliary/lint_group_plugin_test.rs | 8 +- src/test/auxiliary/lint_plugin_test.rs | 9 +- src/test/compile-fail/issue-23046.rs | 4 +- 11 files changed, 266 insertions(+), 150 deletions(-) diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 495044f945949..d9b05d804000a 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -14,7 +14,7 @@ //! compiler code, rather than using their own custom pass. Those //! lints are all available in `rustc_lint::builtin`. -use lint::{LintPass, LintArray}; +use lint::{LintPass, LateLintPass, LintArray}; declare_lint! { pub UNUSED_IMPORTS, @@ -138,3 +138,5 @@ impl LintPass for HardwiredLints { ) } } + +impl LateLintPass for HardwiredLints {} diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 7004dac3d4f40..fe88401a24c20 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -28,7 +28,8 @@ use self::TargetLint::*; use middle::privacy::ExportedItems; use middle::ty::{self, Ty}; use session::{early_error, Session}; -use lint::{Level, LevelSource, Lint, LintId, LintArray, LintPass, LintPassObject}; +use lint::{Level, LevelSource, Lint, LintId, LintArray, LintPass}; +use lint::{EarlyLintPass, EarlyLintPassObject, LateLintPass, LateLintPassObject}; use lint::{Default, CommandLine, Node, Allow, Warn, Deny, Forbid}; use lint::builtin; use util::nodemap::FnvHashMap; @@ -59,7 +60,8 @@ pub struct LintStore { /// Trait objects for each lint pass. /// This is only `None` while iterating over the objects. See the definition /// of run_lints. - passes: Option>, + early_passes: Option>, + late_passes: Option>, /// Lints indexed by name. by_name: FnvHashMap, @@ -115,7 +117,8 @@ impl LintStore { pub fn new() -> LintStore { LintStore { lints: vec!(), - passes: Some(vec!()), + early_passes: Some(vec!()), + late_passes: Some(vec!()), by_name: FnvHashMap(), levels: FnvHashMap(), lint_groups: FnvHashMap(), @@ -133,8 +136,27 @@ impl LintStore { v.1)).collect() } - pub fn register_pass(&mut self, sess: Option<&Session>, - from_plugin: bool, pass: LintPassObject) { + pub fn register_early_pass(&mut self, + sess: Option<&Session>, + from_plugin: bool, + pass: EarlyLintPassObject) { + self.push_pass(sess, from_plugin, &pass); + self.early_passes.as_mut().unwrap().push(pass); + } + + pub fn register_late_pass(&mut self, + sess: Option<&Session>, + from_plugin: bool, + pass: LateLintPassObject) { + self.push_pass(sess, from_plugin, &pass); + self.late_passes.as_mut().unwrap().push(pass); + } + + // Helper method for register_early/late_pass + fn push_pass(&mut self, + sess: Option<&Session>, + from_plugin: bool, + pass: &Box

) { for &lint in pass.get_lints() { self.lints.push((*lint, from_plugin)); @@ -156,7 +178,6 @@ impl LintStore { self.levels.insert(id, (lint.default_level, Default)); } } - self.passes.as_mut().unwrap().push(pass); } pub fn register_group(&mut self, sess: Option<&Session>, @@ -272,8 +293,6 @@ pub struct LateContext<'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> { @@ -293,14 +312,14 @@ pub struct EarlyContext<'a> { } /// Convenience macro for calling a `LintPass` method on every pass in the context. -macro_rules! run_lints { ($cx:expr, $f:ident, $($args:expr),*) => ({ +macro_rules! run_lints { ($cx:expr, $f:ident, $ps: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.mut_lints().passes.take().unwrap(); + let mut passes = $cx.mut_lints().$ps.take().unwrap(); for obj in &mut passes { obj.$f($cx, $($args),*); } - $cx.mut_lints().passes = Some(passes); + $cx.mut_lints().$ps = Some(passes); }) } /// Parse the lint attributes into a vector, with `Err`s for malformed lint @@ -578,11 +597,11 @@ impl<'a, 'tcx> LintContext for LateContext<'a, 'tcx> { } fn enter_attrs(&mut self, attrs: &[hir::Attribute]) { - run_lints!(self, enter_lint_attrs, attrs); + run_lints!(self, enter_lint_attrs, late_passes, attrs); } fn exit_attrs(&mut self, attrs: &[hir::Attribute]) { - run_lints!(self, exit_lint_attrs, attrs); + run_lints!(self, exit_lint_attrs, late_passes, attrs); } } @@ -605,18 +624,18 @@ impl<'a> LintContext for EarlyContext<'a> { } fn enter_attrs(&mut self, attrs: &[hir::Attribute]) { - run_lints!(self, ast_enter_lint_attrs, attrs); + run_lints!(self, enter_lint_attrs, early_passes, attrs); } fn exit_attrs(&mut self, attrs: &[hir::Attribute]) { - run_lints!(self, ast_exit_lint_attrs, attrs); + run_lints!(self, exit_lint_attrs, early_passes, 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); + run_lints!(cx, check_item, late_passes, it); cx.visit_ids(|v| v.visit_item(it)); hir_visit::walk_item(cx, it); }) @@ -624,29 +643,29 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> { fn visit_foreign_item(&mut self, it: &hir::ForeignItem) { self.with_lint_attrs(&it.attrs, |cx| { - run_lints!(cx, check_foreign_item, it); + run_lints!(cx, check_foreign_item, late_passes, it); hir_visit::walk_foreign_item(cx, it); }) } fn visit_pat(&mut self, p: &hir::Pat) { - run_lints!(self, check_pat, p); + run_lints!(self, check_pat, late_passes, p); hir_visit::walk_pat(self, p); } fn visit_expr(&mut self, e: &hir::Expr) { - run_lints!(self, check_expr, e); + run_lints!(self, check_expr, late_passes, e); hir_visit::walk_expr(self, e); } fn visit_stmt(&mut self, s: &hir::Stmt) { - run_lints!(self, check_stmt, s); + run_lints!(self, check_stmt, late_passes, s); hir_visit::walk_stmt(self, s); } 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); + run_lints!(self, check_fn, late_passes, fk, decl, body, span, id); hir_visit::walk_fn(self, fk, decl, body, span); } @@ -655,72 +674,72 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> { ident: ast::Ident, g: &hir::Generics, id: ast::NodeId) { - run_lints!(self, check_struct_def, s, ident, g, id); + run_lints!(self, check_struct_def, late_passes, s, ident, g, id); hir_visit::walk_struct_def(self, s); - run_lints!(self, check_struct_def_post, s, ident, g, id); + run_lints!(self, check_struct_def_post, late_passes, 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); + run_lints!(cx, check_struct_field, late_passes, 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); + run_lints!(cx, check_variant, late_passes, v, g); hir_visit::walk_variant(cx, v, g); - run_lints!(cx, check_variant_post, v, g); + run_lints!(cx, check_variant_post, late_passes, v, g); }) } fn visit_ty(&mut self, t: &hir::Ty) { - run_lints!(self, check_ty, t); + run_lints!(self, check_ty, late_passes, t); hir_visit::walk_ty(self, t); } fn visit_ident(&mut self, sp: Span, id: ast::Ident) { - run_lints!(self, check_ident, sp, id); + run_lints!(self, check_ident, late_passes, sp, id); } fn visit_mod(&mut self, m: &hir::Mod, s: Span, n: ast::NodeId) { - run_lints!(self, check_mod, m, s, n); + run_lints!(self, check_mod, late_passes, m, s, n); hir_visit::walk_mod(self, m); } fn visit_local(&mut self, l: &hir::Local) { - run_lints!(self, check_local, l); + run_lints!(self, check_local, late_passes, l); hir_visit::walk_local(self, l); } fn visit_block(&mut self, b: &hir::Block) { - run_lints!(self, check_block, b); + run_lints!(self, check_block, late_passes, b); hir_visit::walk_block(self, b); } fn visit_arm(&mut self, a: &hir::Arm) { - run_lints!(self, check_arm, a); + run_lints!(self, check_arm, late_passes, a); hir_visit::walk_arm(self, a); } fn visit_decl(&mut self, d: &hir::Decl) { - run_lints!(self, check_decl, d); + run_lints!(self, check_decl, late_passes, d); hir_visit::walk_decl(self, d); } fn visit_expr_post(&mut self, e: &hir::Expr) { - run_lints!(self, check_expr_post, e); + run_lints!(self, check_expr_post, late_passes, e); } fn visit_generics(&mut self, g: &hir::Generics) { - run_lints!(self, check_generics, g); + run_lints!(self, check_generics, late_passes, 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); + run_lints!(cx, check_trait_item, late_passes, trait_item); cx.visit_ids(|v| v.visit_trait_item(trait_item)); hir_visit::walk_trait_item(cx, trait_item); }); @@ -728,43 +747,43 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> { fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) { self.with_lint_attrs(&impl_item.attrs, |cx| { - run_lints!(cx, check_impl_item, impl_item); + run_lints!(cx, check_impl_item, late_passes, impl_item); cx.visit_ids(|v| v.visit_impl_item(impl_item)); hir_visit::walk_impl_item(cx, impl_item); }); } fn visit_opt_lifetime_ref(&mut self, sp: Span, lt: &Option) { - run_lints!(self, check_opt_lifetime_ref, sp, lt); + run_lints!(self, check_opt_lifetime_ref, late_passes, sp, lt); } fn visit_lifetime_ref(&mut self, lt: &hir::Lifetime) { - run_lints!(self, check_lifetime_ref, lt); + run_lints!(self, check_lifetime_ref, late_passes, lt); } fn visit_lifetime_def(&mut self, lt: &hir::LifetimeDef) { - run_lints!(self, check_lifetime_def, lt); + run_lints!(self, check_lifetime_def, late_passes, lt); } fn visit_explicit_self(&mut self, es: &hir::ExplicitSelf) { - run_lints!(self, check_explicit_self, es); + run_lints!(self, check_explicit_self, late_passes, 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); + run_lints!(self, check_path, late_passes, p, id); hir_visit::walk_path(self, p); } fn visit_attribute(&mut self, attr: &ast::Attribute) { - run_lints!(self, check_attribute, attr); + run_lints!(self, check_attribute, late_passes, attr); } } 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); + run_lints!(cx, check_item, early_passes, it); cx.visit_ids(|v| v.visit_item(it)); ast_visit::walk_item(cx, it); }) @@ -772,29 +791,29 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> { 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); + run_lints!(cx, check_foreign_item, early_passes, it); ast_visit::walk_foreign_item(cx, it); }) } fn visit_pat(&mut self, p: &ast::Pat) { - run_lints!(self, check_ast_pat, p); + run_lints!(self, check_pat, early_passes, p); ast_visit::walk_pat(self, p); } fn visit_expr(&mut self, e: &ast::Expr) { - run_lints!(self, check_ast_expr, e); + run_lints!(self, check_expr, early_passes, e); ast_visit::walk_expr(self, e); } fn visit_stmt(&mut self, s: &ast::Stmt) { - run_lints!(self, check_ast_stmt, s); + run_lints!(self, check_stmt, early_passes, 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); + run_lints!(self, check_fn, early_passes, fk, decl, body, span, id); ast_visit::walk_fn(self, fk, decl, body, span); } @@ -803,72 +822,72 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> { ident: ast::Ident, g: &ast::Generics, id: ast::NodeId) { - run_lints!(self, check_ast_struct_def, s, ident, g, id); + run_lints!(self, check_struct_def, early_passes, s, ident, g, id); ast_visit::walk_struct_def(self, s); - run_lints!(self, check_ast_struct_def_post, s, ident, g, id); + run_lints!(self, check_struct_def_post, early_passes, 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); + run_lints!(cx, check_struct_field, early_passes, 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); + run_lints!(cx, check_variant, early_passes, v, g); ast_visit::walk_variant(cx, v, g); - run_lints!(cx, check_ast_variant_post, v, g); + run_lints!(cx, check_variant_post, early_passes, v, g); }) } fn visit_ty(&mut self, t: &ast::Ty) { - run_lints!(self, check_ast_ty, t); + run_lints!(self, check_ty, early_passes, 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); + run_lints!(self, check_ident, early_passes, sp, id); } fn visit_mod(&mut self, m: &ast::Mod, s: Span, n: ast::NodeId) { - run_lints!(self, check_ast_mod, m, s, n); + run_lints!(self, check_mod, early_passes, m, s, n); ast_visit::walk_mod(self, m); } fn visit_local(&mut self, l: &ast::Local) { - run_lints!(self, check_ast_local, l); + run_lints!(self, check_local, early_passes, l); ast_visit::walk_local(self, l); } fn visit_block(&mut self, b: &ast::Block) { - run_lints!(self, check_ast_block, b); + run_lints!(self, check_block, early_passes, b); ast_visit::walk_block(self, b); } fn visit_arm(&mut self, a: &ast::Arm) { - run_lints!(self, check_ast_arm, a); + run_lints!(self, check_arm, early_passes, a); ast_visit::walk_arm(self, a); } fn visit_decl(&mut self, d: &ast::Decl) { - run_lints!(self, check_ast_decl, d); + run_lints!(self, check_decl, early_passes, d); ast_visit::walk_decl(self, d); } fn visit_expr_post(&mut self, e: &ast::Expr) { - run_lints!(self, check_ast_expr_post, e); + run_lints!(self, check_expr_post, early_passes, e); } fn visit_generics(&mut self, g: &ast::Generics) { - run_lints!(self, check_ast_generics, g); + run_lints!(self, check_generics, early_passes, 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); + run_lints!(cx, check_trait_item, early_passes, trait_item); cx.visit_ids(|v| v.visit_trait_item(trait_item)); ast_visit::walk_trait_item(cx, trait_item); }); @@ -876,36 +895,36 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> { 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); + run_lints!(cx, check_impl_item, early_passes, 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); + run_lints!(self, check_opt_lifetime_ref, early_passes, sp, lt); } fn visit_lifetime_ref(&mut self, lt: &ast::Lifetime) { - run_lints!(self, check_ast_lifetime_ref, lt); + run_lints!(self, check_lifetime_ref, early_passes, lt); } fn visit_lifetime_def(&mut self, lt: &ast::LifetimeDef) { - run_lints!(self, check_ast_lifetime_def, lt); + run_lints!(self, check_lifetime_def, early_passes, lt); } fn visit_explicit_self(&mut self, es: &ast::ExplicitSelf) { - run_lints!(self, check_ast_explicit_self, es); + run_lints!(self, check_explicit_self, early_passes, 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); + run_lints!(self, check_path, early_passes, p, id); ast_visit::walk_path(self, p); } fn visit_attribute(&mut self, attr: &ast::Attribute) { - run_lints!(self, check_ast_attribute, attr); + run_lints!(self, check_attribute, early_passes, attr); } } @@ -946,7 +965,9 @@ impl LintPass for GatherNodeLevels { fn get_lints(&self) -> LintArray { lint_array!() } +} +impl LateLintPass for GatherNodeLevels { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { hir::ItemEnum(..) => { @@ -984,7 +1005,7 @@ pub fn check_crate(tcx: &ty::ctxt, // 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); + run_lints!(cx, check_crate, late_passes, krate); hir_visit::walk_crate(cx, krate); }); @@ -1015,7 +1036,7 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) { // 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); + run_lints!(cx, check_crate, early_passes, krate); ast_visit::walk_crate(cx, krate); }); diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index d30f8f3c53ad2..e52b6e91f68cd 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -39,7 +39,7 @@ use syntax::visit as ast_visit; use syntax::ast; use rustc_front::hir; -pub use lint::context::{LateContext, EarlyContext, Context, LintContext, LintStore, +pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore, raw_emit_lint, check_crate, check_ast_crate, gather_attrs, GatherNodeLevels}; @@ -111,14 +111,6 @@ macro_rules! lint_array { ($( $lint:expr ),*) => ( pub type LintArray = &'static [&'static &'static Lint]; -/// Trait for types providing lint checks. -/// -/// Each `check` method checks a single syntax node, and should not -/// invoke methods recursively (unlike `Visitor`). By default they -/// do nothing. -// -// FIXME: eliminate the duplication with `Visitor`. But this also -// contains a few lint-specific methods with no equivalent in `Visitor`. pub trait LintPass { /// Get descriptions of the lints this `LintPass` object can emit. /// @@ -127,7 +119,18 @@ pub trait LintPass { /// parts of the compiler. If you want enforced access restrictions for your /// `Lint`, make it a private `static` item in its own module. fn get_lints(&self) -> LintArray; +} + +/// Trait for types providing lint checks. +/// +/// Each `check` method checks a single syntax node, and should not +/// invoke methods recursively (unlike `Visitor`). By default they +/// do nothing. +// +// FIXME: eliminate the duplication with `Visitor`. But this also +// contains a few lint-specific methods with no equivalent in `Visitor`. +pub trait LateLintPass: LintPass { 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) { } @@ -164,60 +167,63 @@ pub trait LintPass { 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, _: &LateContext, _: &[ast::Attribute]) { } /// Counterpart to `enter_lint_attrs`. fn exit_lint_attrs(&mut self, _: &LateContext, _: &[ast::Attribute]) { } +} + +pub trait EarlyLintPass: LintPass { + fn check_ident(&mut self, _: &EarlyContext, _: Span, _: ast::Ident) { } + fn check_crate(&mut self, _: &EarlyContext, _: &ast::Crate) { } + fn check_mod(&mut self, _: &EarlyContext, _: &ast::Mod, _: Span, _: ast::NodeId) { } + fn check_foreign_item(&mut self, _: &EarlyContext, _: &ast::ForeignItem) { } + fn check_item(&mut self, _: &EarlyContext, _: &ast::Item) { } + fn check_local(&mut self, _: &EarlyContext, _: &ast::Local) { } + fn check_block(&mut self, _: &EarlyContext, _: &ast::Block) { } + fn check_stmt(&mut self, _: &EarlyContext, _: &ast::Stmt) { } + fn check_arm(&mut self, _: &EarlyContext, _: &ast::Arm) { } + fn check_pat(&mut self, _: &EarlyContext, _: &ast::Pat) { } + fn check_decl(&mut self, _: &EarlyContext, _: &ast::Decl) { } + fn check_expr(&mut self, _: &EarlyContext, _: &ast::Expr) { } + fn check_expr_post(&mut self, _: &EarlyContext, _: &ast::Expr) { } + fn check_ty(&mut self, _: &EarlyContext, _: &ast::Ty) { } + fn check_generics(&mut self, _: &EarlyContext, _: &ast::Generics) { } + fn check_fn(&mut self, _: &EarlyContext, + _: ast_visit::FnKind, _: &ast::FnDecl, _: &ast::Block, _: Span, _: ast::NodeId) { } + fn check_trait_item(&mut self, _: &EarlyContext, _: &ast::TraitItem) { } + fn check_impl_item(&mut self, _: &EarlyContext, _: &ast::ImplItem) { } + fn check_struct_def(&mut self, _: &EarlyContext, + _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { } + fn check_struct_def_post(&mut self, _: &EarlyContext, + _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { } + fn check_struct_field(&mut self, _: &EarlyContext, _: &ast::StructField) { } + fn check_variant(&mut self, _: &EarlyContext, _: &ast::Variant, _: &ast::Generics) { } + fn check_variant_post(&mut self, _: &EarlyContext, _: &ast::Variant, _: &ast::Generics) { } + fn check_opt_lifetime_ref(&mut self, + _: &EarlyContext, + _: Span, + _: &Option) { } + fn check_lifetime_ref(&mut self, _: &EarlyContext, _: &ast::Lifetime) { } + fn check_lifetime_def(&mut self, _: &EarlyContext, _: &ast::LifetimeDef) { } + fn check_explicit_self(&mut self, _: &EarlyContext, _: &ast::ExplicitSelf) { } + fn check_mac(&mut self, _: &EarlyContext, _: &ast::Mac) { } + fn check_path(&mut self, _: &EarlyContext, _: &ast::Path, _: ast::NodeId) { } + fn check_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 ast_enter_lint_attrs(&mut self, _: &EarlyContext, _: &[ast::Attribute]) { } + fn enter_lint_attrs(&mut self, _: &EarlyContext, _: &[ast::Attribute]) { } - /// Counterpart to `ast_enter_lint_attrs`. - fn ast_exit_lint_attrs(&mut self, _: &EarlyContext, _: &[ast::Attribute]) { } + /// Counterpart to `enter_lint_attrs`. + fn exit_lint_attrs(&mut self, _: &EarlyContext, _: &[ast::Attribute]) { } } /// A lint pass boxed up as a trait object. -pub type LintPassObject = Box; +pub type EarlyLintPassObject = Box; +pub type LateLintPassObject = Box; /// Identifies a lint known to the compiler. #[derive(Clone, Copy)] diff --git a/src/librustc/plugin/registry.rs b/src/librustc/plugin/registry.rs index ca7ce2308a1cb..50ca092dfe64e 100644 --- a/src/librustc/plugin/registry.rs +++ b/src/librustc/plugin/registry.rs @@ -10,7 +10,7 @@ //! Used by plugin crates to tell `rustc` about the plugins they provide. -use lint::{LintPassObject, LintId, Lint}; +use lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint}; use session::Session; use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT}; @@ -48,7 +48,10 @@ pub struct Registry<'a> { pub syntax_exts: Vec, #[doc(hidden)] - pub lint_passes: Vec, + pub early_lint_passes: Vec, + + #[doc(hidden)] + pub late_lint_passes: Vec, #[doc(hidden)] pub lint_groups: HashMap<&'static str, Vec>, @@ -68,7 +71,8 @@ impl<'a> Registry<'a> { args_hidden: None, krate_span: krate.span, syntax_exts: vec!(), - lint_passes: vec!(), + early_lint_passes: vec!(), + late_lint_passes: vec!(), lint_groups: HashMap::new(), llvm_passes: vec!(), attributes: vec!(), @@ -117,10 +121,14 @@ impl<'a> Registry<'a> { } /// Register a compiler lint pass. - pub fn register_lint_pass(&mut self, lint_pass: LintPassObject) { - self.lint_passes.push(lint_pass); + pub fn register_early_lint_pass(&mut self, lint_pass: EarlyLintPassObject) { + self.early_lint_passes.push(lint_pass); } + /// Register a compiler lint pass. + pub fn register_late_lint_pass(&mut self, lint_pass: LateLintPassObject) { + self.late_lint_passes.push(lint_pass); + } /// Register a lint group. pub fn register_lint_group(&mut self, name: &'static str, to: Vec<&'static Lint>) { self.lint_groups.insert(name, to.into_iter().map(|x| LintId::of(x)).collect()); diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index ff2780918f7bd..ec5ceadd0662c 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -482,13 +482,16 @@ pub fn phase_2_configure_and_expand(sess: &Session, } }); - let Registry { syntax_exts, lint_passes, lint_groups, + let Registry { syntax_exts, early_lint_passes, late_lint_passes, lint_groups, llvm_passes, attributes, .. } = registry; { let mut ls = sess.lint_store.borrow_mut(); - for pass in lint_passes { - ls.register_pass(Some(sess), true, pass); + for pass in early_lint_passes { + ls.register_early_pass(Some(sess), true, pass); + } + for pass in late_lint_passes { + ls.register_late_pass(Some(sess), true, pass); } for (name, to) in lint_groups { diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 556acf44b45d1..394bd2abc08c7 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -38,7 +38,8 @@ 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, LateContext, EarlyContext, LintContext, LintPass, LintArray, Lint}; +use lint::{Level, LateContext, EarlyContext, LintContext, LintArray, Lint}; +use lint::{LintPass, EarlyLintPass, LateLintPass}; use std::collections::HashSet; use std::collections::hash_map::Entry::{Occupied, Vacant}; @@ -72,7 +73,9 @@ impl LintPass for WhileTrue { fn get_lints(&self) -> LintArray { lint_array!(WHILE_TRUE) } +} +impl LateLintPass for WhileTrue { 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 { @@ -121,7 +124,9 @@ impl LintPass for TypeLimits { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_COMPARISONS, OVERFLOWING_LITERALS, EXCEEDING_BITSHIFTS) } +} +impl LateLintPass for TypeLimits { fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { match e.node { hir::ExprUnary(hir::UnNeg, ref expr) => { @@ -699,7 +704,9 @@ impl LintPass for ImproperCTypes { fn get_lints(&self) -> LintArray { lint_array!(IMPROPER_CTYPES) } +} +impl LateLintPass for ImproperCTypes { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { fn check_ty(cx: &LateContext, ty: &hir::Ty) { let mut vis = ImproperCTypesVisitor { cx: cx }; @@ -759,7 +766,9 @@ impl LintPass for BoxPointers { fn get_lints(&self) -> LintArray { lint_array!(BOX_POINTERS) } +} +impl LateLintPass for BoxPointers { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { hir::ItemFn(..) | @@ -828,7 +837,9 @@ impl LintPass for RawPointerDerive { fn get_lints(&self) -> LintArray { lint_array!(RAW_POINTER_DERIVE) } +} +impl LateLintPass for RawPointerDerive { fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { if !attr::contains_name(&item.attrs, "automatically_derived") { return; @@ -884,7 +895,9 @@ impl LintPass for UnusedAttributes { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_ATTRIBUTES) } +} +impl LateLintPass for UnusedAttributes { 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 { @@ -944,7 +957,9 @@ impl LintPass for PathStatements { fn get_lints(&self) -> LintArray { lint_array!(PATH_STATEMENTS) } +} +impl LateLintPass for PathStatements { fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { match s.node { hir::StmtSemi(ref expr, _) => { @@ -978,7 +993,9 @@ impl LintPass for UnusedResults { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_MUST_USE, UNUSED_RESULTS) } +} +impl LateLintPass for UnusedResults { fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) { let expr = match s.node { hir::StmtSemi(ref expr, _) => &**expr, @@ -1084,7 +1101,9 @@ impl LintPass for NonCamelCaseTypes { fn get_lints(&self) -> LintArray { lint_array!(NON_CAMEL_CASE_TYPES) } +} +impl LateLintPass for NonCamelCaseTypes { 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() @@ -1230,7 +1249,9 @@ impl LintPass for NonSnakeCase { fn get_lints(&self) -> LintArray { lint_array!(NON_SNAKE_CASE) } +} +impl LateLintPass for NonSnakeCase { 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))); @@ -1331,7 +1352,9 @@ impl LintPass for NonUpperCaseGlobals { fn get_lints(&self) -> LintArray { lint_array!(NON_UPPER_CASE_GLOBALS) } +} +impl LateLintPass for NonUpperCaseGlobals { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { // only check static constants @@ -1437,8 +1460,10 @@ impl LintPass for UnusedParens { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_PARENS) } +} - fn check_ast_expr(&mut self, cx: &EarlyContext, e: &ast::Expr) { +impl EarlyLintPass for UnusedParens { + fn check_expr(&mut self, cx: &EarlyContext, e: &ast::Expr) { let (value, msg, struct_lit_needs_parens) = match e.node { ast::ExprIf(ref cond, _, _) => (cond, "`if` condition", true), ast::ExprWhile(ref cond, _, _) => (cond, "`while` condition", true), @@ -1456,7 +1481,7 @@ impl LintPass for UnusedParens { self.check_unused_parens_core(cx, &**value, msg, struct_lit_needs_parens); } - fn check_ast_stmt(&mut self, cx: &EarlyContext, s: &ast::Stmt) { + fn check_stmt(&mut self, cx: &EarlyContext, s: &ast::Stmt) { let (value, msg) = match s.node { ast::StmtDecl(ref decl, _) => match decl.node { ast::DeclLocal(ref local) => match local.init { @@ -1484,7 +1509,9 @@ impl LintPass for UnusedImportBraces { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_IMPORT_BRACES) } +} +impl LateLintPass for UnusedImportBraces { 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 { @@ -1514,7 +1541,9 @@ impl LintPass for NonShorthandFieldPatterns { fn get_lints(&self) -> LintArray { lint_array!(NON_SHORTHAND_FIELD_PATTERNS) } +} +impl LateLintPass for NonShorthandFieldPatterns { 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 { @@ -1553,7 +1582,9 @@ impl LintPass for UnusedUnsafe { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_UNSAFE) } +} +impl LateLintPass for UnusedUnsafe { 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. @@ -1578,7 +1609,9 @@ impl LintPass for UnsafeCode { fn get_lints(&self) -> LintArray { lint_array!(UNSAFE_CODE) } +} +impl LateLintPass for UnsafeCode { 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. @@ -1669,7 +1702,9 @@ impl LintPass for UnusedMut { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_MUT) } +} +impl LateLintPass for UnusedMut { fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { if let hir::ExprMatch(_, ref arms, _) = e.node { for a in arms { @@ -1708,7 +1743,9 @@ impl LintPass for UnusedAllocation { fn get_lints(&self) -> LintArray { lint_array!(UNUSED_ALLOCATION) } +} +impl LateLintPass for UnusedAllocation { fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { match e.node { hir::ExprUnary(hir::UnUniq, _) => (), @@ -1813,7 +1850,9 @@ impl LintPass for MissingDoc { fn get_lints(&self) -> LintArray { lint_array!(MISSING_DOCS) } +} +impl LateLintPass for MissingDoc { 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() { @@ -1950,7 +1989,9 @@ impl LintPass for MissingCopyImplementations { fn get_lints(&self) -> LintArray { lint_array!(MISSING_COPY_IMPLEMENTATIONS) } +} +impl LateLintPass for MissingCopyImplementations { fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { if !cx.exported_items.contains(&item.id) { return; @@ -2012,7 +2053,9 @@ impl LintPass for MissingDebugImplementations { fn get_lints(&self) -> LintArray { lint_array!(MISSING_DEBUG_IMPLEMENTATIONS) } +} +impl LateLintPass for MissingDebugImplementations { fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { if !cx.exported_items.contains(&item.id) { return; @@ -2106,7 +2149,9 @@ impl LintPass for Stability { fn get_lints(&self) -> LintArray { lint_array!(DEPRECATED) } +} +impl LateLintPass for Stability { fn check_item(&mut self, cx: &LateContext, item: &hir::Item) { stability::check_item(cx.tcx, item, false, &mut |id, sp, stab| @@ -2150,7 +2195,9 @@ impl LintPass for UnconditionalRecursion { fn get_lints(&self) -> LintArray { lint_array![UNCONDITIONAL_RECURSION] } +} +impl LateLintPass for UnconditionalRecursion { 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>, @@ -2397,7 +2444,9 @@ impl LintPass for PluginAsLibrary { fn get_lints(&self) -> LintArray { lint_array![PLUGIN_AS_LIBRARY] } +} +impl LateLintPass for PluginAsLibrary { 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. @@ -2453,7 +2502,9 @@ impl LintPass for InvalidNoMangleItems { PRIVATE_NO_MANGLE_STATICS, NO_MANGLE_CONST_ITEMS) } +} +impl LateLintPass for InvalidNoMangleItems { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match it.node { hir::ItemFn(..) => { @@ -2499,7 +2550,9 @@ impl LintPass for MutableTransmutes { fn get_lints(&self) -> LintArray { lint_array!(MUTABLE_TRANSMUTES) } +} +impl LateLintPass for MutableTransmutes { fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) { use syntax::abi::RustIntrinsic; @@ -2566,7 +2619,9 @@ impl LintPass for UnstableFeatures { fn get_lints(&self) -> LintArray { lint_array!(UNSTABLE_FEATURES) } +} +impl LateLintPass for UnstableFeatures { 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() { @@ -2593,6 +2648,9 @@ impl LintPass for DropWithReprExtern { fn get_lints(&self) -> LintArray { lint_array!(DROP_WITH_REPR_EXTERN) } +} + +impl LateLintPass for DropWithReprExtern { 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) = diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 517a3d13ddf76..5338316406063 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -67,7 +67,15 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { macro_rules! add_builtin { ($sess:ident, $($name:ident),*,) => ( {$( - store.register_pass($sess, false, box builtin::$name); + store.register_late_pass($sess, false, box builtin::$name); + )*} + ) + } + + macro_rules! add_early_builtin { + ($sess:ident, $($name:ident),*,) => ( + {$( + store.register_early_pass($sess, false, box builtin::$name); )*} ) } @@ -75,7 +83,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { macro_rules! add_builtin_with_new { ($sess:ident, $($name:ident),*,) => ( {$( - store.register_pass($sess, false, box builtin::$name::new()); + store.register_late_pass($sess, false, box builtin::$name::new()); )*} ) } @@ -86,6 +94,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { ) } + add_early_builtin!(sess, + UnusedParens, + ); + add_builtin!(sess, HardwiredLints, WhileTrue, @@ -97,7 +109,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { NonCamelCaseTypes, NonSnakeCase, NonUpperCaseGlobals, - UnusedParens, UnusedImportBraces, NonShorthandFieldPatterns, UnusedUnsafe, @@ -130,7 +141,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { UNUSED_UNSAFE, PATH_STATEMENTS); // We have one lint pass defined specially - store.register_pass(sess, false, box lint::GatherNodeLevels); + store.register_late_pass(sess, false, box lint::GatherNodeLevels); // Insert temporary renamings for a one-time deprecation store.register_renamed("raw_pointer_deriving", "raw_pointer_derive"); diff --git a/src/test/auxiliary/lint_for_crate.rs b/src/test/auxiliary/lint_for_crate.rs index 927b3e1cba988..7ae161a86a361 100644 --- a/src/test/auxiliary/lint_for_crate.rs +++ b/src/test/auxiliary/lint_for_crate.rs @@ -17,7 +17,7 @@ extern crate rustc_front; extern crate syntax; -use rustc::lint::{Context, LintContext, LintPass, LintPassObject, LintArray}; +use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray}; use rustc::plugin::Registry; use rustc_front::hir; use syntax::attr; @@ -30,8 +30,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(CRATE_NOT_OKAY) } +} - fn check_crate(&mut self, cx: &Context, krate: &hir::Crate) { +impl LateLintPass for Pass { + fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) { if !attr::contains_name(&krate.attrs, "crate_okay") { cx.span_lint(CRATE_NOT_OKAY, krate.span, "crate is not marked with #![crate_okay]"); @@ -41,5 +43,5 @@ impl LintPass for Pass { #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - reg.register_lint_pass(box Pass as LintPassObject); + reg.register_late_lint_pass(box Pass as LateLintPassObject); } diff --git a/src/test/auxiliary/lint_group_plugin_test.rs b/src/test/auxiliary/lint_group_plugin_test.rs index 45393913578e5..13cf5f09db32b 100644 --- a/src/test/auxiliary/lint_group_plugin_test.rs +++ b/src/test/auxiliary/lint_group_plugin_test.rs @@ -20,7 +20,7 @@ extern crate rustc_front; extern crate rustc; use rustc_front::hir; -use rustc::lint::{Context, LintContext, LintPass, LintPassObject, LintArray}; +use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray}; use rustc::plugin::Registry; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); @@ -33,8 +33,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(TEST_LINT, PLEASE_LINT) } +} - fn check_item(&mut self, cx: &Context, it: &hir::Item) { +impl LateLintPass for Pass { + fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { match &*it.ident.name.as_str() { "lintme" => cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"), "pleaselintme" => cx.span_lint(PLEASE_LINT, it.span, "item is named 'pleaselintme'"), @@ -45,6 +47,6 @@ impl LintPass for Pass { #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - reg.register_lint_pass(box Pass as LintPassObject); + reg.register_late_lint_pass(box Pass as LateLintPassObject); reg.register_lint_group("lint_me", vec![TEST_LINT, PLEASE_LINT]); } diff --git a/src/test/auxiliary/lint_plugin_test.rs b/src/test/auxiliary/lint_plugin_test.rs index 0dedd78abee05..4f5e8d6e0874c 100644 --- a/src/test/auxiliary/lint_plugin_test.rs +++ b/src/test/auxiliary/lint_plugin_test.rs @@ -19,7 +19,8 @@ extern crate syntax; #[macro_use] extern crate rustc; -use rustc::lint::{EarlyContext, LintContext, LintPass, LintPassObject, LintArray}; +use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass, + EarlyLintPassObject, LintArray}; use rustc::plugin::Registry; use syntax::ast; declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'"); @@ -30,8 +31,10 @@ impl LintPass for Pass { fn get_lints(&self) -> LintArray { lint_array!(TEST_LINT) } +} - fn check_ast_item(&mut self, cx: &EarlyContext, it: &ast::Item) { +impl EarlyLintPass for Pass { + fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) { if it.ident.name == "lintme" { cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"); } @@ -40,5 +43,5 @@ impl LintPass for Pass { #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - reg.register_lint_pass(box Pass as LintPassObject); + reg.register_early_lint_pass(box Pass as EarlyLintPassObject); } diff --git a/src/test/compile-fail/issue-23046.rs b/src/test/compile-fail/issue-23046.rs index 8c83c4cefd191..dba9c32f9b480 100644 --- a/src/test/compile-fail/issue-23046.rs +++ b/src/test/compile-fail/issue-23046.rs @@ -24,7 +24,7 @@ pub fn let_<'var, VAR, F: for<'v: 'var> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>> } fn main() { - let ex = (|x| { + let ex = |x| { let_(add(x,x), |y| { //~ ERROR unable to infer enough type information about `_` - let_(add(x, x), |x|x)})}); + let_(add(x, x), |x|x)})}; } From ed61a64a957d5c13cc524f9d516ac3626861717f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Tue, 15 Sep 2015 17:31:33 +1200 Subject: [PATCH 6/6] rebasing --- src/librustc/lint/context.rs | 34 +++++++++++++--------------------- src/librustc/middle/ty/mod.rs | 2 -- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index fe88401a24c20..9a736747d5291 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -408,8 +408,8 @@ pub trait LintContext: Sized { 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]); + fn enter_attrs(&mut self, attrs: &[ast::Attribute]); + fn exit_attrs(&mut self, attrs: &[ast::Attribute]); /// Get the level of `lint` at the current position of the lint /// traversal. @@ -510,14 +510,6 @@ pub trait LintContext: Sized { 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) - } } @@ -596,11 +588,11 @@ impl<'a, 'tcx> LintContext for LateContext<'a, 'tcx> { &mut self.level_stack } - fn enter_attrs(&mut self, attrs: &[hir::Attribute]) { + fn enter_attrs(&mut self, attrs: &[ast::Attribute]) { run_lints!(self, enter_lint_attrs, late_passes, attrs); } - fn exit_attrs(&mut self, attrs: &[hir::Attribute]) { + fn exit_attrs(&mut self, attrs: &[ast::Attribute]) { run_lints!(self, exit_lint_attrs, late_passes, attrs); } } @@ -623,11 +615,11 @@ impl<'a> LintContext for EarlyContext<'a> { &mut self.level_stack } - fn enter_attrs(&mut self, attrs: &[hir::Attribute]) { + fn enter_attrs(&mut self, attrs: &[ast::Attribute]) { run_lints!(self, enter_lint_attrs, early_passes, attrs); } - fn exit_attrs(&mut self, attrs: &[hir::Attribute]) { + fn exit_attrs(&mut self, attrs: &[ast::Attribute]) { run_lints!(self, exit_lint_attrs, early_passes, attrs); } } @@ -782,7 +774,7 @@ impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'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| { + self.with_lint_attrs(&it.attrs, |cx| { run_lints!(cx, check_item, early_passes, it); cx.visit_ids(|v| v.visit_item(it)); ast_visit::walk_item(cx, it); @@ -790,7 +782,7 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> { } fn visit_foreign_item(&mut self, it: &ast::ForeignItem) { - self.with_ast_lint_attrs(&it.attrs, |cx| { + self.with_lint_attrs(&it.attrs, |cx| { run_lints!(cx, check_foreign_item, early_passes, it); ast_visit::walk_foreign_item(cx, it); }) @@ -828,14 +820,14 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> { } fn visit_struct_field(&mut self, s: &ast::StructField) { - self.with_ast_lint_attrs(&s.node.attrs, |cx| { + self.with_lint_attrs(&s.node.attrs, |cx| { run_lints!(cx, check_struct_field, early_passes, 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| { + self.with_lint_attrs(&v.node.attrs, |cx| { run_lints!(cx, check_variant, early_passes, v, g); ast_visit::walk_variant(cx, v, g); run_lints!(cx, check_variant_post, early_passes, v, g); @@ -886,7 +878,7 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> { } fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) { - self.with_ast_lint_attrs(&trait_item.attrs, |cx| { + self.with_lint_attrs(&trait_item.attrs, |cx| { run_lints!(cx, check_trait_item, early_passes, trait_item); cx.visit_ids(|v| v.visit_trait_item(trait_item)); ast_visit::walk_trait_item(cx, trait_item); @@ -894,7 +886,7 @@ impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> { } fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) { - self.with_ast_lint_attrs(&impl_item.attrs, |cx| { + self.with_lint_attrs(&impl_item.attrs, |cx| { run_lints!(cx, check_impl_item, early_passes, impl_item); cx.visit_ids(|v| v.visit_impl_item(impl_item)); ast_visit::walk_impl_item(cx, impl_item); @@ -1027,7 +1019,7 @@ 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.with_lint_attrs(&krate.attrs, |cx| { cx.visit_id(ast::CRATE_NODE_ID); cx.visit_ids(|v| { v.visited_outermost = true; diff --git a/src/librustc/middle/ty/mod.rs b/src/librustc/middle/ty/mod.rs index fdf23c455ba2f..972f7242808b6 100644 --- a/src/librustc/middle/ty/mod.rs +++ b/src/librustc/middle/ty/mod.rs @@ -2089,8 +2089,6 @@ impl<'tcx> ctxt<'tcx> { hir::ExprCast(..) => { false } - - hir::ExprParen(ref e) => self.expr_is_lval(e), } }