From 0c844730d3f7f7d5d3f01a35b67fa5814ee208ee Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 7 Dec 2022 13:27:04 +1100 Subject: [PATCH 1/5] Remove `$hir` argument from `late_lint_methods!`. Because it's always `'tcx`. --- compiler/rustc_lint/src/lib.rs | 6 +-- compiler/rustc_lint/src/passes.rs | 76 +++++++++++++++---------------- 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 10bae36e0fd3c..daf9dbe2abf64 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -179,8 +179,7 @@ late_lint_methods!( // Keeps a global list of foreign declarations. ClashingExternDeclarations: ClashingExternDeclarations::new(), ] - ], - ['tcx] + ] ); late_lint_methods!( @@ -229,8 +228,7 @@ late_lint_methods!( NamedAsmLabels: NamedAsmLabels, OpaqueHiddenInferredBound: OpaqueHiddenInferredBound, ] - ], - ['tcx] + ] ); pub fn new_lint_store(internal_lints: bool) -> LintStore { diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index 2f53986139e05..c423765b6447b 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -9,49 +9,49 @@ use rustc_span::Span; #[macro_export] macro_rules! late_lint_methods { - ($macro:path, $args:tt, [$hir:tt]) => ( - $macro!($args, [$hir], [ - fn check_body(a: &$hir hir::Body<$hir>); - fn check_body_post(a: &$hir hir::Body<$hir>); + ($macro:path, $args:tt) => ( + $macro!($args, [ + fn check_body(a: &'tcx hir::Body<'tcx>); + fn check_body_post(a: &'tcx hir::Body<'tcx>); fn check_crate(); fn check_crate_post(); - fn check_mod(a: &$hir hir::Mod<$hir>, b: hir::HirId); - fn check_foreign_item(a: &$hir hir::ForeignItem<$hir>); - fn check_item(a: &$hir hir::Item<$hir>); - fn check_item_post(a: &$hir hir::Item<$hir>); - fn check_local(a: &$hir hir::Local<$hir>); - fn check_block(a: &$hir hir::Block<$hir>); - fn check_block_post(a: &$hir hir::Block<$hir>); - fn check_stmt(a: &$hir hir::Stmt<$hir>); - fn check_arm(a: &$hir hir::Arm<$hir>); - fn check_pat(a: &$hir hir::Pat<$hir>); - fn check_expr(a: &$hir hir::Expr<$hir>); - fn check_expr_post(a: &$hir hir::Expr<$hir>); - fn check_ty(a: &$hir hir::Ty<$hir>); - fn check_generic_param(a: &$hir hir::GenericParam<$hir>); - fn check_generics(a: &$hir hir::Generics<$hir>); - fn check_poly_trait_ref(a: &$hir hir::PolyTraitRef<$hir>); + fn check_mod(a: &'tcx hir::Mod<'tcx>, b: hir::HirId); + fn check_foreign_item(a: &'tcx hir::ForeignItem<'tcx>); + fn check_item(a: &'tcx hir::Item<'tcx>); + fn check_item_post(a: &'tcx hir::Item<'tcx>); + fn check_local(a: &'tcx hir::Local<'tcx>); + fn check_block(a: &'tcx hir::Block<'tcx>); + fn check_block_post(a: &'tcx hir::Block<'tcx>); + fn check_stmt(a: &'tcx hir::Stmt<'tcx>); + fn check_arm(a: &'tcx hir::Arm<'tcx>); + fn check_pat(a: &'tcx hir::Pat<'tcx>); + fn check_expr(a: &'tcx hir::Expr<'tcx>); + fn check_expr_post(a: &'tcx hir::Expr<'tcx>); + fn check_ty(a: &'tcx hir::Ty<'tcx>); + fn check_generic_param(a: &'tcx hir::GenericParam<'tcx>); + fn check_generics(a: &'tcx hir::Generics<'tcx>); + fn check_poly_trait_ref(a: &'tcx hir::PolyTraitRef<'tcx>); fn check_fn( - a: rustc_hir::intravisit::FnKind<$hir>, - b: &$hir hir::FnDecl<$hir>, - c: &$hir hir::Body<$hir>, + a: rustc_hir::intravisit::FnKind<'tcx>, + b: &'tcx hir::FnDecl<'tcx>, + c: &'tcx hir::Body<'tcx>, d: Span, e: hir::HirId); - fn check_trait_item(a: &$hir hir::TraitItem<$hir>); - fn check_impl_item(a: &$hir hir::ImplItem<$hir>); - fn check_impl_item_post(a: &$hir hir::ImplItem<$hir>); - fn check_struct_def(a: &$hir hir::VariantData<$hir>); - fn check_field_def(a: &$hir hir::FieldDef<$hir>); - fn check_variant(a: &$hir hir::Variant<$hir>); - fn check_path(a: &hir::Path<$hir>, b: hir::HirId); - fn check_attribute(a: &$hir ast::Attribute); + fn check_trait_item(a: &'tcx hir::TraitItem<'tcx>); + fn check_impl_item(a: &'tcx hir::ImplItem<'tcx>); + fn check_impl_item_post(a: &'tcx hir::ImplItem<'tcx>); + fn check_struct_def(a: &'tcx hir::VariantData<'tcx>); + fn check_field_def(a: &'tcx hir::FieldDef<'tcx>); + fn check_variant(a: &'tcx hir::Variant<'tcx>); + fn check_path(a: &hir::Path<'tcx>, b: hir::HirId); + fn check_attribute(a: &'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(a: &$hir [ast::Attribute]); + fn enter_lint_attrs(a: &'tcx [ast::Attribute]); /// Counterpart to `enter_lint_attrs`. - fn exit_lint_attrs(a: &$hir [ast::Attribute]); + fn exit_lint_attrs(a: &'tcx [ast::Attribute]); ]); ) } @@ -66,14 +66,14 @@ macro_rules! late_lint_methods { // contains a few lint-specific methods with no equivalent in `Visitor`. macro_rules! declare_late_lint_pass { - ([], [$hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( - pub trait LateLintPass<$hir>: LintPass { - $(#[inline(always)] fn $name(&mut self, _: &LateContext<$hir>, $(_: $arg),*) {})* + ([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( + pub trait LateLintPass<'tcx>: LintPass { + $(#[inline(always)] fn $name(&mut self, _: &LateContext<'tcx>, $(_: $arg),*) {})* } ) } -late_lint_methods!(declare_late_lint_pass, [], ['tcx]); +late_lint_methods!(declare_late_lint_pass, []); impl LateLintPass<'_> for HardwiredLints {} @@ -95,7 +95,7 @@ macro_rules! expand_combined_late_lint_pass_methods { #[macro_export] macro_rules! declare_combined_late_lint_pass { - ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], [$hir:tt], $methods:tt) => ( + ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], $methods:tt) => ( #[allow(non_snake_case)] $v struct $name { $($passes: $passes,)* From ac1e69c9033a33e374f1dd91b3e4cd54e1c0033f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 7 Dec 2022 14:18:19 +1100 Subject: [PATCH 2/5] Add some useful comments. --- compiler/rustc_lint/src/lib.rs | 9 ++++++++- compiler/rustc_lint/src/passes.rs | 4 ++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index daf9dbe2abf64..1990a74841bc2 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -127,6 +127,7 @@ fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { late::late_lint_mod(tcx, module_def_id, BuiltinCombinedModuleLateLintPass::new()); } +// See the comment on `BuiltinCombinedEarlyLintPass`, which is similar. early_lint_methods!( declare_combined_early_lint_pass, [ @@ -137,6 +138,9 @@ early_lint_methods!( ] ); +// Declare `BuiltinCombinedEarlyLintPass`, a lint pass that combines multiple +// lint passes into a single pass for maximum speed. Each `check_foo` method +// within this pass simply calls `check_foo` once per listed lint. early_lint_methods!( declare_combined_early_lint_pass, [ @@ -162,7 +166,9 @@ early_lint_methods!( ] ); -// FIXME: Make a separate lint type which do not require typeck tables +// FIXME: Make a separate lint type which does not require typeck tables. + +// See the comment on `BuiltinCombinedEarlyLintPass`, which is similar. late_lint_methods!( declare_combined_late_lint_pass, [ @@ -182,6 +188,7 @@ late_lint_methods!( ] ); +// See the comment on `BuiltinCombinedEarlyLintPass`, which is similar. late_lint_methods!( declare_combined_late_lint_pass, [ diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index c423765b6447b..312dbcd68bdd7 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -73,6 +73,8 @@ macro_rules! declare_late_lint_pass { ) } +// Declare the `LateLintPass` trait, which contains empty default definitions +// for all the `check_*` methods. late_lint_methods!(declare_late_lint_pass, []); impl LateLintPass<'_> for HardwiredLints {} @@ -176,6 +178,8 @@ macro_rules! declare_early_lint_pass { ) } +// Declare the `EarlyLintPass` trait, which contains empty default definitions +// for all the `check_*` methods. early_lint_methods!(declare_early_lint_pass, []); #[macro_export] From ec117c0ebd6a47a2be6fc1e96b8ccc18f10a8c50 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 7 Dec 2022 16:54:02 +1100 Subject: [PATCH 3/5] Rename `$passes` as `$pass` in several macros. Because it makes more sense that way. --- compiler/rustc_lint/src/passes.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index 312dbcd68bdd7..00922cef38462 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -81,8 +81,8 @@ impl LateLintPass<'_> for HardwiredLints {} #[macro_export] macro_rules! expand_combined_late_lint_pass_method { - ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({ - $($self.$passes.$name $params;)* + ([$($pass:ident),*], $self: ident, $name: ident, $params:tt) => ({ + $($self.$pass.$name $params;)* }) } @@ -97,28 +97,28 @@ macro_rules! expand_combined_late_lint_pass_methods { #[macro_export] macro_rules! declare_combined_late_lint_pass { - ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], $methods:tt) => ( + ([$v:vis $name:ident, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => ( #[allow(non_snake_case)] $v struct $name { - $($passes: $passes,)* + $($pass: $pass,)* } impl $name { $v fn new() -> Self { Self { - $($passes: $constructor,)* + $($pass: $constructor,)* } } $v fn get_lints() -> LintArray { let mut lints = Vec::new(); - $(lints.extend_from_slice(&$passes::get_lints());)* + $(lints.extend_from_slice(&$pass::get_lints());)* lints } } impl<'tcx> LateLintPass<'tcx> for $name { - expand_combined_late_lint_pass_methods!([$($passes),*], $methods); + expand_combined_late_lint_pass_methods!([$($pass),*], $methods); } #[allow(rustc::lint_pass_impl_without_macro)] @@ -184,8 +184,8 @@ early_lint_methods!(declare_early_lint_pass, []); #[macro_export] macro_rules! expand_combined_early_lint_pass_method { - ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({ - $($self.$passes.$name $params;)* + ([$($pass:ident),*], $self: ident, $name: ident, $params:tt) => ({ + $($self.$pass.$name $params;)* }) } @@ -200,28 +200,28 @@ macro_rules! expand_combined_early_lint_pass_methods { #[macro_export] macro_rules! declare_combined_early_lint_pass { - ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], $methods:tt) => ( + ([$v:vis $name:ident, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => ( #[allow(non_snake_case)] $v struct $name { - $($passes: $passes,)* + $($pass: $pass,)* } impl $name { $v fn new() -> Self { Self { - $($passes: $constructor,)* + $($pass: $constructor,)* } } $v fn get_lints() -> LintArray { let mut lints = Vec::new(); - $(lints.extend_from_slice(&$passes::get_lints());)* + $(lints.extend_from_slice(&$pass::get_lints());)* lints } } impl EarlyLintPass for $name { - expand_combined_early_lint_pass_methods!([$($passes),*], $methods); + expand_combined_early_lint_pass_methods!([$($pass),*], $methods); } #[allow(rustc::lint_pass_impl_without_macro)] From b08fd6e8efec854d6a9c1a1486f04f8933e30795 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 7 Dec 2022 14:52:28 +1100 Subject: [PATCH 4/5] Inline some hot lint pass functions. These each have a single call site, due to being called from a "combined" lint pass. --- compiler/rustc_lint/src/builtin.rs | 3 +++ compiler/rustc_lint/src/hidden_unicode_codepoints.rs | 1 + compiler/rustc_lint/src/unused.rs | 2 ++ 3 files changed, 6 insertions(+) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 825093384fba7..db3e0f20423bc 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -96,6 +96,7 @@ fn pierce_parens(mut expr: &ast::Expr) -> &ast::Expr { } impl EarlyLintPass for WhileTrue { + #[inline] fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { if let ast::ExprKind::While(cond, _, label) = &e.kind && let cond = pierce_parens(cond) @@ -360,6 +361,7 @@ impl EarlyLintPass for UnsafeCode { } } + #[inline] fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { if let ast::ExprKind::Block(ref blk, _) = e.kind { // Don't warn about generated blocks; that'll just pollute the output. @@ -582,6 +584,7 @@ impl MissingDoc { } impl<'tcx> LateLintPass<'tcx> for MissingDoc { + #[inline] fn enter_lint_attrs(&mut self, _cx: &LateContext<'_>, attrs: &[ast::Attribute]) { let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| { diff --git a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs index 7106e75dba290..dc2f5c0e2967e 100644 --- a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs +++ b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs @@ -121,6 +121,7 @@ impl EarlyLintPass for HiddenUnicodeCodepoints { } } + #[inline] fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { // byte strings are already handled well enough by `EscapeError::NonAsciiCharInByteString` match &expr.kind { diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index b5db94f8c0684..df46e37eea8f1 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -946,6 +946,7 @@ impl UnusedParens { } impl EarlyLintPass for UnusedParens { + #[inline] fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { match e.kind { ExprKind::Let(ref pat, _, _) | ExprKind::ForLoop(ref pat, ..) => { @@ -1164,6 +1165,7 @@ impl EarlyLintPass for UnusedBraces { ::check_stmt(self, cx, s) } + #[inline] fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { ::check_expr(self, cx, e); From d049be30cf3f53ecba2bde4ad5c832866965eb0a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 7 Dec 2022 14:58:48 +1100 Subject: [PATCH 5/5] Split `EarlyContextAndPasses::check_id` in two. --- compiler/rustc_lint/src/early.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 52363b0be2db9..5d81370c35acf 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -37,7 +37,9 @@ pub struct EarlyContextAndPasses<'a> { } impl<'a> EarlyContextAndPasses<'a> { - fn check_id(&mut self, id: ast::NodeId) { + // This always-inlined function is for the hot call site. + #[inline(always)] + fn inlined_check_id(&mut self, id: ast::NodeId) { for early_lint in self.context.buffered.take(id) { let BufferedEarlyLint { span, msg, node_id: _, lint_id, diagnostic } = early_lint; self.context.lookup_with_diagnostics( @@ -50,6 +52,11 @@ impl<'a> EarlyContextAndPasses<'a> { } } + // This non-inlined function is for the cold call sites. + fn check_id(&mut self, id: ast::NodeId) { + self.inlined_check_id(id) + } + /// 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. @@ -61,7 +68,7 @@ impl<'a> EarlyContextAndPasses<'a> { debug!(?id); let push = self.context.builder.push(attrs, is_crate_node, None); - self.check_id(id); + self.inlined_check_id(id); debug!("early context: enter_attrs({:?})", attrs); run_early_passes!(self, enter_lint_attrs, attrs); f(self);