Collect trait impls inside unnamed consts

This commit is contained in:
Jonas Schievink 2021-04-07 03:33:22 +02:00
parent f04f38d3d7
commit 7c1c0e6fea
3 changed files with 61 additions and 19 deletions

View file

@ -107,6 +107,10 @@ impl ItemScope {
.map(|(_, v)| v) .map(|(_, v)| v)
} }
pub fn unnamed_consts(&self) -> impl Iterator<Item = ConstId> + '_ {
self.unnamed_consts.iter().copied()
}
/// Iterate over all module scoped macros /// Iterate over all module scoped macros
pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_))) self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_)))

View file

@ -8,8 +8,8 @@ use arrayvec::ArrayVec;
use base_db::CrateId; use base_db::CrateId;
use chalk_ir::{cast::Cast, Mutability, UniverseIndex}; use chalk_ir::{cast::Cast, Mutability, UniverseIndex};
use hir_def::{ use hir_def::{
lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, lang_item::LangItemTarget, nameres::DefMap, AssocContainerId, AssocItemId, FunctionId,
ImplId, Lookup, ModuleId, TraitId, GenericDefId, HasModule, ImplId, Lookup, ModuleId, TraitId,
}; };
use hir_expand::name::Name; use hir_expand::name::Name;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
@ -100,7 +100,12 @@ impl TraitImpls {
let mut impls = Self { map: FxHashMap::default() }; let mut impls = Self { map: FxHashMap::default() };
let crate_def_map = db.crate_def_map(krate); let crate_def_map = db.crate_def_map(krate);
for (_module_id, module_data) in crate_def_map.modules() { collect_def_map(db, &crate_def_map, &mut impls);
return Arc::new(impls);
fn collect_def_map(db: &dyn HirDatabase, def_map: &DefMap, impls: &mut TraitImpls) {
for (_module_id, module_data) in def_map.modules() {
for impl_id in module_data.scope.impls() { for impl_id in module_data.scope.impls() {
let target_trait = match db.impl_trait(impl_id) { let target_trait = match db.impl_trait(impl_id) {
Some(tr) => tr.skip_binders().hir_trait_id(), Some(tr) => tr.skip_binders().hir_trait_id(),
@ -116,9 +121,17 @@ impl TraitImpls {
.or_default() .or_default()
.push(impl_id); .push(impl_id);
} }
}
Arc::new(impls) // To better support custom derives, collect impls in all unnamed const items.
// const _: () = { ... };
for konst in module_data.scope.unnamed_consts() {
let body = db.body(konst.into());
for (_, block_def_map) in body.blocks(db.upcast()) {
collect_def_map(db, &block_def_map, impls);
}
}
}
}
} }
pub(crate) fn trait_impls_in_deps_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> { pub(crate) fn trait_impls_in_deps_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> {
@ -208,6 +221,9 @@ impl InherentImpls {
} }
} }
// NOTE: We're not collecting inherent impls from unnamed consts here, we intentionally only
// support trait impls there.
Arc::new(Self { map }) Arc::new(Self { map })
} }

View file

@ -1292,3 +1292,25 @@ mod b {
"#]], "#]],
) )
} }
#[test]
fn impl_in_unnamed_const() {
check_types(
r#"
struct S;
trait Tr {
fn method(&self) -> u16;
}
const _: () = {
impl Tr for S {}
};
fn f() {
S.method();
//^^^^^^^^^^ u16
}
"#,
);
}