Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent error report for islice/zip "no overload match" error depending if cache is present #16363

Open
giuliano-macedo opened this issue Oct 29, 2023 · 1 comment
Labels
bug mypy got something wrong topic-incremental

Comments

@giuliano-macedo
Copy link

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)
@giuliano-macedo giuliano-macedo added the bug mypy got something wrong label Oct 29, 2023
@giuliano-macedo
Copy link
Author

giuliano-macedo commented Oct 29, 2023

Just to add more context:
This issue can cause confusion when using mypy-baseline since it wouldn't match the mypy-baseline.txt when running in the CI without cache if the user first create the mypy-baseline.txt in his machine while having the mypy cache

@giuliano-macedo giuliano-macedo changed the title Inconsistent error report for islice/zip "no overload match" depending if cache is present Inconsistent error report for islice/zip "no overload match" error depending if cache is present Oct 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong topic-incremental
Projects
None yet
Development

No branches or pull requests

2 participants