mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 22:31:43 +00:00
Collect inherent impls in unnamed consts
This commit is contained in:
parent
b777d46ae6
commit
20c27dbdbe
2 changed files with 62 additions and 17 deletions
|
@ -246,29 +246,39 @@ pub struct InherentImpls {
|
||||||
|
|
||||||
impl InherentImpls {
|
impl InherentImpls {
|
||||||
pub(crate) fn inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> {
|
pub(crate) fn inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> {
|
||||||
let mut map: FxHashMap<_, Vec<_>> = 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);
|
||||||
for impl_id in module_data.scope.impls() {
|
|
||||||
let data = db.impl_data(impl_id);
|
return Arc::new(impls);
|
||||||
if data.target_trait.is_some() {
|
|
||||||
continue;
|
fn collect_def_map(db: &dyn HirDatabase, def_map: &DefMap, impls: &mut InherentImpls) {
|
||||||
|
for (_module_id, module_data) in def_map.modules() {
|
||||||
|
for impl_id in module_data.scope.impls() {
|
||||||
|
let data = db.impl_data(impl_id);
|
||||||
|
if data.target_trait.is_some() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let self_ty = db.impl_self_ty(impl_id);
|
||||||
|
let fp = TyFingerprint::for_inherent_impl(self_ty.skip_binders());
|
||||||
|
if let Some(fp) = fp {
|
||||||
|
impls.map.entry(fp).or_default().push(impl_id);
|
||||||
|
}
|
||||||
|
// `fp` should only be `None` in error cases (either erroneous code or incomplete name resolution)
|
||||||
}
|
}
|
||||||
|
|
||||||
let self_ty = db.impl_self_ty(impl_id);
|
// To better support custom derives, collect impls in all unnamed const items.
|
||||||
let fp = TyFingerprint::for_inherent_impl(self_ty.skip_binders());
|
// const _: () = { ... };
|
||||||
if let Some(fp) = fp {
|
for konst in module_data.scope.unnamed_consts() {
|
||||||
map.entry(fp).or_default().push(impl_id);
|
let body = db.body(konst.into());
|
||||||
|
for (_, block_def_map) in body.blocks(db.upcast()) {
|
||||||
|
collect_def_map(db, &block_def_map, impls);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// `fp` should only be `None` in error cases (either erroneous code or incomplete name resolution)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: We're not collecting inherent impls from unnamed consts here, we intentionally only
|
|
||||||
// support trait impls there.
|
|
||||||
|
|
||||||
Arc::new(Self { map })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] {
|
pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] {
|
||||||
|
|
|
@ -1294,7 +1294,7 @@ mod b {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn impl_in_unnamed_const() {
|
fn trait_impl_in_unnamed_const() {
|
||||||
check_types(
|
check_types(
|
||||||
r#"
|
r#"
|
||||||
struct S;
|
struct S;
|
||||||
|
@ -1314,3 +1314,38 @@ fn f() {
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn inherent_impl_in_unnamed_const() {
|
||||||
|
check_types(
|
||||||
|
r#"
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
const _: () = {
|
||||||
|
impl S {
|
||||||
|
fn method(&self) -> u16 { 0 }
|
||||||
|
|
||||||
|
pub(super) fn super_method(&self) -> u16 { 0 }
|
||||||
|
|
||||||
|
pub(crate) fn crate_method(&self) -> u16 { 0 }
|
||||||
|
|
||||||
|
pub fn pub_method(&self) -> u16 { 0 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fn f() {
|
||||||
|
S.method();
|
||||||
|
//^^^^^^^^^^ u16
|
||||||
|
|
||||||
|
S.super_method();
|
||||||
|
//^^^^^^^^^^^^^^^^ u16
|
||||||
|
|
||||||
|
S.crate_method();
|
||||||
|
//^^^^^^^^^^^^^^^^ u16
|
||||||
|
|
||||||
|
S.pub_method();
|
||||||
|
//^^^^^^^^^^^^^^ u16
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue