Skip to content

TypeVar bound to Callable confuses Mypy #12297

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

Open
posita opened this issue Mar 6, 2022 · 0 comments
Open

TypeVar bound to Callable confuses Mypy #12297

posita opened this issue Mar 6, 2022 · 0 comments
Labels
bug mypy got something wrong topic-type-variables

Comments

@posita
Copy link
Contributor

posita commented Mar 6, 2022

# test_case.py
from typing import Callable, Optional, TypeVar, Union, overload

class Foo: pass

class Bar: pass

ReturnsFooOrBarT = Callable[..., Union[Foo, Bar]]
TermT = TypeVar("TermT", bound=ReturnsFooOrBarT)

def returns_foo() -> Foo:
    return Foo()

def returns_bar() -> Bar:
    return Bar()

@overload
def do_something_or_something_else(
    *,
    something_else: Union[int, TermT] = 0,
) -> None:
    ...

@overload
def do_something_or_something_else(
    something: TermT,
    *,
    something_else: Union[int, TermT] = 0,
) -> None:
    ...

def do_something_or_something_else(
    something: Optional[TermT] = None,
    *,
    something_else: Union[int, TermT] = 0,
) -> None:
    pass

do_something_or_something_else(something_else=1)
do_something_or_something_else(something_else=returns_bar)
do_something_or_something_else(something_else=returns_foo)

do_something_or_something_else(returns_foo, something_else=1)
do_something_or_something_else(returns_foo, something_else=returns_foo)

do_something_or_something_else(returns_bar, something_else=1)
do_something_or_something_else(returns_bar, something_else=returns_bar)

returns_foo_or_bar: ReturnsFooOrBarT

# These should all validate, no?
returns_foo_or_bar = returns_foo
do_something_or_something_else(returns_foo_or_bar, something_else=1)
do_something_or_something_else(returns_foo_or_bar, something_else=returns_bar)  # <-- false negative?
do_something_or_something_else(returns_foo, something_else=returns_bar)  # <-- false negative?

# These should all validate, no?
returns_foo_or_bar = returns_bar
do_something_or_something_else(returns_foo_or_bar, something_else=1)
do_something_or_something_else(returns_foo_or_bar, something_else=returns_foo)  # <-- false negative?
do_something_or_something_else(returns_bar, something_else=returns_foo)  # <-- false negative?
% mypy --config=/dev/null test_case.py
/dev/null: No [mypy] section in config file
test_case.py:54: error: Value of type variable "TermT" of "do_something_or_something_else" cannot be "Callable[[], object]"
test_case.py:55: error: Value of type variable "TermT" of "do_something_or_something_else" cannot be "Callable[[], object]"
test_case.py:60: error: Value of type variable "TermT" of "do_something_or_something_else" cannot be "Callable[[], object]"
test_case.py:61: error: Value of type variable "TermT" of "do_something_or_something_else" cannot be "Callable[[], object]"
Found 4 errors in 1 file (checked 1 source file)
% python --version
Python 3.9.10
% mypy --version
mypy 0.931
% mypy --config=/dev/null test_case.py

If I s/TermT/ReturnsFooOrBarT/g, the errors go away. The above is a contrived example, but having a TypeVar is helpful when returning a function of the same type that was provided (e.g., with a decorator).

Possibly related to #8922 or #9075?

@posita posita added the bug mypy got something wrong label Mar 6, 2022
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-variables
Projects
None yet
Development

No branches or pull requests

2 participants