Skip to content

operator.getitem(Sequence[_T], operator.index(SupportsIndex) gets confused (no-matching-overload) #3037

Description

@posita

Summary

# getitem_bug.py
from collections.abc import Sequence
from operator import __getitem__, __index__
from typing import SupportsIndex, TypeVar, reveal_type

_T = TypeVar("_T")

def derpitem(seq: Sequence[_T], key: SupportsIndex) -> _T:
    reveal_type(key)  # SupportsIndex
    reveal_type(__index__(key))  # int
    return __getitem__(seq, __index__(key))  # <-- \\BOOM!//

print(list(derpitem("abcdefghi", 3)))

Playground: https://play.ty.dev/bec872f4-361c-4fd3-9eb0-06e82164ca0b

% python getitem_bug.py
Runtime type is 'int'
Runtime type is 'int'
['d']
% mypy --config-file=/dev/null getitem_bug.py  # <-- no error (similar to pyrefly and pyright)
/dev/null: No [mypy] section in config file
getitem_bug.py:10: note: Revealed type is "typing.SupportsIndex"
getitem_bug.py:11: note: Revealed type is "builtins.int"
Success: no issues found in 1 source file
% ty version
ty 0.0.22
% ty check --python-version 3.11 getitem_bug.py  # <-- no likey
info[revealed-type]: Revealed type
  --> getitem_bug.py:10:17
   |
 9 | def derpitem(seq: Sequence[_T], key: SupportsIndex) -> _T:
10 |     reveal_type(key)  # SupportsIndex
   |                 ^^^ `SupportsIndex`
11 |     reveal_type(__index__(key))  # int
12 |     return __getitem__(seq, __index__(key))  # <-- \\BOOM!//
   |

info[revealed-type]: Revealed type
  --> getitem_bug.py:11:17
   |
 9 | def derpitem(seq: Sequence[_T], key: SupportsIndex) -> _T:
10 |     reveal_type(key)  # SupportsIndex
11 |     reveal_type(__index__(key))  # int
   |                 ^^^^^^^^^^^^^^ `int`
12 |     return __getitem__(seq, __index__(key))  # <-- \\BOOM!//
   |

error[no-matching-overload]: No overload of function `getitem` matches arguments
  --> getitem_bug.py:12:12
   |
10 |     reveal_type(key)  # SupportsIndex
11 |     reveal_type(__index__(key))  # int
12 |     return __getitem__(seq, __index__(key))  # <-- \\BOOM!//
   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
info: First overload defined here
   --> stdlib/_operator.pyi:164:5
    |
162 | def delitem(a: MutableMapping[_K, Any], b: _K, /) -> None: ...
163 | @overload
164 | def getitem(a: Sequence[_T], b: slice[int | None], /) -> Sequence[_T]:
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
165 |     """Same as a[b]."""
    |
info: Possible overloads for function `getitem`:
info:   [_T](a: Sequence[_T], b: slice[int | None, int | None, int | None], /) -> Sequence[_T]
info:   [_K, _V](a: SupportsGetItem[_K, _V], b: _K, /) -> _V
info: rule `no-matching-overload` is enabled by default

Found 3 diagnostics

Relevant types:

Version

ty 0.0.22

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions