-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Closed
Labels
Description
I'll try to show a similar but smaller implementation of a decorator I've tried to throw together:
import asyncio
from typing import Awaitable, Callable, TypeVar, overload, cast, Generic
T = TypeVar("T", bound=object)
class Async(Generic[T]):
def __init__(self, f: Callable[[int], Awaitable[T]]):
...
class Sync(Generic[T]):
def __init__(self, f: Callable[[int], T]):
...
@overload
def supposed_overlap(f: Callable[[int], Awaitable[T]]) -> Async[T]:
...
@overload
def supposed_overlap(f: Callable[[int], T]) -> Sync[T]:
...
def supposed_overlap(f: Callable[[int], Awaitable[T] | T]) -> Async[T] | Sync[T]:
if asyncio.iscoroutinefunction(f):
return Async(cast(Callable[[int], Awaitable[T]], f))
else:
return Sync(cast(Callable[[int], T], f))
@supposed_overlap
async def something_async(value: int) -> float:
return 1.1
@supposed_overlap
def something_sync(value: int) -> str:
return "1.1"
reveal_type(something_async)
reveal_type(something_sync)
Resulting in:
18: error: Overloaded function signatures 1 and 2 overlap with incompatible return types [misc]
While the revealed types are correct (as long as the overloads are specified in the order above)
42: note: Revealed type is "Async[builtins.float*]"
43: note: Revealed type is "Sync[builtins.str*]"
I can see why I get this error, that Awaitable
could match with (or be included by) T
as well. But I'd like to express that kind of difference, the naive version being:
- Match only on being
Awaitable
- Everything else
Which mypy already seem to do for me (seeing that reveal_type
is correct) while overlaps doesn't consider ordering
Sorry if I'm just piling to the already existing list of overlap-issues from @overload
, or I'm missing something.. But I had a hard time matching my issue with any of the open ones.
kjagiello