| -- 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] |