Repository: intellij-rust/intellij-rust
Issue: False positive "Match must be exhaustive" on enum defined as associated type in trait

I get false positive "Match must be exhaustive" on enums when the type of the enum is defined as an associated type of a trait.

Here is the shortest example I can come up with:

```rust

struct Foo<V: Input> {
    input: <V as Input>::Source,
}

fn main() {
    let foo1 = Foo::<Input1> {
        input: E1::A,
    };

    match foo1.input {  // <=== Match must be exhaustive [E0004]
        E1::A => 1,
        E1::B => 2,
    };

    let foo2 = Foo::<Input2> {
        input: E2::C,
    };

    match foo2.input {  // <=== Match must be exhaustive [E0004]
        E2::C => 1,
        E2::D => 2,
        E2::E => 3,
    };
}

enum E1 {
    A,
    B,
}

enum E2 {
    C,
    D,
    E,
}

trait Input {
    type Source;
}

struct Input1;

impl Input for Input1 {
    type Source = E1;
}

struct Input2;

impl Input for Input2 {
    type Source = E2;
}
```

**Environment:**

* Intellij-Rust plugin version: 0.2.99.2126-191
* Rust toolchain version: 1.35.0 stable
* IntelliJ Idea IntelliJ IDEA 2019.1.3 (Ultimate Edition)
  Build #IU-191.7479.19, built on May 28, 2019
  JRE: 1.8.0_202-release-1483-b58 amd64
  JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
  Windows 10 10.0 1903


Changed files:
src/test/kotlin/org/rust/lang/core/type/RsGenericExpressionTypeInferenceTest.kt, src/main/kotlin/org/rust/lang/core/types/infer/TypeInferenceWalker.kt

diff --git a/src/main/kotlin/org/rust/lang/core/types/infer/TypeInferenceWalker.kt b/src/main/kotlin/org/rust/lang/core/types/infer/TypeInferenceWalker.kt
index 3677191a8..956947dba 100644
--- a/src/main/kotlin/org/rust/lang/core/types/infer/TypeInferenceWalker.kt
+++ b/src/main/kotlin/org/rust/lang/core/types/infer/TypeInferenceWalker.kt
@@ -770,7 +770,7 @@ class RsTypeInferenceWalker(
         val fieldElement = field.element
 
         val raw = (fieldElement as? RsFieldDecl)?.typeReference?.type ?: TyUnknown
-        return raw.substitute(field.selfTy.typeParameterValues)
+        return raw.substitute(field.selfTy.typeParameterValues).foldWith(associatedTypeNormalizer)
     }
 
     private fun inferDotExprType(expr: RsDotExpr, expected: Ty?): Ty {
diff --git a/src/test/kotlin/org/rust/lang/core/type/RsGenericExpressionTypeInferenceTest.kt b/src/test/kotlin/org/rust/lang/core/type/RsGenericExpressionTypeInferenceTest.kt
index cec63db03..92c8c4288 100644
--- a/src/test/kotlin/org/rust/lang/core/type/RsGenericExpressionTypeInferenceTest.kt
+++ b/src/test/kotlin/org/rust/lang/core/type/RsGenericExpressionTypeInferenceTest.kt
@@ -1587,4 +1587,38 @@ class RsGenericExpressionTypeInferenceTest : RsTypificationTestBase() {
             b;
         } //^ B
     """)
+
+    // Issue https://github.com/intellij-rust/intellij-rust/issues/4026
+    fun `test struct field with associated type`() = testExpr("""
+        struct Foo<V: Trait> {
+            input: <V as Trait>::Item,
+        }
+        trait Trait { type Item; }
+        struct S; struct X;
+        impl Trait for S {
+            type Item = X;
+        }
+        fn main() {
+            let foo1 = Foo::<S> {
+                input: X,
+            };
+
+            foo1.input;
+        }      //^ X
+    """)
+
+    // Issue https://github.com/intellij-rust/intellij-rust/issues/4026
+    fun `test tuple struct field with associated type`() = testExpr("""
+        struct Foo<V: Trait>(<V as Trait>::Item);
+        trait Trait { type Item; }
+        struct S; struct X;
+        impl Trait for S {
+            type Item = X;
+        }
+        fn main() {
+            let foo1 = Foo::<S>(X);
+
+            foo1.0;
+        }      //^ X
+    """)
 }