-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Closed
Labels
bugmypy got something wrongmypy got something wrong
Description
Bug Report
I wrote a higher-order function which converts a function into a coroutine function and also is idempotent on a coroutine function.
I wanted to try TypeGuard
as it seemed to fit this particular use case.
To Reproduce
import typing as t
from typing_extensions import ParamSpec, TypeGuard
T = t.TypeVar("T")
P = ParamSpec("P")
def is_awaitable(
coro_or_value: t.Union[T, t.Awaitable[T]]
) -> TypeGuard[t.Awaitable[T]]:
return hasattr(coro_or_value, "__await__")
def ensure_async(
fn: t.Union[t.Callable[P, T], t.Callable[P, t.Awaitable[T]]]
) -> t.Callable[P, t.Awaitable[T]]:
async def inner(*args: P.args, **kwargs: P.kwargs) -> T:
coro_or_value = fn(*args, **kwargs)
if is_awaitable(coro_or_value):
return await coro_or_value # mypy says: Incompatible return value type (got "T", expected "T")
else:
return coro_or_value # mypy says: Incompatible return value type (got "Union[T, Awaitable[T]]", expected "T")
return inner
def add(x: int, y: int) -> int:
return x + y
async def a_add(x: float, y: float) -> float:
return x + y
if t.TYPE_CHECKING:
reveal_type(ensure_async(add)) # Revealed type is "def (*<nothing>, **<nothing>) -> typing.Awaitable[<nothing>]"
reveal_type(ensure_async(add)(1, 2)) # Revealed type is "typing.Awaitable[<nothing>]"
reveal_type(ensure_async(a_add)) # Revealed type is "def (*<nothing>, **<nothing>) -> typing.Awaitable[<nothing>]"
Expected Behavior
- In the case of
Incompatible return value type (got "T", expected "T")
, I would not expect this message. - In the case of
Incompatible return value type (got "Union[T, Awaitable[T]]", expected "T")
, I would expect that this is whatTypeGuard
is precisely for - knows how to handle theelse
case of type narrowing, so no message.
Actual Behavior
Mypy is not able to typecheck. The important errors:
2022_01_05_typeguard_mypy_bug.py:21: error: Incompatible return value type (got "T", expected "T")
2022_01_05_typeguard_mypy_bug.py:23: error: Incompatible return value type (got "Union[T, Awaitable[T]]", expected "T")
Full mypy log, including the exemplary functions:
2022_01_05_typeguard_mypy_bug.py:21: error: Incompatible return value type (got "T", expected "T")
2022_01_05_typeguard_mypy_bug.py:23: error: Incompatible return value type (got "Union[T, Awaitable[T]]", expected "T")
2022_01_05_typeguard_mypy_bug.py:37: note: Revealed type is "def (*<nothing>, **<nothing>) -> typing.Awaitable[<nothing>]"
2022_01_05_typeguard_mypy_bug.py:37: error: Argument 1 to "ensure_async" has incompatible type "Callable[[int, int], int]"; expected "Callable[[VarArg(<nothing>), KwArg(<nothing>)], Awaitable[<nothing>]]"
2022_01_05_typeguard_mypy_bug.py:38: note: Revealed type is "typing.Awaitable[<nothing>]"
2022_01_05_typeguard_mypy_bug.py:38: error: Argument 1 to "ensure_async" has incompatible type "Callable[[int, int], int]"; expected "Callable[[VarArg(<nothing>), KwArg(<nothing>)], Awaitable[<nothing>]]"
2022_01_05_typeguard_mypy_bug.py:38: error: Argument 1 has incompatible type "int"; expected <nothing>
2022_01_05_typeguard_mypy_bug.py:38: error: Argument 2 has incompatible type "int"; expected <nothing>
2022_01_05_typeguard_mypy_bug.py:39: note: Revealed type is "def (*<nothing>, **<nothing>) -> typing.Awaitable[<nothing>]"
2022_01_05_typeguard_mypy_bug.py:39: error: Argument 1 to "ensure_async" has incompatible type "Callable[[float, float], Coroutine[Any, Any, float]]"; expected "Callable[[VarArg(<nothing>), KwArg(<nothing>)], Awaitable[<nothing>]]"
Found 7 errors in 1 file (checked 1 source file)
(Write what happened.)
Your Environment
- Mypy version used: 0.940+dev.9c05d3d19de74fc10a51aa5b663e6a38bc6abc73
- Python version used: 3.10.1 and 3.9.7
Metadata
Metadata
Assignees
Labels
bugmypy got something wrongmypy got something wrong