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

no error issued when calling a decorated function with the wrong argument type #10704

Closed
clo-vis opened this issue Jun 23, 2021 · 2 comments
Closed
Labels
bug mypy got something wrong topic-paramspec PEP 612, ParamSpec, Concatenate

Comments

@clo-vis
Copy link

clo-vis commented Jun 23, 2021

To Reproduce

Run mypy on this code and then run the code

import functools

@functools.cache
def factorial(n: int) -> int:
    return n * factorial(n-1) if n else 1    

def identity(n: int) -> int:        
    return n

if __name__ == '__main__':
    print(factorial.__name__, factorial.__annotations__)
    print(identity.__name__, identity.__annotations__)
    factorial("")
    identity("")

The output of the program is:

factorial {'n': <class 'int'>, 'return': <class 'int'>}
identity {'n': <class 'int'>, 'return': <class 'int'>}

so type information is available.

Expected Behavior

The lines
factorial("")
and
identity("")
should be both flagged as wrong because the function is called with an incompatible type

Actual Behavior

An error is issued for
identity("")
but not for
factorial("")

As a side note, mypy issues an error

_lru_cache_wrapper[int]" has no attribute "name" for _print(factorial.name, ...)

but this is another issue.

Your Environment

  • Mypy version used: 0.910
  • Mypy command-line flags: none
  • Mypy configuration options from mypy.ini (and other config files): none
  • Python version used: 3.9.5
  • Operating system and version: Windows 10
@clo-vis clo-vis added the bug mypy got something wrong label Jun 23, 2021
@erictraut
Copy link

erictraut commented Jun 23, 2021

This appears to be a deficiency in the functools.pyi type stub. It defines _lru_cache_wrapper and cache as follows:

class _lru_cache_wrapper(Generic[_T]):
    __wrapped__: Callable[..., _T]
    def __call__(self, *args: Hashable, **kwargs: Hashable) -> _T: ...

def cache(__user_function: Callable[..., _T]) -> _lru_cache_wrapper[_T]: ...

Now that typeshed stubs are starting to incorporate PEP 612 (ParamSpec) support, it could be updated to the following:

_P = ParamSpec("_P")

class _lru_cache_wrapper(Generic[_P, _T]):
    __wrapped__: Callable[_P, _T]
    def __call__(self, *args: _P.args, **kwargs: _P.kwargs) -> _T: ...

def cache(__user_function: Callable[_P, _T]) -> _lru_cache_wrapper[_P, _T]: ...

Mypy doesn't currently have full support for ParamSpec (see this tracking issue), but once that support is added, this should address the issue you've reported. I confirmed that it works with pyright.

@JelleZijlstra JelleZijlstra added the topic-paramspec PEP 612, ParamSpec, Concatenate label Mar 19, 2022
@hauntsaninja
Copy link
Collaborator

hauntsaninja commented May 23, 2022

Closing, since the change to typeshed is being tracked in typeshed (any blocking mypy issues should be tracked in a more specific issue than this one).

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-paramspec PEP 612, ParamSpec, Concatenate
Projects
None yet
Development

No branches or pull requests

4 participants