@@ -65,26 +65,20 @@ impl CrateImplDefs {
6565 db : & dyn HirDatabase ,
6666 krate : CrateId ,
6767 ) -> Arc < CrateImplDefs > {
68- // FIXME: This should take visibility and orphan rules into account to keep the result
69- // smaller.
7068 let _p = profile ( "impls_from_deps_query" ) ;
7169 let crate_graph = db. crate_graph ( ) ;
7270 let mut res = CrateImplDefs {
7371 inherent_impls : FxHashMap :: default ( ) ,
7472 impls_by_trait : FxHashMap :: default ( ) ,
7573 } ;
76- let mut seen = FxHashSet :: default ( ) ;
77- let mut worklist =
78- crate_graph[ krate] . dependencies . iter ( ) . map ( |dep| dep. crate_id ) . collect :: < Vec < _ > > ( ) ;
79- while let Some ( krate) = worklist. pop ( ) {
80- if !seen. insert ( krate) {
81- continue ;
82- }
83-
84- // No deduplication, since a) impls can't be reexported, b) we visit a crate only once
85- res. fill ( db, krate) ;
8674
87- worklist. extend ( crate_graph[ krate] . dependencies . iter ( ) . map ( |dep| dep. crate_id ) ) ;
75+ // For each dependency, calculate `impls_from_deps` recursively, then add its own
76+ // `impls_in_crate`.
77+ // As we might visit crates multiple times, `merge` has to deduplicate impls to avoid
78+ // wasting memory.
79+ for dep in & crate_graph[ krate] . dependencies {
80+ res. merge ( & db. impls_from_deps ( dep. crate_id ) ) ;
81+ res. merge ( & db. impls_in_crate ( dep. crate_id ) ) ;
8882 }
8983
9084 Arc :: new ( res)
@@ -116,6 +110,25 @@ impl CrateImplDefs {
116110 }
117111 }
118112
113+ fn merge ( & mut self , other : & Self ) {
114+ for ( fp, impls) in & other. inherent_impls {
115+ let vec = self . inherent_impls . entry ( * fp) . or_default ( ) ;
116+ vec. extend ( impls) ;
117+ vec. sort ( ) ;
118+ vec. dedup ( ) ;
119+ }
120+
121+ for ( trait_, other_map) in & other. impls_by_trait {
122+ let map = self . impls_by_trait . entry ( * trait_) . or_default ( ) ;
123+ for ( fp, impls) in other_map {
124+ let vec = map. entry ( * fp) . or_default ( ) ;
125+ vec. extend ( impls) ;
126+ vec. sort ( ) ;
127+ vec. dedup ( ) ;
128+ }
129+ }
130+ }
131+
119132 pub fn lookup_impl_defs ( & self , ty : & Ty ) -> impl Iterator < Item = ImplId > + ' _ {
120133 let fingerprint = TyFingerprint :: for_impl ( ty) ;
121134 fingerprint. and_then ( |f| self . inherent_impls . get ( & f) ) . into_iter ( ) . flatten ( ) . copied ( )
0 commit comments