Repository navigation
Inconsistent errors reported for protocol matching #13850
Description
I ran into some strange behavior in mypy when investigating a bug reported against pyright.
Here is a sample that demonstrates the issue:
from typing import Generic, Protocol, TypeVar, overload
_T_co = TypeVar("_T_co", covariant=True)
class _NestedSequence(Protocol[_T_co]):
@overload
def __getitem__(self, index: int) -> _T_co | "_NestedSequence[_T_co]":
...
@overload
def __getitem__(self, index: slice) -> "_NestedSequence[_T_co]":
...
# def __contains__(self, __s: object, /) -> bool:
# ...
class MySequence(Generic[_T_co]):
@overload
def __getitem__(self, index: int) -> _T_co:
...
@overload
def __getitem__(self, index: slice) -> "MySequence[_T_co]":
...
def __getitem__(self, index: slice | int) -> "MySequence[_T_co]" | _T_co:
...
def __contains__(self, __s: object, /) -> bool:
...
class MySequenceCopy(Generic[_T_co]):
@overload
def __getitem__(self, index: int) -> _T_co:
...
@overload
def __getitem__(self, index: slice) -> "MySequenceCopy[_T_co]":
...
def __getitem__(self, index: slice | int) -> "MySequenceCopy[_T_co]" | _T_co:
...
def __contains__(self, __s: object, /) -> bool:
...
def func1_1(x: MySequence[int]):
_: _NestedSequence[int] = x # (no error)
def func1_1_copy(x: MySequence[int]):
_: _NestedSequence[int] = x # error: Incompatible types in assignment
def func1_2(x: MySequence[MySequence[int]]):
_: _NestedSequence[int] = x # (no error)
def func2_1(x: MySequenceCopy[int]):
_: _NestedSequence[int] = x # error: Incompatible types in assignment
def func2_1_copy(x: MySequenceCopy[int]):
_: _NestedSequence[int] = x # error: Incompatible types in assignment
def func2_2(x: MySequenceCopy[MySequenceCopy[int]]):
_: _NestedSequence[int] = x # error: Incompatible types in assignment
a: _NestedSequence[int] = [[1, 2, 3]] # error: List item 0/1/2 has incompatible type "int"; expected "_NestedSequence[int]"Strange behavior 1: Function func1_1_copy is an exact copy of func1_1, yet mypy reports an error in func1_1_copy but not in func1_1.
Strange behavior 2: The protocol class MySequenceCopy is an exact copy of MySequence, so I would expect them to behave the same from a type checking perspective. func2_2 is a copy of func2_1 with MySequence replaced with MySequenceCopy, so I would expect the two to produce the same type checking results. Mypy emits no error for func1_2 but emits an error for func2_2.
Strange behavior 3: The protocol class _NestedSequence contains a commented-out __contains__ method. If this method is added back, I would expect there to be no change to the type checking results. Yet, when __contains__ is added here, all of the errors previously reported by mypy disappear. This includes the errors in the final line of the sample. I would not expect the addition of __contains__ to have any impact on the results.
I'm not sure if these three issues are related, but I suspect they are.
I'm using the latest published version of mypy (0.982).
Activity
ilevkivskyi commentedon Jan 25, 2025
On a recent master I see no errors (with or without the
__contains__in the initial protocol).