]> git.lizzy.rs Git - rust.git/commitdiff
Speed up the "builtin lints only" case.
authorNicholas Nethercote <n.nethercote@gmail.com>
Fri, 9 Dec 2022 03:15:26 +0000 (14:15 +1100)
committerNicholas Nethercote <n.nethercote@gmail.com>
Sun, 11 Dec 2022 21:59:27 +0000 (08:59 +1100)
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.

compiler/rustc_lint/src/early.rs
compiler/rustc_lint/src/late.rs

index d6a7a8c65ef0dfe4f1e84254d9d4275fdd5187ef..5f84d5c8b949575394d401a287bbe1b025563376 100644 (file)
@@ -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));
index 11cd246c725af6c7dee43465caee4488087becb1..e2876938d70566477329cc94541c81478a3894f1 100644 (file)
@@ -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.