Repository: rust-lang/rust-analyzer
Pull request #12198 (2022-05-09 15:32:34)

fix: Resolve assoc. types of supertraits in the IDE layer
Fixes https://github.com/rust-lang/rust-analyzer/issues/12166


Patch:
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 496b4168c0..39f88937d6 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -54,7 +54,7 @@ use hir_def::{
 };
 use hir_expand::{name::name, MacroCallKind};
 use hir_ty::{
-    autoderef,
+    all_super_traits, autoderef,
     consteval::{unknown_const_as_generic, ComputedExpr, ConstEvalError, ConstExt},
     diagnostics::BodyValidationDiagnostic,
     method_resolution::{self, TyFingerprint},
@@ -1676,6 +1676,11 @@ impl Trait {
         db.trait_data(self.id).items.iter().map(|(_name, it)| (*it).into()).collect()
     }
 
+    pub fn items_with_supertraits(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
+        let traits = all_super_traits(db.upcast(), self.into());
+        traits.iter().flat_map(|tr| Trait::from(*tr).items(db)).collect()
+    }
+
     pub fn is_auto(self, db: &dyn HirDatabase) -> bool {
         db.trait_data(self.id).is_auto
     }
diff --git a/crates/ide-completion/src/completions/type.rs b/crates/ide-completion/src/completions/type.rs
index 9381548e5e..034a229702 100644
--- a/crates/ide-completion/src/completions/type.rs
+++ b/crates/ide-completion/src/completions/type.rs
@@ -168,8 +168,9 @@ pub(crate) fn complete_type_path(acc: &mut Completions, ctx: &CompletionContext)
                     if let Some(hir::PathResolution::Def(hir::ModuleDef::Trait(trait_))) =
                         ctx.sema.resolve_path(&path_seg.parent_path())
                     {
-                        trait_.items(ctx.sema.db).into_iter().for_each(|it| {
+                        trait_.items_with_supertraits(ctx.sema.db).into_iter().for_each(|it| {
                             if let hir::AssocItem::TypeAlias(alias) = it {
+                                cov_mark::hit!(complete_assoc_type_in_generics_list);
                                 acc.add_type_alias_with_eq(ctx, alias)
                             }
                         });
diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs
index 34b557e21e..bea6f24523 100644
--- a/crates/ide-db/src/defs.rs
+++ b/crates/ide-db/src/defs.rs
@@ -386,9 +386,8 @@ impl NameRefClass {
                     let containing_path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?;
                     let resolved = sema.resolve_path(&containing_path)?;
                     if let PathResolution::Def(ModuleDef::Trait(tr)) = resolved {
-                        // FIXME: resolve in supertraits
                         if let Some(ty) = tr
-                            .items(sema.db)
+                            .items_with_supertraits(sema.db)
                             .iter()
                             .filter_map(|&assoc| match assoc {
                                 hir::AssocItem::TypeAlias(it) => Some(it),
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index 3d22ed9c16..30f48819e6 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -1012,6 +1012,22 @@ fn f() -> impl Iterator<Item$0 = u8> {}
         );
     }
 
+    #[test]
+    fn goto_def_for_super_assoc_ty_in_path() {
+        check(
+            r#"
+trait Super {
+    type Item;
+       //^^^^
+}
+
+trait Sub: Super {}
+
+fn f() -> impl Sub<Item$0 = u8> {}
+"#,
+        );
+    }
+
     #[test]
     fn unknown_assoc_ty() {
         check_unresolved(


Test patch:
diff --git a/crates/ide-completion/src/tests/type_pos.rs b/crates/ide-completion/src/tests/type_pos.rs
index 5224bc4b48..1e1b3f3efb 100644
--- a/crates/ide-completion/src/tests/type_pos.rs
+++ b/crates/ide-completion/src/tests/type_pos.rs
@@ -336,9 +336,13 @@ fn foo<'lt, T, const C: usize>() {
 
 #[test]
 fn completes_types_and_const_in_arg_list() {
+    cov_mark::check!(complete_assoc_type_in_generics_list);
     check(
         r#"
-trait Trait2 {
+trait Trait1 {
+    type Super;
+}
+trait Trait2: Trait1 {
     type Foo;
 }
 
@@ -348,14 +352,16 @@ fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {}
             ct CONST
             cp CONST_PARAM
             en Enum
-            ma makro!(…)          macro_rules! makro
+            ma makro!(…)            macro_rules! makro
             md module
             st Record
             st Tuple
             st Unit
             tt Trait
+            tt Trait1
             tt Trait2
-            ta Foo =  (as Trait2) type Foo
+            ta Foo =  (as Trait2)   type Foo
+            ta Super =  (as Trait1) type Super
             tp T
             un Union
             bt u32