-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Describe the bug
I'm trying to write a decorator that takes an argument and decorates either an async or regular def in the case where there is a shared type parameter in the input and output of the def. Unlike the case discussed in #2142, the two overloads differ only in their outputs. I am aware that in the case the problem can be fixed by using the decorator as @foo instead of @foo(), but in the case we are worried about, @foo() takes a non-empty list of parameters.
To Reproduce
Output = TypeVar("Output")
@overload
def foo() -> (
Callable[[Callable[[Output], Coroutine[Any, Any, Output]]], Callable[[Output], Coroutine[Any, Any, Output]]]
):
...
@overload
def foo() -> Callable[[Callable[[Output], Output]], Callable[[Output], Output]]:
...
def foo() -> (
Callable[[Callable[[Output], Coroutine[Any, Any, Output]]], Callable[[Output], Coroutine[Any, Any, Output]]]
| Callable[[Callable[[Output], Output]], Callable[[Output], Output]]
):
return lambda x: x # do something real here depending on value of `iscoroutinefunction`
def test_foo():
@foo()
def bar(x: int) -> int:
return x + 5
assert bar(1) == 6
@foo()
async def abar(x: int) -> int:
return x + 5
assert asyncio.run(abar(1)) == 6Expected behavior
I think Pyright should successfully typecheck here.
The current behavior depends on the order in which the two @overloads are declared, which indicates that the output constraint on the decorator invocation from def's signature is not active when running type inference for the decorator.
VS Code extension or command-line
Command-line with 1.1.304.