Skip to content

Commit cc1bcc9

Browse files
authored
Properly expand type in generic class with Self and TypeVar with values (python#14491)
Fixes python#14374 It looks like we need to special-case `Self` in `expand_type()` to support it in generics over `TypeVar` with values, since `Self` is the only type variable that can legitimately have other type variables in its upper bound.
1 parent af89564 commit cc1bcc9

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

mypy/expandtype.py

+4
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,10 @@ def visit_instance(self, t: Instance) -> Type:
222222
return args
223223

224224
def visit_type_var(self, t: TypeVarType) -> Type:
225+
# Normally upper bounds can't contain other type variables, the only exception is
226+
# special type variable Self`0 <: C[T, S], where C is the class where Self is used.
227+
if t.id.raw_id == 0:
228+
t = t.copy_modified(upper_bound=t.upper_bound.accept(self))
225229
repl = self.variables.get(t.id, t)
226230
if isinstance(repl, ProperType) and isinstance(repl, Instance):
227231
# TODO: do we really need to do this?

test-data/unit/check-selftype.test

+20
Original file line numberDiff line numberDiff line change
@@ -1785,3 +1785,23 @@ class C(B, Generic[T]):
17851785
inst = super().copy()
17861786
reveal_type(inst) # N: Revealed type is "Self`0"
17871787
return inst
1788+
1789+
[case testTypingSelfWithValuesExpansion]
1790+
from typing import Self, Generic, TypeVar
1791+
1792+
class A: pass
1793+
class B: pass
1794+
T = TypeVar("T", A, B)
1795+
1796+
class C(Generic[T]):
1797+
val: T
1798+
def foo(self, x: T) -> None: ...
1799+
def bar(self, x: T) -> Self:
1800+
reveal_type(self.foo) # N: Revealed type is "def (x: __main__.A)" \
1801+
# N: Revealed type is "def (x: __main__.B)"
1802+
self.foo(x)
1803+
return self
1804+
def baz(self: Self, x: T) -> None:
1805+
reveal_type(self.val) # N: Revealed type is "__main__.A" \
1806+
# N: Revealed type is "__main__.B"
1807+
self.val = x

0 commit comments

Comments
 (0)