Repository: intellij-rust/intellij-rust
Issue: Type hint is incorrect when using alias for generic type

Given the following code:

```rust
struct Wrapper<T> {
    wrapped: T,
}

type WrappedString = Wrapper<String>;

fn foo() -> WrappedString {
    WrappedString {
        wrapped: String::new(),
    }
}

fn main() {
    let var = foo();
}
```

The type hint shown for `var` is `WrappedString<String>`. This is incorrect; it should be either `WrappedString`, or `Wrapper<String>`.

Changed files:
src/test/kotlin/org/rust/ide/hints/RsInlayTypeHintsProviderTest.kt, src/main/kotlin/org/rust/ide/hints/RsTypeHintsPresentationFactory.kt

diff --git a/src/main/kotlin/org/rust/ide/hints/RsTypeHintsPresentationFactory.kt b/src/main/kotlin/org/rust/ide/hints/RsTypeHintsPresentationFactory.kt
index b068d7e4d..69225c37c 100644
--- a/src/main/kotlin/org/rust/ide/hints/RsTypeHintsPresentationFactory.kt
+++ b/src/main/kotlin/org/rust/ide/hints/RsTypeHintsPresentationFactory.kt
@@ -85,22 +85,25 @@ class RsTypeHintsPresentationFactory(private val factory: PresentationFactory, p
         val typeDeclaration = alias ?: type.item
         val typeNamePresentation = factory.psiSingleReference(text(adtName)) { typeDeclaration }
 
-        val typeArguments = mutableListOf<Ty>()
-        for ((argument, parameter) in type.typeArguments.zip(type.item.typeParameters)) {
+        val typeArguments = alias?.typeParameters?.map { (aliasedBy.subst[it] ?: TyUnknown) to it }
+            ?: type.typeArguments.zip(type.item.typeParameters)
+
+        val userVisibleTypeArguments = mutableListOf<Ty>()
+        for ((argument, parameter) in typeArguments) {
             if (!showObviousTypes && isDefaultTypeParameter(argument, parameter)) {
                 // don't show default types
                 continue
             }
-            typeArguments.add(argument)
+            userVisibleTypeArguments.add(argument)
         }
 
-        if (typeArguments.isNotEmpty()) {
+        if (userVisibleTypeArguments.isNotEmpty()) {
             val collapsible = factory.collapsible(
                 prefix = text("<"),
                 collapsed = text(PLACEHOLDER),
-                expanded = { parametersHint(typeArguments, level + 1) },
+                expanded = { parametersHint(userVisibleTypeArguments, level + 1) },
                 suffix = text(">"),
-                startWithPlaceholder = checkSize(level, typeArguments.size)
+                startWithPlaceholder = checkSize(level, userVisibleTypeArguments.size)
             )
             return listOf(typeNamePresentation, collapsible).join()
         }
diff --git a/src/test/kotlin/org/rust/ide/hints/RsInlayTypeHintsProviderTest.kt b/src/test/kotlin/org/rust/ide/hints/RsInlayTypeHintsProviderTest.kt
index d9bebc965..ab979ba37 100644
--- a/src/test/kotlin/org/rust/ide/hints/RsInlayTypeHintsProviderTest.kt
+++ b/src/test/kotlin/org/rust/ide/hints/RsInlayTypeHintsProviderTest.kt
@@ -289,8 +289,7 @@ class RsInlayTypeHintsProviderTest : RsTestBase() {
         }
     """)
 
-    fun `test don't show default type in adt`() = checkByText(
-        """
+    fun `test don't show default type in adt`() = checkByText("""
         struct MyType;
         struct S<A, B = MyType> { x: A, y: B }
 
@@ -298,19 +297,56 @@ class RsInlayTypeHintsProviderTest : RsTestBase() {
             let a = S { x: 42, y: MyType };
             let b/*hint text="[:  [S [< i32 >]]]"*/ = a;
         }
-    """
-    )
+    """)
 
-    fun `test don't show default type in anon type`() = checkByText(
-        """
+    fun `test don't show default type in anon type`() = checkByText("""
         struct MyType;
         trait MyTrait<A, B = MyType> {}
 
         fn foo(x: impl MyTrait<i32>) {
             let y/*hint text="[:  [impl  [MyTrait [< i32 >]] ]]"*/ = x;
         }
-    """
-    )
+    """)
+
+    fun `test type alias 1`() = checkByText("""
+        struct S;
+        type V = S;
+        fn foo(x: V) {
+            let y/*hint text="[:  V]"*/ = x;
+        }
+    """)
+
+    fun `test type alias 2`() = checkByText("""
+        struct S<T>;
+        type V = S<i32>;
+        fn foo(x: V) {
+            let y/*hint text="[:  V]"*/ = x;
+        }
+    """)
+
+    fun `test type alias with type params`() = checkByText("""
+        struct S<T>;
+        type V<T> = S<(T, T)>;
+        fn foo(x: V<i32>) {
+            let y/*hint text="[:  [V [< i32 >]]]"*/ = x;
+        }
+    """)
+
+    fun `test type alias with default generic type param 1`() = checkByText("""
+        struct S<T>;
+        type V<T, V = i32> = S<(T, V)>;
+        fn foo(x: V<u8>) {
+            let y/*hint text="[:  [V [< u8 >]]]"*/ = x;
+        }
+    """)
+
+    fun `test type alias with default generic type param 2`() = checkByText("""
+        struct S<T>;
+        type V<T, V = i32> = S<(T, V)>;
+        fn foo(x: V<u8, f32>) {
+            let y/*hint text="[:  [V [< [u8 ,  f32] >]]]"*/ = x;
+        }
+    """)
 
     private fun checkByText(@Language("Rust") code: String) {
         InlineFile(code.replace(HINT_COMMENT_PATTERN, "<$1/>"))