2Tests consistency of overloads with implementation.
5from typing import Callable, Coroutine, overload
6from types import CoroutineType
8# > If an overload implementation is defined, type checkers should validate
9# > that it is consistent with all of its associated overload signatures.
10# > The implementation should accept all potential sets of arguments
11# > that are accepted by the overloads and should produce all potential return
12# > types produced by the overloads. In typing terms, this means the input
13# > signature of the implementation should be :term:`assignable` to the input
14# > signatures of all overloads, and the return type of all overloads should be
15# > assignable to the return type of the implementation.
17# Return type of all overloads must be assignable to return type of
21def return_type(x: int) -> int:
25def return_type(x: str) -> str: # E[return_type]
Expected a ty diagnostic for this line (tag 'return_type')
28def return_type(x: int | str) -> int: # E[return_type] an overload returns `str`, not assignable to `int`
Expected a ty diagnostic for this line (tag 'return_type')
32# Input signature of implementation must be assignable to signature of each
33# overload. We don't attempt a thorough testing of input signature
34# assignability here; see `callables_subtyping.py` for that:
37def parameter_type(x: int) -> int:
41def parameter_type(x: str) -> str: # E[parameter_type]
Expected a ty diagnostic for this line (tag 'parameter_type')
44def parameter_type(x: int) -> int | str: # E[parameter_type] impl type of `x` must be assignable from overload types of `x`
Expected a ty diagnostic for this line (tag 'parameter_type')
48# > Overloads are allowed to use a mixture of ``async def`` and ``def`` statements
49# > within the same overload definition. Type checkers should convert
50# > ``async def`` statements to a non-async signature (wrapping the return
51# > type in a ``Coroutine``) before testing for implementation consistency
52# > and overlapping overloads (described below).
56# > When a type checker checks the implementation for consistency with overloads,
57# > it should first apply any transforms that change the effective type of the
58# > implementation including the presence of a ``yield`` statement in the
59# > implementation body, the use of ``async def``, and the presence of additional
62# An overload can explicitly return `Coroutine`, while the implementation is an
66def returns_coroutine(x: int) -> CoroutineType[None, None, int]:
70async def returns_coroutine(x: str) -> str:
73async def returns_coroutine(x: int | str) -> int | str:
77# The implementation can explicitly return `Coroutine`, while overloads are
81async def returns_coroutine_2(x: int) -> int:
85async def returns_coroutine_2(x: str) -> str:
88def returns_coroutine_2(x: int | str) -> Coroutine[None, None, int | str]:
91async def _wrapped(x: int | str) -> int | str:
94# Decorator transforms are applied before checking overload consistency:
96def _deco_1(f: Callable) -> Callable[[int], int]:
97 def wrapped(_x: int, /) -> int:
101def _deco_2(f: Callable) -> Callable[[int | str], int | str]:
102 def wrapped(_x: int | str, /) -> int | str:
108def decorated() -> None:
112def decorated(x: str, /) -> str:
116def decorated(y: bytes, z: bytes) -> bytes: