Protocol seems to only match the first overload #6549
-
I want to type the operators of a class that forwards all the operators to the operators of a wrapped type. It seems that I can (ab)use protocols for that purpose, see the example below - but it fails to work when a class uses overloads where the relevant overload isn't the first one. # pyright: reportInvalidStubStatement = false
from __future__ import annotations
from typing import Protocol, TypeVar, overload, Generic
_T = TypeVar("_T", covariant=True)
_Other = TypeVar("_Other", contravariant=True)
_Result = TypeVar("_Result", covariant=True)
# let's ignored __radd__ to keep it simpler
class add(Protocol[_Other, _Result]):
def __add__(self, other: _Other, /) -> _Result: ...
# some class acting as a container that forwards operators to the underlying type
class Series(Generic[_T]):
def __add__(
self: Series[add[_Other, _Result]], other: _Other, /
) -> Series[_Result]: ...
class Timedelta:
@overload
def __add__(self, other: Timestamp, /) -> Timestamp: ... # relevant overload
@overload
def __add__(self, other: int, /) -> Timedelta: ...
class Timestamp:
@overload
def __add__(self, other: int, /) -> Timestamp: ...
@overload
def __add__(self, other: Timedelta, /) -> Timestamp: ... # relevant overload
def test_timedelta_timestamp(x: Series[Timedelta], y: Timestamp):
# works (relevant overload of Timedelta.__add__ is the first one)
reveal_type(x + y)
def test_timestamp_timedelta(x: Series[Timestamp], y: Timedelta):
# fails (relevant overload of Timestamp.__add__ is not the first)
reveal_type(x + y) |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
I agree this is an abuse of the type system, and I don't recommend you use this approach. You're in very iffy and indeterminate areas of the type system. The constraint solver, when solving for the TypeVar |
Beta Was this translation helpful? Give feedback.
I agree this is an abuse of the type system, and I don't recommend you use this approach. You're in very iffy and indeterminate areas of the type system.
The constraint solver, when solving for the TypeVar
_Other
in theadd
protocol must arbitrarily choose from either the first or second overload since both of them match theadd.__add__
method. Choosing the first one seems like a logical choice, since that mirrors the general overload matching behavior for calls.