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

Overloaded function signatures overlap with incompatible return types, class and Callable #1941

Closed
tharvik opened this issue Jul 26, 2016 · 8 comments
Labels

Comments

@tharvik
Copy link
Contributor

tharvik commented Jul 26, 2016

from typing import Any, Callable, overload

F = Callable[..., Any]

class A: ...

@overload
def f(exit: A) -> A: ...
@overload
def f(exit: F) -> F: ...

gives

asd.py:8: error: Overloaded function signatures 1 and 2 overlap with incompatible return types

which I don't understand. There is no overlap (expect that A is also a Callable), so, why the message?

@gvanrossum
Copy link
Member

You've nailed the reason for the overlap: f(A) matches both variants. (For other reasons it's important to accept classes when a callable is needed.)

Note that mypy's @overload processing doesn't go down the alternatives until it finds a match -- it finds all matching alternatives and if there's more than one, simply requires that they have the same return type.

I think we should close this issue as "won't fix". However maybe we need to change the wording in PEP 484 to call out this behavior more. I've opened python/typing#253 to serve that discussion. Feel free to participate!

@tharvik
Copy link
Contributor Author

tharvik commented Jul 26, 2016

Hum, I see, then IMO, PEP 484 should demand that, rather than merging every alternatives, force the mypy to find the "most accurate" type description; so that a general case can be written, and have some specific cases. For example, having a __getitem__ for a map accepting slice index, described as

@overload
def __getitem__(self, k: slice) -> List[_V]: ...  # specific
@overload
def __getitem__(self, k: _K) -> _V: ...  # generic

For now, let's close it.

@tharvik tharvik closed this as completed Jul 26, 2016
@gvanrossum
Copy link
Member

(FWIW, I think the tradition is to list the special cases first and the general case last.)

@tharvik
Copy link
Contributor Author

tharvik commented Jul 26, 2016

(Haha, yeah, that's more readable in a way, updated the comment, now it looks nicer!)

@JukkaL
Copy link
Collaborator

JukkaL commented Jul 26, 2016

Mypy lets you vary the return type even if multiple variants match if your signatures are ordered from narrower to more general. For example, this should be fine:

@overload
def f(x: int) -> str: ...
@overload
def f(x: object) -> object: ...

f(1)  # this is str
f('x')  # this is object
x = 1  # type: object
f(x)  # this is object, which is okay since str is a subclass of object

This would be a problem, though:

@overload
def f(x: int) -> object: ...
@overload
def f(x: object) -> int: ...  # bad

def g(x: object) -> int:
    return f(x) + 3   # the runtime type of x may be int and return value could be anything

g(1)
f(1) + 3   # an error

@tharvik
Copy link
Contributor Author

tharvik commented Jul 27, 2016

@JukkaL But in the current case, it is not working, I tried reordering the overload definition but it doesn't help. From what you wrote, I would have though that the overload for A would be narrower than the overload for Callable.

@JukkaL
Copy link
Collaborator

JukkaL commented Jul 27, 2016

If A is also callable (i.e., it has __call__), then this looks like a problem with subtyping of Callable values. There is already an open issue for this: #797. Also, mypy currently assumes that Callable can overlap with anything, which is another bug.

@gvanrossum
Copy link
Member

gvanrossum commented Jul 27, 2016 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants