From 510a89d584cce0932743d29f4614b2af8a7bf7a2 Mon Sep 17 00:00:00 2001 From: Randolf Scholz Date: Tue, 15 Jul 2025 14:08:45 +0200 Subject: [PATCH 1/2] initial commit + revert debugging --- mypy/expandtype.py | 12 ++++++++---- test-data/unit/check-typevar-defaults.test | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/mypy/expandtype.py b/mypy/expandtype.py index d27105f48ed3..100dc94c8639 100644 --- a/mypy/expandtype.py +++ b/mypy/expandtype.py @@ -246,10 +246,14 @@ def visit_type_var(self, t: TypeVarType) -> Type: if (tvar_id := repl.id) in self.recursive_tvar_guard: return self.recursive_tvar_guard[tvar_id] or repl self.recursive_tvar_guard[tvar_id] = None - repl = repl.accept(self) - if isinstance(repl, TypeVarType): - repl.default = repl.default.accept(self) - self.recursive_tvar_guard[tvar_id] = repl + expanded = repl.accept(self) + + if isinstance(expanded, TypeVarType): + expanded.default = expanded.default.accept(self) + else: + repl = expanded + + self.recursive_tvar_guard[tvar_id] = expanded return repl def visit_param_spec(self, t: ParamSpecType) -> Type: diff --git a/test-data/unit/check-typevar-defaults.test b/test-data/unit/check-typevar-defaults.test index 22270e17787e..b90a3d5789d1 100644 --- a/test-data/unit/check-typevar-defaults.test +++ b/test-data/unit/check-typevar-defaults.test @@ -416,6 +416,24 @@ def func_c4( reveal_type(m) # N: Revealed type is "__main__.ClassC4[builtins.int, builtins.float]" [builtins fixtures/tuple.pyi] +[case testTypeVarDefaultsSwap] +from typing import TypeVar, Generic + +T = TypeVar("T") +X = TypeVar("X", default=object) +Y = TypeVar("Y", default=object) + + +class Foo(Generic[T, Y]): + def test(self) -> None: + reveal_type( Foo[Y, T]() ) # N: Revealed type is "__main__.Foo[Y`2 = builtins.object, T`1]" + + +class Bar(Generic[X, Y]): + def test(self) -> None: + reveal_type( Bar[Y, X]() ) # N: Revealed type is "__main__.Bar[Y`2 = builtins.object, Y`2 = builtins.object]" + + [case testTypeVarDefaultsClassRecursive1] # flags: --disallow-any-generics from typing import Generic, TypeVar, List From 4b34af11984a56785161c6295934e683a838f72e Mon Sep 17 00:00:00 2001 From: Randolf Scholz Date: Tue, 15 Jul 2025 17:38:48 +0200 Subject: [PATCH 2/2] added second test --- mypy/expandtype.py | 12 ++++-------- test-data/unit/check-typevar-defaults.test | 16 +++++++++++++++- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/mypy/expandtype.py b/mypy/expandtype.py index 100dc94c8639..129818b658cc 100644 --- a/mypy/expandtype.py +++ b/mypy/expandtype.py @@ -246,14 +246,10 @@ def visit_type_var(self, t: TypeVarType) -> Type: if (tvar_id := repl.id) in self.recursive_tvar_guard: return self.recursive_tvar_guard[tvar_id] or repl self.recursive_tvar_guard[tvar_id] = None - expanded = repl.accept(self) - - if isinstance(expanded, TypeVarType): - expanded.default = expanded.default.accept(self) - else: - repl = expanded - - self.recursive_tvar_guard[tvar_id] = expanded + repl.default = repl.default.accept(self) + expanded = repl.accept(self) # Note: `expanded is repl` may be true. + repl = repl if isinstance(expanded, TypeVarType) else expanded + self.recursive_tvar_guard[tvar_id] = repl return repl def visit_param_spec(self, t: ParamSpecType) -> Type: diff --git a/test-data/unit/check-typevar-defaults.test b/test-data/unit/check-typevar-defaults.test index b90a3d5789d1..103c0e782797 100644 --- a/test-data/unit/check-typevar-defaults.test +++ b/test-data/unit/check-typevar-defaults.test @@ -431,9 +431,23 @@ class Foo(Generic[T, Y]): class Bar(Generic[X, Y]): def test(self) -> None: - reveal_type( Bar[Y, X]() ) # N: Revealed type is "__main__.Bar[Y`2 = builtins.object, Y`2 = builtins.object]" + reveal_type( Bar[Y, X]() ) # N: Revealed type is "__main__.Bar[Y`2 = builtins.object, X`1 = builtins.object]" +[case testTypeVarDefaultsSwap2] +from typing import TypeVar, Generic + +X = TypeVar("X", default=object) +Y = TypeVar("Y", default=object) +U = TypeVar("U", default=object) +V = TypeVar("V", default=object) + +class Transform(Generic[X, Y]): + def invert(self) -> "Transform[Y, X]": ... + +class Foo(Transform[U, V], Generic[U, V]): + def invert(self) -> "Foo[V, U]": ... + [case testTypeVarDefaultsClassRecursive1] # flags: --disallow-any-generics from typing import Generic, TypeVar, List