diff options
| author | bors <bors@rust-lang.org> | 2024-09-23 19:39:12 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-09-23 19:39:12 +0000 |
| commit | 8ab744e2d195d3afc61ac9aa0dc9a5a36863437a (patch) | |
| tree | 4441ab0b3424784811eab75ac722bb332db2f7b1 | |
| parent | b7ab258a0ea47c020d8e6569e5d8295d8104a513 (diff) | |
| parent | 6b34c8df2cd5db6626e00564446b886b3827b080 (diff) | |
| download | rust-8ab744e2d195d3afc61ac9aa0dc9a5a36863437a.tar.gz rust-8ab744e2d195d3afc61ac9aa0dc9a5a36863437a.zip | |
Auto merge of #13431 - GnomedDev:split-def_path_res, r=y21
Split def_path_res into two parts `def_path_res` previously had two jobs: 1. looking up the crates to find the path in 2. looking up path in said crates This splits that job up into two functions, keeping `def_path_res` as an adapter between the both, to avoid repeating the first step when repeatedly looking up items in the same crate. changelog: none
| -rw-r--r-- | clippy_lints/src/regex.rs | 15 | ||||
| -rw-r--r-- | clippy_utils/src/lib.rs | 40 |
2 files changed, 34 insertions, 21 deletions
diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index f6ef02b7c23..12cbdb854ef 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -3,7 +3,7 @@ use std::fmt::Display; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::source::SpanRangeExt; -use clippy_utils::{def_path_def_ids, path_def_id, paths}; +use clippy_utils::{def_path_res_with_base, find_crates, path_def_id, paths}; use rustc_ast::ast::{LitKind, StrStyle}; use rustc_hir::def_id::DefIdMap; use rustc_hir::{BorrowKind, Expr, ExprKind}; @@ -75,11 +75,14 @@ impl<'tcx> LateLintPass<'tcx> for Regex { // We don't use `match_def_path` here because that relies on matching the exact path, which changed // between regex 1.8 and 1.9 // - // `def_path_def_ids` will resolve through re-exports but is relatively heavy, so we only perform - // the operation once and store the results - let mut resolve = |path, kind| { - for id in def_path_def_ids(cx.tcx, path) { - self.definitions.insert(id, kind); + // `def_path_res_with_base` will resolve through re-exports but is relatively heavy, so we only + // perform the operation once and store the results + let regex_crates = find_crates(cx.tcx, sym!(regex)); + let mut resolve = |path: &[&str], kind: RegexKind| { + for res in def_path_res_with_base(cx.tcx, regex_crates.clone(), &path[1..]) { + if let Some(id) = res.opt_def_id() { + self.definitions.insert(id, kind); + } } }; diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index a925549b0bf..2fee6473910 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -671,6 +671,17 @@ fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Re } } +/// Finds the crates called `name`, may be multiple due to multiple major versions. +pub fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> Vec<Res> { + tcx.crates(()) + .iter() + .copied() + .filter(move |&num| tcx.crate_name(num) == name) + .map(CrateNum::as_def_id) + .map(|id| Res::Def(tcx.def_kind(id), id)) + .collect() +} + /// Resolves a def path like `std::vec::Vec`. /// /// Can return multiple resolutions when there are multiple versions of the same crate, e.g. @@ -681,15 +692,7 @@ fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Re /// /// This function is expensive and should be used sparingly. pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> { - fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> impl Iterator<Item = DefId> + '_ { - tcx.crates(()) - .iter() - .copied() - .filter(move |&num| tcx.crate_name(num) == name) - .map(CrateNum::as_def_id) - } - - let (base, mut path) = match *path { + let (base, path) = match *path { [primitive] => { return vec![PrimTy::from_name(Symbol::intern(primitive)).map_or(Res::Err, Res::PrimTy)]; }, @@ -705,18 +708,25 @@ pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> { None }; - let starts = find_primitive_impls(tcx, base) - .chain(find_crates(tcx, base_sym)) + let crates = find_primitive_impls(tcx, base) .chain(local_crate) - .map(|id| Res::Def(tcx.def_kind(id), id)); + .map(|id| Res::Def(tcx.def_kind(id), id)) + .chain(find_crates(tcx, base_sym)) + .collect(); - let mut resolutions: Vec<Res> = starts.collect(); + def_path_res_with_base(tcx, crates, path) +} +/// Resolves a def path like `vec::Vec` with the base `std`. +/// +/// This is lighter than [`def_path_res`], and should be called with [`find_crates`] looking up +/// items from the same crate repeatedly, although should still be used sparingly. +pub fn def_path_res_with_base(tcx: TyCtxt<'_>, mut base: Vec<Res>, mut path: &[&str]) -> Vec<Res> { while let [segment, rest @ ..] = path { path = rest; let segment = Symbol::intern(segment); - resolutions = resolutions + base = base .into_iter() .filter_map(|res| res.opt_def_id()) .flat_map(|def_id| { @@ -735,7 +745,7 @@ pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> { .collect(); } - resolutions + base } /// Resolves a def path like `std::vec::Vec` to its [`DefId`]s, see [`def_path_res`]. |
