Order of declarations matters, but it shouldn't
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 20.6k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
This replaces #14509.
Bug Report
The order of declarations shouldn't matter to mypy w.r.t.[^wrt] type annotations when from __future__ import annotations is in effect, but in the example that follows, they do.
To Reproduce
Analyze the following code with --strict (or run on mypy-play.net):
from __future__ import annotations
import functools
from typing import (
Any,
Callable,
cast,
Counter,
Optional,
TypeVar,
)
Tc = TypeVar('Tc', bound=Callable[..., Any])
def func_wraps(wraps: Tc) -> Callable[[Callable[..., Any]], Tc]:
'''declare that one function wraps another
Args:
wraps: the function being wrapped
Returns:
a function 'decorator()', where...
Args:
the function which wraps 'wraps'
Returns:
the input argument, unchanged
The type annotations of the return value of the 'decorator()' will
be those of 'wraps'.
'''
def inner(wrapper: Callable[..., Any], /) -> Tc:
'''decorator
Args:
wrapper: the function which wraps 'wraps'
Returns:
the same function, unchanged
'''
wrapper_ = cast(Tc, wrapper)
return functools.wraps(wraps)(wrapper_)
return inner
def function1() -> ChildClass:
return ChildClass()
class ParentClass:
def __init__(self, *, param: Optional[int] = None) -> None:
_ = param
class ChildClass(ParentClass):
some_counter: Counter[int]
@func_wraps(ParentClass.__init__)
def __init__(self, *args: Any, **kwargs: Any):
super().__init__(*args, **kwargs)
self.some_counter = Counter()
def function2() -> ChildClass:
return ChildClass()
Expected Behavior
There should be no errors.
Actual Behavior
The following error is issued w.r.t.[^wrt] function1:
bug.py:47: error: Returning Any from function declared to return "ChildClass" [no-any-return]
Found 1 error in 1 file (checked 1 source file)
Your Environment
- Mypy version used: 0.991, master (2023-01-24)
- Mypy command-line flags:
--show-error-codes --strict --warn-unreachable - Mypy configuration options from
mypy.ini(and other config files): N/A - Python version used: 3.8, 3.11
[^wrt]: with respect to
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the supplied bug.py reproducer with mypy's strict flags, or use the linked mypy-play example, and compare the diagnostics for function1 and function2. Trace the declaration-order handling for postponed annotations and decorated initializers; done means the reproducer reports no errors, including no-any-return for function1.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100