33from typing import Callable
44
55from mypy .nodes import TypeInfo
6- from mypy .types import Instance
6+ from mypy .types import Instance , ProperType , TypeVarLikeType
77from mypy .typestate import type_state
88
99
@@ -15,11 +15,61 @@ def calculate_mro(info: TypeInfo, obj_type: Callable[[], Instance] | None = None
1515 mro = linearize_hierarchy (info , obj_type )
1616 assert mro , f"Could not produce a MRO at all for { info } "
1717 info .mro = mro
18+ fill_mapped_type_vars (info )
1819 # The property of falling back to Any is inherited.
1920 info .fallback_to_any = any (baseinfo .fallback_to_any for baseinfo in info .mro )
2021 type_state .reset_all_subtype_caches_for (info )
2122
2223
24+ def fill_mapped_type_vars (info : TypeInfo ) -> None :
25+ """Calculates the final TypeVar value from inheritor to parent.
26+
27+ class A[T1]:
28+ # mapped_type_vars = {T1: str}
29+
30+ class B[T2]:
31+ # mapped_type_vars = {T2: T4}
32+
33+ class C[T3](B[T3]):
34+ # mapped_type_vars = {T3: T4}
35+
36+ class D[T4](C[T4], A[str]):
37+ # mapped_type_vars = {}
38+ """
39+ bases = {b .type : b for b in info .bases }
40+
41+ for subinfo in filter (lambda x : x .is_generic , info .mro ):
42+ if base_info := bases .get (subinfo ):
43+ subinfo .mapped_type_vars = {
44+ tv : actual_type for tv , actual_type in zip (subinfo .defn .type_vars , base_info .args )
45+ }
46+ info .mapped_type_vars |= subinfo .mapped_type_vars
47+
48+ final_mapped_type_vars : dict [TypeVarLikeType , ProperType ] = {}
49+ for k , v in info .mapped_type_vars .items ():
50+ final_mapped_type_vars [k ] = _resolve_mappped_vars (info .mapped_type_vars , v )
51+
52+ for subinfo in filter (lambda x : x .is_generic , info .mro ):
53+ _resolve_info_type_vars (subinfo , final_mapped_type_vars )
54+
55+
56+ def _resolve_info_type_vars (
57+ info : TypeInfo , mapped_type_vars : dict [TypeVarLikeType , ProperType ]
58+ ) -> None :
59+ final_mapped_type_vars = {}
60+ for tv in info .defn .type_vars :
61+ final_mapped_type_vars [tv ] = _resolve_mappped_vars (mapped_type_vars , tv )
62+ info .mapped_type_vars = final_mapped_type_vars
63+
64+
65+ def _resolve_mappped_vars (
66+ mapped_type_vars : dict [TypeVarLikeType , ProperType ], key : ProperType
67+ ) -> ProperType :
68+ if key in mapped_type_vars :
69+ return _resolve_mappped_vars (mapped_type_vars , mapped_type_vars [key ])
70+ return key
71+
72+
2373class MroError (Exception ):
2474 """Raised if a consistent mro cannot be determined for a class."""
2575
0 commit comments