In the example below, FloatScalar is contravariant in FloatT, but mypy thinks it is invariant
from typing import Self
class FloatScalar[FloatT]: # contravariant
def pow(self, arg: FloatT) -> Self | complex: ...
def upcast(arg: FloatScalar[object]) -> FloatScalar[float]:
return arg # ❌️ Incompatible return value type
https://mypy-play.net/?gist=e9e6d34bee57d1c799b71b0f0573175d
If we remove the union in the return type, inference seems to work as expected:
from typing import Self
class FloatScalar[FloatT]: # contravariant
def pow(self, arg: FloatT) -> Self: ...
def upcast(arg: FloatScalar[object]) -> FloatScalar[float]:
return arg # ✅️
https://mypy-play.net/?gist=b0a994e8dda1b85ce2a4cf26631f843e