-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Closed as not planned
Labels
Description
Bug Report
Mypy does not properly identify the return type of a method returning Self when the object is annotated with a TypeVar bound to a Union.
To Reproduce
from typing import Self, TypeVar, reveal_type
class A:
def clone(self) -> Self:
return self
class B:
def clone(self) -> Self:
return self
class C(B):
pass
AB = TypeVar("AB", bound=A | B)
def func1(x: AB) -> AB:
return x
def func2(x: AB) -> AB:
# This fails with
# error: Incompatible return value type (got "A | B", expected "AB") [return-value]
return x.clone()
reveal_type(func2(A())) # Revealed type is "__main__.A"
reveal_type(func2(B())) # Revealed type is "__main__.B"
reveal_type(func2(C())) # Revealed type is "__main__.C"https://mypy-play.net/?mypy=latest&python=3.12&gist=891e2571039d82531325537a75f334f0
mypy is actually pretty close. It finds that x.clone() returns A | B, but misses that whether A or B is returned is preserved.
Using constraints instead of a bound for the TypeVar, i.e.
AB = TypeVar("AB", A, B)makes mypy happy. However, that does not support my use case, as reveal_type(func2(C())) finds __main__.B. I would like to avoid having to list all subclasses of A and B as constraints to the TypeVar.
Expected Behavior
no error
Actual Behavior
error: Incompatible return value type (got "A | B", expected "AB") [return-value]
Your Environment
- Mypy version used: 1.13.0
- Mypy command-line flags: n/a (https://mypy-play.net/)
- Mypy configuration options from
mypy.ini(and other config files): n/a (https://mypy-play.net/) - Python version used: 3.12