Skip to content

Commit 5ef0c7a

Browse files
bors[bot]Veykril
andauthored
Merge #8283
8283: Resolve associated types r=flodiebold a=Veykril Prior we were only resolving paths until the first type was found, then discarding the result if the path wasn't fully consumed. That of course causes associated types to not resolve. Fixes #5003 Co-authored-by: Lukas Wirth <[email protected]>
2 parents 1c936dc + 9fe10a9 commit 5ef0c7a

File tree

5 files changed

+96
-7
lines changed

5 files changed

+96
-7
lines changed

crates/hir/src/semantics.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,11 @@ impl PathResolution {
7676
pub fn assoc_type_shorthand_candidates<R>(
7777
&self,
7878
db: &dyn HirDatabase,
79-
mut cb: impl FnMut(TypeAlias) -> Option<R>,
79+
mut cb: impl FnMut(&Name, TypeAlias) -> Option<R>,
8080
) -> Option<R> {
81-
associated_type_shorthand_candidates(db, self.in_type_ns()?, |_, _, id| cb(id.into()))
81+
associated_type_shorthand_candidates(db, self.in_type_ns()?, |name, _, id| {
82+
cb(name, id.into())
83+
})
8284
}
8385
}
8486

crates/hir/src/source_analyzer.rs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use hir_def::{
2020
use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
2121
use hir_ty::{
2222
diagnostics::{record_literal_missing_fields, record_pattern_missing_fields},
23-
InferenceResult, Substitution,
23+
InferenceResult, Substitution, TyLoweringContext,
2424
};
2525
use syntax::{
2626
ast::{self, AstNode},
@@ -466,7 +466,21 @@ fn resolve_hir_path_(
466466
prefer_value_ns: bool,
467467
) -> Option<PathResolution> {
468468
let types = || {
469-
resolver.resolve_path_in_type_ns_fully(db.upcast(), path.mod_path()).map(|ty| match ty {
469+
let (ty, unresolved) = match path.type_anchor() {
470+
Some(type_ref) => {
471+
let (_, res) = TyLoweringContext::new(db, resolver).lower_ty_ext(type_ref);
472+
res.map(|ty_ns| (ty_ns, path.segments().first()))
473+
}
474+
None => {
475+
let (ty, remaining) =
476+
resolver.resolve_path_in_type_ns(db.upcast(), path.mod_path())?;
477+
match remaining {
478+
Some(remaining) if remaining > 1 => None,
479+
_ => Some((ty, path.segments().get(1))),
480+
}
481+
}
482+
}?;
483+
let res = match ty {
470484
TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
471485
TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }),
472486
TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {
@@ -476,7 +490,17 @@ fn resolve_hir_path_(
476490
TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
477491
TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()),
478492
TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
479-
})
493+
};
494+
match unresolved {
495+
Some(unresolved) => res
496+
.assoc_type_shorthand_candidates(db, |name, alias| {
497+
(name == unresolved.name).then(|| alias)
498+
})
499+
.map(TypeAlias::from)
500+
.map(Into::into)
501+
.map(PathResolution::Def),
502+
None => Some(res),
503+
}
480504
};
481505

482506
let body_owner = resolver.body_owner();

crates/hir_ty/src/lower.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ impl<'a> TyLoweringContext<'a> {
146146
self.lower_ty_ext(type_ref).0
147147
}
148148

149-
fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option<TypeNs>) {
149+
pub fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option<TypeNs>) {
150150
let mut res = None;
151151
let ty = match type_ref {
152152
TypeRef::Never => TyKind::Never.intern(&Interner),

crates/ide/src/hover.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3834,4 +3834,67 @@ fn foo() {}
38343834
"#]],
38353835
);
38363836
}
3837+
3838+
#[test]
3839+
fn hover_generic_assoc() {
3840+
check(
3841+
r#"
3842+
fn foo<T: A>() where T::Assoc$0: {}
3843+
3844+
trait A {
3845+
type Assoc;
3846+
}"#,
3847+
expect![[r#"
3848+
*Assoc*
3849+
3850+
```rust
3851+
test
3852+
```
3853+
3854+
```rust
3855+
type Assoc
3856+
```
3857+
"#]],
3858+
);
3859+
check(
3860+
r#"
3861+
fn foo<T: A>() {
3862+
let _: <T>::Assoc$0;
3863+
}
3864+
3865+
trait A {
3866+
type Assoc;
3867+
}"#,
3868+
expect![[r#"
3869+
*Assoc*
3870+
3871+
```rust
3872+
test
3873+
```
3874+
3875+
```rust
3876+
type Assoc
3877+
```
3878+
"#]],
3879+
);
3880+
check(
3881+
r#"
3882+
trait A where
3883+
Self::Assoc$0: ,
3884+
{
3885+
type Assoc;
3886+
}"#,
3887+
expect![[r#"
3888+
*Assoc*
3889+
3890+
```rust
3891+
test
3892+
```
3893+
3894+
```rust
3895+
type Assoc
3896+
```
3897+
"#]],
3898+
);
3899+
}
38373900
}

crates/ide_completion/src/completions/qualified_path.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
2424
};
2525

2626
// Add associated types on type parameters and `Self`.
27-
resolution.assoc_type_shorthand_candidates(ctx.db, |alias| {
27+
resolution.assoc_type_shorthand_candidates(ctx.db, |_, alias| {
2828
acc.add_type_alias(ctx, alias);
2929
None::<()>
3030
});

0 commit comments

Comments
 (0)