aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src/method_resolution.rs
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2021-06-13 12:00:34 +0100
committerFlorian Diebold <[email protected]>2021-06-13 12:00:34 +0100
commit5ca71a19903cea277ed8a347b36cffeca6b99922 (patch)
tree20862ee6b7faf2a13ed810af4e8a80ff2cfbab83 /crates/hir_ty/src/method_resolution.rs
parentadbee621a75f47e0da4f30d7205dfce009138865 (diff)
Make block-local trait impls work
As long as either the trait or the implementing type are defined in the same block.
Diffstat (limited to 'crates/hir_ty/src/method_resolution.rs')
-rw-r--r--crates/hir_ty/src/method_resolution.rs64
1 files changed, 38 insertions, 26 deletions
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index f3d390961..3d233b1e2 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -8,7 +8,7 @@ use arrayvec::ArrayVec;
8use base_db::{CrateId, Edition}; 8use base_db::{CrateId, Edition};
9use chalk_ir::{cast::Cast, Mutability, UniverseIndex}; 9use chalk_ir::{cast::Cast, Mutability, UniverseIndex};
10use hir_def::{ 10use hir_def::{
11 lang_item::LangItemTarget, nameres::DefMap, AssocContainerId, AssocItemId, FunctionId, 11 lang_item::LangItemTarget, nameres::DefMap, AssocContainerId, AssocItemId, BlockId, FunctionId,
12 GenericDefId, HasModule, ImplId, Lookup, ModuleId, TraitId, 12 GenericDefId, HasModule, ImplId, Lookup, ModuleId, TraitId,
13}; 13};
14use hir_expand::name::Name; 14use hir_expand::name::Name;
@@ -139,35 +139,47 @@ impl TraitImpls {
139 let mut impls = Self { map: FxHashMap::default() }; 139 let mut impls = Self { map: FxHashMap::default() };
140 140
141 let crate_def_map = db.crate_def_map(krate); 141 let crate_def_map = db.crate_def_map(krate);
142 collect_def_map(db, &crate_def_map, &mut impls); 142 impls.collect_def_map(db, &crate_def_map);
143 143
144 return Arc::new(impls); 144 return Arc::new(impls);
145 }
145 146
146 fn collect_def_map(db: &dyn HirDatabase, def_map: &DefMap, impls: &mut TraitImpls) { 147 pub(crate) fn trait_impls_in_block_query(
147 for (_module_id, module_data) in def_map.modules() { 148 db: &dyn HirDatabase,
148 for impl_id in module_data.scope.impls() { 149 block: BlockId,
149 let target_trait = match db.impl_trait(impl_id) { 150 ) -> Option<Arc<Self>> {
150 Some(tr) => tr.skip_binders().hir_trait_id(), 151 let _p = profile::span("trait_impls_in_block_query");
151 None => continue, 152 let mut impls = Self { map: FxHashMap::default() };
152 };
153 let self_ty = db.impl_self_ty(impl_id);
154 let self_ty_fp = TyFingerprint::for_trait_impl(self_ty.skip_binders());
155 impls
156 .map
157 .entry(target_trait)
158 .or_default()
159 .entry(self_ty_fp)
160 .or_default()
161 .push(impl_id);
162 }
163 153
164 // To better support custom derives, collect impls in all unnamed const items. 154 let block_def_map = db.block_def_map(block)?;
165 // const _: () = { ... }; 155 impls.collect_def_map(db, &block_def_map);
166 for konst in module_data.scope.unnamed_consts() { 156
167 let body = db.body(konst.into()); 157 return Some(Arc::new(impls));
168 for (_, block_def_map) in body.blocks(db.upcast()) { 158 }
169 collect_def_map(db, &block_def_map, impls); 159
170 } 160 fn collect_def_map(&mut self, db: &dyn HirDatabase, def_map: &DefMap) {
161 for (_module_id, module_data) in def_map.modules() {
162 for impl_id in module_data.scope.impls() {
163 let target_trait = match db.impl_trait(impl_id) {
164 Some(tr) => tr.skip_binders().hir_trait_id(),
165 None => continue,
166 };
167 let self_ty = db.impl_self_ty(impl_id);
168 let self_ty_fp = TyFingerprint::for_trait_impl(self_ty.skip_binders());
169 self.map
170 .entry(target_trait)
171 .or_default()
172 .entry(self_ty_fp)
173 .or_default()
174 .push(impl_id);
175 }
176
177 // To better support custom derives, collect impls in all unnamed const items.
178 // const _: () = { ... };
179 for konst in module_data.scope.unnamed_consts() {
180 let body = db.body(konst.into());
181 for (_, block_def_map) in body.blocks(db.upcast()) {
182 self.collect_def_map(db, &block_def_map);
171 } 183 }
172 } 184 }
173 } 185 }