Description
Code to reproduce:
from typing import Callable, NoReturn, TypeVar
def no_return() -> NoReturn:
pass
def use_decorated_before_defined() -> int:
decorated()
if bool():
return 0
else:
no_return()
T = TypeVar('T')
def wrapper(function: T) -> T:
return function
def decorator() -> Callable[[T], T]:
return wrapper
@decorator()
def decorated() -> None: pass
def use_decorated_after_defined() -> int:
decorated()
if bool():
return 0
else:
no_return()
def use_wrapped_before_defined() -> int:
wrapped()
if bool():
return 0
else:
no_return()
@wrapper
def wrapped() -> None: pass
I tested this both with mypy 0.750 and one from the current master branch (526a218), running on CPython 3.7.5. The command line and the output:
% python -m mypy repro.py
repro.py:8: error: Missing return statement
Found 1 error in 1 file (checked 1 source file)
I'd expect no errors here. After some digging in mypy source code I believe use_decorated_before_defined
can't be fully processed when it's type-checked (at least the first time it's entered) because of a) the call to decorated
being looked at before decorated
is defined and b) decorated
being decorated (pardon my repetition) with a result of another function call which I suspect creates a difficult environment for mypy to deduce things and it defers further processing of use_decorated_before_defined
(or at least part of it).
Then, when the call to no_return
is encountered its type is detected as Any
because of the processing being deferred per above, hence the error.
I left two similar variants of the function (use_decorated_after_defined
and use_wrapped_before_defined
) to help narrow things down as those don't trigger the error.