]> git.lizzy.rs Git - rust.git/commitdiff
Resolve associated types
authorLukas Wirth <lukastw97@gmail.com>
Thu, 1 Apr 2021 16:01:18 +0000 (18:01 +0200)
committerLukas Wirth <lukastw97@gmail.com>
Thu, 1 Apr 2021 19:31:25 +0000 (21:31 +0200)
crates/hir/src/semantics.rs
crates/hir/src/source_analyzer.rs
crates/ide/src/hover.rs
crates/ide_completion/src/completions/qualified_path.rs

index d3caeef4ee754c4e6097a3db9c7b0140dc27c711..3bf722d2a708c7473b726c2d11328ab017cbf506 100644 (file)
@@ -76,9 +76,11 @@ fn in_type_ns(&self) -> Option<TypeNs> {
     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())
+        })
     }
 }
 
index 37d162b328a04b392d319884c5d7db5a522b1d0a..8423dd101997bffd2a1206d99d7ed092acae98c2 100644 (file)
@@ -466,7 +466,8 @@ 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, 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();
index 5f9edb4761339c31070d50f7ce1370491f54f43f..8f98056c1c5f84d35a41952b81926282854e5913 100644 (file)
@@ -3834,4 +3834,46 @@ 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#"
+trait A where
+    Self::Assoc$0: ,
+{
+    type Assoc;
+}"#,
+            expect![[r#"
+                *Assoc*
+
+                ```rust
+                test
+                ```
+
+                ```rust
+                type Assoc
+                ```
+            "#]],
+        )
+    }
 }
index 1891eb5b36509f7c98a034920e2d8bae8acc8f86..969249df6035a528154aab0cabe98f8b1c1dd246 100644 (file)
@@ -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::<()>
     });