mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-15 21:47:04 +00:00
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 <lukastw97@gmail.com>
This commit is contained in:
commit
5ef0c7a213
@ -76,9 +76,11 @@ impl PathResolution {
|
||||
pub fn assoc_type_shorthand_candidates<R>(
|
||||
&self,
|
||||
db: &dyn HirDatabase,
|
||||
mut cb: impl FnMut(TypeAlias) -> Option<R>,
|
||||
mut cb: impl FnMut(&Name, TypeAlias) -> Option<R>,
|
||||
) -> Option<R> {
|
||||
associated_type_shorthand_candidates(db, self.in_type_ns()?, |_, _, id| cb(id.into()))
|
||||
associated_type_shorthand_candidates(db, self.in_type_ns()?, |name, _, id| {
|
||||
cb(name, id.into())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,21 @@ fn resolve_hir_path_(
|
||||
prefer_value_ns: bool,
|
||||
) -> Option<PathResolution> {
|
||||
let types = || {
|
||||
resolver.resolve_path_in_type_ns_fully(db.upcast(), path.mod_path()).map(|ty| match ty {
|
||||
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 }),
|
||||
TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {
|
||||
@ -476,7 +490,17 @@ fn resolve_hir_path_(
|
||||
TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
|
||||
TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()),
|
||||
TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
|
||||
})
|
||||
};
|
||||
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),
|
||||
None => Some(res),
|
||||
}
|
||||
};
|
||||
|
||||
let body_owner = resolver.body_owner();
|
||||
|
@ -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),
|
||||
|
@ -3834,4 +3834,67 @@ fn foo() {}
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hover_generic_assoc() {
|
||||
check(
|
||||
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;
|
||||
}"#,
|
||||
expect![[r#"
|
||||
*Assoc*
|
||||
|
||||
```rust
|
||||
test
|
||||
```
|
||||
|
||||
```rust
|
||||
type Assoc
|
||||
```
|
||||
"#]],
|
||||
);
|
||||
check(
|
||||
r#"
|
||||
trait A where
|
||||
Self::Assoc$0: ,
|
||||
{
|
||||
type Assoc;
|
||||
}"#,
|
||||
expect![[r#"
|
||||
*Assoc*
|
||||
|
||||
```rust
|
||||
test
|
||||
```
|
||||
|
||||
```rust
|
||||
type Assoc
|
||||
```
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
|
||||
};
|
||||
|
||||
// Add associated types on type parameters and `Self`.
|
||||
resolution.assoc_type_shorthand_candidates(ctx.db, |alias| {
|
||||
resolution.assoc_type_shorthand_candidates(ctx.db, |_, alias| {
|
||||
acc.add_type_alias(ctx, alias);
|
||||
None::<()>
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user