From 26911aa32cd4fd4b759a578ce3a244e0dcdad14c Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Wed, 6 Aug 2025 16:09:13 +0200 Subject: [PATCH] Optimize `incompatible_msrv` lint This limits repeated lookups in pre-checks (to determine if a MSRV should be checked), especially when those require locking up an interner: - The `core` crate is looked up once when creating the lint, instead of comparing the crate name with `sym::core` at every check. - `span.ctxt().outer_expn_data()` is lookup up only once. --- clippy_lints/src/incompatible_msrv.rs | 23 +++++++++++------------ clippy_lints/src/lib.rs | 2 +- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/clippy_lints/src/incompatible_msrv.rs b/clippy_lints/src/incompatible_msrv.rs index 116d63c3bb15..c905067277aa 100644 --- a/clippy_lints/src/incompatible_msrv.rs +++ b/clippy_lints/src/incompatible_msrv.rs @@ -9,7 +9,7 @@ use rustc_hir::{self as hir, AmbigArg, Expr, ExprKind, HirId, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::TyCtxt; use rustc_session::impl_lint_pass; -use rustc_span::def_id::DefId; +use rustc_span::def_id::{CrateNum, DefId}; use rustc_span::{ExpnKind, Span, sym}; declare_clippy_lint! { @@ -83,16 +83,22 @@ pub struct IncompatibleMsrv { msrv: Msrv, availability_cache: FxHashMap<(DefId, bool), Availability>, check_in_tests: bool, + core_crate: Option, } impl_lint_pass!(IncompatibleMsrv => [INCOMPATIBLE_MSRV]); impl IncompatibleMsrv { - pub fn new(conf: &'static Conf) -> Self { + pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self { Self { msrv: conf.msrv, availability_cache: FxHashMap::default(), check_in_tests: conf.check_incompatible_msrv_in_tests, + core_crate: tcx + .crates(()) + .iter() + .find(|krate| tcx.crate_name(**krate) == sym::core) + .copied(), } } @@ -140,23 +146,16 @@ impl IncompatibleMsrv { // We don't check local items since their MSRV is supposed to always be valid. return; } - if let ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) = span.ctxt().outer_expn_data().kind { + let expn_data = span.ctxt().outer_expn_data(); + if let ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) = expn_data.kind { // Desugared expressions get to cheat and stability is ignored. // Intentionally not using `.from_expansion()`, since we do still care about macro expansions return; } - // Functions coming from `core` while expanding a macro such as `assert*!()` get to cheat too: the // macros may have existed prior to the checked MSRV, but their expansion with a recent compiler // might use recent functions or methods. Compiling with an older compiler would not use those. - if span.from_expansion() - && cx.tcx.crate_name(def_id.krate) == sym::core - && span - .ctxt() - .outer_expn_data() - .macro_def_id - .is_some_and(|def_id| cx.tcx.crate_name(def_id.krate) == sym::core) - { + if Some(def_id.krate) == self.core_crate && expn_data.macro_def_id.map(|did| did.krate) == self.core_crate { return; } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3e3b4253f801..4f963f699d7d 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -797,7 +797,7 @@ pub fn register_lint_passes(store: &mut rustc_lint::LintStore, conf: &'static Co store.register_late_pass(|_| Box::::default()); store.register_late_pass(move |_| Box::new(pub_underscore_fields::PubUnderscoreFields::new(conf))); store.register_late_pass(move |_| Box::new(missing_const_for_thread_local::MissingConstForThreadLocal::new(conf))); - store.register_late_pass(move |_| Box::new(incompatible_msrv::IncompatibleMsrv::new(conf))); + store.register_late_pass(move |tcx| Box::new(incompatible_msrv::IncompatibleMsrv::new(tcx, conf))); store.register_late_pass(|_| Box::new(to_string_trait_impl::ToStringTraitImpl)); store.register_early_pass(|| Box::new(multiple_bound_locations::MultipleBoundLocations)); store.register_late_pass(move |_| Box::new(assigning_clones::AssigningClones::new(conf)));