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