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"
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]
Bug Report
Mypy does not properly identify the return type of a method returning
Self
when the object is annotated with aTypeVar
bound to aUnion
.To Reproduce
https://mypy-play.net/?mypy=latest&python=3.12&gist=891e2571039d82531325537a75f334f0
mypy
is actually pretty close. It finds thatx.clone()
returnsA | B
, but misses that whetherA
orB
is returned is preserved.Using constraints instead of a bound for the
TypeVar
, i.e.makes
mypy
happy. However, that does not support my use case, asreveal_type(func2(C()))
finds__main__.B
. I would like to avoid having to list all subclasses ofA
andB
as constraints to theTypeVar
.Expected Behavior
no error
Actual Behavior
Your Environment
mypy.ini
(and other config files): n/a (https://mypy-play.net/)