diff options
-rw-r--r-- | crates/hir/src/semantics.rs | 6 | ||||
-rw-r--r-- | crates/hir/src/source_analyzer.rs | 30 | ||||
-rw-r--r-- | crates/hir_ty/src/lower.rs | 2 | ||||
-rw-r--r-- | crates/ide/src/hover.rs | 63 | ||||
-rw-r--r-- | crates/ide_completion/src/completions/qualified_path.rs | 2 |
5 files changed, 96 insertions, 7 deletions
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 { | |||
76 | pub fn assoc_type_shorthand_candidates<R>( | 76 | pub fn assoc_type_shorthand_candidates<R>( |
77 | &self, | 77 | &self, |
78 | db: &dyn HirDatabase, | 78 | db: &dyn HirDatabase, |
79 | mut cb: impl FnMut(TypeAlias) -> Option<R>, | 79 | mut cb: impl FnMut(&Name, TypeAlias) -> Option<R>, |
80 | ) -> Option<R> { | 80 | ) -> 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 | }) | ||
82 | } | 84 | } |
83 | } | 85 | } |
84 | 86 | ||
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 37d162b32..8e9ea0a03 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs | |||
@@ -20,7 +20,7 @@ use hir_def::{ | |||
20 | use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; | 20 | use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; |
21 | use hir_ty::{ | 21 | use hir_ty::{ |
22 | diagnostics::{record_literal_missing_fields, record_pattern_missing_fields}, | 22 | diagnostics::{record_literal_missing_fields, record_pattern_missing_fields}, |
23 | InferenceResult, Substitution, | 23 | InferenceResult, Substitution, TyLoweringContext, |
24 | }; | 24 | }; |
25 | use syntax::{ | 25 | use syntax::{ |
26 | ast::{self, AstNode}, | 26 | ast::{self, AstNode}, |
@@ -466,7 +466,21 @@ fn resolve_hir_path_( | |||
466 | prefer_value_ns: bool, | 466 | prefer_value_ns: bool, |
467 | ) -> Option<PathResolution> { | 467 | ) -> Option<PathResolution> { |
468 | let types = || { | 468 | 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 { | ||
470 | TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), | 484 | TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), |
471 | TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }), | 485 | TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }), |
472 | TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { | 486 | TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { |
@@ -476,7 +490,17 @@ fn resolve_hir_path_( | |||
476 | TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), | 490 | TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), |
477 | TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()), | 491 | TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()), |
478 | TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), | 492 | 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 | } | ||
480 | }; | 504 | }; |
481 | 505 | ||
482 | let body_owner = resolver.body_owner(); | 506 | let body_owner = resolver.body_owner(); |
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> { | |||
146 | self.lower_ty_ext(type_ref).0 | 146 | self.lower_ty_ext(type_ref).0 |
147 | } | 147 | } |
148 | 148 | ||
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>) { |
150 | let mut res = None; | 150 | let mut res = None; |
151 | let ty = match type_ref { | 151 | let ty = match type_ref { |
152 | TypeRef::Never => TyKind::Never.intern(&Interner), | 152 | TypeRef::Never => TyKind::Never.intern(&Interner), |
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 5f9edb476..28e2e17dc 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs | |||
@@ -3834,4 +3834,67 @@ fn foo() {} | |||
3834 | "#]], | 3834 | "#]], |
3835 | ); | 3835 | ); |
3836 | } | 3836 | } |
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 | } | ||
3837 | } | 3900 | } |
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 | |||
24 | }; | 24 | }; |
25 | 25 | ||
26 | // Add associated types on type parameters and `Self`. | 26 | // 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| { |
28 | acc.add_type_alias(ctx, alias); | 28 | acc.add_type_alias(ctx, alias); |
29 | None::<()> | 29 | None::<()> |
30 | }); | 30 | }); |