Split def_path_res into two parts

This commit is contained in:
GnomedDev 2024-09-21 16:11:15 +01:00
parent 43e3384581
commit d099ceddad
No known key found for this signature in database
GPG Key ID: 9BF10F8372B254D1
1 changed files with 25 additions and 15 deletions

View File

@ -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`. /// Resolves a def path like `std::vec::Vec`.
/// ///
/// Can return multiple resolutions when there are multiple versions of the same crate, e.g. /// 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. /// This function is expensive and should be used sparingly.
pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> { pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> {
fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> impl Iterator<Item = DefId> + '_ { let (base, path) = match *path {
tcx.crates(())
.iter()
.copied()
.filter(move |&num| tcx.crate_name(num) == name)
.map(CrateNum::as_def_id)
}
let (base, mut path) = match *path {
[primitive] => { [primitive] => {
return vec![PrimTy::from_name(Symbol::intern(primitive)).map_or(Res::Err, Res::PrimTy)]; 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 None
}; };
let starts = find_primitive_impls(tcx, base) let crates = find_primitive_impls(tcx, base)
.chain(find_crates(tcx, base_sym))
.chain(local_crate) .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 { while let [segment, rest @ ..] = path {
path = rest; path = rest;
let segment = Symbol::intern(segment); let segment = Symbol::intern(segment);
resolutions = resolutions base = base
.into_iter() .into_iter()
.filter_map(|res| res.opt_def_id()) .filter_map(|res| res.opt_def_id())
.flat_map(|def_id| { .flat_map(|def_id| {
@ -735,7 +745,7 @@ pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> {
.collect(); .collect();
} }
resolutions base
} }
/// Resolves a def path like `std::vec::Vec` to its [`DefId`]s, see [`def_path_res`]. /// Resolves a def path like `std::vec::Vec` to its [`DefId`]s, see [`def_path_res`].