Open huzecong opened 5 years ago
Alas, this is a legitimate unsafe overlap -- the unsafeness stems from how bools are subtypes of ints in Python.
Basically, we get an unsafe overlap if we try running mypy on following:
# bools are subtypes of ints, so this assignment is safe!
x: int = True
# So we get inconsistent and incompatible results despite that we're using the
# same runtime values:
reveal_type(foo(1, True)) # Revealed type is 'int'
reveal_type(foo(1, x)) # Revealed type is 'Tuple[int, ...]'
Probably the quickest fix would be to just make c
a keyword-only argument in your first overload:
@overload
def foo(a: int, *, c: bool = True) -> int: ...
# Note that 'c' is already a keyword-only argument here.
@overload
def foo(a: int, b: int, *args: int, c: bool = True) -> Tuple[int, ...]: ...
def foo(a, *args, c=True):
if len(args) == 0:
return a
return (a,) + args
This will make it so that doing foo(3, True)
will no longer select the first overload: you need to do foo(3, c=True)
instead.
After this change is made, both calls to foo(...)
above will select the second overload and return a Tuple[int, ...]
. (This also happens to match what your implementation is actually doing.)
@Michael0x2a Thank you so much for the explanation! I had no idea that bool
was a subtype of int
😲. And yes, making c
a keyword-only argument solved the problem.
However, if c
is kept as is, and types of all other arguments are changed from int
to str
, the issue still exists.
@overload
def foo(a: str, c: bool = True) -> str: ...
@overload
def foo(a: str, b: str, *args: str, c: bool = True) -> Tuple[str, ...]: ...
Since bool
is not a subtype of str
, I believe these two signatures do not overlap. However, mypy still reports the said error.
Hmm, I think you might be right -- it looks like this is a legitimate bug after all!
Here's a simpler repro:
from typing import overload
@overload
def foo(b: bool = True) -> str: ...
@overload
def foo(a: str, *, b: bool = True) -> int: ...
def foo(*args, **kwargs): pass
Is there an issue that requests making the error message more explicit about why the function overload has incompatible return types?
@bartenra This? https://github.com/python/mypy/issues/3819
Are you reporting a bug, or opening a feature request?
Bug.
Please insert below the code you are checking with mypy, or a mock-up repro if the source is private.
What is the actual behavior/output?
mypy reported error: Overloaded function signatures 1 and 2 overlap with incompatible return types.
What is the behavior/output you expect?
The two signatures do not overlap so no error should be raised.
Also, no errors were reported when the argument
c
was removed.What are the versions of mypy and Python you are using? Do you see the same issue after installing mypy from Git master?
mypy: The master version (d90eb18). Python: Both 3.7.3 and 3.6.3 are tested and the issue is reproducable.
What are the mypy flags you are using?
No flags were used.