blob: e173fb27e49e6dca83d3d3369427cff7c1963ea9 [file]
-- Test cases for function overloading
[case testTypeCheckOverloadedFunctionBody]
from typing import overload
@overload
def f(x: 'A'):
x = B() # E: Incompatible types in assignment (expression has type "B", variable has type "A")
x = A()
@overload
def f(x: 'B'):
x = A() # E: Incompatible types in assignment (expression has type "A", variable has type "B")
x = B()
class A: pass
class B: pass
[out]
[case testTypeCheckOverloadedMethodBody]
from typing import overload
class A:
@overload
def f(self, x: 'A'):
x = B() # E: Incompatible types in assignment (expression has type "B", variable has type "A")
x = A()
@overload
def f(self, x: 'B'):
x = A() # E: Incompatible types in assignment (expression has type "A", variable has type "B")
x = B()
class B: pass
[out]
[case testCallToOverloadedFunction]
from typing import overload
f(C()) # E: No overload variant of "f" matches argument types [__main__.C]
f(A())
f(B())
@overload
def f(x: 'A') -> None: pass
@overload
def f(x: 'B') -> None: pass
class A: pass
class B: pass
class C: pass
[case testOverloadedFunctionReturnValue]
from typing import overload
a, b = None, None # type: (A, B)
b = f(a) # E: Incompatible types in assignment (expression has type "A", variable has type "B")
a = f(b) # E: Incompatible types in assignment (expression has type "B", variable has type "A")
a = f(a)
b = f(b)
@overload
def f(x: 'A') -> 'A': pass
@overload
def f(x: 'B') -> 'B': pass
class A: pass
class B: pass
[case testCallToOverloadedMethod]
from typing import overload
A().f(C()) # E: No overload variant of "f" of "A" matches argument types [__main__.C]
A().f(A())
A().f(B())
class A:
@overload
def f(self, x: 'A') -> None: pass
@overload
def f(self, x: 'B') -> None: pass
class B: pass
class C: pass
[case testOverloadedMethodReturnValue]
from typing import overload
a, b = None, None # type: (A, B)
b = a.f(a) # E: Incompatible types in assignment (expression has type "A", variable has type "B")
a = a.f(b) # E: Incompatible types in assignment (expression has type "B", variable has type "A")
a = a.f(a)
b = a.f(b)
class A:
@overload
def f(self, x: 'A') -> 'A': pass
@overload
def f(self, x: 'B') -> 'B': pass
class B: pass
[case testOverloadsWithDifferentArgumentCounts]
from typing import overload
a, b = None, None # type: (A, B)
a = f(a)
b = f(a) # E: Incompatible types in assignment (expression has type "A", variable has type "B")
f(b) # E: No overload variant of "f" matches argument types [__main__.B]
b = f(b, a)
a = f(b, a) # E: Incompatible types in assignment (expression has type "B", variable has type "A")
f(a, a) # E: No overload variant of "f" matches argument types [__main__.A, __main__.A]
f(b, b) # E: No overload variant of "f" matches argument types [__main__.B, __main__.B]
@overload
def f(x: 'A') -> 'A': pass
@overload
def f(x: 'B', y: 'A') -> 'B': pass
class A: pass
class B: pass
[case testGenericOverloadVariant]
from typing import overload, TypeVar, Generic
t = TypeVar('t')
ab, ac, b, c = None, None, None, None # type: (A[B], A[C], B, C)
b = f(ab)
c = f(ac)
b = f(ac) # E: Incompatible types in assignment (expression has type "C", variable has type "B")
b = f(b)
c = f(b) # E: Incompatible types in assignment (expression has type "B", variable has type "C")
@overload
def f(x: 'A[t]') -> t: pass
@overload
def f(x: 'B') -> 'B': pass
class A(Generic[t]): pass
class B: pass
class C: pass
[case testOverloadedInit]
from typing import overload
a, b = None, None # type: (A, B)
a = A(a)
a = A(b)
a = A(object()) # E: No overload variant of "A" matches argument types [builtins.object]
class A:
@overload
def __init__(self, a: 'A') -> None: pass
@overload
def __init__(self, b: 'B') -> None: pass
class B: pass
[case testIntersectionTypeCompatibility]
from typing import overload, Callable
o = None # type: object
a = None # type: A
a = f # E: Incompatible types in assignment (expression has type overloaded function, variable has type "A")
o = f
@overload
def f(a: 'A') -> None: pass
@overload
def f(a: Callable[[], None]) -> None: pass
class A: pass
[case testCompatibilityOfIntersectionTypeObjectWithStdType]
from typing import overload
t, a = None, None # type: (type, A)
a = A # E: Incompatible types in assignment (expression has type "A" (type object), variable has type "A")
t = A
class A:
@overload
def __init__(self, a: 'A') -> None: pass
@overload
def __init__(self, a: 'B') -> None: pass
class B: pass
[case testOverloadedGetitem]
from typing import overload
a, b = None, None # type: int, str
a = A()[a]
b = A()[a] # E: Incompatible types in assignment (expression has type "int", variable has type "str")
b = A()[b]
a = A()[b] # E: Incompatible types in assignment (expression has type "str", variable has type "int")
class A:
@overload
def __getitem__(self, a: int) -> int: pass
@overload
def __getitem__(self, b: str) -> str: pass
[case testOverloadedGetitemWithGenerics]
from typing import TypeVar, Generic, overload
t = TypeVar('t')
a, b, c = None, None, None # type: (A, B, C[A])
a = c[a]
b = c[a] # E: Incompatible types in assignment (expression has type "A", variable has type "B")
a = c[b]
b = c[b] # E: Incompatible types in assignment (expression has type "A", variable has type "B")
class C(Generic[t]):
@overload
def __getitem__(self, a: 'A') -> t: pass
@overload
def __getitem__(self, b: 'B') -> t: pass
class A: pass
class B: pass
[case testImplementingOverloadedMethod]
from typing import overload
from abc import abstractmethod, ABCMeta
class I(metaclass=ABCMeta):
@overload
@abstractmethod
def f(self) -> None: pass
@overload
@abstractmethod
def f(self, a: 'A') -> None: pass
class A(I):
@overload
def f(self) -> None: pass
@overload
def f(self, a: 'A') -> None: pass
[case testOverloadWithFunctionType]
from typing import overload, Callable
class A: pass
@overload
def f(x: A) -> None: pass
@overload
def f(x: Callable[[], None]) -> None: pass
f(A())
[builtins fixtures/function.pyi]
[case testVarArgsOverload]
from typing import overload, Any
@overload
def f(x: 'A', *more: Any) -> 'A': pass
@overload
def f(x: 'B', *more: Any) -> 'A': pass
f(A())
f(A(), A, A)
f(B())
f(B(), B)
f(B(), B, B)
f(object()) # E: No overload variant of "f" matches argument types [builtins.object]
class A: pass
class B: pass
[builtins fixtures/list.pyi]
[case testVarArgsOverload2]
from typing import overload
@overload
def f(x: 'A', *more: 'B') -> 'A': pass
@overload
def f(x: 'B', *more: 'A') -> 'A': pass
f(A(), B())
f(A(), B(), B())
f(A(), A(), B()) # E: No overload variant of "f" matches argument types [__main__.A, __main__.A, __main__.B]
f(A(), B(), A()) # E: No overload variant of "f" matches argument types [__main__.A, __main__.B, __main__.A]
class A: pass
class B: pass
[builtins fixtures/list.pyi]
[case testOverloadWithTypeObject]
from typing import overload
@overload
def f(a: 'A', t: type) -> None: pass
@overload
def f(a: 'B', t: type) -> None: pass
f(A(), B)
f(B(), A)
class A: pass
class B: pass
[builtins fixtures/function.pyi]
[case testOverloadedInitAndTypeObjectInOverload]
from typing import overload
@overload
def f(t: type) -> 'A': pass
@overload
def f(t: 'A') -> 'B': pass
a, b = None, None # type: (A, B)
a = f(A)
b = f(a)
b = f(A) # E: Incompatible types in assignment (expression has type "A", variable has type "B")
a = f(a) # E: Incompatible types in assignment (expression has type "B", variable has type "A")
class A:
@overload
def __init__(self) -> None: pass
@overload
def __init__(self, a: 'A') -> None: pass
class B:
pass
[case testOverlappingErasedSignatures]
from typing import overload, List
@overload
def f(a: List[int]) -> int: pass
@overload
def f(a: List[str]) -> int: pass
list_int = [] # type: List[int]
list_str = [] # type: List[str]
list_object = [] # type: List[object]
n = f(list_int)
m = f(list_str)
n = 1
m = 1
n = 'x' # E: Incompatible types in assignment (expression has type "str", variable has type "int")
m = 'x' # E: Incompatible types in assignment (expression has type "str", variable has type "int")
f(list_object) # E: Argument 1 to "f" has incompatible type List[object]; expected List[int]
[builtins fixtures/list.pyi]
[case testOverlappingOverloadSignatures]
from typing import overload
class A: pass
class B(A): pass
@overload
def f(x: B) -> int: pass # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(x: A) -> str: pass
[case testContravariantOverlappingOverloadSignatures]
from typing import overload
class A: pass
class B(A): pass
@overload
def f(x: A) -> A: pass
@overload
def f(x: B) -> B: pass # This is more specific than the first item, and thus
# will never be called.
[case testPartiallyCovariantOverlappingOverloadSignatures]
from typing import overload
class A: pass
class B(A): pass
@overload
def f(x: B) -> A: pass # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(x: A) -> B: pass
[case testPartiallyContravariantOverloadSignatures]
from typing import overload
class A: pass
class B(A): pass
@overload
def g(x: A) -> int: pass # Fine, since A us supertype of B.
@overload
def g(x: B) -> str: pass
[case testCovariantOverlappingOverloadSignatures]
from typing import overload
class A: pass
class B(A): pass
@overload
def g(x: B) -> B: pass
@overload
def g(x: A) -> A: pass
[case testCovariantOverlappingOverloadSignaturesWithSomeSameArgTypes]
from typing import overload
class A: pass
class B(A): pass
@overload
def g(x: int, y: B) -> B: pass
@overload
def g(x: int, y: A) -> A: pass
[case testCovariantOverlappingOverloadSignaturesWithAnyType]
from typing import Any, overload
@overload
def g(x: int) -> int: pass
@overload
def g(x: Any) -> Any: pass
[case testContravariantOverlappingOverloadSignaturesWithAnyType]
from typing import Any, overload
@overload
def g(x: Any) -> Any: pass # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def g(x: int) -> int: pass
[case testOverloadedLtAndGtMethods]
from typing import overload
class A:
def __lt__(self, x: A) -> int: pass
def __gt__(self, x: A) -> int: pass
class B:
@overload
def __lt__(self, x: B) -> int: pass
@overload
def __lt__(self, x: A) -> int: pass
@overload
def __gt__(self, x: B) -> int: pass
@overload
def __gt__(self, x: A) -> int: pass
A() < A()
A() < B()
B() < A()
B() < B()
A() < object() # E: Unsupported operand types for < ("A" and "object")
B() < object() # E: No overload variant of "__lt__" of "B" matches argument types [builtins.object]
[case testOverloadedForwardMethodAndCallingReverseMethod]
from typing import overload
class A:
@overload
def __add__(self, x: 'A') -> int: pass
@overload
def __add__(self, x: int) -> int: pass
class B:
def __radd__(self, x: A) -> int: pass
A() + A()
A() + 1
A() + B()
A() + '' # E: No overload variant of "__add__" of "A" matches argument types [builtins.str]
[case testOverrideOverloadedMethodWithMoreGeneralArgumentTypes]
from typing import overload
class IntSub(int): pass
class StrSub(str): pass
class A:
@overload
def f(self, x: IntSub) -> int: return 0
@overload
def f(self, x: StrSub) -> str: return ''
class B(A):
@overload
def f(self, x: int) -> int: return 0
@overload
def f(self, x: str) -> str: return ''
[out]
[case testOverrideOverloadedMethodWithMoreSpecificArgumentTypes]
from typing import overload
class IntSub(int): pass
class StrSub(str): pass
class A:
@overload
def f(self, x: int) -> int: return 0
@overload
def f(self, x: str) -> str: return ''
class B(A):
@overload
def f(self, x: IntSub) -> int: return 0
@overload
def f(self, x: str) -> str: return ''
class C(A):
@overload
def f(self, x: int) -> int: return 0
@overload
def f(self, x: StrSub) -> str: return ''
class D(A):
@overload
def f(self, x: int) -> int: return 0
@overload
def f(self, x: str) -> str: return ''
[out]
main:12: error: Signature of "f" incompatible with supertype "A"
main:17: error: Signature of "f" incompatible with supertype "A"
[case testOverloadingAndDucktypeCompatibility]
from typing import overload, _promote
class A: pass
@_promote(A)
class B: pass
@overload
def f(n: B) -> B:
return n
@overload
def f(n: A) -> A:
return n
f(B()) + 'x' # E: Unsupported left operand type for + ("B")
f(A()) + 'x' # E: Unsupported left operand type for + ("A")
[case testOverloadingAndIntFloatSubtyping]
from typing import overload
@overload
def f(x: float) -> None: pass
@overload
def f(x: str) -> None: pass
f(1.1)
f('')
f(1)
f(()) # E: No overload variant of "f" matches argument types [Tuple[]]
[builtins fixtures/primitives.pyi]
[out]
[case testOverloadingVariableInputs]
from typing import overload
@overload
def f(x: int, y: int) -> None: pass
@overload
def f(x: int) -> None: pass
f(1)
f(1, 2)
z = (1, 2)
f(*z)
[builtins fixtures/primitives.pyi]
[out]
[case testTypeInferenceSpecialCaseWithOverloading]
from typing import overload
class A:
def __add__(self, x: A) -> A: pass
class B:
def __radd__(self, x: A) -> B: pass
@overload
def f(x: A) -> A: pass
@overload
def f(x: B) -> B: pass
f(A() + B())() # E: "B" not callable
[case testKeywordArgOverload]
from typing import overload
@overload
def f(x: int, y: str) -> int: pass
@overload
def f(x: str, y: int) -> str: pass
f(x=1, y='')() # E: "int" not callable
f(y=1, x='')() # E: "str" not callable
[case testIgnoreOverloadVariantBasedOnKeywordArg]
from typing import overload
@overload
def f(x: int) -> int: pass
@overload
def f(y: int) -> str: pass
f(x=1)() # E: "int" not callable
f(y=1)() # E: "str" not callable
[case testOverloadWithTupleVarArg]
from typing import overload
@overload
def f(x: int, y: str) -> int: pass
@overload
def f(*x: str) -> str: pass
f(*(1,))() # E: No overload variant of "f" matches argument types [Tuple[builtins.int]]
f(*('',))() # E: "str" not callable
f(*(1, ''))() # E: "int" not callable
f(*(1, '', 1))() # E: No overload variant of "f" matches argument types [Tuple[builtins.int, builtins.str, builtins.int]]
[case testPreferExactSignatureMatchInOverload]
from typing import overload, List
@overload
def f(x: int, y: List[int] = None) -> int: pass
@overload
def f(x: int, y: List[str] = None) -> int: pass
f(y=[1], x=0)() # E: "int" not callable
f(y=[''], x=0)() # E: "int" not callable
a = f(y=[['']], x=0) # E: List item 0 has incompatible type List[str]
a() # E: "int" not callable
[builtins fixtures/list.pyi]
[case testOverloadWithDerivedFromAny]
from typing import Any, overload
Base = None # type: Any
class C:
@overload
def __init__(self, a: str) -> None: pass
@overload
def __init__(self, a: int) -> None: pass
class Derived(Base):
def to_dict(self) -> C:
return C(self) # fails without the fix for #1363
C(Derived()) # fails without the hack
C(Base()) # Always ok
[case testOverloadWithBoundedTypeVar]
from typing import overload, TypeVar
T = TypeVar('T', bound=str)
@overload
def f(x: T) -> T: pass
@overload
def f(x: int) -> bool: pass
class mystr(str): pass
f('x')() # E: "str" not callable
f(1)() # E: "bool" not callable
f(1.1) # E: No overload variant of "f" matches argument types [builtins.float]
f(mystr())() # E: "mystr" not callable
[builtins fixtures/primitives.pyi]
[case testOverloadedCallWithVariableTypes]
from typing import overload, TypeVar, List
T = TypeVar('T', bound=str)
@overload
def f(x: T) -> T: pass
@overload
def f(x: List[T]) -> None: pass
class mystr(str): pass
U = TypeVar('U', bound=mystr)
V = TypeVar('V')
def g(x: U, y: V) -> None:
f(x)() # E: "mystr" not callable
f(y) # E: No overload variant of "f" matches argument types [V`-2]
a = f([x]) # E: "f" does not return a value
f([y]) # E: Type argument 1 of "f" has incompatible value "V"
f([x, y]) # E: Type argument 1 of "f" has incompatible value "object"
[builtins fixtures/list.pyi]
[out]
[case testOverlapWithTypeVars]
from typing import overload, TypeVar, Sequence
T = TypeVar('T', bound=str)
@overload
def f(x: Sequence[T]) -> None: pass
@overload
def f(x: Sequence[int]) -> int: pass
# These are considered overlapping despite the bound on T due to runtime type erasure.
[out]
main:4: error: Overloaded function signatures 1 and 2 overlap with incompatible return types
[case testOverlapWithTypeVarsWithValues]
from typing import overload, TypeVar
AnyStr = TypeVar('AnyStr', bytes, str)
@overload
def f(x: int) -> int: pass
@overload
def f(x: AnyStr) -> str: pass
f(1)() # E: "int" not callable
f('1')() # E: "str" not callable
f(b'1')() # E: "str" not callable
f(1.0) # E: No overload variant of "f" matches argument types [builtins.float]
@overload
def g(x: AnyStr, *a: AnyStr) -> None: pass
@overload
def g(x: int, *a: AnyStr) -> None: pass
g('foo')
g('foo', 'bar')
g('foo', b'bar') # E: Type argument 1 of "g" has incompatible value "object"
g(1)
g(1, 'foo')
g(1, 'foo', b'bar') # E: Type argument 1 of "g" has incompatible value "object"
[builtins fixtures/primitives.pyi]
[case testBadOverlapWithTypeVarsWithValues]
from typing import overload, TypeVar
AnyStr = TypeVar('AnyStr', bytes, str)
@overload
def f(x: AnyStr) -> None: pass # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(x: str) -> bool: pass
[builtins fixtures/primitives.pyi]
[case testOverlappingOverloadCounting]
from typing import overload
class A: pass
class B(A): pass
@overload
def f(x: int) -> None: pass
@overload
def f(x: B) -> str: pass # E: Overloaded function signatures 2 and 3 overlap with incompatible return types
@overload
def f(x: A) -> int: pass
[case testOverloadWithTupleMatchingTypeVar]
from typing import TypeVar, Generic, Tuple, overload
T = TypeVar('T')
class A(Generic[T]):
@overload
def f(self, arg: T) -> None:
pass
@overload
def f(self, arg: T, default: int) -> None:
pass
b = A() # type: A[Tuple[int, int]]
b.f((0, 0))
b.f((0, '')) # E: Argument 1 to "f" of "A" has incompatible type "Tuple[int, str]"; expected "Tuple[int, int]"
[case testSingleOverload]
from typing import overload
@overload
def f(a: int) -> None: pass
def f(a: str) -> None: pass
[out]
main:2: error: Single overload definition, multiple required
main:4: error: Name 'f' already defined
[case testSingleOverload2]
from typing import overload
def f(a: int) -> None: pass
@overload
def f(a: str) -> None: pass
[out]
main:3: error: Name 'f' already defined
main:3: error: Single overload definition, multiple required
[case testNonconsecutiveOverloads]
from typing import overload
@overload
def f(a: int) -> None: pass
1
@overload
def f(a: str) -> None: pass
[out]
main:2: error: Single overload definition, multiple required
main:5: error: Name 'f' already defined
main:5: error: Single overload definition, multiple required
[case testNonconsecutiveOverloadsMissingFirstOverload]
from typing import overload
def f(a: int) -> None: pass
1
@overload
def f(a: str) -> None: pass
[out]
main:4: error: Name 'f' already defined
main:4: error: Single overload definition, multiple required
[case testNonconsecutiveOverloadsMissingLaterOverload]
from typing import overload
@overload
def f(a: int) -> None: pass
1
def f(a: str) -> None: pass
[out]
main:2: error: Single overload definition, multiple required
main:5: error: Name 'f' already defined
[case testOverloadTuple]
from typing import overload, Tuple
@overload
def f(x: int, y: Tuple[str, ...]) -> None: pass
@overload
def f(x: int, y: str) -> None: pass
f(1, ('2', '3'))
f(1, (2, '3')) # E: Argument 2 to "f" has incompatible type "Tuple[int, str]"; expected Tuple[str, ...]
f(1, ('2',))
f(1, '2')
f(1, (2, 3)) # E: Argument 2 to "f" has incompatible type "Tuple[int, int]"; expected Tuple[str, ...]
x = ('2', '3') # type: Tuple[str, ...]
f(1, x)
y = (2, 3) # type: Tuple[int, ...]
f(1, y) # E: Argument 2 to "f" has incompatible type Tuple[int, ...]; expected Tuple[str, ...]
[builtins fixtures/tuple.pyi]
[case testCallableSpecificOverload]
from typing import overload, Callable
@overload
def f(a: Callable[[], int]) -> None: pass
@overload
def f(a: str) -> None: pass
f(0) # E: No overload variant of "f" matches argument types [builtins.int]