-
- Notifications
You must be signed in to change notification settings - Fork 3.1k
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 whatTypeGuardis precisely for - knows how to handle theelsecase 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