diff options
| author | Nicholas Nethercote <n.nethercote@gmail.com> | 2022-12-09 14:15:26 +1100 |
|---|---|---|
| committer | Nicholas Nethercote <n.nethercote@gmail.com> | 2022-12-12 08:59:27 +1100 |
| commit | 4ff5a3655f1e7bed94d847f6888a2c0659aba276 (patch) | |
| tree | 91841931c3108d27071d548086276a1de54b8b5d | |
| parent | 3c53781800e50b2abc72c5b1542400eff48a8126 (diff) | |
Speed up the "builtin lints only" case.
This commit partly undoes #104863, which combined the builtin lints pass with other lints. This caused a slowdown, because often there are no other lints, and it's faster to do a pass with a single lint directly than it is to do a combined pass with a `passes` vector containing a single lint.
| -rw-r--r-- | compiler/rustc_lint/src/early.rs | 21 | ||||
| -rw-r--r-- | compiler/rustc_lint/src/late.rs | 37 |
2 files changed, 51 insertions, 7 deletions
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index d6a7a8c65ef..5f84d5c8b94 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -393,12 +393,27 @@ pub fn check_ast_node<'a>( lint_buffer.unwrap_or_default(), ); + // Note: `passes` is often empty. In that case, it's faster to run + // `builtin_lints` directly rather than bundling it up into the + // `RuntimeCombinedEarlyLintPass`. let passes = if pre_expansion { &lint_store.pre_expansion_passes } else { &lint_store.early_passes }; - let mut passes: Vec<EarlyLintPassObject> = passes.iter().map(|mk_pass| (mk_pass)()).collect(); - passes.push(Box::new(builtin_lints)); - let pass = RuntimeCombinedEarlyLintPass { passes: &mut passes[..] }; + if passes.is_empty() { + check_ast_node_inner(sess, check_node, context, builtin_lints); + } else { + let mut passes: Vec<_> = passes.iter().map(|mk_pass| (mk_pass)()).collect(); + passes.push(Box::new(builtin_lints)); + let pass = RuntimeCombinedEarlyLintPass { passes: &mut passes[..] }; + check_ast_node_inner(sess, check_node, context, pass); + } +} +pub fn check_ast_node_inner<'a, T: EarlyLintPass>( + sess: &Session, + check_node: impl EarlyCheckNode<'a>, + context: EarlyContext<'_>, + pass: T, +) { let mut cx = EarlyContextAndPass { context, pass }; cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx)); diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 11cd246c725..e2876938d70 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -349,11 +349,26 @@ pub(super) fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>( only_module: true, }; + // Note: `passes` is often empty. In that case, it's faster to run + // `builtin_lints` directly rather than bundling it up into the + // `RuntimeCombinedLateLintPass`. let mut passes: Vec<_> = unerased_lint_store(tcx).late_module_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect(); - passes.push(Box::new(builtin_lints)); - let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] }; + if passes.is_empty() { + late_lint_mod_inner(tcx, module_def_id, context, builtin_lints); + } else { + passes.push(Box::new(builtin_lints)); + let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] }; + late_lint_mod_inner(tcx, module_def_id, context, pass); + } +} +fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>( + tcx: TyCtxt<'tcx>, + module_def_id: LocalDefId, + context: LateContext<'tcx>, + pass: T, +) { let mut cx = LateContextAndPass { context, pass }; let (module, _span, hir_id) = tcx.hir().get_module(module_def_id); @@ -380,11 +395,25 @@ fn late_lint_crate<'tcx, T: LateLintPass<'tcx> + 'tcx>(tcx: TyCtxt<'tcx>, builti only_module: false, }; + // Note: `passes` is often empty. In that case, it's faster to run + // `builtin_lints` directly rather than bundling it up into the + // `RuntimeCombinedLateLintPass`. let mut passes: Vec<_> = unerased_lint_store(tcx).late_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect(); - passes.push(Box::new(builtin_lints)); - let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] }; + if passes.is_empty() { + late_lint_crate_inner(tcx, context, builtin_lints); + } else { + passes.push(Box::new(builtin_lints)); + let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] }; + late_lint_crate_inner(tcx, context, pass); + } +} +fn late_lint_crate_inner<'tcx, T: LateLintPass<'tcx>>( + tcx: TyCtxt<'tcx>, + context: LateContext<'tcx>, + pass: T, +) { let mut cx = LateContextAndPass { context, pass }; // Visit the whole crate. |
