Skip to content

Type inference fails on decorator designed to work on both async and regular defs #5014

@adampauls

Description

@adampauls

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)) == 6

Expected 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    as designedNot a bug, working as intended

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions