-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
error: Overloaded function signatures 1 and 2 overlap with incompatible return types #4020
Comments
Full code is here: https://github.com/chantisnake/PythonZ/blob/master/pythonz/basic.py |
My guess is that mypy considers I am not sure what to do here, maybe we can allow the definition, and give an error at the call site if an argument matches two overloads with incompatible return types. Or maybe we can infer a union of return types if the argument matches multiple overloads. There is still no 100% agreement on semantics of overloads, see python/typing#253 |
This appeared again, so I raise the priority. Also python/typing#253 is one of the few issues remaining in the "PEP 484 finalization" |
In addition to curry/uncurry style functions, I ran into this when I was handling a decorator that was agnostic to the arity of what it worked on by using |
I ran into this same problem with Here are my simple reproductions (using mypy 0.540): from typing import overload, NamedTuple, Callable
A = NamedTuple('A', [('foo', int)])
B = NamedTuple('B', [('bar', str)])
@overload
def this(arg):
# type: (A) -> str
pass
@overload
def this(arg):
# type: (B) -> int
pass
def this(arg):
pass
# -- callable
@overload
def that(arg):
# type: (str) -> str
pass
@overload
def that(arg):
# type: (Callable) -> int
pass
def that(arg):
pass |
@chadrik I think your particular examples might be related to the fact that if mypy can't determine whether types are overlapping, then it always assumes that they are. |
The last example might actually overlap for real with protocols; you could have a |
The same would be true for any protocol, which effectively means that protocols can't be used with Since this is such an easy trap to fall into, it might be worth considering some adjustments to make it easier to avoid. Here are some ideas:
Why can't mypy determine that |
|
The way mypy handles overloads is inconsistent. Originally mypy did overlapping checks pretty strictly -- for example, two user-defined classes
I don't think that this would be useful, since "type X or any subclass" is so prevalent that this would be very restrictive in practice. For example, all functions in stubs return "type X or any subclass" so about the only the way you can get a guaranteed instance of type
I assume that this means that mypy would complain if the actual argument types match multiple overload items with incompatible return types (we'd have to be silent in case of |
IIUC this is related to the fact that long time ago mypy did some kind of runtime dispatch for overloads. |
All examples in this issue now pass on master. |
I'm running into this issue. I have a simplified example of the issue here: https://gist.github.com/mypy-play/630a35c98137fef0a248078bcb98d193 import typing
from typing import Union, Tuple, List, Literal
import random
class A:
pass
@typing.overload
def foo(x: Literal[False] = False) -> Union[A, Tuple[A, ...], List[Union[A, Tuple[A, ...]]]]:
...
@typing.overload
def foo(x: Literal[True] = True) -> Tuple[Union[A, Tuple[A, ...], List[Union[A, Tuple[A, ...]]]], A]:
...
@typing.overload
def foo(x: bool) -> Union[
Union[A, Tuple[A, ...], List[Union[A, Tuple[A, ...]]]],
Tuple[Union[A, Tuple[A, ...], List[Union[A, Tuple[A, ...]]]], A]
]:
...
def foo(x: bool) -> Union[
Union[A, Tuple[A, ...], List[Union[A, Tuple[A, ...]]]],
Tuple[Union[A, Tuple[A, ...], List[Union[A, Tuple[A, ...]]]], A]
]:
out: Union[A, Tuple[A, ...]] = A() if random.randint(0, 2) else (A(), A())
if x:
return ([out], out)
else:
return out I think the ambiguity is due to the first type in the union, second entry (of the |
Your first two overloads overlap because |
Thanks, didn't realise you should only provide one set of default arguments to one overload. This works great! |
What about in the case the default arguments are needed because of the previous default arguments? from typing import Literal, overload
class Attr(object):
pass
class MutableAttr(Attr):
pass
@overload
def attr(param=1, mutable=False):
# type: (int, Literal[False]) -> Attr
pass
@overload
def attr(param=1, mutable=True):
# type: (int, Literal[True]) -> MutableAttr
pass
def attr(param=1, mutable=True):
# type: (int, bool) -> Attr
if mutable:
return MutableAttr()
else:
return Attr()
reveal_type(attr(mutable=True))
reveal_type(attr(mutable=False)) Result from mypy (it reveals the correct types, but it fails on incompatible return types):
|
You can add more overloads to manually cover all the cases, like |
It works! Thanks :) |
I am trying to implement currying in python, it passes Pycharm type checks (which is not as comprehensive as mypy), but my py gives me tons of error like this:
Here is a sample of my code
The text was updated successfully, but these errors were encountered: