Skip to content

1.7.0: Overloaded function with decorator using ParamSpec does not type check #16474

Closed as not planned

Description

@thomascellerier

Bug Report

Code with overloads with a decorator using a ParamSpec was typechecking fine with mypy 1.6.1 but not with mypy 1.7.0.

To Reproduce

See the following reproducer loosely based on an API client library where I hit this problem.
The library allows optionally parsing the response body into a model class

test_overload.py

import typing

P = typing.ParamSpec("P")
R = typing.TypeVar("R")


def handle_exception(
    func: typing.Callable[P, typing.Awaitable[R]]
) -> typing.Callable[P, typing.Awaitable[R]]:
    return func


class Response:
    pass


class ResponseModel:
    pass


ResponseT = typing.TypeVar("ResponseT", bound=ResponseModel)


@typing.overload
async def request(response_model: type[ResponseT]) -> ResponseT:
    ...

@typing.overload
async def request(response_model: None = ...) -> Response:
    ...


@handle_exception
async def request(
    response_model: type[ResponseT] | None = None,
) -> ResponseT | Response:
    raise NotImplementedError()

It can be reproduced without async too.

test_overload_sync.py

import typing

P = typing.ParamSpec("P")
R = typing.TypeVar("R")


def handle_exception(
    func: typing.Callable[P, R]
) -> typing.Callable[P, R]:
    return func


class Response:
    pass


class ResponseModel:
    pass


ResponseT = typing.TypeVar("ResponseT", bound=ResponseModel)


@typing.overload
def request(response_model: type[ResponseT]) -> ResponseT:
    ...

@typing.overload
def request(response_model: None = ...) -> Response:
    ...


@handle_exception
def request(
    response_model: type[ResponseT] | None = None,
) -> ResponseT | Response:
    raise NotImplementedError()

Expected Behavior

No mypy errors.

This works with 1.6.1:

$ mypy --version
mypy 1.6.1 (compiled: yes)
$ mypy test_overload.py 
Success: no issues found in 1 source file

Actual Behavior

It fails to type check:

$ mypy test_overload.py 
test_overload.py:33: error: Argument 1 to "handle_exception" has incompatible type "Callable[[type[ResponseT] | None], Coroutine[Any, Any, ResponseT | Response]]"; expected "Callable[[VarArg(Never), KwArg(Never)], Awaitable[Never]]"  [arg-type]
test_overload.py:33: error: Overloaded function implementation does not accept all possible arguments of signature 1  [misc]
test_overload.py:33: error: Overloaded function implementation cannot produce return type of signature 1  [misc]
test_overload.py:33: error: Overloaded function implementation does not accept all possible arguments of signature 2  [misc]
test_overload.py:33: error: Overloaded function implementation cannot produce return type of signature 2  [misc]
Found 5 errors in 1 file (checked 1 source file)

Sync version:

$ python3 -m mypy test_overload_sync.py 
test_overload.py:33: error: Argument 1 to "handle_exception" has incompatible type "Callable[[type[ResponseT] | None], ResponseT | Response]"; expected "Callable[[VarArg(Never), KwArg(Never)], Never]"  [arg-type]
test_overload.py:33: error: Overloaded function implementation does not accept all possible arguments of signature 1  [misc]
test_overload.py:33: error: Overloaded function implementation does not accept all possible arguments of signature 2  [misc]

Your Environment

  • Mypy version used: 1.7.0 (compiled)
  • Mypy command-line flags: mypy test_overload.py, tried with and without a clean cache
  • Python version: 3.10.2, 3.11.6

Activity

  1. ilevkivskyi commented on Nov 13, 2023

    @ilevkivskyi
    Member

    This is likely a duplicate of #16451. It should be fixed on latest master (merged few minutes ago). Could you please double-check and re-open if needed?

  2. AlexWaygood commented on Nov 13, 2023

    @AlexWaygood
    Member

    This is likely a duplicate of #16451. It should be fixed on latest master (merged few minutes ago). Could you please double-check and re-open if needed?

    Both snippets pass for me locally with the latest master (but not before #16461)

  3. thomascellerier commented on Nov 14, 2023

    @thomascellerier
    Author

    Thanks!

    I tested as well with master and it works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrongtopic-paramspecPEP 612, ParamSpec, Concatenate

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions