diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 824930a7eb0..c9874f510f7 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -178,10 +178,10 @@ impl LintStore { sess: Option<&Session>, from_plugin: bool, pass: &Box

) { - for &lint in pass.get_lints() { - self.lints.push((*lint, from_plugin)); + for lint in pass.get_lints() { + self.lints.push((lint, from_plugin)); - let id = LintId::of(*lint); + let id = LintId::of(lint); if self.by_name.insert(lint.name_lower(), Id(id)).is_some() { let msg = format!("duplicate specification of lint {}", lint.name_lower()); match (sess, from_plugin) { diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 9338e235c53..bff596e21e5 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -35,7 +35,7 @@ use rustc_data_structures::sync::{self, Lrc}; use errors::{DiagnosticBuilder, DiagnosticId}; use hir::def_id::{CrateNum, LOCAL_CRATE}; -use hir::intravisit::{self, FnKind}; +use hir::intravisit; use hir; use lint::builtin::BuiltinLintDiagnostics; use session::{Session, DiagnosticMessageId}; @@ -123,12 +123,11 @@ macro_rules! declare_lint { #[macro_export] macro_rules! lint_array { ($( $lint:expr ),* $(,)?) => {{ - static ARRAY: LintArray = &[ $( &$lint ),* ]; - ARRAY + vec![$($lint),*] }} } -pub type LintArray = &'static [&'static &'static Lint]; +pub type LintArray = Vec<&'static Lint>; pub trait LintPass { /// Get descriptions of the lints this `LintPass` object can emit. @@ -140,6 +139,80 @@ pub trait LintPass { fn get_lints(&self) -> LintArray; } +#[macro_export] +macro_rules! late_lint_methods { + ($macro:path, $args:tt, [$hir:tt]) => ( + $macro!($args, [$hir], [ + fn check_body(a: &$hir hir::Body); + fn check_body_post(a: &$hir hir::Body); + fn check_name(a: Span, b: ast::Name); + fn check_crate(a: &$hir hir::Crate); + fn check_crate_post(a: &$hir hir::Crate); + fn check_mod(a: &$hir hir::Mod, b: Span, c: ast::NodeId); + fn check_mod_post(a: &$hir hir::Mod, b: Span, c: ast::NodeId); + fn check_foreign_item(a: &$hir hir::ForeignItem); + fn check_foreign_item_post(a: &$hir hir::ForeignItem); + fn check_item(a: &$hir hir::Item); + fn check_item_post(a: &$hir hir::Item); + fn check_local(a: &$hir hir::Local); + fn check_block(a: &$hir hir::Block); + fn check_block_post(a: &$hir hir::Block); + fn check_stmt(a: &$hir hir::Stmt); + fn check_arm(a: &$hir hir::Arm); + fn check_pat(a: &$hir hir::Pat); + fn check_decl(a: &$hir hir::Decl); + fn check_expr(a: &$hir hir::Expr); + fn check_expr_post(a: &$hir hir::Expr); + fn check_ty(a: &$hir hir::Ty); + fn check_generic_param(a: &$hir hir::GenericParam); + fn check_generics(a: &$hir hir::Generics); + fn check_where_predicate(a: &$hir hir::WherePredicate); + fn check_poly_trait_ref(a: &$hir hir::PolyTraitRef, b: hir::TraitBoundModifier); + fn check_fn( + a: hir::intravisit::FnKind<$hir>, + b: &$hir hir::FnDecl, + c: &$hir hir::Body, + d: Span, + e: ast::NodeId); + fn check_fn_post( + a: hir::intravisit::FnKind<$hir>, + b: &$hir hir::FnDecl, + c: &$hir hir::Body, + d: Span, + e: ast::NodeId + ); + fn check_trait_item(a: &$hir hir::TraitItem); + fn check_trait_item_post(a: &$hir hir::TraitItem); + fn check_impl_item(a: &$hir hir::ImplItem); + fn check_impl_item_post(a: &$hir hir::ImplItem); + fn check_struct_def( + a: &$hir hir::VariantData, + b: ast::Name, + c: &$hir hir::Generics, + d: ast::NodeId + ); + fn check_struct_def_post( + a: &$hir hir::VariantData, + b: ast::Name, + c: &$hir hir::Generics, + d: ast::NodeId + ); + fn check_struct_field(a: &$hir hir::StructField); + fn check_variant(a: &$hir hir::Variant, b: &$hir hir::Generics); + fn check_variant_post(a: &$hir hir::Variant, b: &$hir hir::Generics); + fn check_lifetime(a: &$hir hir::Lifetime); + fn check_path(a: &$hir hir::Path, b: ast::NodeId); + fn check_attribute(a: &$hir 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(a: &$hir [ast::Attribute]); + + /// Counterpart to `enter_lint_attrs`. + fn exit_lint_attrs(a: &$hir [ast::Attribute]); + ]); + ) +} /// Trait for types providing lint checks. /// @@ -149,90 +222,67 @@ pub trait LintPass { // // FIXME: eliminate the duplication with `Visitor`. But this also // contains a few lint-specific methods with no equivalent in `Visitor`. -pub trait LateLintPass<'a, 'tcx>: LintPass { - fn check_body(&mut self, _: &LateContext, _: &'tcx hir::Body) { } - fn check_body_post(&mut self, _: &LateContext, _: &'tcx hir::Body) { } - fn check_name(&mut self, _: &LateContext, _: Span, _: ast::Name) { } - fn check_crate(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Crate) { } - fn check_crate_post(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Crate) { } - fn check_mod(&mut self, - _: &LateContext<'a, 'tcx>, - _: &'tcx hir::Mod, - _: Span, - _: ast::NodeId) { } - fn check_mod_post(&mut self, - _: &LateContext<'a, 'tcx>, - _: &'tcx hir::Mod, - _: Span, - _: ast::NodeId) { } - fn check_foreign_item(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::ForeignItem) { } - fn check_foreign_item_post(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::ForeignItem) { } - fn check_item(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Item) { } - fn check_item_post(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Item) { } - fn check_local(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Local) { } - fn check_block(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Block) { } - fn check_block_post(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Block) { } - fn check_stmt(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Stmt) { } - fn check_arm(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Arm) { } - fn check_pat(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Pat) { } - fn check_decl(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Decl) { } - fn check_expr(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Expr) { } - fn check_expr_post(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Expr) { } - fn check_ty(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Ty) { } - fn check_generic_param(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::GenericParam) { } - fn check_generics(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Generics) { } - fn check_where_predicate(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::WherePredicate) { } - fn check_poly_trait_ref(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::PolyTraitRef, - _: hir::TraitBoundModifier) { } - fn check_fn(&mut self, - _: &LateContext<'a, 'tcx>, - _: FnKind<'tcx>, - _: &'tcx hir::FnDecl, - _: &'tcx hir::Body, - _: Span, - _: ast::NodeId) { } - fn check_fn_post(&mut self, - _: &LateContext<'a, 'tcx>, - _: FnKind<'tcx>, - _: &'tcx hir::FnDecl, - _: &'tcx hir::Body, - _: Span, - _: ast::NodeId) { } - fn check_trait_item(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::TraitItem) { } - fn check_trait_item_post(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::TraitItem) { } - fn check_impl_item(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::ImplItem) { } - fn check_impl_item_post(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::ImplItem) { } - fn check_struct_def(&mut self, - _: &LateContext<'a, 'tcx>, - _: &'tcx hir::VariantData, - _: ast::Name, - _: &'tcx hir::Generics, - _: ast::NodeId) { } - fn check_struct_def_post(&mut self, - _: &LateContext<'a, 'tcx>, - _: &'tcx hir::VariantData, - _: ast::Name, - _: &'tcx hir::Generics, - _: ast::NodeId) { } - fn check_struct_field(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::StructField) { } - fn check_variant(&mut self, - _: &LateContext<'a, 'tcx>, - _: &'tcx hir::Variant, - _: &'tcx hir::Generics) { } - fn check_variant_post(&mut self, - _: &LateContext<'a, 'tcx>, - _: &'tcx hir::Variant, - _: &'tcx hir::Generics) { } - fn check_lifetime(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Lifetime) { } - fn check_path(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Path, _: ast::NodeId) { } - fn check_attribute(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx 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<'a, 'tcx>, _: &'tcx [ast::Attribute]) { } +macro_rules! expand_lint_pass_methods { + ($context:ty, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( + $(#[inline(always)] fn $name(&mut self, $context, $(_: $arg),*) {})* + ) +} - /// Counterpart to `enter_lint_attrs`. - fn exit_lint_attrs(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx [ast::Attribute]) { } +macro_rules! declare_late_lint_pass { + ([], [$hir:tt], [$($methods:tt)*]) => ( + pub trait LateLintPass<'a, $hir>: LintPass { + expand_lint_pass_methods!(&LateContext<'a, $hir>, [$($methods)*]); + } + ) +} + +late_lint_methods!(declare_late_lint_pass, [], ['tcx]); + +#[macro_export] +macro_rules! expand_combined_late_lint_pass_method { + ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({ + $($self.$passes.$name $params;)* + }) +} + +#[macro_export] +macro_rules! expand_combined_late_lint_pass_methods { + ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( + $(fn $name(&mut self, context: &LateContext<'a, 'tcx>, $($param: $arg),*) { + expand_combined_late_lint_pass_method!($passes, self, $name, (context, $($param),*)); + })* + ) +} + +#[macro_export] +macro_rules! declare_combined_late_lint_pass { + ([$name:ident, [$($passes:ident: $constructor:expr,)*]], [$hir:tt], $methods:tt) => ( + #[allow(non_snake_case)] + struct $name { + $($passes: $passes,)* + } + + impl $name { + fn new() -> Self { + Self { + $($passes: $constructor,)* + } + } + } + + impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $name { + expand_combined_late_lint_pass_methods!([$($passes),*], $methods); + } + + impl LintPass for $name { + fn get_lints(&self) -> LintArray { + let mut lints = Vec::new(); + $(lints.extend_from_slice(&self.$passes.get_lints());)* + lints + } + } + ) } pub trait EarlyLintPass: LintPass { diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 9ac22f8dceb..f84bfd66a63 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -41,9 +41,14 @@ extern crate rustc_target; extern crate syntax_pos; use rustc::lint; +use rustc::lint::{LateContext, LateLintPass, LintPass, LintArray}; use rustc::lint::builtin::{BARE_TRAIT_OBJECTS, ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE}; use rustc::session; use rustc::util; +use rustc::hir; + +use syntax::ast; +use syntax_pos::Span; use session::Session; use syntax::edition::Edition; @@ -67,14 +72,6 @@ pub use builtin::SoftLints; /// defined in this crate and the ones defined in /// `rustc::lint::builtin`). pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { - macro_rules! add_builtin { - ($sess:ident, $($name:ident),*,) => ( - {$( - store.register_late_pass($sess, false, box $name); - )*} - ) - } - macro_rules! add_early_builtin { ($sess:ident, $($name:ident),*,) => ( {$( @@ -83,14 +80,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { ) } - macro_rules! add_builtin_with_new { - ($sess:ident, $($name:ident),*,) => ( - {$( - store.register_late_pass($sess, false, box $name::new()); - )*} - ) - } - macro_rules! add_early_builtin_with_new { ($sess:ident, $($name:ident),*,) => ( {$( @@ -117,39 +106,38 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) { DeprecatedAttr, ); - add_builtin!(sess, - HardwiredLints, - WhileTrue, - ImproperCTypes, - VariantSizeDifferences, - BoxPointers, - UnusedAttributes, - PathStatements, - UnusedResults, - NonCamelCaseTypes, - NonSnakeCase, - NonUpperCaseGlobals, - NonShorthandFieldPatterns, - UnsafeCode, - UnusedAllocation, - MissingCopyImplementations, - UnstableFeatures, - UnconditionalRecursion, - InvalidNoMangleItems, - PluginAsLibrary, - MutableTransmutes, - UnionsWithDropFields, - UnreachablePub, - TypeAliasBounds, - UnusedBrokenConst, - TrivialConstraints, - ); + late_lint_methods!(declare_combined_late_lint_pass, [BuiltinCombinedLateLintPass, [ + HardwiredLints: HardwiredLints, + WhileTrue: WhileTrue, + ImproperCTypes: ImproperCTypes, + VariantSizeDifferences: VariantSizeDifferences, + BoxPointers: BoxPointers, + UnusedAttributes: UnusedAttributes, + PathStatements: PathStatements, + UnusedResults: UnusedResults, + NonCamelCaseTypes: NonCamelCaseTypes, + NonSnakeCase: NonSnakeCase, + NonUpperCaseGlobals: NonUpperCaseGlobals, + NonShorthandFieldPatterns: NonShorthandFieldPatterns, + UnsafeCode: UnsafeCode, + UnusedAllocation: UnusedAllocation, + MissingCopyImplementations: MissingCopyImplementations, + UnstableFeatures: UnstableFeatures, + UnconditionalRecursion: UnconditionalRecursion, + InvalidNoMangleItems: InvalidNoMangleItems, + PluginAsLibrary: PluginAsLibrary, + MutableTransmutes: MutableTransmutes, + UnionsWithDropFields: UnionsWithDropFields, + UnreachablePub: UnreachablePub, + TypeAliasBounds: TypeAliasBounds, + UnusedBrokenConst: UnusedBrokenConst, + TrivialConstraints: TrivialConstraints, + TypeLimits: TypeLimits::new(), + MissingDoc: MissingDoc::new(), + MissingDebugImplementations: MissingDebugImplementations::new(), + ]], ['tcx]); - add_builtin_with_new!(sess, - TypeLimits, - MissingDoc, - MissingDebugImplementations, - ); + store.register_late_pass(sess, false, box BuiltinCombinedLateLintPass::new()); add_lint_group!(sess, "bad_style", diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index e858f10860b..2d71b48d8ac 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -190,8 +190,8 @@ pub fn run_core(search_paths: SearchPaths, let intra_link_resolution_failure_name = lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE.name; let warnings_lint_name = lint::builtin::WARNINGS.name; let lints = lint::builtin::HardwiredLints.get_lints() - .iter() - .chain(rustc_lint::SoftLints.get_lints()) + .into_iter() + .chain(rustc_lint::SoftLints.get_lints().into_iter()) .filter_map(|lint| { if lint.name == warnings_lint_name || lint.name == intra_link_resolution_failure_name {