Repository: reagento/dishka

Issue:
incorrect substitution of generic parameters
MRE:
```py
import dishka as d
import typing as t

A = t.TypeVar("A")
B = t.TypeVar("B")

class C(t.Generic[A, B]):
 pass

def func(b: type[B]) -> C[int, B]:
 print(b)

provider = d.Provider(scope=d.Scope.APP)
provider.provide(func)
c = d.make_container(provider)
c.get(C[int, bool])
```

Expected output: `<class 'bool'>`
Real output: `<class 'int'>`
Dishka version: 1.4.2

Hints from issue comments:

Solution patch:
diff --git a/src/dishka/registry.py b/src/dishka/registry.py
index fd58d3c..3e9f806 100644
--- a/src/dishka/registry.py
+++ b/src/dishka/registry.py
@@ -6,7 +6,10 @@ from .container_objects import CompiledFactory
 from .dependency_source import (
     Factory,
 )
-from .dependency_source.type_match import is_broader_or_same_type
+from .dependency_source.type_match import (
+    get_typevar_replacement,
+    is_broader_or_same_type,
+)
 from .entities.factory_type import FactoryType
 from .entities.key import DependencyKey
 from .entities.scope import BaseScope
@@ -104,12 +107,10 @@ class Registry:
     def _specialize_generic(
             self, factory: Factory, dependency_key: DependencyKey,
     ) -> Factory:
-        dependency = dependency_key.type_hint
-        params_replacement = dict(zip(
-            get_type_vars(factory.provides.type_hint),
-            get_args(dependency),
-            strict=False,
-        ))
+        params_replacement = get_typevar_replacement(
+            factory.provides.type_hint,
+            dependency_key.type_hint,
+        )
         new_dependencies: list[DependencyKey] = []
         for source_dependency in factory.dependencies:
             hint = source_dependency.type_hint


Test patch:
diff --git a/tests/unit/container/test_generic.py b/tests/unit/container/test_generic.py
index 4b00e59..63799f1 100644
--- a/tests/unit/container/test_generic.py
+++ b/tests/unit/container/test_generic.py
@@ -222,3 +222,36 @@ def test_provide_type_non_generic():
     with container() as c:
         assert c.get(A[str]) == (str, bool)
         assert c.get(A[int]) == (bool, bool)
+
+
+T2 = TypeVar("T2")
+class Multi(Generic[T, T2]):
+    pass
+
+def func_with_at2(b: type[T2]) -> Multi[int, A[T2]]:
+    return b
+
+def func_with_t2(b: type[T2]) -> Multi[int, T2]:
+    return b
+
+
+def func_with_t2t(b: type[T2], a: type[T]) -> Multi[A[T], T2]:
+    return b, a
+
+
+def test_provide_partial_generic():
+    provider = Provider(scope=Scope.APP)
+    provider.provide(func_with_t2)
+    container = make_container(provider)
+    assert container.get(Multi[int, bool]) is bool
+
+    provider = Provider(scope=Scope.APP)
+    provider.provide(func_with_at2)
+    container = make_container(provider)
+    assert container.get(Multi[int, A[bool]]) is bool
+    provider = Provider(scope=Scope.APP)
+
+    provider = Provider(scope=Scope.APP)
+    provider.provide(func_with_t2t)
+    container = make_container(provider)
+    assert container.get(Multi[A[int], A[bool]]) == (A[bool], int)