Repository: intellij-rust/intellij-rust
Issue: `Implement members` fix should take into account defaulted type parameters

## Environment

* **Intellij-Rust plugin version:** 0.2.93.2564-183-nightly
* **Rust toolchain version:** 1.34.0-nightly
* **IDE name and version:** CLion 2018.3.4
* **Operating system:** macOS Mojave 10.14.3

## Steps to reproduce

* Before
```rust
struct S;

trait Op<RHS = Self> {
    fn op(self, rhs: RHS) -> Self;
}

impl Op/*caret*/ for S {
}
```
* After
```rust
struct S;

trait Op<RHS = Self> {
    fn op(self, rhs: RHS) -> Self;
}

impl Op for S {
    fn op(self, rhs: RHS) -> Self {
        unimplemented!()
    }
}
```
* Expected
```rust
struct S;

trait Op<RHS = Self> {
    fn op(self, rhs: RHS) -> Self;
}

impl Op for S {
    fn op(self, rhs: Self) -> Self {
        unimplemented!()
    }
}
```

Changed files:
src/main/kotlin/org/rust/lang/core/resolve/ref/RsPathReferenceImpl.kt
src/test/kotlin/org/rust/ide/refactoring/implementMembers/ImplementMembersHandlerTest.kt
src/test/kotlin/org/rust/lang/core/resolve/RsTypeAwareResolveTest.kt

diff --git a/src/main/kotlin/org/rust/lang/core/resolve/ref/RsPathReferenceImpl.kt b/src/main/kotlin/org/rust/lang/core/resolve/ref/RsPathReferenceImpl.kt
index 858d77e24..00d9163cd 100644
--- a/src/main/kotlin/org/rust/lang/core/resolve/ref/RsPathReferenceImpl.kt
+++ b/src/main/kotlin/org/rust/lang/core/resolve/ref/RsPathReferenceImpl.kt
@@ -114,9 +114,27 @@ fun resolvePath(path: RsPath, lookup: ImplLookup = ImplLookup.relativeTo(path)):
         }
 
         val typeParameters = element.typeParameters.map { TyTypeParameter.named(it) }
+        val typeSubst = buildMap<TyTypeParameter, Ty> {
+            putAll(typeParameters.zip(typeParameters).toMap())
+            val typeDefaults = element.typeParameters.mapNotNull {
+                val param = TyTypeParameter.named(it)
+                val default = it.typeReference?.type ?: return@mapNotNull null
+                param to default
+            }.toMap()
+            putAll(typeDefaults)
+            if (typeArguments != null) {
+                putAll(typeParameters.zip(typeArguments).toMap())
+            }
+        }
+
         val regionParameters = element.lifetimeParameters.map { ReEarlyBound(it) }
-        val typeSubst = typeParameters.zip(typeArguments ?: typeParameters).toMap()
-        val regionSubst = regionParameters.zip(regionArguments ?: regionParameters).toMap()
+        val regionSubst = buildMap<ReEarlyBound, Region> {
+            putAll(regionParameters.zip(regionParameters).toMap())
+            if (regionArguments != null) {
+                putAll(regionParameters.zip(regionArguments).toMap())
+            }
+        }
+
         val newSubst = Substitution(typeSubst, regionSubst)
         BoundElement(element, subst + newSubst, assocTypes)
     }
diff --git a/src/test/kotlin/org/rust/ide/refactoring/implementMembers/ImplementMembersHandlerTest.kt b/src/test/kotlin/org/rust/ide/refactoring/implementMembers/ImplementMembersHandlerTest.kt
index a006f6c7e..7c3d02018 100644
--- a/src/test/kotlin/org/rust/ide/refactoring/implementMembers/ImplementMembersHandlerTest.kt
+++ b/src/test/kotlin/org/rust/ide/refactoring/implementMembers/ImplementMembersHandlerTest.kt
@@ -269,11 +269,13 @@ class ImplementMembersHandlerTest : RsTestBase() {
     """)
 
     fun `test implement generic trait`() = doTest("""
-        trait T<A, B> {
+        trait T<A, B = i16, C = u32> {
             fn f1(_: A) -> A;
             const C1: A;
             fn f2(_: B) -> B;
             const C2: B;
+            fn f3(_: C) -> C;
+            const C3: C;
         }
         struct S;
         impl T<u8, u16> for S {/*caret*/}
@@ -281,13 +283,17 @@ class ImplementMembersHandlerTest : RsTestBase() {
         ImplementMemberSelection("f1(_: A) -> A", true),
         ImplementMemberSelection("C1: A", true),
         ImplementMemberSelection("f2(_: B) -> B", true),
-        ImplementMemberSelection("C2: B", true)
+        ImplementMemberSelection("C2: B", true),
+        ImplementMemberSelection("f3(_: C) -> C", true),
+        ImplementMemberSelection("C3: C", true)
     ), """
-        trait T<A, B> {
+        trait T<A, B = i16, C = u32> {
             fn f1(_: A) -> A;
             const C1: A;
             fn f2(_: B) -> B;
             const C2: B;
+            fn f3(_: C) -> C;
+            const C3: C;
         }
         struct S;
         impl T<u8, u16> for S {
@@ -302,6 +308,12 @@ class ImplementMembersHandlerTest : RsTestBase() {
             }
 
             const C2: u16 = unimplemented!();
+
+            fn f3(_: u32) -> u32 {
+                unimplemented!()
+            }
+
+            const C3: u32 = unimplemented!();
         }
     """)
 
diff --git a/src/test/kotlin/org/rust/lang/core/resolve/RsTypeAwareResolveTest.kt b/src/test/kotlin/org/rust/lang/core/resolve/RsTypeAwareResolveTest.kt
index 956a4742d..dce167e57 100644
--- a/src/test/kotlin/org/rust/lang/core/resolve/RsTypeAwareResolveTest.kt
+++ b/src/test/kotlin/org/rust/lang/core/resolve/RsTypeAwareResolveTest.kt
@@ -751,9 +751,7 @@ class RsTypeAwareResolveTest : RsResolveTestBase() {
         }                   //^
     """, NameResolutionTestmarks.selfRelatedTypeSpecialCase)
 
-    // TODO support default type parameters
-    fun `test Self-qualified path in trait impl is resolved to assoc type of super trait (generic trait 2)`() = expect<IllegalStateException> {
-        checkByCode("""
+    fun `test Self-qualified path in trait impl is resolved to assoc type of super trait (generic trait 2)`() = checkByCode("""
         struct S;
         trait Trait1<T=u8> { type Item; }
         trait Trait2<T>: Trait1<T> { fn foo() -> i32; }
@@ -767,6 +765,5 @@ class RsTypeAwareResolveTest : RsResolveTestBase() {
         impl Trait2<i32> for S {
             fn foo() -> Self::Item { unreachable!() }
         }                   //^
-        """, NameResolutionTestmarks.selfRelatedTypeSpecialCase)
-    }
+    """, NameResolutionTestmarks.selfRelatedTypeSpecialCase)
 }