Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions compiler/rustc_hir_analysis/src/check/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_lint/src/if_let_rescope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down
10 changes: 3 additions & 7 deletions compiler/rustc_lint/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,18 +348,16 @@ 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`.
let mut passes: Vec<_> = unerased_lint_store(tcx.sess)
.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);
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 0 additions & 6 deletions compiler/rustc_lint/src/levels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,6 @@ fn skippable_lints(tcx: TyCtxt<'_>, (): ()) -> UnordSet<LintId> {
let mut skippable: FxHashSet<LintId> = 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);
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -754,15 +753,15 @@ 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<LintId>, 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() {
return true;
}

// 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)]
Expand Down
16 changes: 16 additions & 0 deletions compiler/rustc_middle/src/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_middle/src/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<LintId> {
arena_cache
// This depends on the lint store, which includes internal lints when the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
3 changes: 1 addition & 2 deletions src/tools/clippy/clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading