Open
Description
Bug Report
mypy
generally correctly prioritizes __radd__
if the right operand is a subtype of the left operand. However, I discovered that it can fail to do so when creating a subclass of tuple[int, ...]
.
To Reproduce
- https://mypy-play.net/?mypy=1.15.0&python=3.12&gist=720172b4776456220b93a7d4ab4af4db
- https://mypy-play.net/?mypy=1.15.0&python=3.12&gist=df9688d48ce1cea13d8bdd55b9ee1471&enable-incomplete-feature=PreciseTupleTypes
from typing import assert_type
class Size(tuple[int, ...]):
def __add__(self, other: tuple[int, ...], /) -> "Size": return Size() # type: ignore[override]
def __radd__(self, other: tuple[int, ...], /) -> "Size": return Size()
tup0: tuple[()] = ()
tup1: tuple[int] = (1,)
tup2: tuple[int, int] = (1, 2)
tupN: tuple[int, ...] = (1, 2, 3)
size: Size = Size([3, 4])
# __radd__
assert_type(tup0 + tupN, tuple[int, ...]) # ✅
assert_type(tup1 + tupN, tuple[int, ...]) # ✅
assert_type(tup2 + tupN, tuple[int, ...]) # ✅
assert_type(tupN + tupN, tuple[int, ...]) # ✅
assert_type(tup0 + size, Size) # ❌ False positive
assert_type(tup1 + size, Size) # ❌ False positive
assert_type(tup2 + size, Size) # ❌ False positive
assert_type(tupN + size, Size) # ✅
The bug does seem to be tuple-specific, for instance it does not appear with integer literals: https://mypy-play.net/?mypy=latest&python=3.12&gist=da0763e25cd0654d1a8b8b0b67291bc5
Expected Behavior
All assert_type
in the example above should succeed.