Closed
Description
Seems like mypy uses the first overloaded __call__
signature when using self-type. There is no problem with overloading another dunder method (I tried __get__
) or with regular overload (__call__
but without self-type). If use another method name, for example call
, then everything works fine.
Below is snippet to illustrate the problem:
from typing import Awaitable, Callable, Generic, TypeVar, overload
T = TypeVar("T", "Handler", "AsyncHandler")
Handler = Callable[[], "Result"]
AsyncHandler = Callable[[], Awaitable["Result"]]
class Result:
pass
class Middleware(Generic[T]):
def __init__(self, handler: T):
self.handler: T = handler
@overload
def __call__(self: "Middleware[Handler]") -> Result:
...
@overload
def __call__(self: "Middleware[AsyncHandler]") -> Awaitable[Result]:
...
def __call__(self):
return self.handler()
@overload
def call(self: "Middleware[Handler]") -> Result:
...
@overload
def call(self: "Middleware[AsyncHandler]") -> Awaitable[Result]:
...
def call(self):
return self.handler()
def handler() -> Result:
return Result()
async def async_handler() -> Result:
return Result()
reveal_type(Middleware(handler)) # OK, type is 'Middleware[def () -> Result]'
reveal_type(Middleware(async_handler)) # OK, type is 'Middleware[def () -> Awaitable[Result]]'
reveal_type(Middleware(handler)()) # OK, type is 'Result'
reveal_type(Middleware(handler).call()) # OK, type is 'Result'
reveal_type(Middleware(async_handler)()) # WRONG, type is 'Result', expected 'Awaitable[Result]'
reveal_type(Middleware(async_handler).call()) # OK, type is 'Awaitable[Result]'