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

mypy is unable to correctly disambiguate a union when there is a dependent function type #14421

Open
Jackmin801 opened this issue Jan 10, 2023 · 2 comments
Labels
bug mypy got something wrong topic-type-narrowing Conditional type narrowing / binder

Comments

@Jackmin801
Copy link

Bug Report

mypy is unable to correctly disambiguate a union when there is a dependent function type.
The call meow(s)(s) is always valid as s is either int or str and should not be able to take on both in the line.
However, the dependency of the return type of meow(s) on s is not remembered and mypy becomes upset.

To Reproduce

https://mypy-play.net/?mypy=latest&python=3.11&gist=50bc3d85db8bc5120d881d37b891fd2a

from typing import overload, Callable, Union

@overload
def meow(a: int) -> Callable[[int], int]:
    ...

@overload
def meow(a: str) -> Callable[[str], str]:
    ...

def meow(a):
    return lambda x: x

# OK
a: str = 's'
meow(a)(a)

# Not ok though it should be
s: Union[int, str] = 's'
meow(s)(s)

Expected Behavior

Expected Behavior

Success: no issues found in 1 source file

Actual Behavior

main.py:20: error: Argument 1 has incompatible type "Union[int, str]"; expected "int"  [arg-type]
main.py:20: error: Argument 1 has incompatible type "Union[int, str]"; expected "str"  [arg-type]
Found 2 errors in 1 file (checked 1 source file)

Your Environment

  • Mypy version used: 0.991
  • Mypy command-line flags: none
  • Mypy configuration options from mypy.ini (and other config files): none
  • Python version used: 3.11
@Jackmin801 Jackmin801 added the bug mypy got something wrong label Jan 10, 2023
@tmke8
Copy link
Contributor

tmke8 commented Jan 10, 2023

Hm, the problem is that mypy doesn't keep track of how the type of meow(s) was determined. It's just treated as a union type:

s: Union[int, str] = 's'
reveal_type(meow(s))  # Union[Callable[[int], int], Callable [[str], str]]

When you then do meow(s)(s), mypy only sees that meow(s)(x) either takes an int or a str but it's not known which one, so mypy throws an error.

I would predict that mypy will never support this but I can't be sure. In the meantime, you can maybe solve your problem with a generic function:

MyData = TypeVar("MyData", int, str)
def meow(a: MyData) -> Callable[[MyData], MyData]:
    return lambda x: x

@ichard26 ichard26 added topic-union-types topic-type-narrowing Conditional type narrowing / binder and removed topic-union-types labels Jan 13, 2023
@ichard26
Copy link
Collaborator

See also: #2008 (it's why mypy doesn't narrow s's type on assignment).

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-type-narrowing Conditional type narrowing / binder
Projects
None yet
Development

No branches or pull requests

3 participants