@@ -38,26 +38,66 @@ impl TyFingerprint {
3838 }
3939}
4040
41+ /// A queryable and mergeable collection of impls.
4142#[ derive( Debug , PartialEq , Eq ) ]
4243pub struct CrateImplDefs {
43- impls : FxHashMap < TyFingerprint , Vec < ImplId > > ,
44+ inherent_impls : FxHashMap < TyFingerprint , Vec < ImplId > > ,
4445 impls_by_trait : FxHashMap < TraitId , FxHashMap < Option < TyFingerprint > , Vec < ImplId > > > ,
4546}
4647
4748impl CrateImplDefs {
4849 pub ( crate ) fn impls_in_crate_query ( db : & dyn HirDatabase , krate : CrateId ) -> Arc < CrateImplDefs > {
4950 let _p = profile ( "impls_in_crate_query" ) ;
50- let mut res =
51- CrateImplDefs { impls : FxHashMap :: default ( ) , impls_by_trait : FxHashMap :: default ( ) } ;
51+ let mut res = CrateImplDefs {
52+ inherent_impls : FxHashMap :: default ( ) ,
53+ impls_by_trait : FxHashMap :: default ( ) ,
54+ } ;
55+ res. fill ( db, krate) ;
56+
57+ Arc :: new ( res)
58+ }
59+
60+ /// Collects all impls from transitive dependencies of `krate` that may be used by `krate`.
61+ ///
62+ /// The full set of impls that can be used by `krate` is the returned map plus all the impls
63+ /// from `krate` itself.
64+ pub ( crate ) fn impls_from_deps_query (
65+ db : & dyn HirDatabase ,
66+ krate : CrateId ,
67+ ) -> Arc < CrateImplDefs > {
68+ // FIXME: This should take visibility and orphan rules into account to keep the result
69+ // smaller.
70+ let _p = profile ( "impls_from_deps_query" ) ;
71+ let crate_graph = db. crate_graph ( ) ;
72+ let mut res = CrateImplDefs {
73+ inherent_impls : FxHashMap :: default ( ) ,
74+ impls_by_trait : FxHashMap :: default ( ) ,
75+ } ;
76+ let mut seen = FxHashSet :: default ( ) ;
77+ let mut worklist = vec ! [ krate] ;
78+ while let Some ( krate) = worklist. pop ( ) {
79+ if !seen. insert ( krate) {
80+ continue ;
81+ }
5282
83+ // No deduplication, since a) impls can't be reexported, b) we visit a crate only once
84+ res. fill ( db, krate) ;
85+
86+ worklist. extend ( crate_graph[ krate] . dependencies . iter ( ) . map ( |dep| dep. crate_id ) ) ;
87+ }
88+
89+ Arc :: new ( res)
90+ }
91+
92+ fn fill ( & mut self , db : & dyn HirDatabase , krate : CrateId ) {
5393 let crate_def_map = db. crate_def_map ( krate) ;
5494 for ( _module_id, module_data) in crate_def_map. modules . iter ( ) {
5595 for impl_id in module_data. scope . impls ( ) {
5696 match db. impl_trait ( impl_id) {
5797 Some ( tr) => {
5898 let self_ty = db. impl_self_ty ( impl_id) ;
5999 let self_ty_fp = TyFingerprint :: for_impl ( & self_ty. value ) ;
60- res . impls_by_trait
100+ self . impls_by_trait
61101 . entry ( tr. value . trait_ )
62102 . or_default ( )
63103 . entry ( self_ty_fp)
@@ -67,18 +107,17 @@ impl CrateImplDefs {
67107 None => {
68108 let self_ty = db. impl_self_ty ( impl_id) ;
69109 if let Some ( self_ty_fp) = TyFingerprint :: for_impl ( & self_ty. value ) {
70- res . impls . entry ( self_ty_fp) . or_default ( ) . push ( impl_id) ;
110+ self . inherent_impls . entry ( self_ty_fp) . or_default ( ) . push ( impl_id) ;
71111 }
72112 }
73113 }
74114 }
75115 }
76-
77- Arc :: new ( res)
78116 }
117+
79118 pub fn lookup_impl_defs ( & self , ty : & Ty ) -> impl Iterator < Item = ImplId > + ' _ {
80119 let fingerprint = TyFingerprint :: for_impl ( ty) ;
81- fingerprint. and_then ( |f| self . impls . get ( & f) ) . into_iter ( ) . flatten ( ) . copied ( )
120+ fingerprint. and_then ( |f| self . inherent_impls . get ( & f) ) . into_iter ( ) . flatten ( ) . copied ( )
82121 }
83122
84123 pub fn lookup_impl_defs_for_trait ( & self , tr : TraitId ) -> impl Iterator < Item = ImplId > + ' _ {
@@ -110,7 +149,7 @@ impl CrateImplDefs {
110149 }
111150
112151 pub fn all_impls < ' a > ( & ' a self ) -> impl Iterator < Item = ImplId > + ' a {
113- self . impls
152+ self . inherent_impls
114153 . values ( )
115154 . chain ( self . impls_by_trait . values ( ) . flat_map ( |m| m. values ( ) ) )
116155 . flatten ( )
0 commit comments