Skip to content

Commit a3c2f51

Browse files
Recursively compute impl sets
1 parent a91c2e9 commit a3c2f51

File tree

1 file changed

+26
-13
lines changed

1 file changed

+26
-13
lines changed

crates/ra_hir_ty/src/method_resolution.rs

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)