From 444f6caababc3335b1ed51d08eeedac106fd8077 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 1 Apr 2021 18:01:18 +0200 Subject: Resolve associated types --- crates/hir/src/semantics.rs | 6 ++-- crates/hir/src/source_analyzer.rs | 19 ++++++++-- crates/ide/src/hover.rs | 42 ++++++++++++++++++++++ .../src/completions/qualified_path.rs | 2 +- 4 files changed, 64 insertions(+), 5 deletions(-) (limited to 'crates') diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index d3caeef4e..3bf722d2a 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -76,9 +76,11 @@ impl PathResolution { pub fn assoc_type_shorthand_candidates( &self, db: &dyn HirDatabase, - mut cb: impl FnMut(TypeAlias) -> Option, + mut cb: impl FnMut(&Name, TypeAlias) -> Option, ) -> Option { - 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()) + }) } } diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 37d162b32..8423dd101 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -466,7 +466,8 @@ fn resolve_hir_path_( prefer_value_ns: bool, ) -> Option { let types = || { - resolver.resolve_path_in_type_ns_fully(db.upcast(), path.mod_path()).map(|ty| match ty { + let (ty, remaining) = resolver.resolve_path_in_type_ns(db.upcast(), path.mod_path())?; + 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 +477,21 @@ 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 remaining { + Some(1) => { + let unresolved = path.segments().get(1)?; + 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, + None => Some(res), + } }; let body_owner = resolver.body_owner(); diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 5f9edb476..8f98056c1 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -3834,4 +3834,46 @@ fn foo() {} "#]], ); } + + #[test] + fn hover_generic_assoc() { + check( + r#" +fn foo() where 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 + ``` + "#]], + ) + } } diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs index 1891eb5b3..969249df6 100644 --- a/crates/ide_completion/src/completions/qualified_path.rs +++ b/crates/ide_completion/src/completions/qualified_path.rs @@ -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::<()> }); -- cgit v1.2.3 From 9fe10a96069ea0f617ff86049bb50922b5424fae Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 1 Apr 2021 21:52:07 +0200 Subject: Resolve associated types with type anchors --- crates/hir/src/source_analyzer.rs | 29 +++++++++++++++++++---------- crates/hir_ty/src/lower.rs | 2 +- crates/ide/src/hover.rs | 23 ++++++++++++++++++++++- 3 files changed, 42 insertions(+), 12 deletions(-) (limited to 'crates') diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 8423dd101..8e9ea0a03 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -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 { 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), } }; diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index afbfa12d5..14f34d73c 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs @@ -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) { + pub fn lower_ty_ext(&self, type_ref: &TypeRef) -> (Ty, Option) { let mut res = None; let ty = match type_ref { TypeRef::Never => TyKind::Never.intern(&Interner), diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 8f98056c1..28e2e17dc 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs @@ -3841,6 +3841,27 @@ fn foo() {} r#" fn foo() where T::Assoc$0: {} +trait A { + type Assoc; +}"#, + expect![[r#" + *Assoc* + + ```rust + test + ``` + + ```rust + type Assoc + ``` + "#]], + ); + check( + r#" +fn foo() { + let _: ::Assoc$0; +} + trait A { type Assoc; }"#, @@ -3874,6 +3895,6 @@ trait A where type Assoc ``` "#]], - ) + ); } } -- cgit v1.2.3