From d2d1db8ebe63f7fb127d108112c6ff8cdd128e2e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 9 Jun 2026 18:51:14 +1000 Subject: [PATCH 1/7] Remove lifetime from `RuntimeCombined{Early,Late}LintPass` These structs can own the `Vec`. --- compiler/rustc_lint/src/early.rs | 10 +++++----- compiler/rustc_lint/src/late.rs | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index df6683c14df42..c5c6b6de4cd39 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -246,12 +246,12 @@ impl<'ast, 'ecx, T: EarlyLintPass> ast_visit::Visitor<'ast> for EarlyContextAndP // `check_foo` method in `$methods` within this pass simply calls `check_foo` // once per `$pass`. Compare with `declare_combined_early_lint_pass`, which is // similar, but combines lint passes at compile time. -struct RuntimeCombinedEarlyLintPass<'a> { - passes: &'a mut [EarlyLintPassObject], +struct RuntimeCombinedEarlyLintPass { + passes: Vec, } #[allow(rustc::lint_pass_impl_without_macro)] -impl LintPass for RuntimeCombinedEarlyLintPass<'_> { +impl LintPass for RuntimeCombinedEarlyLintPass { fn name(&self) -> &'static str { panic!() } @@ -262,7 +262,7 @@ impl LintPass for RuntimeCombinedEarlyLintPass<'_> { macro_rules! impl_early_lint_pass { ([], [$($(#[$attr:meta])* fn $f:ident($($param:ident: $arg:ty),*);)*]) => ( - impl EarlyLintPass for RuntimeCombinedEarlyLintPass<'_> { + impl EarlyLintPass for RuntimeCombinedEarlyLintPass { $(fn $f(&mut self, context: &EarlyContext<'_>, $($param: $arg),*) { for pass in self.passes.iter_mut() { pass.$f(context, $($param),*); @@ -338,7 +338,7 @@ pub fn check_ast_node<'a>( } 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[..] }; + let pass = RuntimeCombinedEarlyLintPass { passes }; check_ast_node_inner(sess, check_node, context, pass); } } diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 19008a771dedd..9534a00fbb413 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -305,12 +305,12 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas // `check_foo` method in `$methods` within this pass simply calls `check_foo` // once per `$pass`. Compare with `declare_combined_late_lint_pass`, which is // similar, but combines lint passes at compile time. -struct RuntimeCombinedLateLintPass<'a, 'tcx> { - passes: &'a mut [LateLintPassObject<'tcx>], +struct RuntimeCombinedLateLintPass<'tcx> { + passes: Vec>, } #[allow(rustc::lint_pass_impl_without_macro)] -impl LintPass for RuntimeCombinedLateLintPass<'_, '_> { +impl LintPass for RuntimeCombinedLateLintPass<'_> { fn name(&self) -> &'static str { panic!() } @@ -321,7 +321,7 @@ impl LintPass for RuntimeCombinedLateLintPass<'_, '_> { macro_rules! impl_late_lint_pass { ([], [$($(#[$attr:meta])* fn $f:ident($($param:ident: $arg:ty),*);)*]) => { - impl<'tcx> LateLintPass<'tcx> for RuntimeCombinedLateLintPass<'_, 'tcx> { + impl<'tcx> LateLintPass<'tcx> for RuntimeCombinedLateLintPass<'tcx> { $(fn $f(&mut self, context: &LateContext<'tcx>, $($param: $arg),*) { for pass in self.passes.iter_mut() { pass.$f(context, $($param),*); @@ -367,14 +367,14 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>( } } else { let builtin_lints = Box::new(builtin_lints) as Box>; - let mut binding = store + let passes = store .late_module_passes .iter() .map(|mk_pass| (mk_pass)(tcx)) .chain(std::iter::once(builtin_lints)) .collect::>(); - let pass = RuntimeCombinedLateLintPass { passes: binding.as_mut_slice() }; + let pass = RuntimeCombinedLateLintPass { passes }; late_lint_mod_inner(tcx, module_def_id, context, pass); } } @@ -425,7 +425,7 @@ fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) { let lints_that_dont_need_to_run = tcx.lints_that_dont_need_to_run(()); - let mut filtered_passes: Vec>> = passes + let filtered_passes: Vec>> = passes .into_iter() .filter(|pass| { let lints = (**pass).get_lints(); @@ -436,7 +436,7 @@ fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) { }) .collect(); - let pass = RuntimeCombinedLateLintPass { passes: &mut filtered_passes[..] }; + let pass = RuntimeCombinedLateLintPass { passes: filtered_passes }; let mut cx = LateContextAndPass { context, pass }; // Visit the whole crate. From bde71902e6d37faf402ba0c651dd0d4096b91d64 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 9 Jun 2026 18:54:25 +1000 Subject: [PATCH 2/7] Filter lint passes in place By using `retain` instead of `into_iter`/`filter`/`collect`. --- compiler/rustc_lint/src/late.rs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 9534a00fbb413..5c0cdf799b1be 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -405,7 +405,7 @@ fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>( fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) { // Note: `passes` is often empty. - let passes: Vec<_> = + let mut passes: Vec<_> = unerased_lint_store(tcx.sess).late_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect(); if passes.is_empty() { @@ -425,18 +425,15 @@ fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) { let lints_that_dont_need_to_run = tcx.lints_that_dont_need_to_run(()); - let filtered_passes: Vec>> = passes - .into_iter() - .filter(|pass| { - let lints = (**pass).get_lints(); - // Lintless passes are always in - lints.is_empty() || + passes.retain(|pass| { + let lints = pass.get_lints(); + // Lintless passes are always in + lints.is_empty() || // If the pass doesn't have a single needed lint, omit it !lints.iter().all(|lint| lints_that_dont_need_to_run.contains(&LintId::of(lint))) - }) - .collect(); + }); - let pass = RuntimeCombinedLateLintPass { passes: filtered_passes }; + let pass = RuntimeCombinedLateLintPass { passes }; let mut cx = LateContextAndPass { context, pass }; // Visit the whole crate. From 6f82f62b65dd40c44819a590fdbf767182b2160e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 11 Jun 2026 06:17:02 +1000 Subject: [PATCH 3/7] Remove an unnecessary `'static` bound --- compiler/rustc_lint/src/passes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index 66484b01ff7a8..418d9b4074b48 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -247,5 +247,5 @@ macro_rules! declare_combined_early_lint_pass { } /// A lint pass boxed up as a trait object. -pub(crate) type EarlyLintPassObject = Box; +pub(crate) type EarlyLintPassObject = Box; pub(crate) type LateLintPassObject<'tcx> = Box + 'tcx>; From 777de10b968c7beffb7770693913f27a7b98dd90 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 12 Jun 2026 10:40:00 +1000 Subject: [PATCH 4/7] Rename `{enter,exit}_where_predicate` All the other paired methods in this trait have the form `check_foo`/`check_foo_post`. --- compiler/rustc_lint/src/early.rs | 4 ++-- compiler/rustc_lint/src/passes.rs | 5 ++--- compiler/rustc_lint/src/unused.rs | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index c5c6b6de4cd39..73932203ec74e 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -195,9 +195,9 @@ impl<'ast, 'ecx, T: EarlyLintPass> ast_visit::Visitor<'ast> for EarlyContextAndP } fn visit_where_predicate(&mut self, p: &'ast ast::WherePredicate) { - lint_callback!(self, enter_where_predicate, p); + lint_callback!(self, check_where_predicate, p); ast_visit::walk_where_predicate(self, p); - lint_callback!(self, exit_where_predicate, p); + lint_callback!(self, check_where_predicate_post, p); } fn visit_poly_trait_ref(&mut self, t: &'ast ast::PolyTraitRef) { diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index 418d9b4074b48..b173961703a8e 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -168,9 +168,8 @@ macro_rules! early_lint_methods { fn check_attributes_post(a: &[rustc_ast::Attribute]); fn check_mac_def(a: &rustc_ast::MacroDef); fn check_mac(a: &rustc_ast::MacCall); - - fn enter_where_predicate(a: &rustc_ast::WherePredicate); - fn exit_where_predicate(a: &rustc_ast::WherePredicate); + fn check_where_predicate(a: &rustc_ast::WherePredicate); + fn check_where_predicate_post(a: &rustc_ast::WherePredicate); ]); ) } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 73be0d9a02f3e..dd2cb505cb1bc 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -975,7 +975,7 @@ impl EarlyLintPass for UnusedParens { self.in_no_bounds_pos.clear(); } - fn enter_where_predicate(&mut self, _: &EarlyContext<'_>, pred: &ast::WherePredicate) { + fn check_where_predicate(&mut self, _: &EarlyContext<'_>, pred: &ast::WherePredicate) { use rustc_ast::{WhereBoundPredicate, WherePredicateKind}; if let WherePredicateKind::BoundPredicate(WhereBoundPredicate { bounded_ty, @@ -989,7 +989,7 @@ impl EarlyLintPass for UnusedParens { } } - fn exit_where_predicate(&mut self, _: &EarlyContext<'_>, _: &ast::WherePredicate) { + fn check_where_predicate_post(&mut self, _: &EarlyContext<'_>, _: &ast::WherePredicate) { assert!(!self.with_self_ty_parens); } } From 9f6bdd9a99e83080d229fa476ba2960dc2cb5e45 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 12 Jun 2026 08:20:13 +1000 Subject: [PATCH 5/7] Simplify `{early,late}_lint_methods` use points Currently the use points need to handle method attributes, due to a single low-value doc comment in each macro's body. This commit moves those doc comments so the use points can be simplified. The comments are also made more accurate -- there are now multiple `_post` methods and the comments now cover all of them, not just one of them. --- compiler/rustc_lint/src/passes.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index b173961703a8e..5c101048b8010 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -5,6 +5,7 @@ use crate::context::{EarlyContext, LateContext}; #[macro_export] macro_rules! late_lint_methods { ($macro:path, $args:tt) => ( + // `_post` methods are called *after* recursing into the node. $macro!($args, [ fn check_body(a: &rustc_hir::Body<'tcx>); fn check_body_post(a: &rustc_hir::Body<'tcx>); @@ -13,8 +14,6 @@ macro_rules! late_lint_methods { fn check_mod(a: &'tcx rustc_hir::Mod<'tcx>, b: rustc_hir::HirId); fn check_foreign_item(a: &'tcx rustc_hir::ForeignItem<'tcx>); fn check_item(a: &'tcx rustc_hir::Item<'tcx>); - /// This is called *after* recursing into the item - /// (in contrast to `check_item`, which is checked before). fn check_item_post(a: &'tcx rustc_hir::Item<'tcx>); fn check_local(a: &'tcx rustc_hir::LetStmt<'tcx>); fn check_block(a: &'tcx rustc_hir::Block<'tcx>); @@ -59,7 +58,7 @@ macro_rules! late_lint_methods { // contains a few lint-specific methods with no equivalent in `Visitor`. // macro_rules! declare_late_lint_pass { - ([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( + ([], [$(fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( pub trait LateLintPass<'tcx>: LintPass { $(#[inline(always)] fn $name(&mut self, _: &LateContext<'tcx>, $(_: $arg),*) {})* } @@ -79,7 +78,7 @@ macro_rules! expand_combined_late_lint_pass_method { #[macro_export] macro_rules! expand_combined_late_lint_pass_methods { - ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( + ($passes:tt, [$(fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( $(fn $name(&mut self, context: &$crate::LateContext<'tcx>, $($param: $arg),*) { $crate::expand_combined_late_lint_pass_method!($passes, self, $name, (context, $($param),*)); })* @@ -132,14 +131,13 @@ macro_rules! declare_combined_late_lint_pass { #[macro_export] macro_rules! early_lint_methods { ($macro:path, $args:tt) => ( + // `_post` methods are called *after* recursing into the node. $macro!($args, [ fn check_param(a: &rustc_ast::Param); fn check_ident(a: &rustc_span::Ident); fn check_crate(a: &rustc_ast::Crate); fn check_crate_post(a: &rustc_ast::Crate); fn check_item(a: &rustc_ast::Item); - /// This is called *after* recursing into the item - /// (in contrast to `check_item`, which is checked before). fn check_item_post(a: &rustc_ast::Item); fn check_local(a: &rustc_ast::Local); fn check_block(a: &rustc_ast::Block); @@ -175,7 +173,7 @@ macro_rules! early_lint_methods { } macro_rules! declare_early_lint_pass { - ([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( + ([], [$(fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( pub trait EarlyLintPass: LintPass { $(#[inline(always)] fn $name(&mut self, _: &EarlyContext<'_>, $(_: $arg),*) {})* } @@ -195,7 +193,7 @@ macro_rules! expand_combined_early_lint_pass_method { #[macro_export] macro_rules! expand_combined_early_lint_pass_methods { - ($passes:tt, [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( + ($passes:tt, [$(fn $name:ident($($param:ident: $arg:ty),*);)*]) => ( $(fn $name(&mut self, context: &$crate::EarlyContext<'_>, $($param: $arg),*) { $crate::expand_combined_early_lint_pass_method!($passes, self, $name, (context, $($param),*)); })* From 4ff19e3f04a1801a4768d8a0fdb2dc3481d17f49 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 12 Jun 2026 11:07:40 +1000 Subject: [PATCH 6/7] Put a box within `{Early,Late}LintPassFactory` That reflects how they're mostly used and avoids the need for some long signatures. And it matches `{Early,Late}LintPassObject` nicely. --- compiler/rustc_lint/src/context.rs | 46 ++++++++---------------- compiler/rustc_lint/src/lib.rs | 4 +-- src/tools/clippy/clippy_lints/src/lib.rs | 4 ++- 3 files changed, 19 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 4ea1a3f1209e4..5599e3cdafd63 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -40,9 +40,9 @@ use self::TargetLint::*; use crate::levels::LintLevelsBuilder; use crate::passes::{EarlyLintPassObject, LateLintPassObject}; -type EarlyLintPassFactory = dyn Fn() -> EarlyLintPassObject + sync::DynSend + sync::DynSync; +type EarlyLintPassFactory = Box EarlyLintPassObject + sync::DynSend + sync::DynSync>; type LateLintPassFactory = - dyn for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::DynSend + sync::DynSync; + Box Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> + sync::DynSend + sync::DynSync>; /// Information about the registered lints. pub struct LintStore { @@ -55,11 +55,11 @@ pub struct LintStore { /// interior mutability, we don't enforce this (and lints should, in theory, /// be compatible with being constructed more than once, though not /// necessarily in a sane manner. This is safe though.) - pub pre_expansion_passes: Vec>, - pub early_passes: Vec>, - pub late_passes: Vec>, + pub pre_expansion_passes: Vec, + pub early_passes: Vec, + pub late_passes: Vec, /// This is unique in that we construct them per-module, so not once. - pub late_module_passes: Vec>, + pub late_module_passes: Vec, /// Lints indexed by name. by_name: UnordMap, @@ -165,11 +165,8 @@ impl LintStore { self.lint_groups.keys().copied() } - pub fn register_early_pass( - &mut self, - pass: impl Fn() -> EarlyLintPassObject + 'static + sync::DynSend + sync::DynSync, - ) { - self.early_passes.push(Box::new(pass)); + pub fn register_early_pass(&mut self, pass: EarlyLintPassFactory) { + self.early_passes.push(pass); } /// This lint pass is softly deprecated. It misses expanded code and has caused a few @@ -178,31 +175,16 @@ impl LintStore { /// /// * See [rust#69838](https://github.com/rust-lang/rust/pull/69838) /// * See [rust-clippy#5518](https://github.com/rust-lang/rust-clippy/pull/5518) - pub fn register_pre_expansion_pass( - &mut self, - pass: impl Fn() -> EarlyLintPassObject + 'static + sync::DynSend + sync::DynSync, - ) { - self.pre_expansion_passes.push(Box::new(pass)); + pub fn register_pre_expansion_pass(&mut self, pass: EarlyLintPassFactory) { + self.pre_expansion_passes.push(pass); } - pub fn register_late_pass( - &mut self, - pass: impl for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> - + 'static - + sync::DynSend - + sync::DynSync, - ) { - self.late_passes.push(Box::new(pass)); + pub fn register_late_pass(&mut self, pass: LateLintPassFactory) { + self.late_passes.push(pass); } - pub fn register_late_mod_pass( - &mut self, - pass: impl for<'tcx> Fn(TyCtxt<'tcx>) -> LateLintPassObject<'tcx> - + 'static - + sync::DynSend - + sync::DynSync, - ) { - self.late_module_passes.push(Box::new(pass)); + pub fn register_late_mod_pass(&mut self, pass: LateLintPassFactory) { + self.late_module_passes.push(pass); } /// Helper method for register_early/late_pass diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index ab09c648adcd9..91267c2445ac4 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -694,10 +694,10 @@ fn register_builtins(store: &mut LintStore) { fn register_internals(store: &mut LintStore) { store.register_lints(&InternalCombinedEarlyLintPass::lint_vec()); - store.register_early_pass(|| Box::new(InternalCombinedEarlyLintPass::new())); + store.register_early_pass(Box::new(|| Box::new(InternalCombinedEarlyLintPass::new()))); store.register_lints(&InternalCombinedModuleLateLintPass::lint_vec()); - store.register_late_mod_pass(|_| Box::new(InternalCombinedModuleLateLintPass::new())); + store.register_late_mod_pass(Box::new(|_| Box::new(InternalCombinedModuleLateLintPass::new()))); store.register_group( false, diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 4a7659a9cc210..12d53e742f19a 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -454,7 +454,9 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co // NOTE: Do not add any more pre-expansion passes. These should be removed eventually. // Due to the architecture of the compiler, currently `cfg_attr` attributes on crate // level (i.e `#![cfg_attr(...)]`) will still be expanded even when using a pre-expansion pass. - store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes::new(conf))); + store.register_pre_expansion_pass( + Box::new(move || Box::new(attrs::EarlyAttributes::new(conf))) + ); let format_args_storage = FormatArgsStorage::default(); let attr_storage = AttrStorage::default(); From 618f5cd5c3e718a50f62ef1ed988b9a44515132e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 15 Jun 2026 12:12:35 +1000 Subject: [PATCH 7/7] Move empty passes check in `late_lint_crate` We check if `passes` is empty and then filter elements out of it. This means we can miss optimizing some cases, e.g. when bootstrapping. This commit moves the `is_empty` check after the filtering. --- compiler/rustc_lint/src/late.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 5c0cdf799b1be..1f37ac2d3e0bc 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -404,10 +404,18 @@ fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>( } fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) { - // Note: `passes` is often empty. + let lints_that_dont_need_to_run = tcx.lints_that_dont_need_to_run(()); + + // Note: `passes` is often empty after filtering. let mut passes: Vec<_> = unerased_lint_store(tcx.sess).late_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect(); - + passes.retain(|pass| { + let lints = pass.get_lints(); + // Lintless passes are always in + lints.is_empty() || + // If the pass doesn't have a single needed lint, omit it + !lints.iter().all(|lint| lints_that_dont_need_to_run.contains(&LintId::of(lint))) + }); if passes.is_empty() { return; } @@ -423,16 +431,6 @@ fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) { only_module: false, }; - let lints_that_dont_need_to_run = tcx.lints_that_dont_need_to_run(()); - - passes.retain(|pass| { - let lints = pass.get_lints(); - // Lintless passes are always in - lints.is_empty() || - // If the pass doesn't have a single needed lint, omit it - !lints.iter().all(|lint| lints_that_dont_need_to_run.contains(&LintId::of(lint))) - }); - let pass = RuntimeCombinedLateLintPass { passes }; let mut cx = LateContextAndPass { context, pass };