aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs39
1 files changed, 26 insertions, 13 deletions
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index be685e12f..ed638c195 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -65,26 +65,20 @@ impl CrateImplDefs {
65 db: &dyn HirDatabase, 65 db: &dyn HirDatabase,
66 krate: CrateId, 66 krate: CrateId,
67 ) -> Arc<CrateImplDefs> { 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"); 68 let _p = profile("impls_from_deps_query");
71 let crate_graph = db.crate_graph(); 69 let crate_graph = db.crate_graph();
72 let mut res = CrateImplDefs { 70 let mut res = CrateImplDefs {
73 inherent_impls: FxHashMap::default(), 71 inherent_impls: FxHashMap::default(),
74 impls_by_trait: FxHashMap::default(), 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 Arc::new(res) 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 pub fn lookup_impl_defs(&self, ty: &Ty) -> impl Iterator<Item = ImplId> + '_ { 132 pub fn lookup_impl_defs(&self, ty: &Ty) -> impl Iterator<Item = ImplId> + '_ {
120 let fingerprint = TyFingerprint::for_impl(ty); 133 let fingerprint = TyFingerprint::for_impl(ty);
121 fingerprint.and_then(|f| self.inherent_impls.get(&f)).into_iter().flatten().copied() 134 fingerprint.and_then(|f| self.inherent_impls.get(&f)).into_iter().flatten().copied()