From a7a690762c2db6aa47ab11be381d3767cc6aad0c Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Wed, 29 Jul 2026 23:52:43 +0000 Subject: [PATCH] Hide skippable_lints. --- compiler/rustc_hir_analysis/src/check/region.rs | 5 +---- compiler/rustc_lint/src/if_let_rescope.rs | 5 ++--- compiler/rustc_lint/src/late.rs | 10 +++------- compiler/rustc_lint/src/levels.rs | 6 ------ compiler/rustc_lint/src/lib.rs | 5 ++--- compiler/rustc_middle/src/lint.rs | 16 ++++++++++++++++ compiler/rustc_middle/src/queries.rs | 2 ++ .../src/lint_tail_expr_drop_order.rs | 3 +-- src/tools/clippy/clippy_lints/src/lib.rs | 3 +-- 9 files changed, 28 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index e60318756d5c7..8d0515f8b8556 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -146,10 +146,7 @@ fn resolve_block<'tcx>( let edition = blk.span.edition(); let terminating = edition.at_least_rust_2024(); if !terminating - && !visitor - .tcx - .skippable_lints(()) - .contains(&lint::LintId::of(lint::builtin::TAIL_EXPR_DROP_ORDER)) + && !visitor.tcx.lint_should_be_skipped(lint::builtin::TAIL_EXPR_DROP_ORDER) { // If this temporary scope will be changing once the codebase adopts Rust 2024, // and we are linting about possible semantic changes that would result, diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 60ee55e299d87..30bc8724cc3c9 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -11,7 +11,7 @@ use rustc_middle::ty::significant_drop_order::{ extract_component_with_significant_dtor, ty_dtor_span, }; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_session::lint::{LintId, fcw}; +use rustc_session::lint::fcw; use rustc_session::{declare_lint, impl_lint_pass}; use rustc_span::{DUMMY_SP, Span}; use smallvec::SmallVec; @@ -268,8 +268,7 @@ impl_lint_pass!( impl<'tcx> LateLintPass<'tcx> for IfLetRescope { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { - if expr.span.edition().at_least_rust_2024() - || cx.tcx.skippable_lints(()).contains(&LintId::of(IF_LET_RESCOPE)) + if expr.span.edition().at_least_rust_2024() || cx.tcx.lint_should_be_skipped(IF_LET_RESCOPE) { return; } diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 227bff83cabbf..5f3e902239c36 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -348,8 +348,6 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>( only_module: true, }; - let skippable_lints = tcx.skippable_lints(()); - // Note: `passes` is often empty. In that case, it's faster to run // `builtin_lints` directly rather than bundling it up into the // `RuntimeCombinedLateLintPass`. @@ -357,9 +355,9 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>( .late_lint_mod_passes .iter() .map(|mk_pass| mk_pass(tcx)) - .filter(|pass| is_lint_pass_required(skippable_lints, &pass.get_lints())) + .filter(|pass| is_lint_pass_required(tcx, &pass.get_lints())) .collect(); - let builtin_lints_must_run = is_lint_pass_required(skippable_lints, &builtin_lints.get_lints()); + let builtin_lints_must_run = is_lint_pass_required(tcx, &builtin_lints.get_lints()); if passes.is_empty() { if builtin_lints_must_run { late_lint_mod_inner(tcx, mod_id, context, builtin_lints); @@ -398,14 +396,12 @@ fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>( } fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) { - let skippable_lints = tcx.skippable_lints(()); - // Note: `passes` is often empty after filtering. let passes: Vec<_> = unerased_lint_store(tcx.sess) .late_lint_passes .iter() .map(|mk_pass| mk_pass(tcx)) - .filter(|pass| is_lint_pass_required(skippable_lints, &pass.get_lints())) + .filter(|pass| is_lint_pass_required(tcx, &pass.get_lints())) .collect(); if passes.is_empty() { return; diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 5671e86283f9b..a30f43bf1ca91 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -121,12 +121,6 @@ fn skippable_lints(tcx: TyCtxt<'_>, (): ()) -> UnordSet { let mut skippable: FxHashSet = store .get_lints() .into_iter() - .filter(|lint| { - // Lints that show up in future-compat reports must always be run. - let has_future_breakage = - lint.future_incompatible.is_some_and(|fut| fut.report_in_deps); - !has_future_breakage && !lint.eval_always - }) .filter(|lint| { let level_spec = root_map.lint_level_spec_at_node(tcx, LintId::of(lint), hir::CRATE_HIR_ID); diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 244db06a11d60..6cf5f9ba5e447 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -120,7 +120,6 @@ use ptr_nulls::*; use redundant_semicolon::*; use reference_casting::*; use runtime_symbols::*; -use rustc_data_structures::unord::UnordSet; use rustc_hir::def_id::LocalModId; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; @@ -754,7 +753,7 @@ fn register_internals(store: &mut LintStore) { /// /// Note: this is a conservative estimate intended for optimization purposes. It might return /// `true` for a pass that need not run, but it will never return `false` for a pass that must run. -pub fn is_lint_pass_required(skippable: &UnordSet, lints: &LintVec) -> bool { +pub fn is_lint_pass_required(tcx: TyCtxt<'_>, lints: &LintVec) -> bool { // A pass without any lints? Clippy sometimes does this, to collect things while traversing. // Such a pass must always run. if lints.is_empty() { @@ -762,7 +761,7 @@ pub fn is_lint_pass_required(skippable: &UnordSet, lints: &LintVec) -> b } // Otherwise, the pass must run unless all lints within are skippable. - !lints.iter().all(|lint| skippable.contains(&LintId::of(lint))) + !lints.iter().all(|lint| tcx.lint_should_be_skipped(lint)) } #[cfg(test)] diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index b852a107d3343..21ae6cc3a70f5 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -244,6 +244,22 @@ impl ShallowLintLevelMap { } impl TyCtxt<'_> { + /// Return whether the code to produce this lint can be skipped. + pub fn lint_should_be_skipped(self, lint: &'static Lint) -> bool { + if lint.eval_always { + return false; + } + + // Lints that show up in future-compat reports must always be run. + if let Some(fut) = lint.future_incompatible + && fut.report_in_deps + { + return false; + } + + self.skippable_lints(()).contains(&LintId::of(lint)) + } + /// Fetch and return the user-visible lint level spec for the given lint at the given HirId. pub fn lint_level_spec_at_node(self, lint: &'static Lint, id: HirId) -> StableLevelSpec { self.shallow_lint_levels_on(id.owner).lint_level_spec_at_node(self, LintId::of(lint), id) diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index d455abeaf23ac..f35360baf7279 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -547,6 +547,8 @@ rustc_queries! { desc { "computing `#[expect]`ed lints in this crate" } } + /// Gathers lints that are alloed in the whole crate and do not need to be computed. + /// Do not use this query directly, use `tcx.lint_should_be_skipped(lint)` instead. query skippable_lints(_: ()) -> &'tcx UnordSet { arena_cache // This depends on the lint store, which includes internal lints when the diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs index fe09594d7c5f3..fd175c6f0a3ff 100644 --- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs +++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs @@ -186,8 +186,7 @@ pub(crate) fn run_lint<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &Body< // A synthetic coroutine has no HIR body and it is enough to just analyse the original body return; } - if body.span.edition().at_least_rust_2024() - || tcx.skippable_lints(()).contains(&lint::LintId::of(TAIL_EXPR_DROP_ORDER)) + if body.span.edition().at_least_rust_2024() || tcx.lint_should_be_skipped(TAIL_EXPR_DROP_ORDER) { return; } diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 974abc30db0fd..f3b99ee0911aa 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -469,8 +469,7 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co } store.register_late_lint_pass(Box::new(move |tcx: TyCtxt<'_>| { - let skippable_lints = tcx.skippable_lints(()); - let is_active = |lints: &rustc_lint::LintVec| is_lint_pass_required(skippable_lints, lints); + let is_active = |lints: &rustc_lint::LintVec| is_lint_pass_required(tcx, lints); Box::new(CombinedLateLintPass::new( tcx, conf,