diff options
author | Florian Diebold <[email protected]> | 2021-06-13 12:00:34 +0100 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2021-06-13 12:00:34 +0100 |
commit | 5ca71a19903cea277ed8a347b36cffeca6b99922 (patch) | |
tree | 20862ee6b7faf2a13ed810af4e8a80ff2cfbab83 /crates/hir_ty/src/method_resolution.rs | |
parent | adbee621a75f47e0da4f30d7205dfce009138865 (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.rs | 64 |
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; | |||
8 | use base_db::{CrateId, Edition}; | 8 | use base_db::{CrateId, Edition}; |
9 | use chalk_ir::{cast::Cast, Mutability, UniverseIndex}; | 9 | use chalk_ir::{cast::Cast, Mutability, UniverseIndex}; |
10 | use hir_def::{ | 10 | use 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 | }; |
14 | use hir_expand::name::Name; | 14 | use 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 | } |