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.
This commit is contained in:
Samuel Tardieu 2025-08-06 16:09:13 +02:00
parent 7673826138
commit 26911aa32c
No known key found for this signature in database
GPG key ID: BDDC3208C6FEAFA8
2 changed files with 12 additions and 13 deletions

View file

@ -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;
}

View file

@ -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)));