blob: f49a15ada85cc33c75e5d65324ea73b698187e17 [file] [log] [blame] [edit]
-- Test cases for function overloading
[case testOverloadNotImportedNoCrash]
@overload
def f(a): pass
@overload
def f(a): pass
def f(a): pass
f(0)
@overload # E: Name "overload" is not defined
def g(a:int): pass
def g(a): pass # E: Name "g" already defined on line 9
g(0)
@something # E: Name "something" is not defined
def r(a:int): pass
def r(a): pass # E: Name "r" already defined on line 14
r(0)
[out]
main:2: error: Name "overload" is not defined
main:4: error: Name "f" already defined on line 2
main:4: error: Name "overload" is not defined
main:6: error: Name "f" already defined on line 2
[case testTypeCheckOverloadWithImplementation]
from typing import overload, Any
class A: pass
class B: pass
@overload
def f(x: 'A') -> 'B': ...
@overload
def f(x: 'B') -> 'A': ...
def f(x: Any) -> Any:
pass
reveal_type(f(A())) # N: Revealed type is "__main__.B"
reveal_type(f(B())) # N: Revealed type is "__main__.A"
[builtins fixtures/isinstance.pyi]
[case testTypingExtensionsOverload]
from typing import Any
from typing_extensions import overload
class A: pass
class B: pass
@overload
def f(x: 'A') -> 'B': ...
@overload
def f(x: 'B') -> 'A': ...
def f(x: Any) -> Any:
pass
reveal_type(f(A())) # N: Revealed type is "__main__.B"
reveal_type(f(B())) # N: Revealed type is "__main__.A"
[builtins fixtures/isinstance.pyi]
[case testOverloadNeedsImplementation]
from typing import overload, Any
class A: pass
class B: pass
@overload # E: An overloaded function outside a stub file must have an implementation
def f(x: 'A') -> 'B': ...
@overload
def f(x: 'B') -> 'A': ...
reveal_type(f(A())) # N: Revealed type is "__main__.B"
reveal_type(f(B())) # N: Revealed type is "__main__.A"
[builtins fixtures/isinstance.pyi]
[case testSingleOverloadNoImplementation]
from typing import overload, Any
@overload # E: Single overload definition, multiple required
def f(x: 'A') -> 'B': ...
class A: pass
class B: pass
[builtins fixtures/isinstance.pyi]
[case testOverloadByAnyOtherName]
from typing import overload as rose
from typing import Any
class A: pass
class B: pass
@rose
def f(x: 'A') -> 'B': ...
@rose
def f(x: 'B') -> 'A': ...
def f(x: Any) -> Any:
pass
reveal_type(f(A())) # N: Revealed type is "__main__.B"
reveal_type(f(B())) # N: Revealed type is "__main__.A"
[builtins fixtures/isinstance.pyi]
[case testTypeCheckOverloadWithDecoratedImplementation]
from typing import overload, Any
class A: pass
class B: pass
def deco(fun): ...
@overload
def f(x: 'A') -> 'B': ...
@overload
def f(x: 'B') -> 'A': ...
@deco
def f(x: Any) -> Any:
pass
reveal_type(f(A())) # N: Revealed type is "__main__.B"
reveal_type(f(B())) # N: Revealed type is "__main__.A"
[builtins fixtures/isinstance.pyi]
[case testOverloadDecoratedImplementationNotLast]
from typing import overload, Any
def deco(fun): ...
@overload
def f(x: 'A') -> 'B': ...
@deco # E: The implementation for an overloaded function must come last
def f(x: Any) -> Any:
pass
@overload
def f(x: 'B') -> 'A': ...
class A: pass
class B: pass
[builtins fixtures/isinstance.pyi]
[case testOverloadImplementationNotLast]
from typing import overload, Any
@overload
def f(x: 'A') -> 'B': ...
def f(x: Any) -> Any: # E: The implementation for an overloaded function must come last
pass
@overload
def f(x: 'B') -> 'A': ...
class A: pass
class B: pass
[builtins fixtures/isinstance.pyi]
[case testDecoratedRedefinitionIsNotOverload]
from typing import overload, Any
def deco(fun): ...
@deco
def f(x: 'A') -> 'B': ...
@deco # E: Name "f" already defined on line 5
def f(x: 'B') -> 'A': ...
@deco # E: Name "f" already defined on line 5
def f(x: Any) -> Any: ...
class A: pass
class B: pass
[builtins fixtures/isinstance.pyi]
[case testTypeCheckOverloadWithImplementationError]
from typing import overload, Any
class A: pass
class B: pass
@overload
def f(x: 'A') -> 'B': ...
@overload
def f(x: 'B') -> 'A': ...
def f(x: Any) -> Any:
foo = 1
if int():
foo = "bar" # E: Incompatible types in assignment (expression has type "str", variable has type "int")
@overload
def g(x: 'A') -> 'B': ...
@overload
def g(x: 'B') -> 'A': ...
def g(x):
foo = 1
if int():
foo = "bar"
reveal_type(f(A())) # N: Revealed type is "__main__.B"
reveal_type(f(B())) # N: Revealed type is "__main__.A"
[builtins fixtures/isinstance.pyi]
[case testTypeCheckOverloadWithUntypedImplAndMultipleVariants]
from typing import overload
@overload
def f(x: int) -> str: ...
@overload
def f(x: str) -> int: ... # E: Overloaded function signatures 2 and 3 overlap with incompatible return types
@overload
def f(x: object) -> str: ...
def f(x): ...
[case testTypeCheckOverloadWithImplTooSpecificArg]
from typing import overload, Any
class A: pass
class B: pass
a = A()
@overload
def f(x: 'A') -> 'B': ...
@overload
def f(x: 'B') -> 'A': ...
def f(x: 'A') -> Any: # E: Overloaded function implementation does not accept all possible arguments of signature 2
pass
reveal_type(f(A())) # N: Revealed type is "__main__.B"
reveal_type(f(B())) # N: Revealed type is "__main__.A"
[builtins fixtures/isinstance.pyi]
[case testTypeCheckOverloadWithImplTooSpecificRetType]
from typing import overload, Any
class A: pass
class B: pass
a = A()
@overload
def f(x: 'A') -> 'B': ...
@overload
def f(x: 'B') -> 'A': ...
def f(x: Any) -> 'B': # E: Overloaded function implementation cannot produce return type of signature 2
return B()
reveal_type(f(A())) # N: Revealed type is "__main__.B"
reveal_type(f(B())) # N: Revealed type is "__main__.A"
[builtins fixtures/isinstance.pyi]
[case testTypeCheckOverloadWithImplTypeVar]
from typing import overload, Any, TypeVar
T = TypeVar('T')
class A: pass
class B: pass
a = A()
@overload
def f(x: 'A') -> 'A': ...
@overload
def f(x: 'B') -> 'B': ...
def f(x: T) -> T:
...
reveal_type(f(A())) # N: Revealed type is "__main__.A"
reveal_type(f(B())) # N: Revealed type is "__main__.B"
[builtins fixtures/isinstance.pyi]
[case testTypeCheckOverloadWithImplTypeVarProblems]
from typing import overload, Any, TypeVar, Union
T = TypeVar('T', bound='A')
class A: pass
class B: pass
a = A()
@overload
def f(x: 'A') -> 'A': ...
@overload
def f(x: 'B') -> 'B': ...
def f(x: Union[T, B]) -> T: # E: Overloaded function implementation cannot satisfy signature 2 due to inconsistencies in how they use type variables
...
reveal_type(f(A())) # N: Revealed type is "__main__.A"
reveal_type(f(B())) # N: Revealed type is "__main__.B"
[builtins fixtures/isinstance.pyi]
[case testTypeCheckOverloadImplementationTypeVarWithValueRestriction]
from typing import overload, TypeVar, Union
class A: pass
class B: pass
class C: pass
T = TypeVar('T', A, B)
@overload
def foo(x: T) -> T: ...
@overload
def foo(x: C) -> int: ...
def foo(x: Union[A, B, C]) -> Union[A, B, int]:
if isinstance(x, C):
return 3
else:
return x
@overload
def bar(x: T) -> T: ...
@overload
def bar(x: C) -> int: ...
def bar(x: Union[T, C]) -> Union[T, int]:
if isinstance(x, C):
return 3
else:
return x
[builtins fixtures/isinstancelist.pyi]
[case testTypeCheckOverloadImplementationTypeVarDifferingUsage1]
from typing import overload, Union, List, TypeVar, Generic
T = TypeVar('T')
@overload
def foo(t: List[T]) -> T: ...
@overload
def foo(t: T) -> T: ...
def foo(t: Union[List[T], T]) -> T:
if isinstance(t, list):
return t[0]
else:
return t
class Wrapper(Generic[T]):
@overload
def foo(self, t: List[T]) -> T: ...
@overload
def foo(self, t: T) -> T: ...
def foo(self, t: Union[List[T], T]) -> T:
if isinstance(t, list):
return t[0]
else:
return t
[builtins fixtures/isinstancelist.pyi]
[case testTypeCheckOverloadImplementationTypeVarDifferingUsage2]
from typing import overload, Union, List, TypeVar, Generic
T = TypeVar('T')
# Note: this is unsafe when T = object
@overload
def foo(t: List[T], s: T) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo(t: T, s: T) -> str: ...
def foo(t, s): pass
class Wrapper(Generic[T]):
@overload
def foo(self, t: List[T], s: T) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo(self, t: T, s: T) -> str: ...
def foo(self, t, s): pass
class Dummy(Generic[T]): pass
# Same root issue: why does the additional constraint bound T <: T
# cause the constraint solver to not infer T = object like it did in the
# first example?
@overload
def bar(d: Dummy[T], t: List[T], s: T) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def bar(d: Dummy[T], t: T, s: T) -> str: ...
def bar(d: Dummy[T], t, s): pass
[builtins fixtures/isinstancelist.pyi]
[case testTypeCheckOverloadedFunctionBody]
from foo import *
[file foo.pyi]
from typing import overload
@overload
def f(x: 'A'):
if int():
x = B() # E: Incompatible types in assignment (expression has type "B", variable has type "A")
x = A()
@overload
def f(x: 'B'):
if int():
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 foo import *
[file foo.pyi]
from typing import overload
class A:
@overload
def f(self, x: 'A'):
if int():
x = B() # E: Incompatible types in assignment (expression has type "B", variable has type "A")
x = A()
@overload
def f(self, x: 'B'):
if int():
x = A() # E: Incompatible types in assignment (expression has type "A", variable has type "B")
x = B()
class B: pass
[out]
[case testCallToOverloadedFunction]
from foo import *
[file foo.pyi]
from typing import overload
f(C()) # E: No overload variant of "f" matches argument type "C" \
# N: Possible overload variants: \
# N: def f(x: A) -> None \
# N: def f(x: B) -> None
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 foo import *
[file foo.pyi]
from typing import overload
a: A
b: B
if int():
b = f(a) # E: Incompatible types in assignment (expression has type "A", variable has type "B")
if int():
a = f(b) # E: Incompatible types in assignment (expression has type "B", variable has type "A")
if int():
a = f(a)
if int():
b = f(b)
@overload
def f(x: 'A') -> 'A': pass
@overload
def f(x: 'B') -> 'B': pass
class A: pass
class B: pass
[builtins fixtures/tuple.pyi]
[case testCallToOverloadedMethod]
from foo import *
[file foo.pyi]
from typing import overload
A().f(C()) # E: No overload variant of "f" of "A" matches argument type "C" \
# N: Possible overload variants: \
# N: def f(self, x: A) -> None \
# N: def f(self, x: B) -> None
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 foo import *
[file foo.pyi]
from typing import overload
a: A
b: B
if int():
b = a.f(a) # E: Incompatible types in assignment (expression has type "A", variable has type "B")
if int():
a = a.f(b) # E: Incompatible types in assignment (expression has type "B", variable has type "A")
if int():
a = a.f(a)
if int():
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
[builtins fixtures/tuple.pyi]
[case testOverloadsWithDifferentArgumentCounts]
from foo import *
[file foo.pyi]
from typing import overload
a: A
b: B
if int():
a = f(a)
if int():
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 type "B" \
# N: Possible overload variants: \
# N: def f(x: A) -> A \
# N: def f(x: B, y: A) -> B
if int():
b = f(b, a)
if int():
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 "A", "A" \
# N: Possible overload variants: \
# N: def f(x: A) -> A \
# N: def f(x: B, y: A) -> B
f(b, b) # E: No overload variant of "f" matches argument types "B", "B" \
# N: Possible overload variants: \
# N: def f(x: A) -> A \
# N: def f(x: B, y: A) -> B
@overload
def f(x: 'A') -> 'A': pass
@overload
def f(x: 'B', y: 'A') -> 'B': pass
class A: pass
class B: pass
[builtins fixtures/tuple.pyi]
[case testGenericOverloadVariant]
from foo import *
[file foo.pyi]
from typing import overload, TypeVar, Generic
t = TypeVar('t')
ab: A[B]
ac: A[C]
b: B
c: C
if int():
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
[builtins fixtures/tuple.pyi]
[case testOverloadedInit]
from foo import *
[file foo.pyi]
from typing import overload
a: A
b: B
a = A(a)
a = A(b)
a = A(object()) # E: No overload variant of "A" matches argument type "object" \
# N: Possible overload variants: \
# N: def __init__(self, a: A) -> A \
# N: def __init__(self, b: B) -> A
class A:
@overload
def __init__(self, a: 'A') -> None: pass
@overload
def __init__(self, b: 'B') -> None: pass
class B: pass
[builtins fixtures/tuple.pyi]
[case testIntersectionTypeCompatibility]
from foo import *
[file foo.pyi]
from typing import overload, Callable
o: object
a: A
if int():
a = f # E: Incompatible types in assignment (expression has type overloaded function, variable has type "A")
if int():
o = f
@overload
def f(a: 'A') -> None: pass
@overload
def f(a: Callable[[], None]) -> None: pass
class A: pass
[case testCompatibilityOfIntersectionTypeObjectWithStdType]
from foo import *
[file foo.pyi]
from typing import overload
t: type
a: A
if int():
a = A # E: Incompatible types in assignment (expression has type "Type[A]", 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
[builtins fixtures/tuple.pyi]
[case testOverloadedGetitem]
from foo import *
[file foo.pyi]
from typing import overload
a: int
b: str
if int():
a = A()[a]
if int():
b = A()[a] # E: Incompatible types in assignment (expression has type "int", variable has type "str")
if int():
b = A()[b]
if int():
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
[builtins fixtures/tuple.pyi]
[case testOverloadedGetitemWithGenerics]
from foo import *
[file foo.pyi]
from typing import TypeVar, Generic, overload
t = TypeVar('t')
a: A
b: B
c: C[A]
if int():
a = c[a]
b = c[a] # E: Incompatible types in assignment (expression has type "A", variable has type "B")
if int():
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
[builtins fixtures/tuple.pyi]
[case testImplementingOverloadedMethod]
from foo import *
[file foo.pyi]
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 foo import *
[file foo.pyi]
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 foo import *
[file foo.pyi]
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 type "object" \
# N: Possible overload variants: \
# N: def f(x: A, *more: Any) -> A \
# N: def f(x: B, *more: Any) -> A
class A: pass
class B: pass
[builtins fixtures/list.pyi]
[case testVarArgsOverload2]
from foo import *
[file foo.pyi]
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 "A", "A", "B" \
# N: Possible overload variants: \
# N: def f(x: A, *more: B) -> A \
# N: def f(x: B, *more: A) -> A
f(A(), B(), A()) # E: No overload variant of "f" matches argument types "A", "B", "A" \
# N: Possible overload variants: \
# N: def f(x: A, *more: B) -> A \
# N: def f(x: B, *more: A) -> A
class A: pass
class B: pass
[builtins fixtures/list.pyi]
[case testOverloadWithTypeObject]
from foo import *
[file foo.pyi]
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 foo import *
[file foo.pyi]
from typing import overload
@overload
def f(t: type) -> 'A': pass
@overload
def f(t: 'A') -> 'B': pass
a: A
b: B
if int():
a = f(A)
if int():
b = f(a)
if int():
b = f(A) # E: Incompatible types in assignment (expression has type "A", variable has type "B")
if int():
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
[builtins fixtures/tuple.pyi]
[case testOverlappingErasedSignatures]
from foo import *
[file foo.pyi]
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)
def p(): n, m # Prevent redefinition
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 foo import *
[file foo.pyi]
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 foo import *
[file foo.pyi]
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 # E: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader
[case testPartiallyCovariantOverlappingOverloadSignatures]
from foo import *
[file foo.pyi]
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 foo import *
[file foo.pyi]
from typing import overload
class A: pass
class B(A): pass
@overload
def g(x: A) -> int: pass
@overload
def g(x: B) -> str: pass # E: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader
[case testCovariantOverlappingOverloadSignatures]
from foo import *
[file foo.pyi]
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 foo import *
[file foo.pyi]
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 foo import *
[file foo.pyi]
from typing import Any, overload
@overload
def g(x: int) -> int: pass
@overload
def g(x: Any) -> Any: pass
[case testContravariantOverlappingOverloadSignaturesWithAnyType]
from foo import *
[file foo.pyi]
from typing import Any, overload
@overload
def g(x: Any) -> Any: pass
@overload
def g(x: int) -> int: pass # E: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader
[case testOverloadedLtAndGtMethods]
from foo import *
[file foo.pyi]
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 type "object" \
# N: Possible overload variants: \
# N: def __lt__(self, B, /) -> int \
# N: def __lt__(self, A, /) -> int
[case testOverloadedForwardMethodAndCallingReverseMethod]
from foo import *
[file foo.pyi]
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 type "str" \
# N: Possible overload variants: \
# N: def __add__(self, A, /) -> int \
# N: def __add__(self, int, /) -> int
[case testOverrideOverloadSwapped]
from foo import *
[file foo.pyi]
from typing import overload
class Parent:
@overload
def f(self, x: int) -> int: ...
@overload
def f(self, x: str) -> str: ...
class Child(Parent):
@overload # E: Signature of "f" incompatible with supertype "Parent" \
# N: Overload variants must be defined in the same order as they are in "Parent"
def f(self, x: str) -> str: ...
@overload
def f(self, x: int) -> int: ...
[case testOverrideOverloadSwappedWithExtraVariants]
from foo import *
[file foo.pyi]
from typing import overload
class bool: pass
class Parent:
@overload
def f(self, x: int) -> int: ...
@overload
def f(self, x: str) -> str: ...
class Child1(Parent):
@overload # E: Signature of "f" incompatible with supertype "Parent" \
# N: Overload variants must be defined in the same order as they are in "Parent"
def f(self, x: bool) -> bool: ...
@overload
def f(self, x: str) -> str: ...
@overload
def f(self, x: int) -> int: ...
class Child2(Parent):
@overload # E: Signature of "f" incompatible with supertype "Parent" \
# N: Overload variants must be defined in the same order as they are in "Parent"
def f(self, x: str) -> str: ...
@overload
def f(self, x: bool) -> bool: ...
@overload
def f(self, x: int) -> int: ...
class Child3(Parent):
@overload # E: Signature of "f" incompatible with supertype "Parent" \
# N: Overload variants must be defined in the same order as they are in "Parent"
def f(self, x: str) -> str: ...
@overload
def f(self, x: int) -> int: ...
@overload
def f(self, x: bool) -> bool: ...
[case testOverrideOverloadSwappedWithAdjustedVariants]
from foo import *
[file foo.pyi]
from typing import overload
class A: pass
class B(A): pass
class C(B): pass
class Parent:
@overload
def f(self, x: int) -> int: ...
@overload
def f(self, x: B) -> B: ...
class Child1(Parent):
@overload # Fail
def f(self, x: A) -> B: ...
@overload
def f(self, x: int) -> int: ...
class Child2(Parent):
@overload # Fail
def f(self, x: B) -> C: ...
@overload
def f(self, x: int) -> int: ...
class Child3(Parent):
@overload # Fail
def f(self, x: B) -> A: ...
@overload
def f(self, x: int) -> int: ...
[out]
tmp/foo.pyi:13: error: Signature of "f" incompatible with supertype "Parent"
tmp/foo.pyi:13: note: Overload variants must be defined in the same order as they are in "Parent"
tmp/foo.pyi:18: error: Signature of "f" incompatible with supertype "Parent"
tmp/foo.pyi:18: note: Overload variants must be defined in the same order as they are in "Parent"
tmp/foo.pyi:23: error: Signature of "f" incompatible with supertype "Parent"
tmp/foo.pyi:23: note: Superclass:
tmp/foo.pyi:23: note: @overload
tmp/foo.pyi:23: note: def f(self, x: int) -> int
tmp/foo.pyi:23: note: @overload
tmp/foo.pyi:23: note: def f(self, x: B) -> B
tmp/foo.pyi:23: note: Subclass:
tmp/foo.pyi:23: note: @overload
tmp/foo.pyi:23: note: def f(self, x: B) -> A
tmp/foo.pyi:23: note: @overload
tmp/foo.pyi:23: note: def f(self, x: int) -> int
[case testOverrideOverloadedMethodWithMoreGeneralArgumentTypes]
from foo import *
[file foo.pyi]
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 foo import *
[file foo.pyi]
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 # Fail
def f(self, x: IntSub) -> int: return 0
@overload
def f(self, x: str) -> str: return ''
class C(A):
@overload # Fail
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]
tmp/foo.pyi:12: error: Signature of "f" incompatible with supertype "A"
tmp/foo.pyi:12: note: Superclass:
tmp/foo.pyi:12: note: @overload
tmp/foo.pyi:12: note: def f(self, x: int) -> int
tmp/foo.pyi:12: note: @overload
tmp/foo.pyi:12: note: def f(self, x: str) -> str
tmp/foo.pyi:12: note: Subclass:
tmp/foo.pyi:12: note: @overload
tmp/foo.pyi:12: note: def f(self, x: IntSub) -> int
tmp/foo.pyi:12: note: @overload
tmp/foo.pyi:12: note: def f(self, x: str) -> str
tmp/foo.pyi:17: error: Signature of "f" incompatible with supertype "A"
tmp/foo.pyi:17: note: Superclass:
tmp/foo.pyi:17: note: @overload
tmp/foo.pyi:17: note: def f(self, x: int) -> int
tmp/foo.pyi:17: note: @overload
tmp/foo.pyi:17: note: def f(self, x: str) -> str
tmp/foo.pyi:17: note: Subclass:
tmp/foo.pyi:17: note: @overload
tmp/foo.pyi:17: note: def f(self, x: int) -> int
tmp/foo.pyi:17: note: @overload
tmp/foo.pyi:17: note: def f(self, x: StrSub) -> str
[case testOverloadingAndDucktypeCompatibility]
from foo import *
[file foo.pyi]
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")
[typing fixtures/typing-medium.pyi]
[case testOverloadingAndIntFloatSubtyping]
from foo import *
[file foo.pyi]
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 type "Tuple[]" \
# N: Possible overload variants: \
# N: def f(x: float) -> None \
# N: def f(x: str) -> None
[builtins fixtures/primitives.pyi]
[out]
[case testOverloadingVariableInputs]
from foo import *
[file foo.pyi]
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 foo import *
[file foo.pyi]
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 foo import *
[file foo.pyi]
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 foo import *
[file foo.pyi]
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 foo import *
[file foo.pyi]
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 type "Tuple[int]" \
# N: Possible overload variants: \
# N: def f(x: int, y: str) -> int \
# N: def f(*x: str) -> str
f(*('',))() # E: "str" not callable
f(*(1, ''))() # E: "int" not callable
f(*(1, '', 1))() # E: No overload variant of "f" matches argument type "Tuple[int, str, int]" \
# N: Possible overload variants: \
# N: def f(x: int, y: str) -> int \
# N: def f(*x: str) -> str
[builtins fixtures/tuple.pyi]
[case testPreferExactSignatureMatchInOverload]
# flags: --no-strict-optional
from foo import *
[file foo.pyi]
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]"; expected "int"
reveal_type(a) # N: Revealed type is "builtins.int"
[builtins fixtures/list.pyi]
[case testOverloadWithDerivedFromAny]
from foo import *
[file foo.pyi]
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 foo import *
[file foo.pyi]
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 type "float" \
# N: Possible overload variants: \
# N: def [T <: str] f(x: T) -> T \
# N: def f(x: int) -> bool
f(mystr())() # E: "mystr" not callable
[builtins fixtures/primitives.pyi]
[case testOverloadedCallWithVariableTypes]
from foo import *
[file foo.pyi]
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 type "V" \
# N: Possible overload variants: \
# N: def [T <: str] f(x: T) -> T \
# N: def [T <: str] f(x: List[T]) -> None
a = f([x])
reveal_type(a) # N: Revealed type is "None"
f([y]) # E: Value of type variable "T" of "f" cannot be "V"
f([x, y]) # E: Value of type variable "T" of "f" cannot be "object"
[builtins fixtures/list.pyi]
[out]
[case testOverloadOverlapWithTypeVars]
from foo import *
[file foo.pyi]
from typing import overload, TypeVar, Sequence, List
T = TypeVar('T', bound=str)
@overload
def f(x: Sequence[T]) -> None: pass
@overload
def f(x: Sequence[int]) -> int: pass
@overload
def g(x: Sequence[T]) -> None: pass
@overload
def g(x: Sequence[str]) -> int: pass # E: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader
@overload
def h(x: Sequence[str]) -> int: pass
@overload
def h(x: Sequence[T]) -> None: pass # E: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader
@overload
def i(x: List[str]) -> int: pass # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def i(x: List[T]) -> None: pass
[builtins fixtures/list.pyi]
[case testOverloadOverlapWithTypeVarsWithValues]
from foo import *
[file foo.pyi]
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 type "float" \
# N: Possible overload variants: \
# N: def f(x: int) -> int \
# N: def [AnyStr in (bytes, str)] f(x: AnyStr) -> str
@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: Value of type variable "AnyStr" of "g" cannot be "Sequence[object]"
g(1)
g(1, 'foo')
g(1, 'foo', b'bar') # E: Value of type variable "AnyStr" of "g" cannot be "Sequence[object]"
[builtins fixtures/primitives.pyi]
[case testOverloadOverlapWithTypeVarsWithValuesOrdering]
from foo import *
[file foo.pyi]
from typing import overload, TypeVar
AnyStr = TypeVar('AnyStr', bytes, str)
@overload
def f(x: AnyStr) -> AnyStr: pass
@overload
def f(x: str) -> str: pass # E: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader
@overload
def g(x: str) -> str: pass
@overload
def g(x: AnyStr) -> AnyStr: pass
[builtins fixtures/primitives.pyi]
[case testOverloadsUsingAny]
from typing import overload, List, Any, Union
@overload
def foo(x: List[int]) -> int: ...
@overload
def foo(x: List[str]) -> str: ...
def foo(x): pass
a: List[int]
b: List[str]
c: List[Any]
d: Union[List[int], List[str]]
e: List[bool]
f: List[object]
g: List[Union[int, str]]
reveal_type(foo(a))
reveal_type(foo(b))
reveal_type(foo(c))
reveal_type(foo(d))
foo(e)
foo(f)
foo(g)
[builtins fixtures/list.pyi]
[out]
main:17: note: Revealed type is "builtins.int"
main:18: note: Revealed type is "builtins.str"
main:19: note: Revealed type is "Any"
main:20: note: Revealed type is "Union[builtins.int, builtins.str]"
main:21: error: Argument 1 to "foo" has incompatible type "List[bool]"; expected "List[int]"
main:21: note: "List" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance
main:21: note: Consider using "Sequence" instead, which is covariant
main:22: error: Argument 1 to "foo" has incompatible type "List[object]"; expected "List[int]"
main:23: error: Argument 1 to "foo" has incompatible type "List[Union[int, str]]"; expected "List[int]"
[case testOverloadAgainstEmptyCollections]
from typing import overload, List
@overload
def f(x: List[int]) -> int: ...
@overload
def f(x: List[str]) -> str: ...
def f(x): pass
reveal_type(f([])) # N: Revealed type is "builtins.int"
[builtins fixtures/list.pyi]
[case testOverloadAgainstEmptyCovariantCollections]
from typing import overload, TypeVar, Generic
T = TypeVar('T', covariant=True)
class Wrapper(Generic[T]): pass
class A: pass
class B(A): pass
class C: pass
@overload
def f(x: Wrapper[A]) -> int: ...
@overload
def f(x: Wrapper[C]) -> str: ...
def f(x): pass
reveal_type(f(Wrapper())) # N: Revealed type is "builtins.int"
reveal_type(f(Wrapper[C]())) # N: Revealed type is "builtins.str"
reveal_type(f(Wrapper[B]())) # N: Revealed type is "builtins.int"
[case testOverlappingOverloadCounting]
from foo import *
[file foo.pyi]
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 foo import *
[file foo.pyi]
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]"
[builtins fixtures/tuple.pyi]
[case testSingleOverloadStub]
from foo import *
[file foo.pyi]
from typing import overload
@overload
def f(a: int) -> None: pass
def f(a: int) -> None: pass
[out]
tmp/foo.pyi:2: error: Single overload definition, multiple required
tmp/foo.pyi:4: error: An implementation for an overloaded function is not allowed in a stub file
[case testSingleOverload2]
from foo import *
[file foo.pyi]
from typing import overload
def f(a: int) -> None: pass
@overload
def f(a: str) -> None: pass
[out]
tmp/foo.pyi:3: error: Name "f" already defined on line 2
tmp/foo.pyi:3: error: Single overload definition, multiple required
[case testNonconsecutiveOverloads]
from foo import *
[file foo.pyi]
from typing import overload
@overload
def f(a: int) -> None: pass
1
@overload
def f(a: str) -> None: pass
[out]
tmp/foo.pyi:2: error: Single overload definition, multiple required
tmp/foo.pyi:5: error: Name "f" already defined on line 2
tmp/foo.pyi:5: error: Single overload definition, multiple required
[case testNonconsecutiveOverloadsMissingFirstOverload]
from foo import *
[file foo.pyi]
from typing import overload
def f(a: int) -> None: pass
1
@overload
def f(a: str) -> None: pass
[out]
tmp/foo.pyi:4: error: Name "f" already defined on line 2
tmp/foo.pyi:4: error: Single overload definition, multiple required
[case testNonconsecutiveOverloadsMissingLaterOverload]
from foo import *
[file foo.pyi]
from typing import overload
@overload
def f(a: int) -> None: pass
1
def f(a: str) -> None: pass
[out]
tmp/foo.pyi:2: error: Single overload definition, multiple required
tmp/foo.pyi:5: error: Name "f" already defined on line 2
[case testOverloadTuple]
from foo import *
[file foo.pyi]
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 foo import *
[file foo.pyi]
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 type "int" \
# N: Possible overload variants: \
# N: def f(a: Callable[[], int]) -> None \
# N: def f(a: str) -> None
[case testCustomRedefinitionDecorator]
from typing import Any, Callable, Type
class Chain(object):
def chain(self, function: Callable[[Any], int]) -> 'Chain':
return self
class Test(object):
do_chain = Chain()
@do_chain.chain # E: Name "do_chain" already defined on line 9
def do_chain(self) -> int:
return 2
@do_chain.chain # E: Name "do_chain" already defined on line 11
def do_chain(self) -> int:
return 3
t = Test()
reveal_type(t.do_chain) # N: Revealed type is "__main__.Chain"
[case testOverloadWithOverlappingItemsAndAnyArgument1]
from typing import overload, Any
@overload
def f(x: int) -> int: ...
@overload
def f(x: object) -> object: ...
def f(x): pass
a: Any
reveal_type(f(a)) # N: Revealed type is "Any"
[case testOverloadWithOverlappingItemsAndAnyArgument2]
from typing import overload, Any
@overload
def f(x: int) -> int: ...
@overload
def f(x: float) -> float: ...
def f(x): pass
a: Any
reveal_type(f(a)) # N: Revealed type is "Any"
[case testOverloadWithOverlappingItemsAndAnyArgument3]
from typing import overload, Any
@overload
def f(x: int) -> int: ...
@overload
def f(x: str) -> str: ...
def f(x): pass
a: Any
reveal_type(f(a)) # N: Revealed type is "Any"
[case testOverloadWithOverlappingItemsAndAnyArgument4]
from typing import overload, Any
@overload
def f(x: int, y: int, z: str) -> int: ...
@overload
def f(x: object, y: int, z: str) -> object: ...
def f(x): pass
a: Any
# Any causes ambiguity
reveal_type(f(a, 1, '')) # N: Revealed type is "Any"
# Any causes no ambiguity
reveal_type(f(1, a, a)) # N: Revealed type is "builtins.int"
reveal_type(f('', a, a)) # N: Revealed type is "builtins.object"
# Like above, but use keyword arguments.
reveal_type(f(y=1, z='', x=a)) # N: Revealed type is "Any"
reveal_type(f(y=a, z='', x=1)) # N: Revealed type is "builtins.int"
reveal_type(f(z='', x=1, y=a)) # N: Revealed type is "builtins.int"
reveal_type(f(z='', x=a, y=1)) # N: Revealed type is "Any"
[case testOverloadWithOverlappingItemsAndAnyArgument5]
from typing import overload, Any, Union
class A: pass
class B(A): pass
@overload
def f(x: B) -> B: ...
@overload
def f(x: Union[A, B]) -> A: ...
def f(x): pass
# Note: overloads ignore promotions so we treat 'int' and 'float' as distinct types
@overload
def g(x: int) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def g(x: Union[int, float]) -> float: ...
def g(x): pass
a: Any
reveal_type(f(a)) # N: Revealed type is "Any"
reveal_type(g(a)) # N: Revealed type is "Any"
[case testOverloadWithOverlappingItemsAndAnyArgument6]
from typing import overload, Any
@overload
def f(x: int, y: int) -> int: ...
@overload
def f(x: float, y: int, z: str) -> float: ...
@overload
def f(x: object, y: int, z: str, a: None) -> str: ...
def f(x): pass
a: Any
# Any causes ambiguity
reveal_type(f(*a)) # N: Revealed type is "Any"
reveal_type(f(a, *a)) # N: Revealed type is "Any"
reveal_type(f(1, *a)) # N: Revealed type is "Any"
reveal_type(f(1.1, *a)) # N: Revealed type is "Any"
reveal_type(f('', *a)) # N: Revealed type is "builtins.str"
[case testOverloadWithOverlappingItemsAndAnyArgument7]
from typing import overload, Any
@overload
def f(x: int, y: int, z: int) -> int: ...
@overload
def f(x: object, y: int, z: int) -> object: ...
def f(x): pass
@overload
def g(x: int, y: int, z: int) -> int: ...
@overload
def g(x: object, y: int, z: str) -> object: ...
def g(x): pass
a: Any
reveal_type(f(1, *a)) # N: Revealed type is "builtins.int"
reveal_type(g(1, *a)) # N: Revealed type is "Any"
[case testOverloadWithOverlappingItemsAndAnyArgument8]
from typing import overload, Any
@overload
def f(x: int, y: int, z: int) -> str: ...
@overload
def f(x: object, y: int, z: int) -> str: ...
def f(x): pass
a: Any
# The return type is not ambiguous so Any arguments cause no ambiguity.
reveal_type(f(a, 1, 1)) # N: Revealed type is "builtins.str"
reveal_type(f(1, *a)) # N: Revealed type is "builtins.str"
[case testOverloadWithOverlappingItemsAndAnyArgument9]
from typing import overload, Any, List
@overload
def f(x: List[int]) -> List[int]: ...
@overload
def f(x: List[Any]) -> List[Any]: ...
def f(x): pass
a: Any
b: List[Any]
c: List[str]
d: List[int]
reveal_type(f(a)) # N: Revealed type is "builtins.list[Any]"
reveal_type(f(b)) # N: Revealed type is "builtins.list[Any]"
reveal_type(f(c)) # N: Revealed type is "builtins.list[Any]"
reveal_type(f(d)) # N: Revealed type is "builtins.list[builtins.int]"
[builtins fixtures/list.pyi]
[case testOverloadWithOverlappingItemsAndAnyArgument10]
from typing import overload, Any
@overload
def f(*, x: int = 3, y: int = 3) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(**kwargs: str) -> str: ...
def f(*args, **kwargs): pass
# Checking an overload flagged as unsafe is a bit weird, but this is the
# cleanest way to make sure 'Any' ambiguity checks work correctly with
# keyword arguments.
a: Any
i: int
reveal_type(f(x=a, y=i)) # N: Revealed type is "builtins.int"
reveal_type(f(y=a)) # N: Revealed type is "Any"
reveal_type(f(x=a, y=a)) # N: Revealed type is "Any"
[builtins fixtures/dict.pyi]
[case testOverloadWithOverlappingItemsAndAnyArgument11]
from typing import overload, Any, Dict
@overload
def f(x: int = 3, **kwargs: int) -> int: ...
@overload
def f(**kwargs: str) -> str: ...
def f(*args, **kwargs): pass
a: Dict[str, Any]
i: int
reveal_type(f(x=i, **a)) # N: Revealed type is "builtins.int"
reveal_type(f(**a)) # N: Revealed type is "Any"
[builtins fixtures/dict.pyi]
[case testOverloadWithOverlappingItemsAndAnyArgument12]
from typing import overload, Any
@overload
def f(x: int) -> Any: ...
@overload
def f(x: str) -> str: ...
def f(x): pass
a: Any
reveal_type(f(a)) # N: Revealed type is "Any"
[case testOverloadWithOverlappingItemsAndAnyArgument13]
from typing import Any, overload, TypeVar, Generic
class slice: pass
T = TypeVar('T')
class A(Generic[T]):
@overload
def f(self, x: int) -> T: ...
@overload
def f(self, x: slice) -> A[T]: ...
def f(self, x): ...
i: Any
a: A[Any]
reveal_type(a.f(i)) # N: Revealed type is "Any"
[case testOverloadWithOverlappingItemsAndAnyArgument14]
from typing import Any, overload, TypeVar, Generic
T = TypeVar('T')
class Wrapper(Generic[T]): pass
class slice: pass
class A(Generic[T]):
@overload
def f(self, x: int) -> Wrapper[T]: ...
@overload
def f(self, x: slice) -> Wrapper[A[T]]: ...
def f(self, x): ...
i: Any
a: A[Any]
reveal_type(a.f(i)) # N: Revealed type is "__main__.Wrapper[Any]"
[case testOverloadWithOverlappingItemsAndAnyArgument15]
from typing import overload, Any, Union
@overload
def f(x: int) -> str: ...
@overload
def f(x: str) -> str: ...
def f(x): pass
@overload
def g(x: int) -> Union[str, int]: ...
@overload
def g(x: str) -> Union[int, str]: ...
def g(x): pass
a: Any
reveal_type(f(a)) # N: Revealed type is "builtins.str"
reveal_type(g(a)) # N: Revealed type is "Union[builtins.str, builtins.int]"
[case testOverloadWithOverlappingItemsAndAnyArgument16]
from typing import overload, Any, Union, Callable
@overload
def f(x: int) -> Callable[[int, int], int]: ...
@overload
def f(x: str) -> Callable[[str], str]: ...
def f(x): pass
a: Any
reveal_type(f(a)) # N: Revealed type is "def (*Any, **Any) -> Any"
reveal_type(f(a)(a)) # N: Revealed type is "Any"
[case testOverloadOnOverloadWithType]
from typing import Any, Type, TypeVar, overload
from mod import MyInt
T = TypeVar('T')
@overload
def make(cls: Type[T]) -> T: pass
@overload
def make() -> Any: pass
def make(*args):
pass
c = make(MyInt)
reveal_type(c) # N: Revealed type is "mod.MyInt"
[file mod.pyi]
from typing import overload
class MyInt:
@overload
def __init__(self, x: str) -> None: pass
@overload
def __init__(self, x: str, y: int) -> None: pass
[builtins fixtures/tuple.pyi]
[out]
[case testOverloadTupleInstance]
from typing import overload, Tuple, Any
class A: ...
class A1(A): ...
class B: ...
class C: ...
class D: ...
@overload
def f(x: A) -> A: ...
@overload
def f(x: Tuple[C]) -> B: ...
@overload
def f(x: Tuple[A1, int]) -> C: ... # E: Overloaded function signatures 3 and 5 overlap with incompatible return types
@overload
def f(x: Tuple[A, str]) -> D: ...
@overload
def f(x: Tuple[A, int]) -> D: ...
@overload
def f(x: Tuple[()]) -> D: ...
def f(x: Any) -> Any:...
[builtins fixtures/tuple.pyi]
[case testOverloadTupleEllipsisNumargs]
from typing import overload, Tuple, Any
class A: ...
class B: ...
@overload
def r1(x: Tuple[()]) -> B: ... # E: Overloaded function signatures 1 and 4 overlap with incompatible return types
@overload
def r1(x: Tuple[A]) -> B: ... # E: Overloaded function signatures 2 and 4 overlap with incompatible return types
@overload
def r1(x: Tuple[A, A]) -> B: ... # E: Overloaded function signatures 3 and 4 overlap with incompatible return types
@overload
def r1(x: Tuple[A, ...]) -> A: ...
def r1(x: Any) -> Any: ...
@overload
def r2(x: Tuple[A, ...]) -> A: ...
@overload
def r2(x: Tuple[A, A]) -> B: ... # E: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader
@overload
def r2(x: Tuple[A]) -> B: ... # E: Overloaded function signature 3 will never be matched: signature 1's parameter type(s) are the same or broader
@overload
def r2(x: Tuple[()]) -> B: ... # E: Overloaded function signature 4 will never be matched: signature 1's parameter type(s) are the same or broader
def r2(x: Any) -> Any: ...
[builtins fixtures/tuple.pyi]
[case testOverloadTupleEllipsisVariance]
from typing import overload, Tuple, Any
class A: ...
class A1(A): ...
class B: ...
class C: ...
class D: ...
@overload
def r(x: Tuple[A1, ...]) -> A: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def r(x: Tuple[A, ...]) -> B: ...
@overload
def r(x: Tuple[B, ...]) -> C: ...
def r(x: Any) -> Any:...
@overload
def g(x: A) -> A: ...
@overload
def g(x: Tuple[A1, ...]) -> B: ... # E: Overloaded function signatures 2 and 3 overlap with incompatible return types
@overload
def g(x: Tuple[A, A]) -> C: ...
@overload
def g(x: Tuple[A, B]) -> D: ...
def g(x: Any) -> Any:...
[builtins fixtures/tuple.pyi]
[case testOverloadWithMethodOverrideAndImplementation]
from typing import overload, Union, Any
class Parent:
@overload
def f(self, arg: int) -> int: ...
@overload
def f(self, arg: str) -> str: ...
def f(self, arg: Any) -> Any: ...
class Child1(Parent):
@overload
def f(self, arg: int) -> int: ...
@overload
def f(self, arg: str) -> str: ...
def f(self, arg: Union[int, str]) -> Union[int, str]: ...
class Child2(Parent):
@overload
def f(self, arg: int) -> int: ...
@overload
def f(self, arg: str) -> str: ...
def f(self, arg: Union[int, str]) -> int: ... # E: Overloaded function implementation cannot produce return type of signature 2
class Child3(Parent):
@overload
def f(self, arg: int) -> int: ...
@overload
def f(self, arg: str) -> str: ...
def f(self, arg: Any) -> Any: ...
class Child4(Parent):
@overload
def f(self, arg: int) -> int: ...
@overload
def f(self, arg: str) -> str: ...
def f(self, arg: Union[int, str]) -> Union[int, str]:
return b'' # E: Incompatible return value type (got "bytes", expected "Union[int, str]")
[builtins fixtures/tuple.pyi]
[case testOverloadWithIncompatibleMethodOverrideAndImplementation]
from typing import overload, Union, Any
class StrSub: pass
class ParentWithTypedImpl:
@overload
def f(self, arg: int) -> int: ...
@overload
def f(self, arg: str) -> str: ...
def f(self, arg: Union[int, str]) -> Union[int, str]: ...
class Child1(ParentWithTypedImpl):
@overload # Fail
def f(self, arg: int) -> int: ...
@overload
def f(self, arg: StrSub) -> str: ...
def f(self, arg: Union[int, StrSub]) -> Union[int, str]: ...
class Child2(ParentWithTypedImpl):
@overload # Fail
def f(self, arg: int) -> int: ...
@overload
def f(self, arg: StrSub) -> str: ...
def f(self, arg: Any) -> Any: ...
class ParentWithDynamicImpl:
@overload
def f(self, arg: int) -> int: ...
@overload
def f(self, arg: str) -> str: ...
def f(self, arg: Any) -> Any: ...
class Child3(ParentWithDynamicImpl):
@overload # Fail
def f(self, arg: int) -> int: ...
@overload
def f(self, arg: StrSub) -> str: ...
def f(self, arg: Union[int, StrSub]) -> Union[int, str]: ...
class Child4(ParentWithDynamicImpl):
@overload # Fail
def f(self, arg: int) -> int: ...
@overload
def f(self, arg: StrSub) -> str: ...
def f(self, arg: Any) -> Any: ...
[builtins fixtures/tuple.pyi]
[out]
main:13: error: Signature of "f" incompatible with supertype "ParentWithTypedImpl"
main:13: note: Superclass:
main:13: note: @overload
main:13: note: def f(self, arg: int) -> int
main:13: note: @overload
main:13: note: def f(self, arg: str) -> str
main:13: note: Subclass:
main:13: note: @overload
main:13: note: def f(self, arg: int) -> int
main:13: note: @overload
main:13: note: def f(self, arg: StrSub) -> str
main:20: error: Signature of "f" incompatible with supertype "ParentWithTypedImpl"
main:20: note: Superclass:
main:20: note: @overload
main:20: note: def f(self, arg: int) -> int
main:20: note: @overload
main:20: note: def f(self, arg: str) -> str
main:20: note: Subclass:
main:20: note: @overload
main:20: note: def f(self, arg: int) -> int
main:20: note: @overload
main:20: note: def f(self, arg: StrSub) -> str
main:34: error: Signature of "f" incompatible with supertype "ParentWithDynamicImpl"
main:34: note: Superclass:
main:34: note: @overload
main:34: note: def f(self, arg: int) -> int
main:34: note: @overload
main:34: note: def f(self, arg: str) -> str
main:34: note: Subclass:
main:34: note: @overload
main:34: note: def f(self, arg: int) -> int
main:34: note: @overload
main:34: note: def f(self, arg: StrSub) -> str
main:41: error: Signature of "f" incompatible with supertype "ParentWithDynamicImpl"
main:41: note: Superclass:
main:41: note: @overload
main:41: note: def f(self, arg: int) -> int
main:41: note: @overload
main:41: note: def f(self, arg: str) -> str
main:41: note: Subclass:
main:41: note: @overload
main:41: note: def f(self, arg: int) -> int
main:41: note: @overload
main:41: note: def f(self, arg: StrSub) -> str
[case testOverloadAnyIsConsideredValidReturnSubtype]
from typing import Any, overload, Optional
@overload
def foo(x: None) -> Any: ...
@overload
def foo(x: Optional[str]) -> str: ...
def foo(x): pass
@overload
def bar(x: None) -> object: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def bar(x: Optional[str]) -> str: ...
def bar(x): pass
[case testOverloadWithNonPositionalArgs]
from typing import overload
class A: ...
class B: ...
class C: ...
@overload
def foo(*, p1: A, p2: B = B()) -> A: ...
@overload
def foo(*, p2: B = B()) -> B: ...
def foo(p1, p2=None): ...
reveal_type(foo()) # N: Revealed type is "__main__.B"
reveal_type(foo(p2=B())) # N: Revealed type is "__main__.B"
reveal_type(foo(p1=A())) # N: Revealed type is "__main__.A"
[case testOverloadWithNonPositionalArgsIgnoresOrder]
from typing import overload
class A: ...
class B(A): ...
class X: ...
class Y: ...
@overload
def f(*, p1: X, p2: A) -> X: ...
@overload
def f(*, p2: B, p1: X) -> Y: ... # E: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader
def f(*, p1, p2): ...
@overload
def g(*, p1: X, p2: B) -> X: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def g(*, p2: A, p1: X) -> Y: ...
def g(*, p1, p2): ...
[case testOverloadWithVariableArgsAreOverlapping]
from wrapper import *
[file wrapper.pyi]
from typing import overload
@overload
def foo1(*x: int) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo1(x: int, y: int, z: int) -> str: ...
@overload
def foo2(*x: int) -> int: ...
@overload
def foo2(x: int, y: str, z: int) -> str: ...
@overload
def bar1(x: int, y: int, z: int) -> str: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def bar1(*x: int) -> int: ...
@overload
def bar2(x: int, y: str, z: int) -> str: ...
@overload
def bar2(*x: int) -> int: ...
[builtins fixtures/tuple.pyi]
[case testOverloadDetectsPossibleMatchesWithGenerics]
from typing import overload, TypeVar, Generic
T = TypeVar('T')
@overload
def foo(x: None, y: None) -> str: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo(x: T, y: T) -> int: ...
def foo(x): ...
# What if 'T' is 'object'?
@overload
def bar(x: None, y: int) -> str: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def bar(x: T, y: T) -> int: ...
def bar(x, y): ...
class Wrapper(Generic[T]):
@overload
def foo(self, x: None, y: None) -> str: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo(self, x: T, y: None) -> int: ...
def foo(self, x): ...
@overload
def bar(self, x: None, y: int) -> str: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def bar(self, x: T, y: T) -> int: ...
def bar(self, x, y): ...
[case testOverloadFlagsPossibleMatches]
from wrapper import *
[file wrapper.pyi]
from typing import overload
@overload
def foo1(x: str) -> str: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo1(x: str, y: str = ...) -> int: ...
@overload
def foo2(x: str, y: str = ...) -> int: ...
@overload
def foo2(x: str) -> str: ... # E: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader
@overload
def foo3(x: str) -> str: ...
@overload
def foo3(x: str, y: str) -> int: ...
[case testOverloadPossibleOverlapWithArgsAndKwargs]
from wrapper import *
[file wrapper.pyi]
from typing import overload
@overload
def foo1(*args: int) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo1(**kwargs: int) -> str: ...
@overload
def foo2(**kwargs: int) -> str: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo2(*args: int) -> int: ...
[builtins fixtures/dict.pyi]
[case testOverloadPossibleOverlapWithVarargs]
from wrapper import *
[file wrapper.pyi]
from typing import overload
@overload
def foo1(*args: int) -> int: ...
@overload
def foo1(*args2: int) -> str: ... # E: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader
@overload
def foo2(*args: int) -> str: ...
@overload
def foo2(*args2: str) -> int: ...
@overload
def foo3(*args: int) -> str: ...
@overload
def foo3(*args: str) -> int: ...
[builtins fixtures/tuple.pyi]
[case testOverloadPossibleOverlapWithVarargs2]
from wrapper import *
[file wrapper.pyi]
from typing import overload
@overload
def foo1(*args: str) -> int: ...
@overload
def foo1(x: int, *args2: int) -> str: ...
@overload
def foo2(x: int, *args: int) -> str: ...
@overload
def foo2(*args2: str) -> int: ...
@overload
def foo3(*args: int) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo3(x: int, *args2: int) -> str: ...
@overload
def foo4(x: int, *args: int) -> str: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo4(*args2: int) -> int: ...
[builtins fixtures/tuple.pyi]
[case testOverloadPossibleOverlapWithVarargs3]
from wrapper import *
[file wrapper.pyi]
from typing import overload
class Other: ...
@overload
def foo1(x: Other, *args: int) -> str: ...
@overload
def foo1(*args: str) -> int: ...
@overload
def foo2(*args: int) -> str: ...
@overload
def foo2(x: Other, *args: str) -> int: ...
@overload
def foo3(x: Other = ..., *args: int) -> str: ...
@overload
def foo3(*args: str) -> int: ...
@overload
def foo4(*args: int) -> str: ...
@overload
def foo4(x: Other = ..., *args: str) -> int: ...
[builtins fixtures/tuple.pyi]
[case testOverloadPossibleOverlapWithVarargs4]
from typing import overload
@overload
def foo1(x: int = 0, y: int = 0) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo1(*xs: int) -> str: ...
def foo1(*args): pass
@overload
def foo2(*xs: int) -> str: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo2(x: int = 0, y: int = 0) -> int: ...
def foo2(*args): pass
[builtins fixtures/tuple.pyi]
[case testOverloadPossibleOverlapWithKwargs]
from wrapper import *
[file wrapper.pyi]
from typing import overload
@overload
def foo1(**kwargs: int) -> int: ...
@overload
def foo1(**kwargs2: int) -> str: ... # E: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader
@overload
def foo2(**kwargs: int) -> str: ...
@overload
def foo2(**kwargs2: str) -> int: ...
@overload
def foo(**kwargs: int) -> str: ...
@overload
def foo(**kwargs: str) -> int: ...
[builtins fixtures/dict.pyi]
[case testOverloadPossibleOverlapMixingNamedArgsWithVarargs]
from wrapper import *
[file wrapper.pyi]
from typing import overload
@overload
def foo1(x: str, *, y: str) -> str: ...
@overload
def foo1(*x: str) -> int: ...
@overload
def foo2(*x: str) -> int: ...
@overload
def foo2(x: str, *, y: str) -> str: ...
[builtins fixtures/tuple.pyi]
[case testOverloadPossibleOverlapMixingOptionalArgsWithVarargs]
from wrapper import *
[file wrapper.pyi]
from typing import overload
@overload
def foo1(x: str, y: str = ..., z: str = ...) -> str: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo1(*x: str) -> int: ...
@overload
def foo2(*x: str) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo2(x: str, y: str = ..., z: str = ...) -> str: ...
@overload
def foo3(x: int, y: str = ..., z: str = ...) -> str: ...
@overload
def foo3(*x: str) -> int: ...
[builtins fixtures/tuple.pyi]
[case testOverloadPossibleOverlapMixingOptionalArgsWithVarargs2]
from wrapper import *
[file wrapper.pyi]
from typing import overload
@overload
def foo1(x: str, y: str = ..., z: int = ...) -> str: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo1(*x: str) -> int: ...
@overload
def foo2(x: str, y: str = ..., z: int = ...) -> str: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo2(*x: str) -> int: ...
[builtins fixtures/tuple.pyi]
[case testOverloadPossibleOverlapMixingNamedArgsWithKwargs]
from wrapper import *
[file wrapper.pyi]
from typing import overload
@overload
def foo1(*, x: str, y: str, z: str) -> str: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo1(**x: str) -> int: ...
@overload
def foo2(**x: str) -> int: ...
@overload
def foo2(*, x: str, y: str, z: str) -> str: ... # E: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader
@overload
def foo3(*, x: int, y: str, z: str) -> str: ...
@overload
def foo3(*x: str) -> int: ...
[builtins fixtures/dict.pyi]
[case testOverloadPossibleOverlapMixingNamedArgsWithKwargs2]
from wrapper import *
[file wrapper.pyi]
from typing import overload
@overload
def foo1(*, x: str, y: str, z: int) -> str: ...
@overload
def foo1(**x: str) -> int: ...
@overload
def foo2(**x: str) -> int: ...
@overload
def foo2(*, x: str, y: str, z: int) -> str: ...
@overload
def foo3(*, x: str, y: str, z: int = ...) -> str: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo3(**x: str) -> int: ...
@overload
def foo4(**x: str) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo4(*, x: str, y: str, z: int = ...) -> str: ...
[builtins fixtures/dict.pyi]
[case testOverloadPossibleOverlapMixingNamedArgsWithKwargs3]
from wrapper import *
[file wrapper.pyi]
from typing import overload
@overload
def foo1(x: str, *, y: str, z: str) -> str: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo1(**x: str) -> int: ...
@overload
def foo2(**x: str) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo2(x: str, *, y: str, z: str) -> str: ...
[builtins fixtures/dict.pyi]
[case testOverloadVarargInputAndVarargDefinition]
from typing import overload, List
class A: ...
class B: ...
class C: ...
@overload
def foo(x: int) -> A: ...
@overload
def foo(x: int, y: int) -> B: ...
@overload
def foo(x: int, y: int, z: int, *args: int) -> C: ...
def foo(*args): pass
reveal_type(foo(1)) # N: Revealed type is "__main__.A"
reveal_type(foo(1, 2)) # N: Revealed type is "__main__.B"
reveal_type(foo(1, 2, 3)) # N: Revealed type is "__main__.C"
reveal_type(foo(*[1])) # N: Revealed type is "__main__.C"
reveal_type(foo(*[1, 2])) # N: Revealed type is "__main__.C"
reveal_type(foo(*[1, 2, 3])) # N: Revealed type is "__main__.C"
x: List[int]
reveal_type(foo(*x)) # N: Revealed type is "__main__.C"
y: List[str]
foo(*y) # E: No overload variant of "foo" matches argument type "List[str]" \
# N: Possible overload variants: \
# N: def foo(x: int) -> A \
# N: def foo(x: int, y: int) -> B \
# N: def foo(x: int, y: int, z: int, *args: int) -> C
[builtins fixtures/list.pyi]
[case testOverloadMultipleVarargDefinition]
from typing import overload, List, Any
class A: ...
class B: ...
class C: ...
class D: ...
@overload
def foo(x: int) -> A: ...
@overload
def foo(x: int, y: int) -> B: ...
@overload
def foo(x: int, y: int, z: int, *args: int) -> C: ...
@overload
def foo(*x: str) -> D: ...
def foo(*args): pass
reveal_type(foo(*[1, 2])) # N: Revealed type is "__main__.C"
reveal_type(foo(*["a", "b"])) # N: Revealed type is "__main__.D"
x: List[Any]
reveal_type(foo(*x)) # N: Revealed type is "Any"
[builtins fixtures/list.pyi]
[case testOverloadMultipleVarargDefinitionComplex]
from typing import TypeVar, overload, Any, Callable
T1 = TypeVar('T1')
T2 = TypeVar('T2')
T3 = TypeVar('T3')
@overload
def chain_call(input_value: T1,
f1: Callable[[T1], T2]) -> T2: ...
@overload
def chain_call(input_value: T1,
f1: Callable[[T1], T2],
f2: Callable[[T2], T3]) -> T3: ...
@overload
def chain_call(input_value: T1,
*f_rest: Callable[[T1], T1]) -> T1: ...
@overload
def chain_call(input_value: T1,
f1: Callable[[T1], T2],
f2: Callable[[T2], T3],
f3: Callable[[T3], Any],
*f_rest: Callable[[Any], Any]) -> Any: ...
def chain_call(input_value, *f_rest):
for function in f_rest:
input_value = function(input_value)
return input_value
class A: ...
class B: ...
class C: ...
class D: ...
def f(x: A) -> A: ...
def f1(x: A) -> B: ...
def f2(x: B) -> C: ...
def f3(x: C) -> D: ...
reveal_type(chain_call(A(), f1, f2)) # N: Revealed type is "__main__.C"
reveal_type(chain_call(A(), f1, f2, f3)) # N: Revealed type is "Any"
reveal_type(chain_call(A(), f, f, f, f)) # N: Revealed type is "__main__.A"
[builtins fixtures/list.pyi]
[case testOverloadVarargsSelection]
from typing import overload, Tuple
@overload
def f(x: int) -> Tuple[int]: ...
@overload
def f(x: int, y: int) -> Tuple[int, int]: ...
@overload
def f(*xs: int) -> Tuple[int, ...]: ...
def f(*args): pass
i: int
reveal_type(f(i)) # N: Revealed type is "Tuple[builtins.int]"
reveal_type(f(i, i)) # N: Revealed type is "Tuple[builtins.int, builtins.int]"
reveal_type(f(i, i, i)) # N: Revealed type is "builtins.tuple[builtins.int, ...]"
reveal_type(f(*[])) # N: Revealed type is "builtins.tuple[builtins.int, ...]"
reveal_type(f(*[i])) # N: Revealed type is "builtins.tuple[builtins.int, ...]"
reveal_type(f(*[i, i])) # N: Revealed type is "builtins.tuple[builtins.int, ...]"
reveal_type(f(*[i, i, i])) # N: Revealed type is "builtins.tuple[builtins.int, ...]"
[builtins fixtures/list.pyi]
[case testOverloadVarargsSelectionWithTuples]
from typing import overload, Tuple
@overload
def f(x: int) -> Tuple[int]: ...
@overload
def f(x: int, y: int) -> Tuple[int, int]: ...
@overload
def f(*xs: int) -> Tuple[int, ...]: ...
def f(*args): pass
i: int
reveal_type(f(*())) # N: Revealed type is "builtins.tuple[builtins.int, ...]"
reveal_type(f(*(i,))) # N: Revealed type is "Tuple[builtins.int]"
reveal_type(f(*(i, i))) # N: Revealed type is "Tuple[builtins.int, builtins.int]"
reveal_type(f(*(i, i, i))) # N: Revealed type is "builtins.tuple[builtins.int, ...]"
[builtins fixtures/tuple.pyi]
[case testOverloadVarargsSelectionWithNamedTuples]
from typing import overload, Tuple, NamedTuple
@overload
def f(x: int, y: int) -> Tuple[int, int]: ...
@overload
def f(*xs: int) -> Tuple[int, ...]: ...
def f(*args): pass
A = NamedTuple('A', [('x', int), ('y', int)])
B = NamedTuple('B', [('a', int), ('b', int)])
C = NamedTuple('C', [('a', int), ('b', int), ('c', int)])
a: A
b: B
c: C
reveal_type(f(*a)) # N: Revealed type is "Tuple[builtins.int, builtins.int]"
reveal_type(f(*b)) # N: Revealed type is "Tuple[builtins.int, builtins.int]"
reveal_type(f(*c)) # N: Revealed type is "builtins.tuple[builtins.int, ...]"
[builtins fixtures/tuple.pyi]
[case testOverloadKwargsSelectionWithDict]
from typing import overload, Tuple, Dict
@overload
def f(*, x: int) -> Tuple[int]: ...
@overload
def f(*, x: int, y: int) -> Tuple[int, int]: ...
@overload
def f(**xs: int) -> Tuple[int, ...]: ...
def f(**kwargs): pass
empty: Dict[str, int]
reveal_type(f(**empty)) # N: Revealed type is "builtins.tuple[builtins.int, ...]"
reveal_type(f(**{'x': 4})) # N: Revealed type is "builtins.tuple[builtins.int, ...]"
reveal_type(f(**{'x': 4, 'y': 4})) # N: Revealed type is "builtins.tuple[builtins.int, ...]"
reveal_type(f(**{'a': 4, 'b': 4, 'c': 4})) # N: Revealed type is "builtins.tuple[builtins.int, ...]"
[builtins fixtures/dict.pyi]
[case testOverloadKwargsSelectionWithTypedDict]
from typing import overload, Tuple
from typing_extensions import TypedDict
@overload
def f(*, x: int) -> Tuple[int]: ...
@overload
def f(*, x: int, y: int) -> Tuple[int, int]: ...
@overload
def f(**xs: int) -> Tuple[int, ...]: ...
def f(**args): pass
A = TypedDict('A', {'x': int})
B = TypedDict('B', {'x': int, 'y': int})
C = TypedDict('C', {'x': int, 'y': int, 'z': int})
a: A
b: B
c: C
reveal_type(f(**a)) # N: Revealed type is "Tuple[builtins.int]"
reveal_type(f(**b)) # N: Revealed type is "Tuple[builtins.int, builtins.int]"
reveal_type(f(**c)) # N: Revealed type is "builtins.tuple[builtins.int, ...]"
[builtins fixtures/dict.pyi]
[case testOverloadVarargsAndKwargsSelection]
from typing import overload, Any, Tuple, Dict
class A: pass
class B(A): pass
@overload
def f(x: int, y: int) -> B: pass
@overload
def f(x: int, y: int, **kwargs: int) -> A: pass
@overload
def f(*args: int, **kwargs: int) -> Any: pass
def f(*args, **kwargs): pass
a: Tuple[int, int]
b: Tuple[int, ...]
c: Dict[str, int]
reveal_type(f(*a, **c)) # N: Revealed type is "__main__.A"
reveal_type(f(*b, **c)) # N: Revealed type is "__main__.A"
reveal_type(f(*a)) # N: Revealed type is "__main__.B"
reveal_type(f(*b)) # N: Revealed type is "Any"
# TODO: Should this be 'Any' instead?
# The first matching overload with a kwarg is f(int, int, **int) -> A,
# but f(*int, **int) -> Any feels like a better fit.
reveal_type(f(**c)) # N: Revealed type is "__main__.A"
[builtins fixtures/args.pyi]
[case testOverloadWithPartiallyOverlappingUnions]
from typing import overload, Union
class A: ...
class B: ...
class C: ...
class D: ...
@overload
def f(x: Union[A, B]) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(x: Union[B, C]) -> str: ...
def f(x): ...
@overload
def g(x: Union[A, B]) -> int: ...
@overload
def g(x: Union[B, C]) -> int: ...
def g(x): ...
@overload
def h(x: Union[A, B]) -> int: ...
@overload
def h(x: Union[C, D]) -> str: ...
def h(x): ...
@overload
def i(x: Union[A, B]) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def i(x: Union[A, B, C]) -> str: ...
def i(x): ...
[case testOverloadWithPartiallyOverlappingUnionsNested]
from typing import overload, Union, List
class A: ...
class B: ...
class C: ...
class D: ...
@overload
def f(x: List[Union[A, B]]) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(x: List[Union[B, C]]) -> str: ...
def f(x): ...
@overload
def g(x: List[Union[A, B]]) -> int: ...
@overload
def g(x: List[Union[B, C]]) -> int: ...
def g(x): ...
@overload
def h(x: List[Union[A, B]]) -> int: ...
@overload
def h(x: List[Union[C, D]]) -> str: ...
def h(x): ...
@overload
def i(x: List[Union[A, B]]) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def i(x: List[Union[A, B, C]]) -> str: ...
def i(x): ...
[builtins fixtures/list.pyi]
[case testOverloadPartialOverlapWithUnrestrictedTypeVar]
from typing import TypeVar, overload
T = TypeVar('T')
@overload
def f(x: int) -> str: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(x: T) -> T: ...
def f(x): ...
@overload
def g(x: int) -> int: ...
@overload
def g(x: T) -> T: ...
def g(x): ...
[case testOverloadPartialOverlapWithUnrestrictedTypeVarNested]
from typing import TypeVar, overload, List
T = TypeVar('T')
@overload
def f1(x: List[int]) -> str: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f1(x: List[T]) -> T: ...
def f1(x): ...
@overload
def f2(x: List[int]) -> List[str]: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f2(x: List[T]) -> List[T]: ...
def f2(x): ...
@overload
def g1(x: List[int]) -> int: ...
@overload
def g1(x: List[T]) -> T: ...
def g1(x): ...
@overload
def g2(x: List[int]) -> List[int]: ...
@overload
def g2(x: List[T]) -> List[T]: ...
def g2(x): ...
[builtins fixtures/list.pyi]
[case testOverloadPartialOverlapWithUnrestrictedTypeVarInClass]
from typing import TypeVar, overload, Generic
T = TypeVar('T')
class Wrapper(Generic[T]):
@overload
def f(self, x: int) -> str: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(self, x: T) -> T: ...
def f(self, x): ...
# TODO: This shouldn't trigger an error message?
# Related to testTypeCheckOverloadImplementationTypeVarDifferingUsage2?
# See https://github.com/python/mypy/issues/5510
@overload
def g(self, x: int) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def g(self, x: T) -> T: ...
def g(self, x): ...
[case testOverloadPartialOverlapWithUnrestrictedTypeVarInClassNested]
from typing import TypeVar, overload, Generic, List
T = TypeVar('T')
class Wrapper(Generic[T]):
@overload
def f1(self, x: List[int]) -> str: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f1(self, x: List[T]) -> T: ...
def f1(self, x): ...
@overload
def f2(self, x: List[int]) -> List[str]: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f2(self, x: List[T]) -> List[T]: ...
def f2(self, x): ...
# TODO: This shouldn't trigger an error message?
# See https://github.com/python/mypy/issues/5510
@overload
def g1(self, x: List[int]) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def g1(self, x: List[T]) -> T: ...
def g1(self, x): ...
@overload
def g2(self, x: List[int]) -> List[int]: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def g2(self, x: List[T]) -> List[T]: ...
def g2(self, x): ...
[builtins fixtures/list.pyi]
[case testOverloadTypedDictDifferentRequiredKeysMeansDictsAreDisjoint]
from typing import overload
from mypy_extensions import TypedDict
A = TypedDict('A', {'x': int, 'y': int})
B = TypedDict('B', {'x': int, 'y': str})
@overload
def f(x: A) -> int: ...
@overload
def f(x: B) -> str: ...
def f(x): pass
[builtins fixtures/dict.pyi]
[case testOverloadedTypedDictPartiallyOverlappingRequiredKeys]
from typing import overload, Union
from mypy_extensions import TypedDict
A = TypedDict('A', {'x': int, 'y': Union[int, str]})
B = TypedDict('B', {'x': int, 'y': Union[str, float]})
@overload
def f(x: A) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(x: B) -> str: ...
def f(x): pass
@overload
def g(x: A) -> int: ...
@overload
def g(x: B) -> object: ...
def g(x): pass
[builtins fixtures/dict.pyi]
[case testOverloadedTypedDictFullyNonTotalDictsAreAlwaysPartiallyOverlapping]
from typing import overload
from mypy_extensions import TypedDict
A = TypedDict('A', {'x': int, 'y': str}, total=False)
B = TypedDict('B', {'a': bool}, total=False)
C = TypedDict('C', {'x': str, 'y': int}, total=False)
@overload
def f(x: A) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(x: B) -> str: ...
def f(x): pass
@overload
def g(x: A) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def g(x: C) -> str: ...
def g(x): pass
[builtins fixtures/dict.pyi]
[case testOverloadedTotalAndNonTotalTypedDictsCanPartiallyOverlap]
from typing import overload, Union
from mypy_extensions import TypedDict
A = TypedDict('A', {'x': int, 'y': str})
B = TypedDict('B', {'x': Union[int, str], 'y': str, 'z': int}, total=False)
@overload
def f1(x: A) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f1(x: B) -> str: ...
def f1(x): pass
@overload
def f2(x: B) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f2(x: A) -> str: ...
def f2(x): pass
[builtins fixtures/dict.pyi]
[case testOverloadedTypedDictsWithSomeOptionalKeysArePartiallyOverlapping]
from typing import overload, Union
from mypy_extensions import TypedDict
class A(TypedDict):
x: int
y: int
class B(TypedDict, total=False):
z: str
class C(TypedDict, total=False):
z: int
@overload
def f(x: B) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(x: C) -> str: ...
def f(x): pass
[builtins fixtures/dict.pyi]
[case testOverloadedPartiallyOverlappingInheritedTypes1]
from typing import overload, List, Union, TypeVar, Generic
class A: pass
class B: pass
class C: pass
T = TypeVar('T')
class ListSubclass(List[T]): pass
class Unrelated(Generic[T]): pass
@overload
def f(x: List[Union[A, B]]) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(x: ListSubclass[Union[B, C]]) -> str: ...
def f(x): pass
@overload
def g(x: List[Union[A, B]]) -> int: ...
@overload
def g(x: Unrelated[Union[B, C]]) -> str: ...
def g(x): pass
[builtins fixtures/list.pyi]
[case testOverloadedPartiallyOverlappingInheritedTypes2]
from typing import overload, List, Union
class A: pass
class B: pass
class C: pass
class ListSubclass(List[Union[B, C]]): pass
@overload
def f(x: List[Union[A, B]]) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(x: ListSubclass) -> str: ...
def f(x): pass
[builtins fixtures/list.pyi]
[case testOverloadedPartiallyOverlappingInheritedTypes3]
from typing import overload, Union, Dict, TypeVar
class A: pass
class B: pass
class C: pass
S = TypeVar('S')
class DictSubclass(Dict[str, S]): pass
@overload
def f(x: Dict[str, Union[A, B]]) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(x: DictSubclass[Union[B, C]]) -> str: ...
def f(x): pass
[builtins fixtures/dict.pyi]
[case testOverloadedPartiallyOverlappingTypeVarsAndUnion]
from typing import overload, TypeVar, Union
class A: pass
class B: pass
class C: pass
S = TypeVar('S', A, B)
@overload
def f(x: S) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(x: Union[B, C]) -> str: ...
def f(x): pass
@overload
def g(x: Union[B, C]) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def g(x: S) -> str: ...
def g(x): pass
[case testOverloadPartiallyOverlappingTypeVarsIdentical]
from typing import overload, TypeVar, Union
T = TypeVar('T')
class A: pass
class B: pass
class C: pass
@overload
def f(x: T, y: T, z: Union[A, B]) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(x: T, y: T, z: Union[B, C]) -> str: ...
def f(x, y, z): pass
[case testOverloadedPartiallyOverlappingCallables]
from typing import overload, Union, Callable
class A: pass
class B: pass
class C: pass
@overload
def f(x: Callable[[Union[A, B]], int]) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(x: Callable[[Union[B, C]], int]) -> str: ...
def f(x): pass
[case testOverloadNotConfusedForProperty]
from typing import overload
class PropertyClass:
@property
def foo(self) -> str: return "..."
@foo.setter
def foo(self, value: str) -> None: pass
@foo.deleter
def foo(self) -> None: pass
class OverloadClass:
@overload
def foo(self) -> str: pass
@overload
def foo(self, value: str) -> None: pass
@overload
def foo(self) -> None: pass # E: Overloaded function signature 3 will never be matched: signature 1's parameter type(s) are the same or broader
def foo(self, *args): pass
[builtins fixtures/property.pyi]
[case testOverloadInferUnionReturnBasic]
from typing import overload, Union
class A: ...
class B: ...
class C: ...
class D: ...
@overload
def f1(x: A) -> B: ...
@overload
def f1(x: C) -> D: ...
def f1(x): ...
arg1: Union[A, C]
reveal_type(f1(arg1)) # N: Revealed type is "Union[__main__.B, __main__.D]"
arg2: Union[A, B]
f1(arg2) # E: Argument 1 to "f1" has incompatible type "Union[A, B]"; expected "A"
@overload
def f2(x: A) -> B: ...
@overload
def f2(x: C) -> B: ...
def f2(x): ...
reveal_type(f2(arg1)) # N: Revealed type is "__main__.B"
[case testOverloadInferUnionReturnMultipleArguments]
from typing import overload, Union
class A: ...
class B: ...
class C: ...
class D: ...
@overload
def f1(x: A, y: C) -> B: ...
@overload
def f1(x: C, y: A) -> D: ...
def f1(x, y): ...
arg1: Union[A, C]
reveal_type(f1(arg1, arg1))
@overload
def f2(x: A, y: C) -> B: ...
@overload
def f2(x: C, y: C) -> D: ...
def f2(x, y): ...
reveal_type(f2(arg1, arg1))
reveal_type(f2(arg1, C()))
[out]
main:15: note: Revealed type is "__main__.B"
main:15: error: Argument 1 to "f1" has incompatible type "Union[A, C]"; expected "A"
main:15: error: Argument 2 to "f1" has incompatible type "Union[A, C]"; expected "C"
main:23: note: Revealed type is "__main__.B"
main:23: error: Argument 1 to "f2" has incompatible type "Union[A, C]"; expected "A"
main:23: error: Argument 2 to "f2" has incompatible type "Union[A, C]"; expected "C"
main:24: note: Revealed type is "Union[__main__.B, __main__.D]"
[case testOverloadInferUnionRespectsVariance]
from typing import overload, TypeVar, Union, Generic
class A: pass
class B(A): pass
class C(B): pass
T_co = TypeVar('T_co', covariant=True)
T_contra = TypeVar('T_contra', contravariant=True)
class WrapperCo(Generic[T_co]): pass
class WrapperContra(Generic[T_contra]): pass
@overload
def foo(x: WrapperCo[B]) -> int: ...
@overload
def foo(x: WrapperContra[B]) -> str: ...
def foo(x): pass
compat: Union[WrapperCo[C], WrapperContra[A]]
reveal_type(foo(compat)) # N: Revealed type is "Union[builtins.int, builtins.str]"
not_compat: Union[WrapperCo[A], WrapperContra[C]]
foo(not_compat) # E: Argument 1 to "foo" has incompatible type "Union[WrapperCo[A], WrapperContra[C]]"; expected "WrapperCo[B]"
[case testOverloadInferUnionIfParameterNamesAreDifferent]
from typing import overload, Union
class A: ...
class B: ...
class C: ...
@overload
def f(x: A) -> B: ...
@overload
def f(y: B) -> C: ...
def f(x): ...
x: Union[A, B]
reveal_type(f(A())) # N: Revealed type is "__main__.B"
reveal_type(f(B())) # N: Revealed type is "__main__.C"
reveal_type(f(x)) # N: Revealed type is "Union[__main__.B, __main__.C]"
[case testOverloadInferUnionReturnFunctionsWithKwargs]
from typing import overload, Union, Optional
class A: ...
class B: ...
class C: ...
class D(B, C): ...
@overload
def f(x: A) -> D: ...
@overload
def f(x: A, y: Optional[B] = None) -> C: ...
@overload
def f(x: A, z: Optional[C] = None) -> B: ...
def f(x, y=None, z=None): ...
reveal_type(f(A(), B())) # N: Revealed type is "__main__.C"
reveal_type(f(A(), C())) # N: Revealed type is "__main__.B"
arg: Union[B, C]
reveal_type(f(A(), arg)) # N: Revealed type is "Union[__main__.C, __main__.B]"
reveal_type(f(A())) # N: Revealed type is "__main__.D"
[builtins fixtures/tuple.pyi]
[case testOverloadInferUnionWithDifferingLengths]
from typing import overload, Union
class Parent: ...
class Child(Parent): ...
class A: ...
class B: ...
@overload
def f(x: A) -> Child: ...
@overload
def f(x: B, y: B = B()) -> Parent: ...
def f(*args): ...
x: Union[A, B]
reveal_type(f(x)) # N: Revealed type is "__main__.Parent"
f(x, B()) # E: Argument 1 to "f" has incompatible type "Union[A, B]"; expected "B"
[builtins fixtures/tuple.pyi]
[case testOverloadInferUnionWithMixOfPositionalAndOptionalArgs]
from typing import overload, Union, Optional
class A: ...
class B: ...
@overload
def f(x: A) -> int: ...
@overload
def f(x: Optional[B] = None) -> str: ...
def f(*args): ...
x: Union[A, B]
y: Optional[A]
z: Union[A, Optional[B]]
reveal_type(f(x)) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(f(y)) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(f(z)) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(f()) # N: Revealed type is "builtins.str"
[builtins fixtures/tuple.pyi]
[case testOverloadingInferUnionReturnWithTypevarWithValueRestriction]
from typing import overload, Union, TypeVar, Generic
class A: pass
class B: pass
class C: pass
T = TypeVar('T', B, C)
class Wrapper(Generic[T]):
@overload
def f(self, x: T) -> B: ...
@overload
def f(self, x: A) -> C: ...
def f(self, x): ...
obj: Wrapper[B] = Wrapper()
x: Union[A, B]
reveal_type(obj.f(A())) # N: Revealed type is "__main__.C"
reveal_type(obj.f(B())) # N: Revealed type is "__main__.B"
reveal_type(obj.f(x)) # N: Revealed type is "Union[__main__.C, __main__.B]"
[case testOverloadingInferUnionReturnWithFunctionTypevarReturn]
from typing import overload, Union, TypeVar, Generic
T = TypeVar('T')
class W1(Generic[T]): pass
class W2(Generic[T]): pass
class A: pass
class B: pass
@overload
def foo(x: W1[T]) -> T: ...
@overload
def foo(x: W2[T]) -> T: ...
def foo(x): ...
def bar(x: Union[W1[T], W2[T]]) -> T: ...
def wrapper() -> None:
obj1: Union[W1[A], W2[A]]
a1: A = foo(obj1)
a2 = foo(obj1)
reveal_type(a1) # N: Revealed type is "__main__.A"
reveal_type(a2) # N: Revealed type is "__main__.A"
obj2: Union[W1[A], W2[B]]
reveal_type(foo(obj2)) # N: Revealed type is "Union[__main__.A, __main__.B]"
bar(obj2) # E: Cannot infer type argument 1 of "bar"
b1_overload: A = foo(obj2) # E: Incompatible types in assignment (expression has type "Union[A, B]", variable has type "A")
b1_union: A = bar(obj2) # E: Cannot infer type argument 1 of "bar"
[case testOverloadingInferUnionReturnWithObjectTypevarReturn]
from typing import overload, Union, TypeVar, Generic
T = TypeVar('T')
class W1(Generic[T]): pass
class W2(Generic[T]): pass
class A: pass
class B: pass
class SomeType(Generic[T]):
@overload
def foo(self, x: W1[T]) -> T: ...
@overload
def foo(self, x: W2[T]) -> T: ...
def foo(self, x): ...
def bar(self, x: Union[W1[T], W2[T]]) -> T: ...
def wrapper() -> None:
obj1: Union[W1[A], W2[A]]
a1 = SomeType[A]().foo(obj1)
reveal_type(a1) # N: Revealed type is "__main__.A"
# Note: These should be fine, but mypy has an unrelated bug
# that makes them error out?
a2_overload: A = SomeType().foo(obj1) # E: Argument 1 to "foo" of "SomeType" has incompatible type "Union[W1[A], W2[A]]"; expected "W1[<nothing>]"
a2_union: A = SomeType().bar(obj1) # E: Argument 1 to "bar" of "SomeType" has incompatible type "Union[W1[A], W2[A]]"; expected "Union[W1[<nothing>], W2[<nothing>]]"
SomeType().foo(obj1) # E: Argument 1 to "foo" of "SomeType" has incompatible type "Union[W1[A], W2[A]]"; expected "W1[<nothing>]"
SomeType().bar(obj1) # E: Argument 1 to "bar" of "SomeType" has incompatible type "Union[W1[A], W2[A]]"; expected "Union[W1[<nothing>], W2[<nothing>]]"
[case testOverloadingInferUnionReturnWithBadObjectTypevarReturn]
from typing import overload, Union, TypeVar, Generic
T = TypeVar('T')
class W1(Generic[T]): pass
class W2(Generic[T]): pass
class A: pass
class B: pass
class SomeType(Generic[T]):
@overload
def foo(self, x: W1[T]) -> T: ...
@overload
def foo(self, x: W2[T]) -> T: ...
def foo(self, x): ...
def bar(self, x: Union[W1[T], W2[T]]) -> T: ...
def wrapper(mysterious: T) -> T:
obj1: Union[W1[A], W2[B]]
SomeType().foo(obj1) # E: Argument 1 to "foo" of "SomeType" has incompatible type "Union[W1[A], W2[B]]"; expected "W1[<nothing>]"
SomeType().bar(obj1) # E: Argument 1 to "bar" of "SomeType" has incompatible type "Union[W1[A], W2[B]]"; expected "Union[W1[<nothing>], W2[<nothing>]]"
SomeType[A]().foo(obj1) # E: Argument 1 to "foo" of "SomeType" has incompatible type "Union[W1[A], W2[B]]"; expected "W1[A]"
SomeType[A]().bar(obj1) # E: Argument 1 to "bar" of "SomeType" has incompatible type "Union[W1[A], W2[B]]"; expected "Union[W1[A], W2[A]]"
SomeType[T]().foo(obj1) # E: Argument 1 to "foo" of "SomeType" has incompatible type "Union[W1[A], W2[B]]"; expected "W1[T]"
SomeType[T]().bar(obj1) # E: Argument 1 to "bar" of "SomeType" has incompatible type "Union[W1[A], W2[B]]"; expected "Union[W1[T], W2[T]]"
return mysterious
[case testOverloadingInferUnionReturnWithMixedTypevars]
from typing import overload, Generic, TypeVar, List, Tuple, Union
class A: pass
class B(A): pass
class C(A): pass
T = TypeVar('T', bound=A)
S = TypeVar('S')
class Dummy(Generic[T]):
@overload
def foo(self, x: List[Tuple[T, S]], y: S) -> T: ...
@overload
def foo(self, x: List[S], y: S) -> S: ...
def foo(self, x: Union[List[Tuple[T, S]], List[S]], y: S) -> Union[T, S]: ...
T1 = TypeVar('T1', bound=A)
def t_is_same_bound(arg1: T1, arg2: S) -> Tuple[T1, S]:
x1: Union[List[S], List[Tuple[T1, S]]]
y1: S
reveal_type(Dummy[T1]().foo(x1, y1)) # N: Revealed type is "Union[S`-2, T1`-1]"
x2: Union[List[T1], List[Tuple[T1, T1]]]
y2: T1
reveal_type(Dummy[T1]().foo(x2, y2)) # N: Revealed type is "T1`-1"
return arg1, arg2
[builtins fixtures/list.pyi]
[case testOverloadingInferUnionReturnWithMixedTypevarsInnerMismatch]
from typing import overload, Generic, TypeVar, List, Tuple, Union
class A: pass
class B(A): pass
class C(A): pass
T = TypeVar('T', bound=A)
S = TypeVar('S')
class Dummy(Generic[T]):
@overload
def foo(self, x: List[Tuple[T, S]], y: S) -> T: ...
@overload
def foo(self, x: List[S], y: S) -> S: ...
def foo(self, x: Union[List[Tuple[T, S]], List[S]], y: S) -> Union[T, S]: ...
T1 = TypeVar('T1', bound=A)
def t_is_same_bound(arg1: T1, arg2: S) -> Tuple[T1, S]:
# The arguments in the tuple are swapped
x3: Union[List[S], List[Tuple[S, T1]]]
y3: S
Dummy[T1]().foo(x3, y3) # E: Cannot infer type argument 1 of "foo" of "Dummy" \
# E: Argument 1 to "foo" of "Dummy" has incompatible type "Union[List[S], List[Tuple[S, T1]]]"; expected "List[Tuple[T1, Any]]"
x4: Union[List[int], List[Tuple[C, int]]]
y4: int
reveal_type(Dummy[C]().foo(x4, y4)) # N: Revealed type is "Union[builtins.int, __main__.C]"
Dummy[A]().foo(x4, y4) # E: Argument 1 to "foo" of "Dummy" has incompatible type "Union[List[int], List[Tuple[C, int]]]"; expected "List[Tuple[A, int]]"
return arg1, arg2
[builtins fixtures/list.pyi]
[case testOverloadingInferUnionReturnWithMixedTypevarsTighterBound]
from typing import overload, Generic, TypeVar, List, Tuple, Union
class A: pass
class B(A): pass
class C(A): pass
T = TypeVar('T', bound=A)
S = TypeVar('S')
class Dummy(Generic[T]):
@overload
def foo(self, x: List[Tuple[T, S]], y: S) -> T: ...
@overload
def foo(self, x: List[S], y: S) -> S: ...
def foo(self, x: Union[List[Tuple[T, S]], List[S]], y: S) -> Union[T, S]: ...
T1 = TypeVar('T1', bound=B)
def t_is_tighter_bound(arg1: T1, arg2: S) -> Tuple[T1, S]:
x1: Union[List[S], List[Tuple[T1, S]]]
y1: S
reveal_type(Dummy[T1]().foo(x1, y1)) # N: Revealed type is "Union[S`-2, T1`-1]"
x2: Union[List[T1], List[Tuple[T1, T1]]]
y2: T1
reveal_type(Dummy[T1]().foo(x2, y2)) # N: Revealed type is "T1`-1"
return arg1, arg2
[builtins fixtures/list.pyi]
[case testOverloadingInferUnionReturnWithTypevarsAndValueRestrictions]
from typing import overload, Generic, TypeVar, List, Tuple, Union
class A: pass
class B(A): pass
class C(A): pass
T = TypeVar('T', bound=A)
S = TypeVar('S')
class Dummy(Generic[T]):
@overload
def foo(self, x: List[Tuple[T, S]], y: S) -> T: ...
@overload
def foo(self, x: List[S], y: S) -> S: ...
def foo(self, x: Union[List[Tuple[T, S]], List[S]], y: S) -> Union[T, S]: ...
T3 = TypeVar('T3', B, C)
def t_is_compatible_bound(arg1: T3, arg2: S) -> Tuple[T3, S]:
x1: Union[List[S], List[Tuple[T3, S]]]
y1: S
reveal_type(Dummy[T3]().foo(x1, y1))
x2: Union[List[T3], List[Tuple[T3, T3]]]
y2: T3
reveal_type(Dummy[T3]().foo(x2, y2))
return arg1, arg2
[builtins fixtures/list.pyi]
[out]
main:22: note: Revealed type is "Union[S`-2, __main__.B]"
main:22: note: Revealed type is "Union[S`-2, __main__.C]"
main:26: note: Revealed type is "__main__.B"
main:26: note: Revealed type is "__main__.C"
[case testOverloadInferUnionReturnWithInconsistentTypevarNames]
from typing import overload, TypeVar, Union
T = TypeVar('T')
S = TypeVar('S')
@overload
def consistent(x: T, y: str) -> T: ...
@overload
def consistent(x: T, y: int) -> T: ...
def consistent(x: T, y: Union[str, int]) -> T:
return x
@overload
def inconsistent(x: T, y: str) -> T: ...
@overload
def inconsistent(x: S, y: int) -> S: ...
def inconsistent(x: T, y: Union[str, int]) -> T:
return x
def test(x: T) -> T:
y: Union[str, int]
reveal_type(consistent(x, y)) # N: Revealed type is "T`-1"
# On one hand, this overload is defined in a weird way; on the other, there's technically nothing wrong with it.
inconsistent(x, y)
return x
[case testOverloadsAndNoneWithoutStrictOptional]
# flags: --no-strict-optional
from typing import overload, Optional
@overload
def f(x: None) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(x: object) -> str: ...
def f(x): ...
# We pretend strict-optional is enabled for overload definitions,
# even in non-strict optional mode
@overload
def g(x: None) -> int: ...
@overload
def g(x: int) -> str: ...
def g(x): ...
# Calls are still checked normally though
a: None
b: int
c: Optional[int]
reveal_type(g(a)) # N: Revealed type is "builtins.int"
reveal_type(g(b)) # N: Revealed type is "builtins.str"
reveal_type(g(c)) # N: Revealed type is "builtins.str"
[case testOverloadsAndNoneWithStrictOptional]
from typing import overload, Optional
@overload
def f(x: None) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(x: object) -> str: ...
def f(x): ...
@overload
def g(x: None) -> int: ...
@overload
def g(x: int) -> str: ...
def g(x): ...
a: None
b: int
c: Optional[int]
reveal_type(g(a)) # N: Revealed type is "builtins.int"
reveal_type(g(b)) # N: Revealed type is "builtins.str"
reveal_type(g(c)) # N: Revealed type is "Union[builtins.str, builtins.int]"
[case testOverloadsNoneAndTypeVarsWithNoStrictOptional]
# flags: --no-strict-optional
from typing import Callable, Iterable, TypeVar, overload, Optional
T = TypeVar('T')
S = TypeVar('S')
@overload
def mymap(func: None, seq: Iterable[T]) -> Iterable[T]: ...
@overload
def mymap(func: Callable[[T], S], seq: Iterable[T]) -> Iterable[S]: ...
def mymap(*args): ...
seq = [1, 2, 3]
f1: Callable[[int], str]
f2: None
f3: Optional[Callable[[int], str]]
reveal_type(mymap(f1, seq)) # N: Revealed type is "typing.Iterable[builtins.str]"
reveal_type(mymap(f2, seq)) # N: Revealed type is "typing.Iterable[builtins.int]"
reveal_type(mymap(f3, seq)) # N: Revealed type is "typing.Iterable[builtins.str]"
[builtins fixtures/list.pyi]
[typing fixtures/typing-medium.pyi]
[case testOverloadsNoneAndTypeVarsWithStrictOptional]
from typing import Callable, Iterable, TypeVar, overload, Optional
T = TypeVar('T')
S = TypeVar('S')
@overload
def mymap(func: None, seq: Iterable[T]) -> Iterable[T]: ...
@overload
def mymap(func: Callable[[T], S], seq: Iterable[T]) -> Iterable[S]: ...
def mymap(*args): ...
seq = [1, 2, 3]
f1: Callable[[int], str]
f2: None
f3: Optional[Callable[[int], str]]
reveal_type(mymap(f1, seq)) # N: Revealed type is "typing.Iterable[builtins.str]"
reveal_type(mymap(f2, seq)) # N: Revealed type is "typing.Iterable[builtins.int]"
reveal_type(mymap(f3, seq)) # N: Revealed type is "Union[typing.Iterable[builtins.str], typing.Iterable[builtins.int]]"
[builtins fixtures/list.pyi]
[typing fixtures/typing-medium.pyi]
[case testOverloadsAndNoReturnNarrowTypeNoStrictOptional1]
# flags: --no-strict-optional
from typing import overload, Union, NoReturn
@overload
def narrow_int(x: str) -> NoReturn: ...
@overload
def narrow_int(x: int) -> int: ...
def narrow_int(x: Union[int, str]) -> Union[int, NoReturn]:
assert isinstance(x, int)
return x
def test_narrow_int() -> None:
a: Union[int, str]
if int():
a = narrow_int(a)
reveal_type(a) # N: Revealed type is "builtins.int"
b: int
if int():
b = narrow_int(b)
reveal_type(b) # N: Revealed type is "builtins.int"
c: str
if int():
c = narrow_int(c)
reveal_type(c) # Note: branch is now dead, so no type is revealed
# TODO: maybe we should make mypy report a warning instead?
[builtins fixtures/isinstance.pyi]
[typing fixtures/typing-medium.pyi]
[case testOverloadsAndNoReturnNarrowTypeWithStrictOptional1]
from typing import overload, Union, NoReturn
@overload
def narrow_int(x: str) -> NoReturn: ...
@overload
def narrow_int(x: int) -> int: ...
def narrow_int(x: Union[int, str]) -> Union[int, NoReturn]:
assert isinstance(x, int)
return x
def test_narrow_int() -> None:
a: Union[int, str]
if int():
a = narrow_int(a)
reveal_type(a) # N: Revealed type is "builtins.int"
b: int
if int():
b = narrow_int(b)
reveal_type(b) # N: Revealed type is "builtins.int"
c: str
if int():
c = narrow_int(c)
reveal_type(c) # Note: branch is now dead, so no type is revealed
# TODO: maybe we should make mypy report a warning instead?
[builtins fixtures/isinstance.pyi]
[typing fixtures/typing-medium.pyi]
[case testOverloadsAndNoReturnNarrowTypeNoStrictOptional2]
# flags: --no-strict-optional
from typing import overload, Union, TypeVar, NoReturn, Optional
T = TypeVar('T')
@overload
def narrow_none(x: None) -> NoReturn: ...
@overload
def narrow_none(x: T) -> T: ...
def narrow_none(x: Optional[T]) -> Union[NoReturn, T]:
assert x is not None
return x
def test_narrow_none() -> None:
a: Optional[int]
if int():
a = narrow_none(a)
reveal_type(a) # N: Revealed type is "builtins.int"
b: int
if int():
b = narrow_none(b)
reveal_type(b) # N: Revealed type is "builtins.int"
c: None
if int():
c = narrow_none(c)
reveal_type(c) # Note: branch is now dead, so no type is revealed
[builtins fixtures/isinstance.pyi]
[typing fixtures/typing-medium.pyi]
[case testOverloadsAndNoReturnNarrowTypeWithStrictOptional2]
from typing import overload, Union, TypeVar, NoReturn, Optional
T = TypeVar('T')
@overload
def narrow_none(x: None) -> NoReturn: ...
@overload
def narrow_none(x: T) -> T: ...
def narrow_none(x: Optional[T]) -> Union[NoReturn, T]:
assert x is not None
return x
def test_narrow_none() -> None:
a: Optional[int]
if int():
a = narrow_none(a)
reveal_type(a) # N: Revealed type is "builtins.int"
b: int
if int():
b = narrow_none(b)
reveal_type(b) # N: Revealed type is "builtins.int"
c: None
if int():
c = narrow_none(c)
reveal_type(c) # Branch is now dead
[builtins fixtures/isinstance.pyi]
[typing fixtures/typing-medium.pyi]
[case testOverloadsAndNoReturnNarrowTypeNoStrictOptional3]
# flags: --no-strict-optional
from typing import overload, TypeVar, NoReturn, Optional
@overload
def narrow_none_v2(x: None) -> NoReturn: ...
@overload
def narrow_none_v2(x: T) -> T: ...
def narrow_none_v2(x: Optional[T]) -> T:
assert x is not None
return x
def test_narrow_none_v2() -> None:
a: Optional[int]
if int():
a = narrow_none_v2(a)
reveal_type(a) # N: Revealed type is "builtins.int"
b: int
if int():
b = narrow_none_v2(b)
reveal_type(b) # N: Revealed type is "builtins.int"
c: None
if int():
c = narrow_none_v2(c)
reveal_type(c) # Note: branch is now dead, so no type is revealed
[builtins fixtures/isinstance.pyi]
[typing fixtures/typing-medium.pyi]
[case testOverloadsAndNoReturnNarrowTypeWithStrictOptional3]
from typing import overload, TypeVar, NoReturn, Optional
@overload
def narrow_none_v2(x: None) -> NoReturn: ...
@overload
def narrow_none_v2(x: T) -> T: ...
def narrow_none_v2(x: Optional[T]) -> T:
assert x is not None
return x
def test_narrow_none_v2() -> None:
a: Optional[int]
if int():
a = narrow_none_v2(a)
reveal_type(a) # N: Revealed type is "builtins.int"
b: int
if int():
b = narrow_none_v2(b)
reveal_type(b) # N: Revealed type is "builtins.int"
c: None
if int():
c = narrow_none_v2(c)
reveal_type(c) # Note: branch is now dead, so no type is revealed
[builtins fixtures/isinstance.pyi]
[typing fixtures/typing-medium.pyi]
[case testOverloadsAndNoReturnNarrowWhenBlacklistingSubtype]
from typing import TypeVar, NoReturn, Union, overload
class Parent: ...
class A(Parent): ...
class B(Parent): ...
T = TypeVar('T', bound=Parent)
@overload
def narrow_to_not_a(x: A) -> NoReturn: ...
@overload
def narrow_to_not_a(x: T) -> T: ...
def narrow_to_not_a(x: T) -> Union[NoReturn, T]:
assert not isinstance(x, A)
return x
def test() -> None:
val: Union[A, B]
if int():
val = narrow_to_not_a(val)
reveal_type(val) # N: Revealed type is "__main__.B"
val2: A
if int():
val2 = narrow_to_not_a(val2)
reveal_type(val2) # Branch now dead
[builtins fixtures/isinstance.pyi]
[typing fixtures/typing-medium.pyi]
[case testOverloadsAndNoReturnNarrowWhenBlacklistingSubtype2]
from typing import TypeVar, NoReturn, Union, overload
class Parent: ...
class A(Parent): ...
class B(Parent): ...
T = TypeVar('T', bound=Parent)
@overload
def narrow_to_not_a_v2(x: A) -> NoReturn: ...
@overload
def narrow_to_not_a_v2(x: T) -> T: ...
def narrow_to_not_a_v2(x: T) -> T:
assert not isinstance(x, A)
return x
def test_v2(val: Union[A, B], val2: A) -> None:
if int():
val = narrow_to_not_a_v2(val)
reveal_type(val) # N: Revealed type is "__main__.B"
if int():
val2 = narrow_to_not_a_v2(val2)
reveal_type(val2) # Branch now dead
[builtins fixtures/isinstance.pyi]
[typing fixtures/typing-medium.pyi]
[case testOverloadWithNonGenericDescriptor]
from typing import overload, Any, Optional, Union
class NumberAttribute:
@overload
def __get__(self, instance: None, owner: Any) -> 'NumberAttribute': ...
@overload
def __get__(self, instance: object, owner: Any) -> int: ...
def __get__(self, instance: Optional[object], owner: Any) -> Union['NumberAttribute', int]:
if instance is None:
return self
else:
return 3
def foo(self) -> str: ...
class MyModel:
my_number = NumberAttribute()
reveal_type(MyModel().my_number) # N: Revealed type is "builtins.int"
MyModel().my_number.foo() # E: "int" has no attribute "foo"
reveal_type(MyModel.my_number) # N: Revealed type is "__main__.NumberAttribute"
reveal_type(MyModel.my_number.foo()) # N: Revealed type is "builtins.str"
[builtins fixtures/isinstance.pyi]
[typing fixtures/typing-medium.pyi]
[case testOverloadWithNonGenericDescriptorLookalike]
from typing import overload, Any, Optional, Union
class FakeAttribute:
@overload
def dummy(self, instance: None, owner: Any) -> 'FakeAttribute': ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def dummy(self, instance: object, owner: Any) -> int: ...
def dummy(self, instance: Optional[object], owner: Any) -> Union['FakeAttribute', int]: ...
[case testOverloadWithGenericDescriptor]
from typing import overload, Any, Optional, TypeVar, Type, Union, Generic
T = TypeVar('T')
class NumberAttribute(Generic[T]):
@overload
def __get__(self, instance: None, owner: Type[T]) -> 'NumberAttribute[T]': ...
@overload
def __get__(self, instance: T, owner: Type[T]) -> int: ...
def __get__(self, instance: Optional[T], owner: Type[T]) -> Union['NumberAttribute[T]', int]:
if instance is None:
return self
else:
return 3
def foo(self) -> str: ...
class MyModel:
my_number = NumberAttribute[MyModel]()
reveal_type(MyModel().my_number) # N: Revealed type is "builtins.int"
MyModel().my_number.foo() # E: "int" has no attribute "foo"
reveal_type(MyModel.my_number) # N: Revealed type is "__main__.NumberAttribute[__main__.MyModel]"
reveal_type(MyModel.my_number.foo()) # N: Revealed type is "builtins.str"
reveal_type(NumberAttribute[MyModel]().__get__(None, MyModel)) # N: Revealed type is "__main__.NumberAttribute[__main__.MyModel]"
reveal_type(NumberAttribute[str]().__get__(None, str)) # N: Revealed type is "__main__.NumberAttribute[builtins.str]"
[builtins fixtures/isinstance.pyi]
[typing fixtures/typing-medium.pyi]
[case testOverloadWithGenericDescriptorLookalike]
from typing import overload, Any, Optional, TypeVar, Type, Union, Generic
T = TypeVar('T')
class FakeAttribute(Generic[T]):
@overload
def dummy(self, instance: None, owner: Type[T]) -> 'FakeAttribute[T]': ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def dummy(self, instance: T, owner: Type[T]) -> int: ...
def dummy(self, instance: Optional[T], owner: Type[T]) -> Union['FakeAttribute[T]', int]: ...
[case testOverloadWithClassMethods]
from typing import overload
class Wrapper:
@overload
@classmethod
def foo(cls, x: int) -> int: ...
@overload
@classmethod
def foo(cls, x: str) -> str: ...
@classmethod
def foo(cls, x): pass
reveal_type(Wrapper.foo(3)) # N: Revealed type is "builtins.int"
reveal_type(Wrapper.foo("foo")) # N: Revealed type is "builtins.str"
[builtins fixtures/classmethod.pyi]
[case testOverloadWithInconsistentClassMethods]
from typing import overload
class Wrapper1:
@overload # E: Overload does not consistently use the "@classmethod" decorator on all function signatures.
@classmethod
def foo(cls, x: int) -> int: ...
@overload
@classmethod
def foo(cls, x: str) -> str: ...
def foo(cls, x): pass
class Wrapper2:
@overload # E: Overload does not consistently use the "@classmethod" decorator on all function signatures.
@classmethod
def foo(cls, x: int) -> int: ...
@overload
def foo(cls, x: str) -> str: ...
@classmethod
def foo(cls, x): pass
class Wrapper3:
@overload # E: Overload does not consistently use the "@classmethod" decorator on all function signatures.
def foo(cls, x: int) -> int: ...
@overload
def foo(cls, x: str) -> str: ...
@classmethod
def foo(cls, x): pass
[builtins fixtures/classmethod.pyi]
[case testOverloadWithSwappedDecorators]
from typing import overload
class Wrapper1:
@classmethod
@overload
def foo(cls, x: int) -> int: ...
@classmethod
@overload
def foo(cls, x: str) -> str: ...
@classmethod
def foo(cls, x): pass
class Wrapper2:
@classmethod
@overload
def foo(cls, x: int) -> int: ...
@overload
@classmethod
def foo(cls, x: str) -> str: ...
@classmethod
def foo(cls, x): pass
class Wrapper3:
@classmethod # E: Overload does not consistently use the "@classmethod" decorator on all function signatures.
@overload
def foo(cls, x: int) -> int: ...
@overload
def foo(cls, x: str) -> str: ...
def foo(cls, x): pass
reveal_type(Wrapper1.foo(3)) # N: Revealed type is "builtins.int"
reveal_type(Wrapper2.foo(3)) # N: Revealed type is "builtins.int"
[builtins fixtures/classmethod.pyi]
[case testOverloadFaultyClassMethodInheritance]
from typing import overload
class A: pass
class B(A): pass
class C(B): pass
class Parent:
@overload
@classmethod
def foo(cls, x: B) -> int: ...
@overload
@classmethod
def foo(cls, x: str) -> str: ...
@classmethod
def foo(cls, x): pass
class BadChild(Parent):
@overload # Fail
@classmethod
def foo(cls, x: C) -> int: ...
@overload
@classmethod
def foo(cls, x: str) -> str: ...
@classmethod
def foo(cls, x): pass
class GoodChild(Parent):
@overload
@classmethod
def foo(cls, x: A) -> int: ...
@overload
@classmethod
def foo(cls, x: str) -> str: ...
@classmethod
def foo(cls, x): pass
[builtins fixtures/classmethod.pyi]
[out]
main:20: error: Signature of "foo" incompatible with supertype "Parent"
main:20: note: Superclass:
main:20: note: @overload
main:20: note: @classmethod
main:20: note: def foo(cls, x: B) -> int
main:20: note: @overload
main:20: note: @classmethod
main:20: note: def foo(cls, x: str) -> str
main:20: note: Subclass:
main:20: note: @overload
main:20: note: @classmethod
main:20: note: def foo(cls, x: C) -> int
main:20: note: @overload
main:20: note: @classmethod
main:20: note: def foo(cls, x: str) -> str
[case testOverloadClassMethodMixingInheritance]
from typing import overload
class BadParent:
@overload
@classmethod
def foo(cls, x: int) -> int: ...
@overload
@classmethod
def foo(cls, x: str) -> str: ...
@classmethod
def foo(cls, x): pass
class BadChild(BadParent):
@overload # Fail
def foo(cls, x: int) -> int: ...
@overload
def foo(cls, x: str) -> str: ...
def foo(cls, x): pass
class GoodParent:
@overload
def foo(cls, x: int) -> int: ...
@overload
def foo(cls, x: str) -> str: ...
def foo(cls, x): pass
class GoodChild(GoodParent):
@overload
@classmethod
def foo(cls, x: int) -> int: ...
@overload
@classmethod
def foo(cls, x: str) -> str: ...
@classmethod
def foo(cls, x): pass
[builtins fixtures/classmethod.pyi]
[out]
main:16: error: Signature of "foo" incompatible with supertype "BadParent"
main:16: note: Superclass:
main:16: note: @overload
main:16: note: @classmethod
main:16: note: def foo(cls, x: int) -> int
main:16: note: @overload
main:16: note: @classmethod
main:16: note: def foo(cls, x: str) -> str
main:16: note: Subclass:
main:16: note: @overload
main:16: note: def foo(cls, x: int) -> int
main:16: note: @overload
main:16: note: def foo(cls, x: str) -> str
[case testOverloadClassMethodImplementation]
from typing import overload, Union
class Wrapper:
@classmethod
def other(cls) -> str:
return "..."
@overload
@classmethod
def foo(cls, x: int) -> int: ...
@overload
@classmethod
def foo(cls, x: str) -> str: ...
@classmethod # E: Overloaded function implementation cannot produce return type of signature 1
def foo(cls, x: Union[int, str]) -> str:
reveal_type(cls) # N: Revealed type is "Type[__main__.Wrapper]"
reveal_type(cls.other()) # N: Revealed type is "builtins.str"
return "..."
[builtins fixtures/classmethod.pyi]
[case testOverloadWithStaticMethods]
from typing import overload
class Wrapper:
@overload
@staticmethod
def foo(x: int) -> int: ...
@overload
@staticmethod
def foo(x: str) -> str: ...
@staticmethod
def foo(x): pass
reveal_type(Wrapper.foo(3)) # N: Revealed type is "builtins.int"
reveal_type(Wrapper.foo("foo")) # N: Revealed type is "builtins.str"
[builtins fixtures/staticmethod.pyi]
[case testOverloadWithInconsistentStaticMethods]
from typing import overload, Union
class Wrapper1:
@overload # E: Overload does not consistently use the "@staticmethod" decorator on all function signatures.
@staticmethod
def foo(x: int) -> int: ...
@overload
@staticmethod
def foo(x: str) -> str: ...
def foo(x): pass
class Wrapper2:
@overload # E: Overload does not consistently use the "@staticmethod" decorator on all function signatures.
@staticmethod
def foo(x: int) -> int: ...
@overload
def foo(x: str) -> str: ... # E: Self argument missing for a non-static method (or an invalid type for self)
@staticmethod
def foo(x): pass
class Wrapper3:
@overload # E: Overload does not consistently use the "@staticmethod" decorator on all function signatures.
@staticmethod
def foo(x: int) -> int: ...
@overload
@staticmethod
def foo(x: str) -> str: ...
def foo(x: Union[int, str]): pass # E: Self argument missing for a non-static method (or an invalid type for self)
[builtins fixtures/staticmethod.pyi]
[case testOverloadWithSwappedDecorators2]
from typing import overload
class Wrapper1:
@staticmethod
@overload
def foo(x: int) -> int: ...
@staticmethod
@overload
def foo(x: str) -> str: ...
@staticmethod
def foo(x): pass
class Wrapper2:
@staticmethod
@overload
def foo(x: int) -> int: ...
@overload
@staticmethod
def foo(x: str) -> str: ...
@staticmethod
def foo(x): pass
class Wrapper3:
@staticmethod # E: Overload does not consistently use the "@staticmethod" decorator on all function signatures.
@overload
def foo(x: int) -> int: ...
@overload
def foo(x: str) -> str: ... # E: Self argument missing for a non-static method (or an invalid type for self)
@staticmethod
def foo(x): pass
reveal_type(Wrapper1.foo(3)) # N: Revealed type is "builtins.int"
reveal_type(Wrapper2.foo(3)) # N: Revealed type is "builtins.int"
[builtins fixtures/staticmethod.pyi]
[case testOverloadFaultyStaticMethodInheritance]
from typing import overload
class A: pass
class B(A): pass
class C(B): pass
class Parent:
@overload
@staticmethod
def foo(x: B) -> int: ...
@overload
@staticmethod
def foo(x: str) -> str: ...
@staticmethod
def foo(x): pass
class BadChild(Parent):
@overload # Fail
@staticmethod
def foo(x: C) -> int: ...
@overload
@staticmethod
def foo(x: str) -> str: ...
@staticmethod
def foo(x): pass
class GoodChild(Parent):
@overload
@staticmethod
def foo(x: A) -> int: ...
@overload
@staticmethod
def foo(x: str) -> str: ...
@staticmethod
def foo(x): pass
[builtins fixtures/staticmethod.pyi]
[out]
main:20: error: Signature of "foo" incompatible with supertype "Parent"
main:20: note: Superclass:
main:20: note: @overload
main:20: note: @staticmethod
main:20: note: def foo(x: B) -> int
main:20: note: @overload
main:20: note: @staticmethod
main:20: note: def foo(x: str) -> str
main:20: note: Subclass:
main:20: note: @overload
main:20: note: @staticmethod
main:20: note: def foo(x: C) -> int
main:20: note: @overload
main:20: note: @staticmethod
main:20: note: def foo(x: str) -> str
[case testOverloadStaticMethodMixingInheritance]
from typing import overload
class BadParent:
@overload
@staticmethod
def foo(x: int) -> int: ...
@overload
@staticmethod
def foo(x: str) -> str: ...
@staticmethod
def foo(x): pass
class BadChild(BadParent):
@overload # Fail
def foo(self, x: int) -> int: ...
@overload
def foo(self, x: str) -> str: ...
def foo(self, x): pass
class GoodParent:
@overload
def foo(self, x: int) -> int: ...
@overload
def foo(self, x: str) -> str: ...
def foo(self, x): pass
class GoodChild(GoodParent):
@overload
@staticmethod
def foo(x: int) -> int: ...
@overload
@staticmethod
def foo(x: str) -> str: ...
@staticmethod
def foo(x): pass
[builtins fixtures/staticmethod.pyi]
[out]
main:16: error: Signature of "foo" incompatible with supertype "BadParent"
main:16: note: Superclass:
main:16: note: @overload
main:16: note: @staticmethod
main:16: note: def foo(x: int) -> int
main:16: note: @overload
main:16: note: @staticmethod
main:16: note: def foo(x: str) -> str
main:16: note: Subclass:
main:16: note: @overload
main:16: note: def foo(self, x: int) -> int
main:16: note: @overload
main:16: note: def foo(self, x: str) -> str
[case testOverloadStaticMethodImplementation]
from typing import overload, Union
class Wrapper:
@staticmethod
def other() -> str:
return "..."
@overload
@staticmethod
def foo(x: int) -> int: ...
@overload
@staticmethod
def foo(x: str) -> str: ...
@staticmethod # E: Overloaded function implementation cannot produce return type of signature 1
def foo(x: Union[int, str]) -> str:
return 3 # E: Incompatible return value type (got "int", expected "str")
[builtins fixtures/staticmethod.pyi]
[case testUnionMathOverloadingReturnsBestType]
from typing import Union, overload
@overload
def f(x: Union[int, str]) -> int: ...
@overload
def f(x: object) -> object: ...
def f(x):
pass
x: Union[int, str]
reveal_type(f(x)) # N: Revealed type is "builtins.int"
[out]
[case testOverloadAndSelfTypes]
from typing import overload, Union, TypeVar, Type
T = TypeVar('T', bound='Parent')
class Parent:
@overload
def foo(self: T, x: int) -> T: pass
@overload
def foo(self, x: str) -> str: pass
def foo(self: T, x: Union[int, str]) -> Union[T, str]:
reveal_type(self.bar()) # N: Revealed type is "builtins.str"
return self
def bar(self) -> str: pass
class Child(Parent):
def child_only(self) -> int: pass
x: Union[int, str]
reveal_type(Parent().foo(3)) # N: Revealed type is "__main__.Parent"
reveal_type(Child().foo(3)) # N: Revealed type is "__main__.Child"
reveal_type(Child().foo("...")) # N: Revealed type is "builtins.str"
reveal_type(Child().foo(x)) # N: Revealed type is "Union[__main__.Child, builtins.str]"
reveal_type(Child().foo(3).child_only()) # N: Revealed type is "builtins.int"
[case testOverloadAndClassTypes]
from typing import overload, Union, TypeVar, Type
T = TypeVar('T', bound='Parent')
class Parent:
@overload
@classmethod
def foo(cls: Type[T], x: int) -> Type[T]: pass
@overload
@classmethod
def foo(cls, x: str) -> str: pass
@classmethod
def foo(cls: Type[T], x: Union[int, str]) -> Union[Type[T], str]:
reveal_type(cls.bar()) # N: Revealed type is "builtins.str"
return cls
@classmethod
def bar(cls) -> str: pass
class Child(Parent):
def child_only(self) -> int: pass
x: Union[int, str]
reveal_type(Parent.foo(3)) # N: Revealed type is "Type[__main__.Parent]"
reveal_type(Child.foo(3)) # N: Revealed type is "Type[__main__.Child]"
reveal_type(Child.foo("...")) # N: Revealed type is "builtins.str"
reveal_type(Child.foo(x)) # N: Revealed type is "Union[Type[__main__.Child], builtins.str]"
reveal_type(Child.foo(3)().child_only()) # N: Revealed type is "builtins.int"
[builtins fixtures/classmethod.pyi]
[case testOptionalIsNotAUnionIfNoStrictOverload]
# flags: --no-strict-optional
from typing import Optional, overload
class B: pass
class C(B): pass
@overload
def rp(x: C) -> C: ...
@overload
def rp(x: B) -> B: ...
def rp(x):
pass
x: Optional[C]
reveal_type(rp(x)) # N: Revealed type is "__main__.C"
[out]
[case testUnionMathTrickyOverload1]
from typing import Union, overload
@overload
def f(x: int, y: int) -> int: ...
@overload
def f(x: object, y: str) -> str: ...
def f(x):
pass
x: Union[int, str]
y: Union[int, str]
f(x, y)
[out]
main:12: error: Argument 1 to "f" has incompatible type "Union[int, str]"; expected "int"
main:12: error: Argument 2 to "f" has incompatible type "Union[int, str]"; expected "int"
[case testUnionMathTrickyOverload2]
from typing import overload, Union, Any
class C:
def f(self, other: C) -> C: ...
class D(C):
@overload
def f(self, other: D) -> D: ...
@overload
def f(self, other: C) -> C: ...
def f(self, other): ...
x: D
y: Union[D, Any]
reveal_type(x.f(y)) # N: Revealed type is "Union[__main__.D, Any]"
[out]
[case testManyUnionsInOverload]
from typing import overload, TypeVar, Union
T = TypeVar('T')
@overload
def f(x: int, y: object, z: object, t: object, u: object, w: object, v: object, s: object) -> int: ...
@overload
def f(x: str, y: object, z: object, t: object, u: object, w: object, v: object, s: object) -> str: ...
@overload
def f(x: T, y: object, z: object, t: object, u: object, w: object, v: object, s: object) -> T: ...
def f(*args, **kwargs):
pass
class A: pass
class B: pass
x: Union[int, str, A, B]
y = f(x, x, x, x, x, x, x, x) # 8 args
reveal_type(y) # N: Revealed type is "Union[builtins.int, builtins.str, __main__.A, __main__.B]"
[builtins fixtures/dict.pyi]
[out]
[case testOverloadsWithNoneComingSecondAreAlwaysFlaggedInNoStrictOptional]
# flags: --no-strict-optional
from typing import overload
@overload
def none_first(x: None) -> None: ...
@overload
def none_first(x: int) -> int: ...
def none_first(x: int) -> int:
return x
@overload
def none_second(x: int) -> int: ...
@overload
def none_second(x: None) -> None: ... # E: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader
def none_second(x: int) -> int:
return x
[case testOverloadsWithNoneComingSecondIsOkInStrictOptional]
from typing import overload, Optional
@overload
def none_first(x: None) -> None: ...
@overload
def none_first(x: int) -> int: ...
def none_first(x: Optional[int]) -> Optional[int]:
return x
@overload
def none_second(x: int) -> int: ...
@overload
def none_second(x: None) -> None: ...
def none_second(x: Optional[int]) -> Optional[int]:
return x
@overload
def none_loose_impl(x: None) -> None: ...
@overload
def none_loose_impl(x: int) -> int: ...
def none_loose_impl(x: int) -> int:
return x
[out]
main:21: error: Overloaded function implementation does not accept all possible arguments of signature 1
main:21: error: Overloaded function implementation cannot produce return type of signature 1
[case testTooManyUnionsException]
from typing import overload, Union
@overload
def f(*args: int) -> int: ...
@overload
def f(*args: str) -> str: ...
def f(*args):
pass
x: Union[int, str]
f(x, x, x, x, x, x, x, x)
[builtins fixtures/tuple.pyi]
[out]
main:11: error: Not all union combinations were tried because there are too many unions
main:11: error: Argument 1 to "f" has incompatible type "Union[int, str]"; expected "int"
main:11: error: Argument 2 to "f" has incompatible type "Union[int, str]"; expected "int"
main:11: error: Argument 3 to "f" has incompatible type "Union[int, str]"; expected "int"
main:11: error: Argument 4 to "f" has incompatible type "Union[int, str]"; expected "int"
main:11: error: Argument 5 to "f" has incompatible type "Union[int, str]"; expected "int"
main:11: error: Argument 6 to "f" has incompatible type "Union[int, str]"; expected "int"
main:11: error: Argument 7 to "f" has incompatible type "Union[int, str]"; expected "int"
main:11: error: Argument 8 to "f" has incompatible type "Union[int, str]"; expected "int"
[case testSafeDunderOverlapInSubclass]
from typing import overload
class A:
def __add__(self, x : 'A') -> 'A': ...
class B(A):
@overload
def __add__(self, x : 'B') -> 'B': ...
@overload
def __add__(self, x : 'A') -> 'A' : ...
def __add__(self, x):
pass
[out]
[case testUnsafeDunderOverlapInSubclass]
from typing import overload
class A:
def __add__(self, x : 'A') -> 'A':
if isinstance(x, A):
return A()
else:
return NotImplemented
# This is unsafe override because of the problem below
class B(A):
@overload # Fail
def __add__(self, x : 'Other') -> 'B' : ...
@overload
def __add__(self, x : 'A') -> 'A': ...
def __add__(self, x):
if isinstance(x, Other):
return B()
elif isinstance(x, A):
return A()
else:
return NotImplemented
class Other:
def __radd__(self, x: 'A') -> 'Other':
if isinstance(x, A):
return Other()
else:
return NotImplemented
actually_b: A = B()
reveal_type(actually_b + Other()) # Note
# Runtime type is B, this is why we report the error on overriding.
[builtins fixtures/isinstance.pyi]
[out]
main:12: error: Signature of "__add__" incompatible with supertype "A"
main:12: note: Superclass:
main:12: note: def __add__(self, A, /) -> A
main:12: note: Subclass:
main:12: note: @overload
main:12: note: def __add__(self, Other, /) -> B
main:12: note: @overload
main:12: note: def __add__(self, A, /) -> A
main:12: note: Overloaded operator methods can't have wider argument types in overrides
main:32: note: Revealed type is "__main__.Other"
[case testOverloadErrorMessageManyMatches]
from typing import overload
class A: pass
class B: pass
class C: pass
class D: pass
@overload
def f(x: A) -> None: ...
@overload
def f(x: B) -> None: ...
@overload
def f(x: C) -> None: ...
@overload
def f(x: D) -> None: ...
@overload
def f(x: int, y: int) -> None: ...
def f(*args): pass
f(3) # E: No overload variant of "f" matches argument type "int" \
# N: Possible overload variants: \
# N: def f(x: A) -> None \
# N: def f(x: B) -> None \
# N: def f(x: C) -> None \
# N: def f(x: D) -> None \
# N: def f(x: int, y: int) -> None
@overload
def g(x: A) -> None: ...
@overload
def g(x: B) -> None: ...
@overload
def g(x: C) -> None: ...
def g(*args): pass
g(3) # E: No overload variant of "g" matches argument type "int" \
# N: Possible overload variants: \
# N: def g(x: A) -> None \
# N: def g(x: B) -> None \
# N: def g(x: C) -> None
[builtins fixtures/tuple.pyi]
[case testOverloadedInIter]
from lib import f, g
for fun in [f, g]:
reveal_type(fun) # N: Revealed type is "Overload(def (x: builtins.int) -> builtins.str, def (x: builtins.str) -> builtins.int)"
[file lib.pyi]
from typing import overload
@overload
def f(x: int) -> str: ...
@overload
def f(x: str) -> int: ...
@overload
def g(x: int) -> str: ...
@overload
def g(x: str) -> int: ...
[builtins fixtures/list.pyi]
[typing fixtures/typing-medium.pyi]
[out]
[case testNestedOverloadsNoCrash]
from typing import overload
def f() -> None:
@overload
def g(x: str) -> str: ...
@overload
def g(x: int) -> int: ...
def g(x):
pass
g(str())
[out]
[case testNestedOverloadsTypeVar]
from typing import overload, TypeVar
T = TypeVar('T')
def f() -> None:
@overload
def g(x: str) -> str: ...
@overload
def g(x: T, y: int) -> T: ...
def g(x):
pass
g(str(), str()) # E: No overload variant of "g" matches argument types "str", "str" \
# N: Possible overload variants: \
# N: def g(x: str) -> str \
# N: def [T] g(x: T, y: int) -> T
reveal_type(g(str(), int())) # N: Revealed type is "builtins.str"
[out]
[case testNestedOverloadsTypeVarOverlap]
from typing import overload, TypeVar
T = TypeVar('T')
def f() -> None:
@overload
def g(x: str) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def g(x: T) -> T: ...
def g(x):
pass
[out]
[case testNestedOverloadsMutuallyRecursive]
from typing import overload, TypeVar, Dict, Any
class C: ...
T = TypeVar('T')
def f() -> None:
@overload
def g() -> None: ...
@overload
def g(x: T) -> Dict[int, T]: ...
def g(*args, **kwargs) -> Any:
reveal_type(h(C())) # N: Revealed type is "builtins.dict[builtins.str, __main__.C]"
@overload
def h() -> None: ...
@overload
def h(x: T) -> Dict[str, T]: ...
def h(*args, **kwargs) -> Any:
reveal_type(g(C())) # N: Revealed type is "builtins.dict[builtins.int, __main__.C]"
[builtins fixtures/dict.pyi]
[out]
[case testOverloadConstrainedTypevarNotShadowingAny]
from lib import attr
from typing import Any
reveal_type(attr(1)) # N: Revealed type is "builtins.int"
reveal_type(attr("hi")) # N: Revealed type is "builtins.int"
x: Any
reveal_type(attr(x)) # N: Revealed type is "Any"
attr("hi", 1) # E: No overload variant of "attr" matches argument types "str", "int" \
# N: Possible overload variants: \
# N: def [T in (int, float)] attr(default: T = ..., blah: int = ...) -> T \
# N: def attr(default: Any = ...) -> int
[file lib.pyi]
from typing import overload, Any, TypeVar
T = TypeVar('T', int, float)
@overload
def attr(default: T = ..., blah: int = ...) -> T: ...
@overload
def attr(default: Any = ...) -> int: ...
[out]
[case testOverloadBoundedTypevarNotShadowingAny]
from lib import attr
from typing import Any
reveal_type(attr(1)) # N: Revealed type is "builtins.int"
reveal_type(attr("hi")) # N: Revealed type is "builtins.int"
x: Any
reveal_type(attr(x)) # N: Revealed type is "Any"
attr("hi", 1) # E: No overload variant of "attr" matches argument types "str", "int" \
# N: Possible overload variants: \
# N: def [T <: int] attr(default: T = ..., blah: int = ...) -> T \
# N: def attr(default: Any = ...) -> int
[file lib.pyi]
from typing import overload, TypeVar, Any
T = TypeVar('T', bound=int)
@overload
def attr(default: T = ..., blah: int = ...) -> T: ...
@overload
def attr(default: Any = ...) -> int: ...
[out]
[case testAnyIsOKAsFallbackInOverloads]
import stub
[file stub.pyi]
from typing import TypeVar, Any, overload
T = TypeVar('T')
@overload
def foo(x: T) -> T: ...
@overload
def foo(x: Any) -> Any: ...
@overload
def bar(x: T) -> T: ...
@overload
def bar(x: Any) -> int: ...
[out]
[case testOverloadsIgnorePromotions]
from typing import overload, List, Union, _promote
class Parent: pass
class Child(Parent): pass
children: List[Child]
parents: List[Parent]
@overload
def f(x: Child) -> List[Child]: pass # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(x: Parent) -> List[Parent]: pass
def f(x: Union[Child, Parent]) -> Union[List[Child], List[Parent]]:
if isinstance(x, Child):
reveal_type(x) # N: Revealed type is "__main__.Child"
return children
else:
reveal_type(x) # N: Revealed type is "__main__.Parent"
return parents
ints: List[int]
floats: List[float]
@overload
def g(x: int) -> List[int]: pass
@overload
def g(x: float) -> List[float]: pass
def g(x: Union[int, float]) -> Union[List[int], List[float]]:
if isinstance(x, int):
reveal_type(x) # N: Revealed type is "builtins.int"
return ints
else:
reveal_type(x) # N: Revealed type is "builtins.float"
return floats
[builtins fixtures/isinstancelist.pyi]
[typing fixtures/typing-medium.pyi]
[case testOverloadsTypesAndUnions]
from typing import overload, Type, Union
class A: pass
class B: pass
@overload
def f(x: Type[A]) -> int: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f(x: Union[Type[A], Type[B]]) -> str: ...
def f(x: Union[Type[A], Type[B]]) -> Union[int, str]:
return 1
[case testBadOverloadProbableMatch]
from typing import overload, List, Type
class Other: pass
@overload
def multiple_plausible(x: int) -> int: ...
@overload
def multiple_plausible(x: str) -> str: ...
def multiple_plausible(x): pass
@overload
def single_plausible(x: Type[int]) -> int: ...
@overload
def single_plausible(x: List[str]) -> str: ...
def single_plausible(x): pass
a = multiple_plausible(Other()) # E: No overload variant of "multiple_plausible" matches argument type "Other" \
# N: Possible overload variants: \
# N: def multiple_plausible(x: int) -> int \
# N: def multiple_plausible(x: str) -> str
reveal_type(a) # N: Revealed type is "Any"
b = single_plausible(Other) # E: Argument 1 to "single_plausible" has incompatible type "Type[Other]"; expected "Type[int]"
reveal_type(b) # N: Revealed type is "builtins.int"
c = single_plausible([Other()]) # E: List item 0 has incompatible type "Other"; expected "str"
reveal_type(c) # N: Revealed type is "builtins.str"
[builtins fixtures/list.pyi]
[case testDisallowUntypedDecoratorsOverload]
# flags: --disallow-untyped-decorators
from typing import Any, Callable, overload, TypeVar
F = TypeVar('F', bound=Callable[..., Any])
@overload
def dec(x: F) -> F: ...
@overload
def dec(x: str) -> Callable[[F], F]: ...
def dec(x) -> Any:
pass
@dec
def f(name: str) -> int:
return 0
@dec('abc')
def g(name: str) -> int:
return 0
reveal_type(f) # N: Revealed type is "def (name: builtins.str) -> builtins.int"
reveal_type(g) # N: Revealed type is "def (name: builtins.str) -> builtins.int"
[case testDisallowUntypedDecoratorsOverloadDunderCall]
# flags: --disallow-untyped-decorators
from typing import Any, Callable, overload, TypeVar
F = TypeVar('F', bound=Callable[..., Any])
class Dec:
@overload
def __call__(self, x: F) -> F: ...
@overload
def __call__(self, x: str) -> Callable[[F], F]: ...
def __call__(self, x) -> Any:
pass
dec = Dec()
@dec
def f(name: str) -> int:
return 0
@dec('abc')
def g(name: str) -> int:
return 0
reveal_type(f) # N: Revealed type is "def (name: builtins.str) -> builtins.int"
reveal_type(g) # N: Revealed type is "def (name: builtins.str) -> builtins.int"
[case testOverloadBadArgumentsInferredToAny1]
from typing import Union, Any, overload
def bar(x: int) -> Union[int, Any]: ...
@overload
def foo(x: str) -> None: ...
@overload
def foo(x: int) -> None: ...
def foo(x) -> None: pass
foo(bar('lol')) # E: Argument 1 to "bar" has incompatible type "str"; expected "int"
[case testOverloadBadArgumentsInferredToAny2]
from typing import Union, Iterable, Tuple, TypeVar, Generic, overload, Any
class A:
def foo(self) -> Iterable[int]: pass
def bar(x: int) -> Union[A, int]: ...
_T = TypeVar('_T')
@overload
def foo() -> None: ...
@overload
def foo(iterable: Iterable[_T]) -> None: ...
def foo(iterable = None) -> None: pass
foo(bar('lol').foo()) # E: Item "int" of "Union[A, int]" has no attribute "foo" \
# E: Argument 1 to "bar" has incompatible type "str"; expected "int"
[case testOverloadInferringArgumentsUsingContext1]
from typing import Optional, List, overload, TypeVar
T = TypeVar('T')
def g(x: Optional[T] = None) -> List[T]: ...
@overload
def f(x: int) -> int: ...
@overload
def f(x: List[int]) -> List[int]: ...
def f(x): pass
reveal_type(f(g())) # N: Revealed type is "builtins.list[builtins.int]"
[builtins fixtures/list.pyi]
[case testOverloadInferringArgumentsUsingContext2-skip]
# TODO: Overloads only use outer context to infer type variables in a given overload variant,
# but never use outer context to _choose_ a better overload in ambiguous situations
# like empty containers or multiple inheritance, instead just always choosing the first one.
from typing import Optional, List, overload, TypeVar
T = TypeVar('T')
@overload
def g(x: List[str]) -> List[str]: ...
@overload
def g(x: List[int]) -> List[int]: ...
def g(x):
pass
@overload
def f(x: int) -> int: ...
@overload
def f(x: List[int]) -> List[int]: ...
def f(x):
pass
reveal_type(f(g([]))) # N: Revealed type is "builtins.list[builtins.int]"
[builtins fixtures/list.pyi]
[case testOverloadDeferredNode]
from typing import Callable, TypeVar, Generic, Any, overload
_S = TypeVar('_S')
_T = TypeVar('_T')
_R = TypeVar('_R')
@overload
def partial(__func: Callable[[_T], _S], __arg: _T) -> Callable[[], _S]: ...
@overload
def partial(__func: Callable[[_T, _S], _S], __arg: _T) -> Callable[[_S], _R]: ...
def partial(*args: Any) -> Any:
pass
def f(f: Callable[[int], int]) -> None:
pass
def dec(f: Callable[[_S, _T], _R]) -> Callable[[_S, _T], _R]: pass
def asdf() -> None:
f(partial(lol, 0))
@dec
def lol(x: int, y: int) -> int:
pass
[builtins fixtures/tuple.pyi]
[case testVeryBrokenOverload]
import lib
reveal_type(lib.func)
[file lib.pyi]
@overload
def func(x: int) -> int: ...
def func(x):
return x
[out]
tmp/lib.pyi:1: error: Name "overload" is not defined
tmp/lib.pyi:4: error: Name "func" already defined on line 1
main:2: note: Revealed type is "Any"
-- Order of errors is different
[case testVeryBrokenOverload2]
import lib
reveal_type(lib.func)
[file lib.pyi]
@overload
def func(x: int) -> int: ...
@overload
def func(x: str) -> str: ...
[out]
tmp/lib.pyi:1: error: Name "overload" is not defined
tmp/lib.pyi:3: error: Name "func" already defined on line 1
tmp/lib.pyi:3: error: Name "overload" is not defined
main:3: note: Revealed type is "Any"
[case testLiteralSubtypeOverlap]
from typing import overload
from typing_extensions import Literal
class MyInt(int): ...
# Strictly speaking we can't prove this is unsafe (this depends on the implementation),
# but such APIs seem like an anti-pattern anyways.
@overload
def foo(x: Literal[0]) -> None: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def foo(x: MyInt) -> int: ...
def foo(x):
...
[builtins fixtures/tuple.pyi]
[case testOverloadedToGeneric]
from typing import TypeVar, Callable, NewType, overload, Union
# int in our stubs isn't overloaded
class fakeint:
@overload
def __init__(self, x: Union[str, bytes] = ...) -> None: ...
@overload
def __init__(self, x: Union[str, bytes], base: int) -> None: ...
def __init__(self, *args) -> None: pass # type: ignore
U = TypeVar('U')
V = TypeVar('V')
W = TypeVar('W')
def compose(f: Callable[[U], V], g: Callable[[W], U]) -> Callable[[W], V]:
return lambda x: f(g(x))
ID = NewType("ID", fakeint)
compose(ID, fakeint)("test")
reveal_type(compose(ID, fakeint)) # N: Revealed type is "def (Union[builtins.str, builtins.bytes]) -> __main__.ID"
[builtins fixtures/tuple.pyi]
[case testOverloadTwoTypeArgs]
from typing import Generic, overload, TypeVar, Any
T1 = TypeVar("T1")
T2 = TypeVar("T2")
class A: ...
class B: ...
class G(Generic[T1, T2]): ...
@overload
def f1(g: G[A, A]) -> A: ...
@overload
def f1(g: G[A, B]) -> B: ...
def f1(g: Any) -> Any: ...
@overload
def f2(g: G[A, Any]) -> A: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def f2(g: G[A, B], x: int = ...) -> B: ...
def f2(g: Any, x: int = ...) -> Any: ...
[case testOverloadTypeVsCallable]
from typing import TypeVar, Type, Callable, Any, overload, Optional
class Foo:
def __init__(self, **kwargs: Any): pass
_T = TypeVar('_T')
@overload
def register(cls: Type[_T]) -> int: ...
@overload
def register(cls: Callable[..., _T]) -> Optional[int]: ...
def register(cls: Any) -> Any: return None
x = register(Foo)
reveal_type(x) # N: Revealed type is "builtins.int"
[builtins fixtures/dict.pyi]
[case testOverloadWithObjectDecorator]
from typing import Any, Callable, Union, overload
class A:
def __call__(self, *arg, **kwargs) -> None: ...
def dec_a(f: Callable[..., Any]) -> A:
return A()
@overload
def f_a(arg: int) -> None: ...
@overload
def f_a(arg: str) -> None: ...
@dec_a
def f_a(arg): ...
class B:
def __call__(self, arg: Union[int, str]) -> None: ...
def dec_b(f: Callable[..., Any]) -> B:
return B()
@overload
def f_b(arg: int) -> None: ...
@overload
def f_b(arg: str) -> None: ...
@dec_b
def f_b(arg): ...
class C:
def __call__(self, arg: int) -> None: ...
def dec_c(f: Callable[..., Any]) -> C:
return C()
@overload
def f_c(arg: int) -> None: ...
@overload
def f_c(arg: str) -> None: ...
@dec_c # E: Overloaded function implementation does not accept all possible arguments of signature 2
def f_c(arg): ...
[builtins fixtures/dict.pyi]
[case testOverloadWithErrorDecorator]
from typing import Any, Callable, TypeVar, overload
def dec_d(f: Callable[..., Any]) -> int: ...
@overload
def f_d(arg: int) -> None: ...
@overload
def f_d(arg: str) -> None: ...
@dec_d # E: "int" not callable
def f_d(arg): ...
Bad1 = TypeVar('Good') # type: ignore
def dec_e(f: Bad1) -> Bad1: ... # type: ignore
@overload
def f_e(arg: int) -> None: ...
@overload
def f_e(arg: str) -> None: ...
@dec_e # E: Bad1? not callable
def f_e(arg): ...
class Bad2:
def __getattr__(self, attr):
# __getattr__ is not called for implicit `__call__`
if attr == "__call__":
return lambda *a, **kw: print(a, kw)
raise AttributeError
@overload
def f_f(arg: int) -> None: ...
@overload
def f_f(arg: str) -> None: ...
@Bad2() # E: "Bad2" not callable
def f_f(arg): ...
[builtins fixtures/dict.pyi]
[case testOverloadIfBasic]
# flags: --always-true True --always-false False
from typing import overload
class A: ...
class B: ...
class C: ...
class D: ...
# -----
# Test basic overload merging
# -----
@overload
def f1(g: A) -> A: ...
if True:
@overload
def f1(g: B) -> B: ...
def f1(g): ...
reveal_type(f1(A())) # N: Revealed type is "__main__.A"
reveal_type(f1(B())) # N: Revealed type is "__main__.B"
@overload
def f2(g: A) -> A: ...
@overload
def f2(g: B) -> B: ...
if False:
@overload
def f2(g: C) -> C: ...
def f2(g): ...
reveal_type(f2(A())) # N: Revealed type is "__main__.A"
reveal_type(f2(C())) # E: No overload variant of "f2" matches argument type "C" \
# N: Possible overload variants: \
# N: def f2(g: A) -> A \
# N: def f2(g: B) -> B \
# N: Revealed type is "Any"
@overload
def f3(g: A) -> A: ...
@overload
def f3(g: B) -> B: ...
if maybe_true: # E: Condition can't be inferred, unable to merge overloads \
# E: Name "maybe_true" is not defined
@overload
def f3(g: C) -> C: ...
def f3(g): ...
reveal_type(f3(A())) # N: Revealed type is "__main__.A"
reveal_type(f3(C())) # E: No overload variant of "f3" matches argument type "C" \
# N: Possible overload variants: \
# N: def f3(g: A) -> A \
# N: def f3(g: B) -> B \
# N: Revealed type is "Any"
if True:
@overload
def f4(g: A) -> A: ...
if True:
@overload
def f4(g: B) -> B: ...
@overload
def f4(g: C) -> C: ...
def f4(g): ...
reveal_type(f4(A())) # N: Revealed type is "__main__.A"
reveal_type(f4(B())) # N: Revealed type is "__main__.B"
reveal_type(f4(C())) # N: Revealed type is "__main__.C"
if True:
@overload
def f5(g: A) -> A: ...
@overload
def f5(g: B) -> B: ...
if True:
@overload
def f5(g: C) -> C: ...
@overload
def f5(g: D) -> D: ...
def f5(g): ...
reveal_type(f5(A())) # N: Revealed type is "__main__.A"
reveal_type(f5(B())) # N: Revealed type is "__main__.B"
reveal_type(f5(C())) # N: Revealed type is "__main__.C"
reveal_type(f5(D())) # N: Revealed type is "__main__.D"
[case testOverloadIfSysVersion]
# flags: --python-version 3.9
from typing import overload
import sys
class A: ...
class B: ...
class C: ...
# -----
# "Real" world example
# Test overload merging for sys.version_info
# -----
@overload
def f1(g: A) -> A: ...
if sys.version_info >= (3, 9):
@overload
def f1(g: B) -> B: ...
def f1(g): ...
reveal_type(f1(A())) # N: Revealed type is "__main__.A"
reveal_type(f1(B())) # N: Revealed type is "__main__.B"
@overload
def f2(g: A) -> A: ...
@overload
def f2(g: B) -> B: ...
if sys.version_info >= (3, 10):
@overload
def f2(g: C) -> C: ...
def f2(g): ...
reveal_type(f2(A())) # N: Revealed type is "__main__.A"
reveal_type(f2(C())) # E: No overload variant of "f2" matches argument type "C" \
# N: Possible overload variants: \
# N: def f2(g: A) -> A \
# N: def f2(g: B) -> B \
# N: Revealed type is "Any"
[builtins fixtures/ops.pyi]
[case testOverloadIfMerging]
# flags: --always-true True
from typing import overload
class A: ...
class B: ...
class C: ...
# -----
# Test overload merging
# -----
@overload
def f1(g: A) -> A: ...
if True:
# Some comment
@overload
def f1(g: B) -> B: ...
def f1(g): ...
reveal_type(f1(A())) # N: Revealed type is "__main__.A"
reveal_type(f1(B())) # N: Revealed type is "__main__.B"
@overload
def f2(g: A) -> A: ...
if True:
@overload
def f2(g: bytes) -> B: ...
@overload
def f2(g: B) -> C: ...
def f2(g): ...
reveal_type(f2(A())) # N: Revealed type is "__main__.A"
reveal_type(f2(B())) # N: Revealed type is "__main__.C"
@overload
def f3(g: A) -> A: ...
@overload
def f3(g: B) -> B: ...
if True:
def f3(g): ...
reveal_type(f3(A())) # N: Revealed type is "__main__.A"
reveal_type(f3(B())) # N: Revealed type is "__main__.B"
if True:
@overload
def f4(g: A) -> A: ...
@overload
def f4(g: B) -> B: ...
def f4(g): ...
reveal_type(f4(A())) # N: Revealed type is "__main__.A"
reveal_type(f4(B())) # N: Revealed type is "__main__.B"
if True:
# Some comment
@overload
def f5(g: A) -> A: ...
@overload
def f5(g: B) -> B: ...
def f5(g): ...
reveal_type(f5(A())) # N: Revealed type is "__main__.A"
reveal_type(f5(B())) # N: Revealed type is "__main__.B"
[case testOverloadIfNotMerging]
# flags: --always-true True
from typing import overload
class A: ...
class B: ...
class C: ...
# -----
# Don't merge if IfStmt contains nodes other than overloads
# -----
@overload # E: An overloaded function outside a stub file must have an implementation
def f1(g: A) -> A: ...
@overload
def f1(g: B) -> B: ...
if True:
@overload # E: Name "f1" already defined on line 12 \
# E: Single overload definition, multiple required
def f1(g: C) -> C: ...
pass # Some other action
def f1(g): ... # E: Name "f1" already defined on line 12
reveal_type(f1(A())) # N: Revealed type is "__main__.A"
reveal_type(f1(C())) # E: No overload variant of "f1" matches argument type "C" \
# N: Possible overload variants: \
# N: def f1(g: A) -> A \
# N: def f1(g: B) -> B \
# N: Revealed type is "Any"
if True:
pass # Some other action
@overload # E: Single overload definition, multiple required
def f2(g: A) -> A: ...
@overload # E: Name "f2" already defined on line 26
def f2(g: B) -> B: ...
@overload
def f2(g: C) -> C: ...
def f2(g): ...
reveal_type(f2(A())) # N: Revealed type is "__main__.A"
reveal_type(f2(C())) # N: Revealed type is "__main__.A" \
# E: Argument 1 to "f2" has incompatible type "C"; expected "A"
[case testOverloadIfOldStyle]
# flags: --always-false var_false --always-true var_true
from typing import overload
class A: ...
class B: ...
# -----
# Test old style to make sure it still works
# -----
var_true = True
var_false = False
if var_false:
@overload
def f1(g: A) -> A: ...
@overload
def f1(g: B) -> B: ...
def f1(g): ...
elif var_true:
@overload
def f1(g: A) -> A: ...
@overload
def f1(g: B) -> B: ...
def f1(g): ...
else:
@overload
def f1(g: A) -> A: ...
@overload
def f1(g: B) -> B: ...
def f1(g): ...
reveal_type(f1(A())) # N: Revealed type is "__main__.A"
reveal_type(f1(B())) # N: Revealed type is "__main__.B"
[case testOverloadIfElse]
# flags: --always-true True --always-false False
from typing import overload
class A: ...
class B: ...
class C: ...
class D: ...
# -----
# Match the first always-true block
# -----
@overload
def f1(x: A) -> A: ...
if True:
@overload
def f1(x: B) -> B: ...
elif False:
@overload
def f1(x: C) -> C: ...
else:
@overload
def f1(x: D) -> D: ...
def f1(x): ...
reveal_type(f1(A())) # N: Revealed type is "__main__.A"
reveal_type(f1(B())) # N: Revealed type is "__main__.B"
reveal_type(f1(C())) # E: No overload variant of "f1" matches argument type "C" \
# N: Possible overload variants: \
# N: def f1(x: A) -> A \
# N: def f1(x: B) -> B \
# N: Revealed type is "Any"
@overload
def f2(x: A) -> A: ...
if False:
@overload
def f2(x: B) -> B: ...
elif True:
@overload
def f2(x: C) -> C: ...
else:
@overload
def f2(x: D) -> D: ...
def f2(x): ...
reveal_type(f2(A())) # N: Revealed type is "__main__.A"
reveal_type(f2(B())) # E: No overload variant of "f2" matches argument type "B" \
# N: Possible overload variants: \
# N: def f2(x: A) -> A \
# N: def f2(x: C) -> C \
# N: Revealed type is "Any"
reveal_type(f2(C())) # N: Revealed type is "__main__.C"
@overload
def f3(x: A) -> A: ...
if False:
@overload
def f3(x: B) -> B: ...
elif False:
@overload
def f3(x: C) -> C: ...
else:
@overload
def f3(x: D) -> D: ...
def f3(x): ...
reveal_type(f3(A())) # N: Revealed type is "__main__.A"
reveal_type(f3(C())) # E: No overload variant of "f3" matches argument type "C" \
# N: Possible overload variants: \
# N: def f3(x: A) -> A \
# N: def f3(x: D) -> D \
# N: Revealed type is "Any"
reveal_type(f3(D())) # N: Revealed type is "__main__.D"
[case testOverloadIfElse2]
# flags: --always-true True
from typing import overload
class A: ...
class B: ...
class C: ...
class D: ...
# -----
# Match the first always-true block
# Don't merge overloads if can't be certain about execution of block
# -----
@overload
def f1(x: A) -> A: ...
if True:
@overload
def f1(x: B) -> B: ...
else:
@overload
def f1(x: D) -> D: ...
def f1(x): ...
reveal_type(f1(A())) # N: Revealed type is "__main__.A"
reveal_type(f1(B())) # N: Revealed type is "__main__.B"
reveal_type(f1(D())) # E: No overload variant of "f1" matches argument type "D" \
# N: Possible overload variants: \
# N: def f1(x: A) -> A \
# N: def f1(x: B) -> B \
# N: Revealed type is "Any"
@overload
def f2(x: A) -> A: ...
if True:
@overload
def f2(x: B) -> B: ...
elif maybe_true:
@overload
def f2(x: C) -> C: ...
else:
@overload
def f2(x: D) -> D: ...
def f2(x): ...
reveal_type(f2(A())) # N: Revealed type is "__main__.A"
reveal_type(f2(B())) # N: Revealed type is "__main__.B"
reveal_type(f2(C())) # E: No overload variant of "f2" matches argument type "C" \
# N: Possible overload variants: \
# N: def f2(x: A) -> A \
# N: def f2(x: B) -> B \
# N: Revealed type is "Any"
@overload # E: Single overload definition, multiple required
def f3(x: A) -> A: ...
if maybe_true: # E: Condition can't be inferred, unable to merge overloads \
# E: Name "maybe_true" is not defined
@overload
def f3(x: B) -> B: ...
elif True:
@overload
def f3(x: C) -> C: ...
else:
@overload
def f3(x: D) -> D: ...
def f3(x): ...
reveal_type(f3(A())) # N: Revealed type is "__main__.A"
reveal_type(f3(B())) # E: No overload variant of "f3" matches argument type "B" \
# N: Possible overload variant: \
# N: def f3(x: A) -> A \
# N: Revealed type is "Any"
@overload # E: Single overload definition, multiple required
def f4(x: A) -> A: ...
if maybe_true: # E: Condition can't be inferred, unable to merge overloads \
# E: Name "maybe_true" is not defined
@overload
def f4(x: B) -> B: ...
else:
@overload
def f4(x: D) -> D: ...
def f4(x): ...
reveal_type(f4(A())) # N: Revealed type is "__main__.A"
reveal_type(f4(B())) # E: No overload variant of "f4" matches argument type "B" \
# N: Possible overload variant: \
# N: def f4(x: A) -> A \
# N: Revealed type is "Any"
[case testOverloadIfElse3]
# flags: --always-false False
from typing import overload
class A: ...
class B: ...
class C: ...
class D: ...
class E: ...
# -----
# Match the first always-true block
# Don't merge overloads if can't be certain about execution of block
# -----
@overload
def f1(x: A) -> A: ...
if False:
@overload
def f1(x: B) -> B: ...
else:
@overload
def f1(x: D) -> D: ...
def f1(x): ...
reveal_type(f1(A())) # N: Revealed type is "__main__.A"
reveal_type(f1(B())) # E: No overload variant of "f1" matches argument type "B" \
# N: Possible overload variants: \
# N: def f1(x: A) -> A \
# N: def f1(x: D) -> D \
# N: Revealed type is "Any"
reveal_type(f1(D())) # N: Revealed type is "__main__.D"
@overload # E: Single overload definition, multiple required
def f2(x: A) -> A: ...
if False:
@overload
def f2(x: B) -> B: ...
elif maybe_true: # E: Condition can't be inferred, unable to merge overloads \
# E: Name "maybe_true" is not defined
@overload
def f2(x: C) -> C: ...
else:
@overload
def f2(x: D) -> D: ...
def f2(x): ...
reveal_type(f2(A())) # N: Revealed type is "__main__.A"
reveal_type(f2(C())) # E: No overload variant of "f2" matches argument type "C" \
# N: Possible overload variant: \
# N: def f2(x: A) -> A \
# N: Revealed type is "Any"
@overload # E: Single overload definition, multiple required
def f3(x: A) -> A: ...
if maybe_true: # E: Condition can't be inferred, unable to merge overloads \
# E: Name "maybe_true" is not defined
@overload
def f3(x: B) -> B: ...
elif False:
@overload
def f3(x: C) -> C: ...
else:
@overload
def f3(x: D) -> D: ...
def f3(x): ...
reveal_type(f3(A())) # N: Revealed type is "__main__.A"
reveal_type(f3(B())) # E: No overload variant of "f3" matches argument type "B" \
# N: Possible overload variant: \
# N: def f3(x: A) -> A \
# N: Revealed type is "Any"
def g(bool_var: bool) -> None:
@overload
def f4(x: A) -> A: ...
if bool_var: # E: Condition can't be inferred, unable to merge overloads
@overload
def f4(x: B) -> B: ...
elif maybe_true: # E: Name "maybe_true" is not defined
# No 'Condition cannot be inferred' error here since it's already
# emitted on the first condition, 'bool_var', above.
@overload
def f4(x: C) -> C: ...
else:
@overload
def f4(x: D) -> D: ...
@overload
def f4(x: E) -> E: ...
def f4(x): ...
reveal_type(f4(E())) # N: Revealed type is "__main__.E"
reveal_type(f4(B())) # E: No overload variant of "f4" matches argument type "B" \
# N: Possible overload variants: \
# N: def f4(x: A) -> A \
# N: def f4(x: E) -> E \
# N: Revealed type is "Any"
[case testOverloadIfSkipUnknownExecution]
# flags: --always-true True
from typing import overload
class A: ...
class B: ...
class C: ...
class D: ...
# -----
# If blocks should be skipped if execution can't be certain
# Overload name must match outer name
# -----
@overload # E: Single overload definition, multiple required
def f1(x: A) -> A: ...
if maybe_true: # E: Condition can't be inferred, unable to merge overloads \
# E: Name "maybe_true" is not defined
@overload
def f1(x: B) -> B: ...
def f1(x): ...
reveal_type(f1(A())) # N: Revealed type is "__main__.A"
if maybe_true: # E: Condition can't be inferred, unable to merge overloads \
# E: Name "maybe_true" is not defined
@overload
def f2(x: A) -> A: ...
@overload
def f2(x: B) -> B: ...
@overload
def f2(x: C) -> C: ...
def f2(x): ...
reveal_type(f2(A())) # E: No overload variant of "f2" matches argument type "A" \
# N: Possible overload variants: \
# N: def f2(x: B) -> B \
# N: def f2(x: C) -> C \
# N: Revealed type is "Any"
if True:
@overload # E: Single overload definition, multiple required
def f3(x: A) -> A: ...
if maybe_true: # E: Condition can't be inferred, unable to merge overloads \
# E: Name "maybe_true" is not defined
@overload
def f3(x: B) -> B: ...
def f3(x): ...
reveal_type(f3(A())) # N: Revealed type is "__main__.A"
if True:
if maybe_true: # E: Condition can't be inferred, unable to merge overloads \
# E: Name "maybe_true" is not defined
@overload
def f4(x: A) -> A: ...
@overload
def f4(x: B) -> B: ...
@overload
def f4(x: C) -> C: ...
def f4(x): ...
reveal_type(f4(A())) # E: No overload variant of "f4" matches argument type "A" \
# N: Possible overload variants: \
# N: def f4(x: B) -> B \
# N: def f4(x: C) -> C \
# N: Revealed type is "Any"
[case testOverloadIfDontSkipUnrelatedOverload]
# flags: --always-true True
from typing import overload
class A: ...
class B: ...
class C: ...
class D: ...
# -----
# Don't skip if block if overload name doesn't match outer name
# -----
@overload # E: Single overload definition, multiple required
def f1(x: A) -> A: ...
if maybe_true: # E: Name "maybe_true" is not defined
@overload # E: Single overload definition, multiple required
def g1(x: B) -> B: ...
def f1(x): ... # E: Name "f1" already defined on line 13
reveal_type(f1(A())) # N: Revealed type is "__main__.A"
if maybe_true: # E: Name "maybe_true" is not defined
@overload # E: Single overload definition, multiple required
def g2(x: A) -> A: ...
@overload
def f2(x: B) -> B: ...
@overload
def f2(x: C) -> C: ...
def f2(x): ...
reveal_type(f2(A())) # E: No overload variant of "f2" matches argument type "A" \
# N: Possible overload variants: \
# N: def f2(x: B) -> B \
# N: def f2(x: C) -> C \
# N: Revealed type is "Any"
if True:
@overload # E: Single overload definition, multiple required
def f3(x: A) -> A: ...
def f3(x): ...
if maybe_true: # E: Name "maybe_true" is not defined
@overload # E: Single overload definition, multiple required
def g3(x: B) -> B: ...
reveal_type(f3(A())) # N: Revealed type is "__main__.A"
if True:
if maybe_true: # E: Name "maybe_true" is not defined
@overload # E: Single overload definition, multiple required
def g4(x: A) -> A: ...
@overload
def f4(x: B) -> B: ...
@overload
def f4(x: C) -> C: ...
def f4(x): ...
reveal_type(f4(A())) # E: No overload variant of "f4" matches argument type "A" \
# N: Possible overload variants: \
# N: def f4(x: B) -> B \
# N: def f4(x: C) -> C \
# N: Revealed type is "Any"
[case testOverloadIfNotMergingDifferentNames]
# flags: --always-true True
from typing import overload
class A: ...
class B: ...
class C: ...
class D: ...
# -----
# Don't merge overloads if IfStmts contains overload with different name
# -----
@overload # E: An overloaded function outside a stub file must have an implementation
def f1(x: A) -> A: ...
@overload
def f1(x: B) -> B: ...
if True:
@overload # E: Single overload definition, multiple required
def g1(x: C) -> C: ...
def f1(x): ... # E: Name "f1" already defined on line 13
reveal_type(f1(A())) # N: Revealed type is "__main__.A"
reveal_type(f1(C())) # E: No overload variant of "f1" matches argument type "C" \
# N: Possible overload variants: \
# N: def f1(x: A) -> A \
# N: def f1(x: B) -> B \
# N: Revealed type is "Any"
if True:
@overload # E: Single overload definition, multiple required
def g2(x: A) -> A: ...
@overload
def f2(x: B) -> B: ...
@overload
def f2(x: C) -> C: ...
def f2(x): ...
reveal_type(f2(A())) # E: No overload variant of "f2" matches argument type "A" \
# N: Possible overload variants: \
# N: def f2(x: B) -> B \
# N: def f2(x: C) -> C \
# N: Revealed type is "Any"
reveal_type(f2(B())) # N: Revealed type is "__main__.B"
if True:
if True:
@overload # E: Single overload definition, multiple required
def g3(x: A) -> A: ...
@overload
def f3(x: B) -> B: ...
@overload
def f3(x: C) -> C: ...
def f3(x): ...
reveal_type(f3(A())) # E: No overload variant of "f3" matches argument type "A" \
# N: Possible overload variants: \
# N: def f3(x: B) -> B \
# N: def f3(x: C) -> C \
# N: Revealed type is "Any"
reveal_type(f3(B())) # N: Revealed type is "__main__.B"
[case testOverloadIfSplitFunctionDef]
# flags: --always-true True --always-false False
from typing import overload
class A: ...
class B: ...
class C: ...
class D: ...
# -----
# Test split FuncDefs
# -----
@overload
def f1(x: A) -> A: ...
@overload
def f1(x: B) -> B: ...
if True:
def f1(x): ...
reveal_type(f1(A())) # N: Revealed type is "__main__.A"
@overload
def f2(x: A) -> A: ...
@overload
def f2(x: B) -> B: ...
if False:
def f2(x): ...
else:
def f2(x): ...
reveal_type(f2(A())) # N: Revealed type is "__main__.A"
@overload # E: An overloaded function outside a stub file must have an implementation
def f3(x: A) -> A: ...
@overload
def f3(x: B) -> B: ...
if True:
def f3(x): ... # E: Name "f3" already defined on line 31
else:
pass # some other node
def f3(x): ...
reveal_type(f3(A())) # N: Revealed type is "__main__.A"
[case testOverloadIfMixed]
# flags: --always-true True --always-false False
from typing import overload, TYPE_CHECKING
class A: ...
class B: ...
class C: ...
class D: ...
if maybe_var: # E: Name "maybe_var" is not defined
pass
if True:
@overload
def f1(x: A) -> A: ...
@overload
def f1(x: B) -> B: ...
def f1(x): ...
reveal_type(f1(A())) # N: Revealed type is "__main__.A"
reveal_type(f1(B())) # N: Revealed type is "__main__.B"
if True:
@overload
def f2(x: A) -> A: ...
@overload
def f2(x: B) -> B: ...
def f2(x): ...
reveal_type(f2(A())) # N: Revealed type is "__main__.A"
reveal_type(f2(B())) # N: Revealed type is "__main__.B"
if True:
@overload
def f3(x: A) -> A: ...
@overload
def f3(x: B) -> B: ...
def f3(x): ...
reveal_type(f3(A())) # N: Revealed type is "__main__.A"
reveal_type(f3(B())) # N: Revealed type is "__main__.B"
# Don't crash with AssignmentStmt if elif
@overload # E: Single overload definition, multiple required
def f4(x: A) -> A: ...
if False:
@overload
def f4(x: B) -> B: ...
elif True:
var = 1
def f4(x): ... # E: Name "f4" already defined on line 39
if TYPE_CHECKING:
@overload
def f5(x: A) -> A: ...
@overload
def f5(x: B) -> B: ...
def f5(x): ...
reveal_type(f5(A())) # N: Revealed type is "__main__.A"
reveal_type(f5(B())) # N: Revealed type is "__main__.B"
# Test from check-functions - testUnconditionalRedefinitionOfConditionalFunction
# Don't merge If blocks if they appear before any overloads
# and don't contain any overloads themselves.
if maybe_true: # E: Name "maybe_true" is not defined
def f6(x): ...
def f6(x): ... # E: Name "f6" already defined on line 61
if maybe_true: # E: Name "maybe_true" is not defined
pass # Some other node
def f7(x): ...
def f7(x): ... # E: Name "f7" already defined on line 66
@overload
def f8(x: A) -> A: ...
@overload
def f8(x: B) -> B: ...
if False:
def f8(x: C) -> C: ...
def f8(x): ...
reveal_type(f8(A())) # N: Revealed type is "__main__.A"
reveal_type(f8(C())) # E: No overload variant of "f8" matches argument type "C" \
# N: Possible overload variants: \
# N: def f8(x: A) -> A \
# N: def f8(x: B) -> B \
# N: Revealed type is "Any"
if maybe_true: # E: Condition can't be inferred, unable to merge overloads \
# E: Name "maybe_true" is not defined
@overload
def f9(x: A) -> A: ...
if another_maybe_true: # E: Condition can't be inferred, unable to merge overloads \
# E: Name "another_maybe_true" is not defined
@overload
def f9(x: B) -> B: ...
@overload
def f9(x: C) -> C: ...
@overload
def f9(x: D) -> D: ...
def f9(x): ...
reveal_type(f9(A())) # E: No overload variant of "f9" matches argument type "A" \
# N: Possible overload variants: \
# N: def f9(x: C) -> C \
# N: def f9(x: D) -> D \
# N: Revealed type is "Any"
reveal_type(f9(C())) # N: Revealed type is "__main__.C"
if True:
if maybe_true: # E: Condition can't be inferred, unable to merge overloads \
# E: Name "maybe_true" is not defined
@overload
def f10(x: A) -> A: ...
if another_maybe_true: # E: Condition can't be inferred, unable to merge overloads \
# E: Name "another_maybe_true" is not defined
@overload
def f10(x: B) -> B: ...
@overload
def f10(x: C) -> C: ...
@overload
def f10(x: D) -> D: ...
def f10(x): ...
reveal_type(f10(A())) # E: No overload variant of "f10" matches argument type "A" \
# N: Possible overload variants: \
# N: def f10(x: C) -> C \
# N: def f10(x: D) -> D \
# N: Revealed type is "Any"
reveal_type(f10(C())) # N: Revealed type is "__main__.C"
if some_var: # E: Name "some_var" is not defined
pass
@overload
def f11(x: A) -> A: ...
@overload
def f11(x: B) -> B: ...
def f11(x): ...
reveal_type(f11(A())) # N: Revealed type is "__main__.A"
if True:
if some_var: # E: Name "some_var" is not defined
pass
@overload
def f12(x: A) -> A: ...
@overload
def f12(x: B) -> B: ...
def f12(x): ...
reveal_type(f12(A())) # N: Revealed type is "__main__.A"
[typing fixtures/typing-medium.pyi]
[case testOverloadIfUnconditionalFuncDef]
# flags: --always-true True --always-false False
from typing import overload
class A: ...
class B: ...
# -----
# Don't merge conditional FuncDef after unconditional one
# -----
@overload
def f1(x: A) -> A: ...
@overload
def f1(x: B) -> B: ...
def f1(x): ...
@overload
def f2(x: A) -> A: ...
if True:
@overload
def f2(x: B) -> B: ...
def f2(x): ...
if True:
def f2(x): ... # E: Name "f2" already defined on line 17
[case testOverloadItemHasMoreGeneralReturnType]
from typing import overload
@overload
def f() -> object: ...
@overload
def f(x: int) -> object: ...
def f(x: int = 0) -> int:
return x
@overload
def g() -> object: ...
@overload
def g(x: int) -> str: ...
def g(x: int = 0) -> int: # E: Overloaded function implementation cannot produce return type of signature 2
return x
[case testOverloadIfNestedOk]
# flags: --always-true True --always-false False
from typing import overload
class A: ...
class B: ...
class C: ...
class D: ...
@overload
def f1(g: A) -> A: ...
if True:
@overload
def f1(g: B) -> B: ...
if True:
@overload
def f1(g: C) -> C: ...
@overload
def f1(g: D) -> D: ...
def f1(g): ...
reveal_type(f1(A())) # N: Revealed type is "__main__.A"
reveal_type(f1(B())) # N: Revealed type is "__main__.B"
reveal_type(f1(C())) # N: Revealed type is "__main__.C"
reveal_type(f1(D())) # N: Revealed type is "__main__.D"
@overload
def f2(g: A) -> A: ...
if True:
@overload
def f2(g: B) -> B: ...
if True:
@overload
def f2(g: C) -> C: ...
if True:
@overload
def f2(g: D) -> D: ...
def f2(g): ...
reveal_type(f2(A())) # N: Revealed type is "__main__.A"
reveal_type(f2(B())) # N: Revealed type is "__main__.B"
reveal_type(f2(C())) # N: Revealed type is "__main__.C"
reveal_type(f2(D())) # N: Revealed type is "__main__.D"
@overload
def f3(g: A) -> A: ...
if True:
if True:
@overload
def f3(g: B) -> B: ...
if True:
@overload
def f3(g: C) -> C: ...
def f3(g): ...
reveal_type(f3(A())) # N: Revealed type is "__main__.A"
reveal_type(f3(B())) # N: Revealed type is "__main__.B"
reveal_type(f3(C())) # N: Revealed type is "__main__.C"
@overload
def f4(g: A) -> A: ...
if True:
if False:
@overload
def f4(g: B) -> B: ...
else:
@overload
def f4(g: C) -> C: ...
def f4(g): ...
reveal_type(f4(A())) # N: Revealed type is "__main__.A"
reveal_type(f4(B())) # E: No overload variant of "f4" matches argument type "B" \
# N: Possible overload variants: \
# N: def f4(g: A) -> A \
# N: def f4(g: C) -> C \
# N: Revealed type is "Any"
reveal_type(f4(C())) # N: Revealed type is "__main__.C"
@overload
def f5(g: A) -> A: ...
if True:
if False:
@overload
def f5(g: B) -> B: ...
elif True:
@overload
def f5(g: C) -> C: ...
def f5(g): ...
reveal_type(f5(A())) # N: Revealed type is "__main__.A"
reveal_type(f5(B())) # E: No overload variant of "f5" matches argument type "B" \
# N: Possible overload variants: \
# N: def f5(g: A) -> A \
# N: def f5(g: C) -> C \
# N: Revealed type is "Any"
reveal_type(f5(C())) # N: Revealed type is "__main__.C"
[case testOverloadIfNestedFailure]
# flags: --always-true True --always-false False
from typing import overload
class A: ...
class B: ...
class C: ...
class D: ...
@overload # E: Single overload definition, multiple required
def f1(g: A) -> A: ...
if True:
@overload # E: Single overload definition, multiple required
def f1(g: B) -> B: ...
if maybe_true: # E: Condition can't be inferred, unable to merge overloads \
# E: Name "maybe_true" is not defined
@overload
def f1(g: C) -> C: ...
@overload
def f1(g: D) -> D: ...
def f1(g): ... # E: Name "f1" already defined on line 9
@overload # E: Single overload definition, multiple required
def f2(g: A) -> A: ...
if True:
if False:
@overload
def f2(g: B) -> B: ...
elif maybe_true: # E: Name "maybe_true" is not defined
@overload # E: Single overload definition, multiple required
def f2(g: C) -> C: ...
def f2(g): ... # E: Name "f2" already defined on line 21
@overload # E: Single overload definition, multiple required
def f3(g: A) -> A: ...
if True:
@overload # E: Single overload definition, multiple required
def f3(g: B) -> B: ...
if True:
pass # Some other node
@overload # E: Name "f3" already defined on line 32 \
# E: An overloaded function outside a stub file must have an implementation
def f3(g: C) -> C: ...
@overload
def f3(g: D) -> D: ...
def f3(g): ... # E: Name "f3" already defined on line 32
[case testOverloadingWithParamSpec]
from typing import TypeVar, Callable, Any, overload
from typing_extensions import ParamSpec, Concatenate
P = ParamSpec("P")
R = TypeVar("R")
@overload
def func(x: Callable[Concatenate[Any, P], R]) -> Callable[P, R]: ... # E: Overloaded function signatures 1 and 2 overlap with incompatible return types
@overload
def func(x: Callable[P, R]) -> Callable[Concatenate[str, P], R]: ...
def func(x: Callable[..., R]) -> Callable[..., R]: ...
def foo(arg1: str, arg2: int) -> bytes: ...
reveal_type(func(foo)) # N: Revealed type is "def (arg2: builtins.int) -> builtins.bytes"
def bar() -> int: ...
reveal_type(func(bar)) # N: Revealed type is "def (builtins.str) -> builtins.int"
baz: Callable[[str, str], str] = lambda x, y: 'baz'
reveal_type(func(baz)) # N: Revealed type is "def (builtins.str) -> builtins.str"
eggs = lambda: 'eggs'
reveal_type(func(eggs)) # N: Revealed type is "def (builtins.str) -> builtins.str"
spam: Callable[..., str] = lambda x, y: 'baz'
reveal_type(func(spam)) # N: Revealed type is "def (*Any, **Any) -> builtins.str"
[builtins fixtures/paramspec.pyi]
[case testGenericOverloadOverlapWithType]
import m
[file m.pyi]
from typing import TypeVar, Type, overload, Callable
T = TypeVar("T", bound=str)
@overload
def foo(x: Type[T] | int) -> int: ...
@overload
def foo(x: Callable[[int], bool]) -> str: ...
[case testGenericOverloadOverlapWithCollection]
import m
[file m.pyi]
from typing import TypeVar, Sequence, overload, List
T = TypeVar("T", bound=str)
@overload
def foo(x: List[T]) -> str: ...
@overload
def foo(x: Sequence[int]) -> int: ...
[builtins fixtures/list.pyi]
# Also see `check-python38.test` for similar tests with `/` args:
[case testOverloadPositionalOnlyErrorMessageOldStyle]
from typing import overload
@overload
def foo(__a: int): ...
@overload
def foo(a: str): ...
def foo(a): ...
foo(a=1)
[out]
main:9: error: No overload variant of "foo" matches argument type "int"
main:9: note: Possible overload variants:
main:9: note: def foo(int, /) -> Any
main:9: note: def foo(a: str) -> Any
[case testOverloadUnionGenericBounds]
from typing import overload, TypeVar, Sequence, Union
class Entity: ...
class Assoc: ...
E = TypeVar("E", bound=Entity)
A = TypeVar("A", bound=Assoc)
class Test:
@overload
def foo(self, arg: Sequence[E]) -> None: ...
@overload
def foo(self, arg: Sequence[A]) -> None: ...
def foo(self, arg: Union[Sequence[E], Sequence[A]]) -> None:
...
[case testOverloadedStaticMethodOnInstance]
from typing import overload
class Snafu(object):
@overload
@staticmethod
def snafu(value: bytes) -> bytes: ...
@overload
@staticmethod
def snafu(value: str) -> str: ...
@staticmethod
def snafu(value):
...
reveal_type(Snafu().snafu('123')) # N: Revealed type is "builtins.str"
reveal_type(Snafu.snafu('123')) # N: Revealed type is "builtins.str"
[builtins fixtures/staticmethod.pyi]