Skip to content

Commit

Permalink
Properly expand type in generic class with Self and TypeVar with valu…
Browse files Browse the repository at this point in the history
…es (#14491)

Fixes #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.
  • Loading branch information
ilevkivskyi authored Jan 21, 2023
1 parent af89564 commit cc1bcc9
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 0 deletions.
4 changes: 4 additions & 0 deletions mypy/expandtype.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ def visit_instance(self, t: Instance) -> Type:
return args

def visit_type_var(self, t: TypeVarType) -> Type:
# Normally upper bounds can't contain other type variables, the only exception is
# special type variable Self`0 <: C[T, S], where C is the class where Self is used.
if t.id.raw_id == 0:
t = t.copy_modified(upper_bound=t.upper_bound.accept(self))
repl = self.variables.get(t.id, t)
if isinstance(repl, ProperType) and isinstance(repl, Instance):
# TODO: do we really need to do this?
Expand Down
20 changes: 20 additions & 0 deletions test-data/unit/check-selftype.test
Original file line number Diff line number Diff line change
Expand Up @@ -1785,3 +1785,23 @@ class C(B, Generic[T]):
inst = super().copy()
reveal_type(inst) # N: Revealed type is "Self`0"
return inst

[case testTypingSelfWithValuesExpansion]
from typing import Self, Generic, TypeVar

class A: pass
class B: pass
T = TypeVar("T", A, B)

class C(Generic[T]):
val: T
def foo(self, x: T) -> None: ...
def bar(self, x: T) -> Self:
reveal_type(self.foo) # N: Revealed type is "def (x: __main__.A)" \
# N: Revealed type is "def (x: __main__.B)"
self.foo(x)
return self
def baz(self: Self, x: T) -> None:
reveal_type(self.val) # N: Revealed type is "__main__.A" \
# N: Revealed type is "__main__.B"
self.val = x

0 comments on commit cc1bcc9

Please sign in to comment.