Skip to content

Commit

Permalink
Auto merge of rust-lang#125116 - blyxyas:ignore-allowed-lints-final, …
Browse files Browse the repository at this point in the history
…r=<try>

(Big performance change) Do not run lints that cannot emit

Before this lint, adding a lint was a difficult matter because it always had some overhead involved. This was because all lints would run, no matter their default level, or if the user had `#![allow]`ed them. This PR changes that. This change would improve both the Rust lint infrastructure and Clippy, but Clippy will see the most benefit, as it has about 900 registered lints (and growing!)

So yeah, with this little patch we filter all lints pre-linting, and remove any lint that is either:
- Manually `#![allow]`ed in the whole crate,
- Allowed in the command line, or
- Not manually enabled with `#[warn]` or similar, and its default level is `Allow`

As some lints **need** to run, this PR also adds **loadbearing lints**. On a lint declaration, you can use the `[loadbearing: true]` marker to label it as loadbearing. A loadbearing lint will never be filtered.

**Phase 1/2** Not all lints are being filtered, I'm still working on it, but this branch still gives us about a 2% improvement, so why not merge it already.

Fixes rust-lang#106983
  • Loading branch information
bors committed Sep 3, 2024
2 parents d6c8169 + 2aaf2f2 commit 50e9dfe
Show file tree
Hide file tree
Showing 50 changed files with 421 additions and 74 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4033,6 +4033,7 @@ dependencies = [
"rustc_hir",
"rustc_hir_pretty",
"rustc_index",
"rustc_lint_defs",
"rustc_macros",
"rustc_query_system",
"rustc_serialize",
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/attr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ impl AttrItem {
self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span))
}

fn meta_item_list(&self) -> Option<ThinVec<NestedMetaItem>> {
pub fn meta_item_list(&self) -> Option<ThinVec<NestedMetaItem>> {
match &self.args {
AttrArgs::Delimited(args) if args.delim == Delimiter::Parenthesis => {
MetaItemKind::list_from_tokens(args.tokens.clone())
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
tcx.ensure().check_mod_privacy(module);
});
});
}
} // { sess.time("mir_checking", || { tcx.hir().mir_for }) }
);

// This check has to be run after all lints are done processing. We don't
Expand Down
13 changes: 10 additions & 3 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
//! If you define a new `LateLintPass`, you will also need to add it to the
//! `late_lint_methods!` invocation in `lib.rs`.
use std::default::Default;
use std::fmt::Write;

use ast::token::TokenKind;
Expand Down Expand Up @@ -73,6 +74,10 @@ use crate::{
fluent_generated as fluent, EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level,
LintContext,
};
// use std::fmt::Write;

// hardwired lints from rustc_lint_defs
// pub use rustc_session::lint::builtin::*;

declare_lint! {
/// The `while_true` lint detects `while true { }`.
Expand Down Expand Up @@ -242,7 +247,8 @@ declare_lint! {
/// behavior.
UNSAFE_CODE,
Allow,
"usage of `unsafe` code and other potentially unsound constructs"
"usage of `unsafe` code and other potentially unsound constructs",
[loadbearing: true]
}

declare_lint_pass!(UnsafeCode => [UNSAFE_CODE]);
Expand Down Expand Up @@ -390,6 +396,7 @@ declare_lint! {
report_in_external_macro
}

#[derive(Default)]
pub struct MissingDoc;

impl_lint_pass!(MissingDoc => [MISSING_DOCS]);
Expand Down Expand Up @@ -830,8 +837,8 @@ pub struct DeprecatedAttr {

impl_lint_pass!(DeprecatedAttr => []);

impl DeprecatedAttr {
pub fn new() -> DeprecatedAttr {
impl Default for DeprecatedAttr {
fn default() -> Self {
DeprecatedAttr { depr_attrs: deprecated_attributes() }
}
}
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_lint/src/early.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,9 @@ impl LintPass for RuntimeCombinedEarlyLintPass<'_> {
fn name(&self) -> &'static str {
panic!()
}
fn get_lints(&self) -> crate::LintVec {
panic!()
}
}

macro_rules! impl_early_lint_pass {
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_lint/src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,8 @@ declare_tool_lint! {
pub rustc::UNTRANSLATABLE_DIAGNOSTIC,
Deny,
"prevent creation of diagnostics which cannot be translated",
report_in_external_macro: true
report_in_external_macro: true,
[loadbearing: true]
}

declare_tool_lint! {
Expand All @@ -434,7 +435,8 @@ declare_tool_lint! {
pub rustc::DIAGNOSTIC_OUTSIDE_OF_IMPL,
Deny,
"prevent diagnostic creation outside of `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls",
report_in_external_macro: true
report_in_external_macro: true,
[loadbearing: true]
}

declare_lint_pass!(Diagnostics => [UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL]);
Expand Down
63 changes: 55 additions & 8 deletions compiler/rustc_lint/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@ use rustc_hir::def_id::{LocalDefId, LocalModDefId};
use rustc_hir::{intravisit as hir_visit, HirId};
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::lint::builtin::HardwiredLints;
use rustc_session::lint::LintPass;
use rustc_session::Session;
use rustc_span::Span;
use tracing::debug;

use crate::passes::LateLintPassObject;
use crate::{LateContext, LateLintPass, LintStore};
use crate::{LateContext, LateLintPass, LintId, LintStore};

/// Extract the [`LintStore`] from [`Session`].
///
Expand Down Expand Up @@ -327,6 +328,9 @@ impl LintPass for RuntimeCombinedLateLintPass<'_, '_> {
fn name(&self) -> &'static str {
panic!()
}
fn get_lints(&self) -> crate::LintVec {
panic!()
}
}

macro_rules! impl_late_lint_pass {
Expand Down Expand Up @@ -362,13 +366,33 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
// 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 late_module_passes = &unerased_lint_store(tcx.sess).late_module_passes;
if late_module_passes.is_empty() {
let store = unerased_lint_store(tcx.sess);

if store.late_module_passes.is_empty() {
late_lint_mod_inner(tcx, module_def_id, context, builtin_lints);
} else {
let mut passes: Vec<_> = late_module_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect();
passes.push(Box::new(builtin_lints));
let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] };
let passes: Vec<_> =
store.late_module_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect();
// Filter unused lints
let lints_that_dont_need_to_run = tcx.lints_that_dont_need_to_run(());
let mut filtered_passes: Vec<Box<dyn LateLintPass<'tcx>>> = passes
.into_iter()
.filter(|pass| {
let lints = LintPass::get_lints(pass);
if lints.is_empty() {
true
} else {
lints
.iter()
.any(|lint| !lints_that_dont_need_to_run.contains(&LintId::of(lint)))
}
})
.collect();

filtered_passes.push(Box::new(builtin_lints));
filtered_passes.push(Box::new(HardwiredLints));

let pass = RuntimeCombinedLateLintPass { passes: &mut filtered_passes[..] };
late_lint_mod_inner(tcx, module_def_id, context, pass);
}
}
Expand Down Expand Up @@ -399,7 +423,7 @@ fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>(

fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) {
// Note: `passes` is often empty.
let mut passes: Vec<_> =
let passes: Vec<_> =
unerased_lint_store(tcx.sess).late_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect();

if passes.is_empty() {
Expand All @@ -417,7 +441,30 @@ fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) {
only_module: false,
};

let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] };
let lints_that_dont_need_to_run = tcx.lints_that_dont_need_to_run(());

// dbg!(&lints_that_dont_need_to_run);
let mut filtered_passes: Vec<Box<dyn LateLintPass<'tcx>>> = passes
.into_iter()
.filter(|pass| {
let lints = LintPass::get_lints(pass);
!lints.iter().all(|lint| lints_that_dont_need_to_run.contains(&LintId::of(lint)))
})
.collect();

filtered_passes.push(Box::new(HardwiredLints));

// let mut filtered_passes: Vec<Box<dyn LateLintPass<'tcx>>> = passes
// .into_iter()
// .filter(|pass| {
// let lints = LintPass::get_lints(pass);
// lints.iter()
// .any(|lint|
// !lints_that_dont_need_to_run.contains(&LintId::of(lint)))
// }).collect();
//

let pass = RuntimeCombinedLateLintPass { passes: &mut filtered_passes[..] };
late_lint_crate_inner(tcx, context, pass);
}

Expand Down
Loading

0 comments on commit 50e9dfe

Please sign in to comment.