diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 39 |
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() |