Skip to content

Commit cf41e14

Browse files
Merge #8390
8390: Support trait impls in unnamed consts r=jonas-schievink a=jonas-schievink Fixes #7550 bors r+ Co-authored-by: Jonas Schievink <jonasschievink@gmail.com>
2 parents 3e7ac2b + 7c1c0e6 commit cf41e14

File tree

4 files changed

+90
-33
lines changed

4 files changed

+90
-33
lines changed

crates/hir_def/src/item_scope.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
1111
use stdx::format_to;
1212

1313
use crate::{
14-
db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ImplId,
14+
db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ConstId, ImplId,
1515
LocalModuleId, MacroDefId, ModuleDefId, ModuleId, TraitId,
1616
};
1717

@@ -37,6 +37,7 @@ pub struct ItemScope {
3737

3838
defs: Vec<ModuleDefId>,
3939
impls: Vec<ImplId>,
40+
unnamed_consts: Vec<ConstId>,
4041
/// Traits imported via `use Trait as _;`.
4142
unnamed_trait_imports: FxHashMap<TraitId, Visibility>,
4243
/// Macros visible in current module in legacy textual scope
@@ -106,6 +107,10 @@ impl ItemScope {
106107
.map(|(_, v)| v)
107108
}
108109

110+
pub fn unnamed_consts(&self) -> impl Iterator<Item = ConstId> + '_ {
111+
self.unnamed_consts.iter().copied()
112+
}
113+
109114
/// Iterate over all module scoped macros
110115
pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
111116
self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_)))
@@ -156,6 +161,10 @@ impl ItemScope {
156161
self.impls.push(imp)
157162
}
158163

164+
pub(crate) fn define_unnamed_const(&mut self, konst: ConstId) {
165+
self.unnamed_consts.push(konst);
166+
}
167+
159168
pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroDefId) {
160169
self.legacy_macros.insert(name, mac);
161170
}
@@ -295,6 +304,7 @@ impl ItemScope {
295304
unresolved,
296305
defs,
297306
impls,
307+
unnamed_consts,
298308
unnamed_trait_imports,
299309
legacy_macros,
300310
} = self;
@@ -304,6 +314,7 @@ impl ItemScope {
304314
unresolved.shrink_to_fit();
305315
defs.shrink_to_fit();
306316
impls.shrink_to_fit();
317+
unnamed_consts.shrink_to_fit();
307318
unnamed_trait_imports.shrink_to_fit();
308319
legacy_macros.shrink_to_fit();
309320
}

crates/hir_def/src/nameres/collector.rs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,19 +1163,27 @@ impl ModCollector<'_, '_> {
11631163
}
11641164
ModItem::Const(id) => {
11651165
let it = &self.item_tree[id];
1166-
1167-
if let Some(name) = &it.name {
1168-
def = Some(DefData {
1169-
id: ConstLoc {
1170-
container: module.into(),
1171-
id: ItemTreeId::new(self.file_id, id),
1172-
}
1173-
.intern(self.def_collector.db)
1174-
.into(),
1175-
name,
1176-
visibility: &self.item_tree[it.visibility],
1177-
has_constructor: false,
1178-
});
1166+
let const_id = ConstLoc {
1167+
container: module.into(),
1168+
id: ItemTreeId::new(self.file_id, id),
1169+
}
1170+
.intern(self.def_collector.db);
1171+
1172+
match &it.name {
1173+
Some(name) => {
1174+
def = Some(DefData {
1175+
id: const_id.into(),
1176+
name,
1177+
visibility: &self.item_tree[it.visibility],
1178+
has_constructor: false,
1179+
});
1180+
}
1181+
None => {
1182+
// const _: T = ...;
1183+
self.def_collector.def_map.modules[self.module_id]
1184+
.scope
1185+
.define_unnamed_const(const_id);
1186+
}
11791187
}
11801188
}
11811189
ModItem::Static(id) => {

crates/hir_ty/src/method_resolution.rs

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ use arrayvec::ArrayVec;
88
use base_db::CrateId;
99
use chalk_ir::{cast::Cast, Mutability, UniverseIndex};
1010
use hir_def::{
11-
lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule,
12-
ImplId, Lookup, ModuleId, TraitId,
11+
lang_item::LangItemTarget, nameres::DefMap, AssocContainerId, AssocItemId, FunctionId,
12+
GenericDefId, HasModule, ImplId, Lookup, ModuleId, TraitId,
1313
};
1414
use hir_expand::name::Name;
1515
use rustc_hash::{FxHashMap, FxHashSet};
@@ -100,25 +100,38 @@ impl TraitImpls {
100100
let mut impls = Self { map: FxHashMap::default() };
101101

102102
let crate_def_map = db.crate_def_map(krate);
103-
for (_module_id, module_data) in crate_def_map.modules() {
104-
for impl_id in module_data.scope.impls() {
105-
let target_trait = match db.impl_trait(impl_id) {
106-
Some(tr) => tr.skip_binders().hir_trait_id(),
107-
None => continue,
108-
};
109-
let self_ty = db.impl_self_ty(impl_id);
110-
let self_ty_fp = TyFingerprint::for_impl(self_ty.skip_binders());
111-
impls
112-
.map
113-
.entry(target_trait)
114-
.or_default()
115-
.entry(self_ty_fp)
116-
.or_default()
117-
.push(impl_id);
103+
collect_def_map(db, &crate_def_map, &mut impls);
104+
105+
return Arc::new(impls);
106+
107+
fn collect_def_map(db: &dyn HirDatabase, def_map: &DefMap, impls: &mut TraitImpls) {
108+
for (_module_id, module_data) in def_map.modules() {
109+
for impl_id in module_data.scope.impls() {
110+
let target_trait = match db.impl_trait(impl_id) {
111+
Some(tr) => tr.skip_binders().hir_trait_id(),
112+
None => continue,
113+
};
114+
let self_ty = db.impl_self_ty(impl_id);
115+
let self_ty_fp = TyFingerprint::for_impl(self_ty.skip_binders());
116+
impls
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+
}
118133
}
119134
}
120-
121-
Arc::new(impls)
122135
}
123136

124137
pub(crate) fn trait_impls_in_deps_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> {
@@ -208,6 +221,9 @@ impl InherentImpls {
208221
}
209222
}
210223

224+
// NOTE: We're not collecting inherent impls from unnamed consts here, we intentionally only
225+
// support trait impls there.
226+
211227
Arc::new(Self { map })
212228
}
213229

crates/hir_ty/src/tests/method_resolution.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,3 +1292,25 @@ mod b {
12921292
"#]],
12931293
)
12941294
}
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+
}

0 commit comments

Comments
 (0)