Resolve associated types with type anchors

This commit is contained in:
Lukas Wirth 2021-04-01 21:52:07 +02:00
parent 444f6caaba
commit 9fe10a9606
3 changed files with 42 additions and 12 deletions

View File

@ -20,7 +20,7 @@ use hir_def::{
use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
use hir_ty::{
diagnostics::{record_literal_missing_fields, record_pattern_missing_fields},
InferenceResult, Substitution,
InferenceResult, Substitution, TyLoweringContext,
};
use syntax::{
ast::{self, AstNode},
@ -466,7 +466,20 @@ fn resolve_hir_path_(
prefer_value_ns: bool,
) -> Option<PathResolution> {
let types = || {
let (ty, remaining) = resolver.resolve_path_in_type_ns(db.upcast(), path.mod_path())?;
let (ty, unresolved) = match path.type_anchor() {
Some(type_ref) => {
let (_, res) = TyLoweringContext::new(db, resolver).lower_ty_ext(type_ref);
res.map(|ty_ns| (ty_ns, path.segments().first()))
}
None => {
let (ty, remaining) =
resolver.resolve_path_in_type_ns(db.upcast(), path.mod_path())?;
match remaining {
Some(remaining) if remaining > 1 => None,
_ => Some((ty, path.segments().get(1))),
}
}
}?;
let res = match ty {
TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }),
@ -478,18 +491,14 @@ fn resolve_hir_path_(
TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()),
TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
};
match remaining {
Some(1) => {
let unresolved = path.segments().get(1)?;
res.assoc_type_shorthand_candidates(db, |name, alias| {
match unresolved {
Some(unresolved) => res
.assoc_type_shorthand_candidates(db, |name, alias| {
(name == unresolved.name).then(|| alias)
})
.map(TypeAlias::from)
.map(Into::into)
.map(PathResolution::Def)
}
// ambiguous
Some(_) => None,
.map(PathResolution::Def),
None => Some(res),
}
};

View File

@ -146,7 +146,7 @@ impl<'a> TyLoweringContext<'a> {
self.lower_ty_ext(type_ref).0
}
fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option<TypeNs>) {
pub fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option<TypeNs>) {
let mut res = None;
let ty = match type_ref {
TypeRef::Never => TyKind::Never.intern(&Interner),

View File

@ -3841,6 +3841,27 @@ fn foo() {}
r#"
fn foo<T: A>() where T::Assoc$0: {}
trait A {
type Assoc;
}"#,
expect![[r#"
*Assoc*
```rust
test
```
```rust
type Assoc
```
"#]],
);
check(
r#"
fn foo<T: A>() {
let _: <T>::Assoc$0;
}
trait A {
type Assoc;
}"#,
@ -3874,6 +3895,6 @@ trait A where
type Assoc
```
"#]],
)
);
}
}