aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2021-04-07 02:33:22 +0100
committerJonas Schievink <[email protected]>2021-04-07 02:33:22 +0100
commit7c1c0e6feadc017f5919f789f974405635fc25e3 (patch)
treebe2ec91cdd13c8125e560bb414a37866ae573642 /crates
parentf04f38d3d79c3cc51956bc530a34e32945cdb294 (diff)
Collect trait impls inside unnamed consts
Diffstat (limited to 'crates')
-rw-r--r--crates/hir_def/src/item_scope.rs4
-rw-r--r--crates/hir_ty/src/method_resolution.rs54
-rw-r--r--crates/hir_ty/src/tests/method_resolution.rs22
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;
8use base_db::CrateId; 8use base_db::CrateId;
9use chalk_ir::{cast::Cast, Mutability, UniverseIndex}; 9use chalk_ir::{cast::Cast, Mutability, UniverseIndex};
10use hir_def::{ 10use 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};
14use hir_expand::name::Name; 14use hir_expand::name::Name;
15use rustc_hash::{FxHashMap, FxHashSet}; 15use 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]
1297fn impl_in_unnamed_const() {
1298 check_types(
1299 r#"
1300struct S;
1301
1302trait Tr {
1303 fn method(&self) -> u16;
1304}
1305
1306const _: () = {
1307 impl Tr for S {}
1308};
1309
1310fn f() {
1311 S.method();
1312 //^^^^^^^^^^ u16
1313}
1314 "#,
1315 );
1316}