Skip to content

Commit 88e5890

Browse files
committed
feat: improve inherent associated type support
Extract the inherent impl type alias lookup into a shared `find_inherent_assoc_type()` helper, wire it into IDE path resolution
1 parent d6cf318 commit 88e5890

File tree

4 files changed

+95
-43
lines changed

4 files changed

+95
-43
lines changed

crates/hir-ty/src/lower/path.rs

Lines changed: 4 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use either::Either;
44
use hir_def::{
5-
AssocItemId, GenericDefId, GenericParamId, HasModule, Lookup, TraitId, TypeParamId,
5+
GenericDefId, GenericParamId, Lookup, TraitId, TypeParamId,
66
expr_store::{
77
ExpressionStore, HygieneId,
88
path::{
@@ -19,7 +19,6 @@ use hir_def::{
1919
};
2020
use rustc_type_ir::{
2121
AliasTerm, AliasTy, AliasTyKind,
22-
fast_reject::{TreatParams, simplify_type},
2322
inherent::{GenericArgs as _, Region as _, Ty as _},
2423
};
2524
use smallvec::SmallVec;
@@ -35,7 +34,6 @@ use crate::{
3534
AssocTypeShorthandResolution, GenericPredicateSource, LifetimeElisionKind,
3635
PathDiagnosticCallbackData,
3736
},
38-
method_resolution::InherentImpls,
3937
next_solver::{
4038
Binder, Clause, Const, DbInterner, EarlyBinder, ErrorGuaranteed, GenericArg, GenericArgs,
4139
Predicate, ProjectionPredicate, Region, TraitRef, Ty,
@@ -524,44 +522,9 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
524522
}
525523
// associated types in inherent impl
526524
Some(TypeNs::AdtId(adt)) => {
527-
let adt_ty = Ty::new_adt(
528-
interner,
529-
adt,
530-
GenericArgs::identity_for_item(interner, adt.into()),
531-
);
532-
let Some(simplified) = simplify_type(interner, adt_ty, TreatParams::AsRigid) else {
533-
return error_ty();
534-
};
535-
536-
let module = adt.module(db);
537-
let krate = module.krate(db);
538-
let block = module.block(db);
539-
540-
let mut found_alias = None;
541-
InherentImpls::for_each_crate_and_block(db, krate, block, &mut |impls| {
542-
if found_alias.is_some() {
543-
return;
544-
}
545-
for &impl_id in impls.for_self_ty(&simplified) {
546-
// skip trait impl, only need inherent impl
547-
if db.impl_signature(impl_id).target_trait.is_some() {
548-
continue;
549-
}
550-
for (name, item) in impl_id.impl_items(db).items.iter() {
551-
if name == assoc_name
552-
&& let AssocItemId::TypeAliasId(alias_id) = item
553-
{
554-
found_alias = Some(*alias_id);
555-
break;
556-
}
557-
}
558-
if found_alias.is_some() {
559-
break;
560-
}
561-
}
562-
});
563-
564-
let Some(alias_id) = found_alias else {
525+
let Some(alias_id) =
526+
crate::method_resolution::find_inherent_assoc_type(db, adt, assoc_name)
527+
else {
565528
return error_ty();
566529
};
567530

crates/hir-ty/src/method_resolution.rs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ use tracing::{debug, instrument};
1313

1414
use base_db::Crate;
1515
use hir_def::{
16-
AssocItemId, BlockId, BuiltinDeriveImplId, ConstId, FunctionId, GenericParamId, HasModule,
17-
ImplId, ItemContainerId, ModuleId, TraitId,
16+
AdtId, AssocItemId, BlockId, BuiltinDeriveImplId, ConstId, FunctionId, GenericParamId,
17+
HasModule, ImplId, ItemContainerId, ModuleId, TraitId, TypeAliasId,
1818
attrs::AttrFlags,
1919
builtin_derive::BuiltinDeriveImplMethod,
2020
expr_store::path::GenericArgs as HirGenericArgs,
@@ -877,3 +877,42 @@ impl TraitImpls {
877877
}
878878
}
879879
}
880+
881+
pub fn find_inherent_assoc_type(
882+
db: &dyn HirDatabase,
883+
adt: AdtId,
884+
name: &Name,
885+
) -> Option<TypeAliasId> {
886+
use rustc_type_ir::inherent::GenericArgs;
887+
888+
let interner = DbInterner::new_no_crate(db);
889+
890+
let adt_ty = Ty::new_adt(interner, adt, GenericArgs::identity_for_item(interner, adt.into()));
891+
let simplified = simplify_type(interner, adt_ty, TreatParams::AsRigid)?;
892+
893+
let module = adt.module(db);
894+
let mut found = None;
895+
896+
InherentImpls::for_each_crate_and_block(db, module.krate(db), module.block(db), &mut |impls| {
897+
if found.is_some() {
898+
return;
899+
}
900+
for &impl_id in impls.for_self_ty(&simplified) {
901+
if db.impl_signature(impl_id).target_trait.is_some() {
902+
continue;
903+
}
904+
for (n, item) in impl_id.impl_items(db).items.iter() {
905+
if n == name
906+
&& let AssocItemId::TypeAliasId(id) = item
907+
{
908+
found = Some(*id);
909+
break;
910+
}
911+
}
912+
if found.is_some() {
913+
break;
914+
}
915+
}
916+
});
917+
found
918+
}

crates/hir/src/source_analyzer.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1678,6 +1678,14 @@ fn resolve_hir_path_(
16781678
return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into()));
16791679
}
16801680

1681+
// inherent associated types
1682+
if let (Some(unresolved), TypeNs::AdtId(adt_id)) = (&unresolved, &ty)
1683+
&& let Some(alias_id) =
1684+
method_resolution::find_inherent_assoc_type(db, *adt_id, unresolved.name)
1685+
{
1686+
return Some(PathResolution::Def(ModuleDefId::from(alias_id).into()));
1687+
}
1688+
16811689
let res = match ty {
16821690
TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
16831691
TypeNs::GenericParam(id) => PathResolution::TypeParam(id.into()),
@@ -1827,6 +1835,14 @@ fn resolve_hir_path_qualifier(
18271835
return Some(PathResolution::Def(ModuleDefId::from(type_alias_id).into()));
18281836
}
18291837

1838+
// inherent associated types
1839+
if let (Some(unresolved), TypeNs::AdtId(adt_id)) = (&unresolved, &ty)
1840+
&& let Some(alias_id) =
1841+
method_resolution::find_inherent_assoc_type(db, *adt_id, unresolved.name)
1842+
{
1843+
return Some(PathResolution::Def(ModuleDefId::from(alias_id).into()));
1844+
}
1845+
18301846
let res = match ty {
18311847
TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
18321848
TypeNs::GenericParam(id) => PathResolution::TypeParam(id.into()),

crates/ide/src/goto_definition.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1811,6 +1811,40 @@ fn f() -> impl Iterator<Item$0 = u8> {}
18111811
);
18121812
}
18131813

1814+
#[test]
1815+
fn goto_def_for_inherent_assoc_ty_in_path() {
1816+
check(
1817+
r#"
1818+
struct A;
1819+
impl A {
1820+
type B = i32;
1821+
//^
1822+
}
1823+
1824+
fn main() {
1825+
let _x: A::B$0;
1826+
}
1827+
"#,
1828+
);
1829+
}
1830+
1831+
#[test]
1832+
fn goto_def_for_inherent_assoc_ty_in_qualifier() {
1833+
check(
1834+
r#"
1835+
struct A;
1836+
impl A {
1837+
type B = [u8; 3];
1838+
//^
1839+
}
1840+
1841+
fn main() {
1842+
let _x = A::B$0::default();
1843+
}
1844+
"#,
1845+
);
1846+
}
1847+
18141848
#[test]
18151849
fn goto_def_for_super_assoc_ty_in_path() {
18161850
check(

0 commit comments

Comments
 (0)