Description
Bug Report
Depending if the cache is present or not, mypy will accuse different overload methods names for typing errors in zip/islice uses.
I've tried to reproduce de error using specific overload methods in a custom class, however mypy is consistent in this case (see extra section in the end of the issue) .
To Reproduce
main.py file:
from itertools import islice
islice([], "2")
steps to reproduce inconsistent report:
rm -rf .mypy_cache/
mypy main.py # no cache present
mypy main.py # cache is present
Expected Behavior
I would expect mypy
to always report that the islice
function/class doesn't have the required overload even if it doesn't have a cache already built.
$ rm -rf .mypy_cache
$ mypy main.py
main.py:2: error: No overload variant of "islice" matches argument types "list[<nothing>]", "str" [call-overload]
main.py:2: note: Possible overload variants:
main.py:2: note: def [_T] islice(self, Iterable[_T], int | None, /) -> islice[_T]
main.py:2: note: def [_T] islice(self, Iterable[_T], int | None, int | None, int | None = ..., /) -> islice[_T]
Found 1 error in 1 file (checked 1 source file)
$ mypy main.py
main.py:2: error: No overload variant of "islice" matches argument types "list[<nothing>]", "str" [call-overload]
main.py:2: note: Possible overload variants:
main.py:2: note: def [_T] islice(self, Iterable[_T], int | None, /) -> islice[_T]
main.py:2: note: def [_T] islice(self, Iterable[_T], int | None, int | None, int | None = ..., /) -> islice[_T]
Found 1 error in 1 file (checked 1 source file)
Actual Behavior
$ rm -rf .mypy_cache
$ mypy main.py
main.py:2: error: No overload variant of "islice" matches argument types "list[<nothing>]", "str" [call-overload]
main.py:2: note: Possible overload variants:
main.py:2: note: def [_T] __init__(self, Iterable[_T], int | None, /) -> islice[_T]
main.py:2: note: def [_T] __init__(self, Iterable[_T], int | None, int | None, int | None = ..., /) -> islice[_T]
Found 1 error in 1 file (checked 1 source file)
$ mypy main.py
main.py:2: error: No overload variant of "islice" matches argument types "list[<nothing>]", "str" [call-overload]
main.py:2: note: Possible overload variants:
main.py:2: note: def [_T] islice(self, Iterable[_T], int | None, /) -> islice[_T]
main.py:2: note: def [_T] islice(self, Iterable[_T], int | None, int | None, int | None = ..., /) -> islice[_T]
Found 1 error in 1 file (checked 1 source file)
Note that the first mypy execution accused the __init__
method not having the requested overload, and in the second execution it changed to islice
.
Your Environment
- Mypy version used: mypy 1.6.1 (compiled: yes)
- Mypy command-line flags: (none)
- Mypy configuration options from
mypy.ini
(and other config files): (none) - Python version used: 3.11.5
extra
If main.py is:
from typing import Generic, Iterable, Iterator, Self, TypeVar, overload
_T = TypeVar("_T")
class islice(Iterator[_T], Generic[_T]):
@overload
def __init__(self, __iterable: Iterable[_T], __stop: int | None) -> None: ...
@overload
def __init__(self, __iterable: Iterable[_T], __start: int | None, __stop: int | None, __step: int | None = ...) -> None: ...
def __iter__(self) -> Self: ...
def __next__(self) -> _T: ...
islice([], "2")
mypy will always accuse that the __init__
method doesn't have the overload requested:
$ rm -rf .mypy_cache
$ mypy main.py
main.py:4: error: An overloaded function outside a stub file must have an implementation [no-overload-impl]
main.py:8: error: Missing return statement [empty-body]
main.py:8: note: If the method is meant to be abstract, use @abc.abstractmethod
main.py:9: error: Missing return statement [empty-body]
main.py:9: note: If the method is meant to be abstract, use @abc.abstractmethod
main.py:10: error: No overload variant of "islice" matches argument types "list[<nothing>]", "str" [call-overload]
main.py:10: note: Possible overload variants:
main.py:10: note: def [_T] __init__(self, Iterable[_T], int | None, /) -> islice[_T]
main.py:10: note: def [_T] __init__(self, Iterable[_T], int | None, int | None, int | None = ..., /) -> islice[_T]
Found 4 errors in 1 file (checked 1 source file)
$ mypy main.py
main.py:4: error: An overloaded function outside a stub file must have an implementation [no-overload-impl]
main.py:8: error: Missing return statement [empty-body]
main.py:8: note: If the method is meant to be abstract, use @abc.abstractmethod
main.py:9: error: Missing return statement [empty-body]
main.py:9: note: If the method is meant to be abstract, use @abc.abstractmethod
main.py:10: error: No overload variant of "islice" matches argument types "list[<nothing>]", "str" [call-overload]
main.py:10: note: Possible overload variants:
main.py:10: note: def [_T] __init__(self, Iterable[_T], int | None, /) -> islice[_T]
main.py:10: note: def [_T] __init__(self, Iterable[_T], int | None, int | None, int | None = ..., /) -> islice[_T]
Found 4 errors in 1 file (checked 1 source file)
another example
the same issue can happen with the zip
method:
main.py
zip([], 2)
mypy execution:
$ rm -rf .mypy_cache
$ mypy main.py
main.py:1: error: No overload variant of "zip" matches argument types "list[<nothing>]", "int" [call-overload]
main.py:1: note: Possible overload variants:
main.py:1: note: def [_T_co, _T1] __new__(cls, Iterable[_T1], /, *, strict: bool = ...) -> zip[tuple[_T1]]
main.py:1: note: def [_T_co, _T1, _T2] __new__(cls, Iterable[_T1], Iterable[_T2], /, *, strict: bool = ...) -> zip[tuple[_T1, _T2]]
main.py:1: note: def [_T_co, _T1, _T2, _T3] __new__(cls, Iterable[_T1], Iterable[_T2], Iterable[_T3], /, *, strict: bool = ...) -> zip[tuple[_T1, _T2, _T3]]
main.py:1: note: def [_T_co, _T1, _T2, _T3, _T4] __new__(cls, Iterable[_T1], Iterable[_T2], Iterable[_T3], Iterable[_T4], /, *, strict: bool = ...) -> zip[tuple[_T1, _T2, _T3, _T4]]
main.py:1: note: def [_T_co, _T1, _T2, _T3, _T4, _T5] __new__(cls, Iterable[_T1], Iterable[_T2], Iterable[_T3], Iterable[_T4], Iterable[_T5], /, *, strict: bool = ...) -> zip[tuple[_T1, _T2, _T3, _T4, _T5]]
main.py:1: note: def [_T_co] __new__(cls, Iterable[Any], Iterable[Any], Iterable[Any], Iterable[Any], Iterable[Any], Iterable[Any], /, *iterables: Iterable[Any], strict: bool = ...) -> zip[tuple[Any, ...]]
Found 1 error in 1 file (checked 1 source file)
$ mypy main.py
main.py:1: error: No overload variant of "zip" matches argument types "list[<nothing>]", "int" [call-overload]
main.py:1: note: Possible overload variants:
main.py:1: note: def [_T_co, _T1] zip(Iterable[_T1], /, *, strict: bool = ...) -> zip[tuple[_T1]]
main.py:1: note: def [_T_co, _T1, _T2] zip(Iterable[_T1], Iterable[_T2], /, *, strict: bool = ...) -> zip[tuple[_T1, _T2]]
main.py:1: note: def [_T_co, _T1, _T2, _T3] zip(Iterable[_T1], Iterable[_T2], Iterable[_T3], /, *, strict: bool = ...) -> zip[tuple[_T1, _T2, _T3]]
main.py:1: note: def [_T_co, _T1, _T2, _T3, _T4] zip(Iterable[_T1], Iterable[_T2], Iterable[_T3], Iterable[_T4], /, *, strict: bool = ...) -> zip[tuple[_T1, _T2, _T3, _T4]]
main.py:1: note: def [_T_co, _T1, _T2, _T3, _T4, _T5] zip(Iterable[_T1], Iterable[_T2], Iterable[_T3], Iterable[_T4], Iterable[_T5], /, *, strict: bool = ...) -> zip[tuple[_T1, _T2, _T3, _T4, _T5]]
main.py:1: note: def [_T_co] zip(Iterable[Any], Iterable[Any], Iterable[Any], Iterable[Any], Iterable[Any], Iterable[Any], /, *iterables: Iterable[Any], strict: bool = ...) -> zip[tuple[Any, ...]]
Found 1 error in 1 file (checked 1 source file)