mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-24 13:43:17 +00:00
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
This commit is contained in:
commit
8ab744e2d1
2 changed files with 34 additions and 21 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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`].
|
||||
|
|
Loading…
Reference in a new issue