@@ -673,6 +673,17 @@ fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Re
673
673
}
674
674
}
675
675
676
+ /// Finds the crates called `name`, may be multiple due to multiple major versions.
677
+ pub fn find_crates ( tcx : TyCtxt < ' _ > , name : Symbol ) -> Vec < Res > {
678
+ tcx. crates ( ( ) )
679
+ . iter ( )
680
+ . copied ( )
681
+ . filter ( move |& num| tcx. crate_name ( num) == name)
682
+ . map ( CrateNum :: as_def_id)
683
+ . map ( |id| Res :: Def ( tcx. def_kind ( id) , id) )
684
+ . collect ( )
685
+ }
686
+
676
687
/// Resolves a def path like `std::vec::Vec`.
677
688
///
678
689
/// Can return multiple resolutions when there are multiple versions of the same crate, e.g.
@@ -683,15 +694,7 @@ fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Re
683
694
///
684
695
/// This function is expensive and should be used sparingly.
685
696
pub fn def_path_res ( tcx : TyCtxt < ' _ > , path : & [ & str ] ) -> Vec < Res > {
686
- fn find_crates ( tcx : TyCtxt < ' _ > , name : Symbol ) -> impl Iterator < Item = DefId > + ' _ {
687
- tcx. crates ( ( ) )
688
- . iter ( )
689
- . copied ( )
690
- . filter ( move |& num| tcx. crate_name ( num) == name)
691
- . map ( CrateNum :: as_def_id)
692
- }
693
-
694
- let ( base, mut path) = match * path {
697
+ let ( base, path) = match * path {
695
698
[ primitive] => {
696
699
return vec ! [ PrimTy :: from_name( Symbol :: intern( primitive) ) . map_or( Res :: Err , Res :: PrimTy ) ] ;
697
700
} ,
@@ -707,18 +710,25 @@ pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> {
707
710
None
708
711
} ;
709
712
710
- let starts = find_primitive_impls ( tcx, base)
711
- . chain ( find_crates ( tcx, base_sym) )
713
+ let crates = find_primitive_impls ( tcx, base)
712
714
. chain ( local_crate)
713
- . map ( |id| Res :: Def ( tcx. def_kind ( id) , id) ) ;
715
+ . map ( |id| Res :: Def ( tcx. def_kind ( id) , id) )
716
+ . chain ( find_crates ( tcx, base_sym) )
717
+ . collect ( ) ;
714
718
715
- let mut resolutions: Vec < Res > = starts. collect ( ) ;
719
+ def_path_res_in_crates ( tcx, crates, path)
720
+ }
716
721
722
+ /// Resolves a def path like `vec::Vec` with the crate `std`.
723
+ ///
724
+ /// This is lighter than [`def_path_res`], and should be called with [`find_crates`] looking up
725
+ /// items from the same crate repeatedly, although should still be used sparingly.
726
+ pub fn def_path_res_in_crates ( tcx : TyCtxt < ' _ > , mut crates : Vec < Res > , mut path : & [ & str ] ) -> Vec < Res > {
717
727
while let [ segment, rest @ ..] = path {
718
728
path = rest;
719
729
let segment = Symbol :: intern ( segment) ;
720
730
721
- resolutions = resolutions
731
+ crates = crates
722
732
. into_iter ( )
723
733
. filter_map ( |res| res. opt_def_id ( ) )
724
734
. flat_map ( |def_id| {
@@ -737,7 +747,7 @@ pub fn def_path_res(tcx: TyCtxt<'_>, path: &[&str]) -> Vec<Res> {
737
747
. collect ( ) ;
738
748
}
739
749
740
- resolutions
750
+ crates
741
751
}
742
752
743
753
/// Resolves a def path like `std::vec::Vec` to its [`DefId`]s, see [`def_path_res`].
0 commit comments