@@ -65,26 +65,20 @@ impl CrateImplDefs {
65
65
db : & dyn HirDatabase ,
66
66
krate : CrateId ,
67
67
) -> Arc < CrateImplDefs > {
68
- // FIXME: This should take visibility and orphan rules into account to keep the result
69
- // smaller.
70
68
let _p = profile ( "impls_from_deps_query" ) ;
71
69
let crate_graph = db. crate_graph ( ) ;
72
70
let mut res = CrateImplDefs {
73
71
inherent_impls : FxHashMap :: default ( ) ,
74
72
impls_by_trait : FxHashMap :: default ( ) ,
75
73
} ;
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) ;
86
74
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 ) ) ;
88
82
}
89
83
90
84
Arc :: new ( res)
@@ -116,6 +110,25 @@ impl CrateImplDefs {
116
110
}
117
111
}
118
112
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
+
119
132
pub fn lookup_impl_defs ( & self , ty : & Ty ) -> impl Iterator < Item = ImplId > + ' _ {
120
133
let fingerprint = TyFingerprint :: for_impl ( ty) ;
121
134
fingerprint. and_then ( |f| self . inherent_impls . get ( & f) ) . into_iter ( ) . flatten ( ) . copied ( )
0 commit comments