Skip to content

Incorrect type inference with __radd__ with subclass of tuple[int, ...] #19006

Open
@randolf-scholz

Description

@randolf-scholz

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

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrongtopic-runtime-semanticsmypy doesn't model runtime semantics correctly

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions