diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir_def/src/item_scope.rs | 4 | ||||
-rw-r--r-- | crates/hir_ty/src/method_resolution.rs | 54 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/method_resolution.rs | 22 |
3 files changed, 61 insertions, 19 deletions
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index 08feee1e7..9014468ea 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs | |||
@@ -107,6 +107,10 @@ impl ItemScope { | |||
107 | .map(|(_, v)| v) | 107 | .map(|(_, v)| v) |
108 | } | 108 | } |
109 | 109 | ||
110 | pub fn unnamed_consts(&self) -> impl Iterator<Item = ConstId> + '_ { | ||
111 | self.unnamed_consts.iter().copied() | ||
112 | } | ||
113 | |||
110 | /// Iterate over all module scoped macros | 114 | /// Iterate over all module scoped macros |
111 | pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { | 115 | pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { |
112 | self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_))) | 116 | self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_))) |
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index ee725fd46..f29319f20 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs | |||
@@ -8,8 +8,8 @@ use arrayvec::ArrayVec; | |||
8 | use base_db::CrateId; | 8 | use base_db::CrateId; |
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, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, | 11 | lang_item::LangItemTarget, nameres::DefMap, AssocContainerId, AssocItemId, FunctionId, |
12 | 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; |
15 | use rustc_hash::{FxHashMap, FxHashSet}; | 15 | use rustc_hash::{FxHashMap, FxHashSet}; |
@@ -100,25 +100,38 @@ impl TraitImpls { | |||
100 | let mut impls = Self { map: FxHashMap::default() }; | 100 | let mut impls = Self { map: FxHashMap::default() }; |
101 | 101 | ||
102 | let crate_def_map = db.crate_def_map(krate); | 102 | let crate_def_map = db.crate_def_map(krate); |
103 | for (_module_id, module_data) in crate_def_map.modules() { | 103 | collect_def_map(db, &crate_def_map, &mut impls); |
104 | for impl_id in module_data.scope.impls() { | 104 | |
105 | let target_trait = match db.impl_trait(impl_id) { | 105 | return Arc::new(impls); |
106 | Some(tr) => tr.skip_binders().hir_trait_id(), | 106 | |
107 | None => continue, | 107 | fn collect_def_map(db: &dyn HirDatabase, def_map: &DefMap, impls: &mut TraitImpls) { |
108 | }; | 108 | for (_module_id, module_data) in def_map.modules() { |
109 | let self_ty = db.impl_self_ty(impl_id); | 109 | for impl_id in module_data.scope.impls() { |
110 | let self_ty_fp = TyFingerprint::for_impl(self_ty.skip_binders()); | 110 | let target_trait = match db.impl_trait(impl_id) { |
111 | impls | 111 | Some(tr) => tr.skip_binders().hir_trait_id(), |
112 | .map | 112 | None => continue, |
113 | .entry(target_trait) | 113 | }; |
114 | .or_default() | 114 | let self_ty = db.impl_self_ty(impl_id); |
115 | .entry(self_ty_fp) | 115 | let self_ty_fp = TyFingerprint::for_impl(self_ty.skip_binders()); |
116 | .or_default() | 116 | impls |
117 | .push(impl_id); | 117 | .map |
118 | .entry(target_trait) | ||
119 | .or_default() | ||
120 | .entry(self_ty_fp) | ||
121 | .or_default() | ||
122 | .push(impl_id); | ||
123 | } | ||
124 | |||
125 | // To better support custom derives, collect impls in all unnamed const items. | ||
126 | // const _: () = { ... }; | ||
127 | for konst in module_data.scope.unnamed_consts() { | ||
128 | let body = db.body(konst.into()); | ||
129 | for (_, block_def_map) in body.blocks(db.upcast()) { | ||
130 | collect_def_map(db, &block_def_map, impls); | ||
131 | } | ||
132 | } | ||
118 | } | 133 | } |
119 | } | 134 | } |
120 | |||
121 | Arc::new(impls) | ||
122 | } | 135 | } |
123 | 136 | ||
124 | pub(crate) fn trait_impls_in_deps_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> { | 137 | pub(crate) fn trait_impls_in_deps_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> { |
@@ -208,6 +221,9 @@ impl InherentImpls { | |||
208 | } | 221 | } |
209 | } | 222 | } |
210 | 223 | ||
224 | // NOTE: We're not collecting inherent impls from unnamed consts here, we intentionally only | ||
225 | // support trait impls there. | ||
226 | |||
211 | Arc::new(Self { map }) | 227 | Arc::new(Self { map }) |
212 | } | 228 | } |
213 | 229 | ||
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs index 61f18b0d2..4b2c82b41 100644 --- a/crates/hir_ty/src/tests/method_resolution.rs +++ b/crates/hir_ty/src/tests/method_resolution.rs | |||
@@ -1292,3 +1292,25 @@ mod b { | |||
1292 | "#]], | 1292 | "#]], |
1293 | ) | 1293 | ) |
1294 | } | 1294 | } |
1295 | |||
1296 | #[test] | ||
1297 | fn impl_in_unnamed_const() { | ||
1298 | check_types( | ||
1299 | r#" | ||
1300 | struct S; | ||
1301 | |||
1302 | trait Tr { | ||
1303 | fn method(&self) -> u16; | ||
1304 | } | ||
1305 | |||
1306 | const _: () = { | ||
1307 | impl Tr for S {} | ||
1308 | }; | ||
1309 | |||
1310 | fn f() { | ||
1311 | S.method(); | ||
1312 | //^^^^^^^^^^ u16 | ||
1313 | } | ||
1314 | "#, | ||
1315 | ); | ||
1316 | } | ||