about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSamuel Tardieu <sam@rfc1149.net>2025-08-06 16:09:13 +0200
committerSamuel Tardieu <sam@rfc1149.net>2025-08-06 16:30:31 +0200
commit26911aa32cd4fd4b759a578ce3a244e0dcdad14c (patch)
tree0f1e3f3bc646a602769c0556a8d1bb859028470d
parent7673826138e7fee1534b7bbf7bf4d8651c924166 (diff)
downloadrust-26911aa32cd4fd4b759a578ce3a244e0dcdad14c.tar.gz
rust-26911aa32cd4fd4b759a578ce3a244e0dcdad14c.zip
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.
-rw-r--r--clippy_lints/src/incompatible_msrv.rs23
-rw-r--r--clippy_lints/src/lib.rs2
2 files changed, 12 insertions, 13 deletions
diff --git a/clippy_lints/src/incompatible_msrv.rs b/clippy_lints/src/incompatible_msrv.rs
index 116d63c3bb1..c905067277a 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<CrateNum>,
 }
 
 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 3e3b4253f80..4f963f699d7 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::<unconditional_recursion::UnconditionalRecursion>::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)));