Skip to content

"Cannot determine type of ..." when using decorators #11212

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
orsinium opened this issue Sep 28, 2021 · 3 comments · Fixed by #11215
Open

"Cannot determine type of ..." when using decorators #11212

orsinium opened this issue Sep 28, 2021 · 3 comments · Fixed by #11215
Labels
bug mypy got something wrong

Comments

@orsinium
Copy link

orsinium commented Sep 28, 2021

Bug Report

To Reproduce

Content of tmp.py

from typing import Callable, TypeVar

C = TypeVar('C', bound=Callable)

def dec(val: None) -> Callable[[C], C]:
    def wrapper(f):
        return f
    return wrapper

# E: Cannot determine type of "foo"  [has-type]
lambda: foo() == 2

@dec(None)
def foo() -> int:
    return 2

foo() == 2  # this one is fine

Running mypy:

$ mypy --config-file='' tmp.py 
tmp.py:13: error: Cannot determine type of "foo"

Your Environment

  • Mypy version used: 0.910
  • Mypy command-line flags: --
  • Mypy configuration options from mypy.ini (and other config files): --
  • Python version used: Python 3.9.0
  • Operating system and version: 5.4.0-81-generic #91-Ubuntu SMP Thu Jul 15 19:09:17 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
@orsinium orsinium added the bug mypy got something wrong label Sep 28, 2021
@orsinium orsinium changed the title "Cannot determine type of ..." for decorator "Cannot determine type of ..." when using decorators Sep 28, 2021
@orsinium
Copy link
Author

orsinium commented Sep 28, 2021

Surprisingly, with a regular identity as a decorator it works fine:

from typing import Callable, TypeVar

C = TypeVar('C', bound=Callable)

def dec(f: C) -> C:
    return f

lambda: foo() == 2

@dec
def foo() -> int:
    return 2

Another surprising discovery: it also works fine when both the function and the lambda are enclosed:

from typing import Callable, TypeVar

C = TypeVar('C', bound=Callable)

def dec(val: None) -> Callable[[C], C]:
    def wrapper(f):
        return f
    return wrapper

def f() -> None:
    lambda: foo() == 2

    @dec(None)
    def foo() -> int:
        return 2

If you're wondering what can be a use case, I'm making a decorator for providing function usage examples for deal:

@deal.example(lambda: double1(2) == 4)
def double1(x: int) -> int:
    return x * 2

Here, lambda is passed as an argument into the decorator and it produces the same error as in the issue description.

@sobolevn
Copy link
Member

@orsinium Hi 👋 😊 Glad to see you here (but, I am sorry that something does not work for you!)

I will try to solve this, I have some ideas about the possible cause, but no promises here: inference is always quite hard and any changes there can have massive influence on other features.

@orsinium
Copy link
Author

orsinium commented Sep 28, 2021

I'm glad to see you there too :) When you mentioned inference, I made another surprising discovery: it also works well when I use a function instead of a lambda:

from typing import Callable, TypeVar

C = TypeVar('C', bound=Callable)

def dec(val: None) -> Callable[[C], C]:
    def wrapper(f):
        return f
    return wrapper

def f() -> None:
    foo() == 2

@dec(None)
def foo() -> int:
    return 2

What an interesting case! Something very specific to lambdas in a global namespace, hmm.

JelleZijlstra pushed a commit that referenced this issue Sep 28, 2021
…e_type` (#11215)

Closes #11212

Previously `mypy` was ignoring `lambda` scope in `handle_cannot_determine_type`.
I guess it was done to fix some `lambda` related crashes.

I've also noticed one crash with this new solution in existing test. I happened because when right `or` part is unreachable, there's not `binder.frame` for it. So, I've made a temporary scope of it.
@hauntsaninja hauntsaninja reopened this Dec 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants