-- 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 8
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 13
r(0)
[out]
main:1: error: Name 'overload' is not defined
main:3: error: Name 'f' already defined on line 1
main:3: error: Name 'overload' is not defined
main:5: error: Name 'f' already defined on line 1

[case testTypeCheckOverloadWithImplementation]
from typing import overload, Any
@overload
def f(x: 'A') -> 'B': ...
@overload
def f(x: 'B') -> 'A': ...

def f(x: Any) -> Any:
    pass

reveal_type(f(A())) # E: Revealed type is '__main__.B'
reveal_type(f(B())) # E: Revealed type is '__main__.A'

class A: pass
class B: pass
[builtins fixtures/isinstance.pyi]

[case testOverloadNeedsImplementation]
from typing import overload, Any
@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())) # E: Revealed type is '__main__.B'
reveal_type(f(B())) # E: Revealed type is '__main__.A'

class A: pass
class B: pass
[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
@rose
def f(x: 'A') -> 'B': ...
@rose
def f(x: 'B') -> 'A': ...

def f(x: Any) -> Any:
    pass

reveal_type(f(A())) # E: Revealed type is '__main__.B'
reveal_type(f(B())) # E: Revealed type is '__main__.A'

class A: pass
class B: pass
[builtins fixtures/isinstance.pyi]

[case testTypeCheckOverloadWithDecoratedImplementation]
from typing import overload, Any

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())) # E: Revealed type is '__main__.B'
reveal_type(f(B())) # E: Revealed type is '__main__.A'

class A: pass
class B: pass
[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 testTypeCheckOverloadWithImplementationPy2]
# flags: --python-version 2.7

from typing import overload
@overload
def f(x):
    # type: (A) -> B
    pass

@overload
def f(x):
    # type: (B) -> A
    pass

def f(x):
    pass

reveal_type(f(A()))  # E: Revealed type is '__main__.B'
reveal_type(f(B()))  # E: Revealed type is '__main__.A'

class A: pass
class B: pass
[builtins fixtures/isinstance.pyi]

[case testTypeCheckOverloadWithImplementationError]
from typing import overload, Any

@overload
def f(x: 'A') -> 'B': ...
@overload
def f(x: 'B') -> 'A': ...

def f(x: Any) -> Any:
    foo = 1
    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
    foo = "bar"

reveal_type(f(A()))  # E: Revealed type is '__main__.B'
reveal_type(f(B()))  # E: Revealed type is '__main__.A'

class A: pass
class B: pass
[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())) # E: Revealed type is '__main__.B'
reveal_type(f(B())) # E: 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())) # E: Revealed type is '__main__.B'
reveal_type(f(B())) # E: 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())) # E: Revealed type is '__main__.A'
reveal_type(f(B())) # E: 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())) # E: Revealed type is '__main__.A'
reveal_type(f(B())) # E: 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'):
    x = B() # E: Incompatible types in assignment (expression has type "B", variable has type "A")
    x = A()
@overload
def f(x: 'B'):
    x = A() # E: Incompatible types in assignment (expression has type "A", variable has type "B")
    x = B()
class A: pass
class B: pass
[out]

[case testTypeCheckOverloadedMethodBody]
from foo import *
[file foo.pyi]
from typing import overload
class A:
    @overload
    def f(self, x: 'A'):
        x = B() # E: Incompatible types in assignment (expression has type "B", variable has type "A")
        x = A()
    @overload
    def f(self, x: 'B'):
        x = A() # E: Incompatible types in assignment (expression has type "A", variable has type "B")
        x = B()
class B: pass
[out]

[case testCallToOverloadedFunction]
from 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, b = None, None # type: (A, B)
b = f(a) # E: Incompatible types in assignment (expression has type "A", variable has type "B")
a = f(b) # E: Incompatible types in assignment (expression has type "B", variable has type "A")
a = f(a)
b = f(b)

@overload
def f(x: 'A') -> 'A': pass
@overload
def f(x: 'B') -> 'B': pass
class A: pass
class B: pass

[case testCallToOverloadedMethod]
from 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, b = None, None # type: (A, B)
b = a.f(a) # E: Incompatible types in assignment (expression has type "A", variable has type "B")
a = a.f(b) # E: Incompatible types in assignment (expression has type "B", variable has type "A")
a = a.f(a)
b = a.f(b)

class A:
  @overload
  def f(self, x: 'A') -> 'A': pass
  @overload
  def f(self, x: 'B') -> 'B': pass
class B: pass

[case testOverloadsWithDifferentArgumentCounts]
from foo import *
[file foo.pyi]
from typing import overload
a, b = None, None # type: (A, B)
a = f(a)
b = f(a) # E: Incompatible types in assignment (expression has type "A", variable has type "B")
f(b)     # E: No overload variant of "f" matches argument type "B" \
         # N: Possible overload variant: \
         # N:     def f(x: A) -> A \
         # N:     <1 more non-matching overload not shown>
b = f(b, a)
a = f(b, a) # E: Incompatible types in assignment (expression has type "B", variable has type "A")
f(a, a)     # E: No overload variant of "f" matches argument types "A", "A" \
            # N: Possible overload variant: \
            # N:     def f(x: B, y: A) -> B \
            # N:     <1 more non-matching overload not shown>
f(b, b)     # E: No overload variant of "f" matches argument types "B", "B" \
            # N: Possible overload variant: \
            # N:     def f(x: B, y: A) -> B \
            # N:     <1 more non-matching overload not shown>

@overload
def f(x: 'A') -> 'A': pass
@overload
def f(x: 'B', y: 'A') -> 'B': pass
class A: pass
class B: pass

[case testGenericOverloadVariant]
from foo import *
[file foo.pyi]
from typing import overload, TypeVar, Generic
t = TypeVar('t')
ab, ac, b, c = None, None, None, None # type: (A[B], A[C], B, C)
b = f(ab)
c = f(ac)
b = f(ac) # E: Incompatible types in assignment (expression has type "C", variable has type "B")
b = f(b)
c = f(b)  # E: Incompatible types in assignment (expression has type "B", variable has type "C")
@overload
def f(x: 'A[t]') -> t: pass
@overload
def f(x: 'B') -> 'B': pass
class A(Generic[t]): pass
class B: pass
class C: pass

[case testOverloadedInit]
from foo import *
[file foo.pyi]
from typing import overload
a, b = None, None # type: (A, B)
a = A(a)
a = A(b)
a = A(object()) # E: No overload variant of "A" matches argument 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

[case testIntersectionTypeCompatibility]
from foo import *
[file foo.pyi]
from typing import overload, Callable
o = None # type: object
a = None # type: A

a = f # E: Incompatible types in assignment (expression has type overloaded function, variable has type "A")
o = f

@overload
def f(a: 'A') -> None: pass
@overload
def f(a: Callable[[], None]) -> None: pass
class A: pass

[case testCompatibilityOfIntersectionTypeObjectWithStdType]
from foo import *
[file foo.pyi]
from typing import overload
t, a = None, None # type: (type, A)

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

[case testOverloadedGetitem]
from foo import *
[file foo.pyi]
from typing import overload
a, b = None, None # type: int, str
a = A()[a]
b = A()[a] # E: Incompatible types in assignment (expression has type "int", variable has type "str")
b = A()[b]
a = A()[b] # E: Incompatible types in assignment (expression has type "str", variable has type "int")

class A:
    @overload
    def __getitem__(self, a: int) -> int: pass
    @overload
    def __getitem__(self, b: str) -> str: pass

[case testOverloadedGetitemWithGenerics]
from foo import *
[file foo.pyi]
from typing import TypeVar, Generic, overload
t = TypeVar('t')
a, b, c = None, None, None # type: (A, B, C[A])
a = c[a]
b = c[a] # E: Incompatible types in assignment (expression has type "A", variable has type "B")
a = c[b]
b = c[b] # E: Incompatible types in assignment (expression has type "A", variable has type "B")

class C(Generic[t]):
    @overload
    def __getitem__(self, a: 'A') -> t: pass
    @overload
    def __getitem__(self, b: 'B') -> t: pass
class A: pass
class B: pass

[case testImplementingOverloadedMethod]
from 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, b = None, None # type: (A, B)
a = f(A)
b = f(a)
b = f(A) # E: Incompatible types in assignment (expression has type "A", variable has type "B")
a = f(a) # E: Incompatible types in assignment (expression has type "B", variable has type "A")
class A:
   @overload
   def __init__(self) -> None: pass
   @overload
   def __init__(self, a: 'A') -> None: pass
class B:
    pass

[case testOverlappingErasedSignatures]
from 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)
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                           # 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: A) -> B: ...
    @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: B) -> C: ...
    @overload
    def f(self, x: int) -> int: ...
class Child3(Parent):
    @overload                           # E: Signature of "f" incompatible with supertype "Parent"
    def f(self, x: B) -> A: ...
    @overload
    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
    def f(self, x: IntSub) -> int: return 0
    @overload
    def f(self, x: str) -> str: return ''
class C(A):
    @overload
    def f(self, x: int) -> int: return 0
    @overload
    def f(self, x: StrSub) -> str: return ''
class D(A):
    @overload
    def f(self, x: int) -> int: return 0
    @overload
    def f(self, x: str) -> str: return ''
[out]
tmp/foo.pyi:12: error: Signature of "f" incompatible with supertype "A"
tmp/foo.pyi:17: error: Signature of "f" incompatible with supertype "A"

[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")

[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 variant: \
           # N:     def f(*x: str) -> str \
           # N:     <1 more non-matching overload not shown>
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 variant: \
                 # N:     def f(*x: str) -> str \
                 # N:     <1 more non-matching overload not shown>

[case testPreferExactSignatureMatchInOverload]
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)  # E: 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]) # E: "f" does not return a value
    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 "object"
g(1)
g(1, 'foo')
g(1, 'foo', b'bar') # E: Value of type variable "AnyStr" of "g" cannot be "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: error: Revealed type is 'builtins.int'
main:18: error: Revealed type is 'builtins.str'
main:19: error: Revealed type is 'Any'
main:20: error: 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 http://mypy.readthedocs.io/en/latest/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([]))  # E: 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()))     # E: Revealed type is 'builtins.int'
reveal_type(f(Wrapper[C]()))  # E: Revealed type is 'builtins.str'
reveal_type(f(Wrapper[B]()))  # E: 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]"

[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
    def do_chain(self) -> int:
        return 2

    @do_chain.chain  # E: Name 'do_chain' already defined on line 10
    def do_chain(self) -> int:
        return 3

t = Test()
reveal_type(t.do_chain)  # E: 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))  # E: 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))  # E: 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))  # E: 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, ''))  # E: Revealed type is 'Any'
# Any causes no ambiguity
reveal_type(f(1, a, a))  # E: Revealed type is 'builtins.int'
reveal_type(f('', a, a))  # E: Revealed type is 'builtins.object'
# Like above, but use keyword arguments.
reveal_type(f(y=1, z='', x=a))  # E: Revealed type is 'Any'
reveal_type(f(y=a, z='', x=1))  # E: Revealed type is 'builtins.int'
reveal_type(f(z='', x=1, y=a))  # E: Revealed type is 'builtins.int'
reveal_type(f(z='', x=a, y=1))  # E: 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))  # E: Revealed type is 'Any'
reveal_type(g(a))  # E: 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))  # E: Revealed type is 'Any'
reveal_type(f(a, *a))  # E: Revealed type is 'Any'
reveal_type(f(1, *a))  # E: Revealed type is 'Any'
reveal_type(f(1.1, *a))  # E: Revealed type is 'Any'
reveal_type(f('', *a))  # E: 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))  # E: Revealed type is 'builtins.int'
reveal_type(g(1, *a))  # E: 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)) # E: Revealed type is 'builtins.str'
reveal_type(f(1, *a))  # E: 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)) # E: Revealed type is 'builtins.list[Any]'
reveal_type(f(b))  # E: Revealed type is 'builtins.list[Any]'
reveal_type(f(c))  # E: Revealed type is 'builtins.list[Any]'
reveal_type(f(d))  # E: 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))  # E: Revealed type is 'builtins.int'
reveal_type(f(y=a))       # E: Revealed type is 'Any'
reveal_type(f(x=a, y=a))  # E: 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))  # E: Revealed type is 'builtins.int'
reveal_type(f(**a))       # E: 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))  # E: 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))  # E: 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))  # E: 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))  # E: Revealed type is 'builtins.str'
reveal_type(g(a))  # E: 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))     # E: Revealed type is 'def (*Any, **Any) -> Any'
reveal_type(f(a)(a))  # E: 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) # E: 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
[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:...

[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 True  # E: Incompatible return value type (got "bool", 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 # E: Signature of "f" incompatible with supertype "ParentWithTypedImpl"
    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 # E: Signature of "f" incompatible with supertype "ParentWithTypedImpl"
    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 # E: Signature of "f" incompatible with supertype "ParentWithDynamicImpl"
    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 # E: Signature of "f" incompatible with supertype "ParentWithDynamicImpl"
    def f(self, arg: int) -> int: ...
    @overload
    def f(self, arg: StrSub) -> str: ...
    def f(self, arg: Any) -> Any: ...

[builtins fixtures/tuple.pyi]

[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())  # E: Revealed type is '__main__.B'
reveal_type(foo(p2=B()))  # E: Revealed type is '__main__.B'
reveal_type(foo(p1=A()))  # E: 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: ...

[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: ...

[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: ...

[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: ...

[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

[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: ...

[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: ...

[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: ...

[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))        # E: Revealed type is '__main__.A'
reveal_type(foo(1, 2))     # E: Revealed type is '__main__.B'
reveal_type(foo(1, 2, 3))  # E: Revealed type is '__main__.C'

reveal_type(foo(*[1]))        # E: Revealed type is '__main__.C'
reveal_type(foo(*[1, 2]))     # E: Revealed type is '__main__.C'
reveal_type(foo(*[1, 2, 3]))  # E: Revealed type is '__main__.C'

x: List[int]
reveal_type(foo(*x))  # E: 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, y: int, z: int, *args: int) -> C \
         # N:     def foo(x: int) -> A \
         # N:     def foo(x: int, y: int) -> B
[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]))      # E: Revealed type is '__main__.C'
reveal_type(foo(*["a", "b"]))  # E: Revealed type is '__main__.D'

x: List[Any]
reveal_type(foo(*x))  # E: 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))       # E: Revealed type is '__main__.C*'
reveal_type(chain_call(A(), f1, f2, f3))   # E: Revealed type is 'Any'
reveal_type(chain_call(A(), f, f, f, f))   # E: 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))           # E: Revealed type is 'Tuple[builtins.int]'
reveal_type(f(i, i))        # E: Revealed type is 'Tuple[builtins.int, builtins.int]'
reveal_type(f(i, i, i))     # E: Revealed type is 'builtins.tuple[builtins.int]'

reveal_type(f(*[]))         # E: Revealed type is 'builtins.tuple[builtins.int]'
reveal_type(f(*[i]))        # E: Revealed type is 'builtins.tuple[builtins.int]'
reveal_type(f(*[i, i]))     # E: Revealed type is 'builtins.tuple[builtins.int]'
reveal_type(f(*[i, i, i]))  # E: 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(*()))         # E: Revealed type is 'builtins.tuple[builtins.int]'
reveal_type(f(*(i,)))       # E: Revealed type is 'Tuple[builtins.int]'
reveal_type(f(*(i, i)))     # E: Revealed type is 'Tuple[builtins.int, builtins.int]'
reveal_type(f(*(i, i, i)))  # E: 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))  # E: Revealed type is 'Tuple[builtins.int, builtins.int]'
reveal_type(f(*b))  # E: Revealed type is 'Tuple[builtins.int, builtins.int]'
reveal_type(f(*c))  # E: 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))                      # E: Revealed type is 'builtins.tuple[builtins.int]'
reveal_type(f(**{'x': 4}))                   # E: Revealed type is 'builtins.tuple[builtins.int]'
reveal_type(f(**{'x': 4, 'y': 4}))           # E: Revealed type is 'builtins.tuple[builtins.int]'
reveal_type(f(**{'a': 4, 'b': 4, 'c': 4}))   # E: Revealed type is 'builtins.tuple[builtins.int]'
[builtins fixtures/dict.pyi]

[case testOverloadKwargsSelectionWithTypedDict-skip]
# TODO: Mypy doesn't seem to correctly destructure typed dicts in general.
#       We should re-enable this once https://github.com/python/mypy/issues/5198 is resolved
from typing import overload, Tuple
from mypy_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))  # E: Revealed type is 'Tuple[builtins.int]'
reveal_type(f(**b))  # E: Revealed type is 'Tuple[builtins.int, builtins.int]'
reveal_type(f(**c))  # E: 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))  # E: Revealed type is '__main__.A'
reveal_type(f(*b, **c))  # E: Revealed type is '__main__.A'
reveal_type(f(*a))       # E: Revealed type is '__main__.B'
reveal_type(f(*b))       # E: 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))      # E: 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))  # E: 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))  # E: 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: error: 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: error: 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: error: 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))  # E: 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()))  # E: Revealed type is '__main__.B'
reveal_type(f(B()))  # E: Revealed type is '__main__.C'
reveal_type(f(x))    # E: 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()))  # E: Revealed type is '__main__.C'
reveal_type(f(A(), C()))  # E: Revealed type is '__main__.B'

arg: Union[B, C]
reveal_type(f(A(), arg))  # E: Revealed type is 'Union[__main__.C, __main__.B]'
reveal_type(f(A()))       # E: 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))  # E: Revealed type is '__main__.Parent'
f(x, B())  # E: Argument 1 to "f" has incompatible type "Union[A, B]"; expected "B"

[case testOverloadInferUnionWithMixOfPositionalAndOptionalArgs]
# flags: --strict-optional
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))  # E: Revealed type is 'Union[builtins.int, builtins.str]'
reveal_type(f(y))  # E: Revealed type is 'Union[builtins.int, builtins.str]'
reveal_type(f(z))  # E: Revealed type is 'Union[builtins.int, builtins.str]'
reveal_type(f())   # E: Revealed type is 'builtins.str'

[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()))  # E: Revealed type is '__main__.C'
reveal_type(obj.f(B()))  # E: Revealed type is '__main__.B'
reveal_type(obj.f(x))    # E: 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)  # E: Revealed type is '__main__.A'
    reveal_type(a2)  # E: Revealed type is '__main__.A*'

    obj2: Union[W1[A], W2[B]]

    reveal_type(foo(obj2))  # E: 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)  # E: 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))  # E: 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))  # E: 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))  # E: 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))  # E: 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))  # E: 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: error: Revealed type is 'Union[S`-2, __main__.B]'
main:22: error: Revealed type is 'Union[S`-2, __main__.C]'
main:26: error: Revealed type is '__main__.B*'
main:26: error: 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))  # E: 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))  # E: Revealed type is 'builtins.int'
reveal_type(g(b))  # E: Revealed type is 'builtins.str'
reveal_type(g(c))  # E: Revealed type is 'builtins.str'

[case testOverloadsAndNoneWithStrictOptional]
# flags: --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): ...

@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))  # E: Revealed type is 'builtins.int'
reveal_type(g(b))  # E: Revealed type is 'builtins.str'
reveal_type(g(c))  # E: 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))  # E: Revealed type is 'typing.Iterable[builtins.str*]'
reveal_type(mymap(f2, seq))  # E: Revealed type is 'typing.Iterable[builtins.int*]'
reveal_type(mymap(f3, seq))  # E: Revealed type is 'typing.Iterable[builtins.str*]'

[builtins fixtures/list.pyi]
[typing fixtures/typing-full.pyi]

[case testOverloadsNoneAndTypeVarsWithStrictOptional]
# flags: --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))  # E: Revealed type is 'typing.Iterable[builtins.str*]'
reveal_type(mymap(f2, seq))  # E: Revealed type is 'typing.Iterable[builtins.int*]'
reveal_type(mymap(f3, seq))  # E: Revealed type is 'Union[typing.Iterable[builtins.str*], typing.Iterable[builtins.int*]]'

[builtins fixtures/list.pyi]
[typing fixtures/typing-full.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]
    a = narrow_int(a)
    reveal_type(a)  # E: Revealed type is 'builtins.int'

    b: int
    b = narrow_int(b)
    reveal_type(b)  # E: Revealed type is 'builtins.int'

    c: str
    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-full.pyi]

[case testOverloadsAndNoReturnNarrowTypeWithStrictOptional1]
# flags: --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]
    a = narrow_int(a)
    reveal_type(a)  # E: Revealed type is 'builtins.int'

    b: int
    b = narrow_int(b)
    reveal_type(b)  # E: Revealed type is 'builtins.int'

    c: str
    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-full.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]
    a = narrow_none(a)
    reveal_type(a)  # E: Revealed type is 'Union[builtins.int, None]'

    b: int
    b = narrow_none(b)
    reveal_type(b)  # E: Revealed type is 'builtins.int'

    c: None
    c = narrow_none(c)
    reveal_type(c)  # Note: branch is now dead, so no type is revealed

[builtins fixtures/isinstance.pyi]
[typing fixtures/typing-full.pyi]

[case testOverloadsAndNoReturnNarrowTypeWithStrictOptional2]
# flags: --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]
    a = narrow_none(a)
    reveal_type(a)  # E: Revealed type is 'builtins.int'

    b: int
    b = narrow_none(b)
    reveal_type(b)  # E: Revealed type is 'builtins.int'

    c: None
    c = narrow_none(c)
    reveal_type(c)  # Branch is now dead

[builtins fixtures/isinstance.pyi]
[typing fixtures/typing-full.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]
    a = narrow_none_v2(a)
    reveal_type(a)  # E: Revealed type is 'Union[builtins.int, None]'

    b: int
    b = narrow_none_v2(b)
    reveal_type(b)  # E: Revealed type is 'builtins.int'

    c: None
    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-full.pyi]

[case testOverloadsAndNoReturnNarrowTypeWithStrictOptional3]
# flags: --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]
    a = narrow_none_v2(a)
    reveal_type(a)  # E: Revealed type is 'builtins.int'

    b: int
    b = narrow_none_v2(b)
    reveal_type(b)  # E: Revealed type is 'builtins.int'

    c: None
    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-full.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]
    val = narrow_to_not_a(val)
    reveal_type(val)   # E: Revealed type is '__main__.B'

    val2: A
    val2 = narrow_to_not_a(val2)
    reveal_type(val2)  # Branch now dead

[builtins fixtures/isinstance.pyi]
[typing fixtures/typing-full.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() -> None:
    val: Union[A, B]
    val = narrow_to_not_a_v2(val)
    reveal_type(val)   # E: Revealed type is '__main__.B'

    val2: A
    val2 = narrow_to_not_a_v2(val2)
    reveal_type(val2)  # Branch now dead

[builtins fixtures/isinstance.pyi]
[typing fixtures/typing-full.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)  # E: Revealed type is 'builtins.int'
MyModel().my_number.foo()         # E: "int" has no attribute "foo"

reveal_type(MyModel.my_number)        # E: Revealed type is '__main__.NumberAttribute'
reveal_type(MyModel.my_number.foo())  # E: Revealed type is 'builtins.str'

[builtins fixtures/isinstance.pyi]
[typing fixtures/typing-full.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)  # E: Revealed type is 'builtins.int'
MyModel().my_number.foo()         # E: "int" has no attribute "foo"

reveal_type(MyModel.my_number)        # E: Revealed type is '__main__.NumberAttribute[__main__.MyModel*]'
reveal_type(MyModel.my_number.foo())  # E: Revealed type is 'builtins.str'

reveal_type(NumberAttribute[MyModel]().__get__(None, MyModel))  # E: Revealed type is '__main__.NumberAttribute[__main__.MyModel*]'
reveal_type(NumberAttribute[str]().__get__(None, str))      # E: Revealed type is '__main__.NumberAttribute[builtins.str*]'

[builtins fixtures/isinstance.pyi]
[typing fixtures/typing-full.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 testOverloadLambdaUnpackingInference]
# flags: --py2
from typing import Callable, TypeVar, overload

T = TypeVar('T')
S = TypeVar('S')

@overload
def foo(func, item):
    # type: (Callable[[T], S], T) -> S
    pass

@overload
def foo():
    # type: () -> None
    pass

def foo(*args):
    pass

def add_proxy(x, y):
    # type: (int, str) -> str
    pass

# The lambda definition is a syntax error in Python 3
tup = (1, '2')
reveal_type(foo(lambda (x, y): add_proxy(x, y), tup))  # E: Revealed type is 'builtins.str*'
[builtins fixtures/primitives.pyi]

[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))      # E: Revealed type is 'builtins.int'
reveal_type(Wrapper.foo("foo"))  # E: 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))  # E: Revealed type is 'builtins.int'
reveal_type(Wrapper2.foo(3))  # E: 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  # E: Signature of "foo" incompatible with supertype "Parent"
    @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]

[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                           # E: Signature of "foo" incompatible with supertype "BadParent"
    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]

[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)          # E: Revealed type is 'def () -> __main__.Wrapper'
        reveal_type(cls.other())  # E: 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))      # E: Revealed type is 'builtins.int'
reveal_type(Wrapper.foo("foo"))  # E: 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 testOverloadWithSwappedDecorators]
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))  # E: Revealed type is 'builtins.int'
reveal_type(Wrapper2.foo(3))  # E: 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  # E: Signature of "foo" incompatible with supertype "Parent"
    @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]

[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                            # E: Signature of "foo" incompatible with supertype "BadParent"
    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]

[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))  # E: 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())    # E: 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))                  # E: Revealed type is '__main__.Parent*'
reveal_type(Child().foo(3))                   # E: Revealed type is '__main__.Child*'
reveal_type(Child().foo("..."))               # E: Revealed type is 'builtins.str'
reveal_type(Child().foo(x))                   # E: Revealed type is 'Union[__main__.Child*, builtins.str]'
reveal_type(Child().foo(3).child_only())      # E: 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())    # E: 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))                  # E: Revealed type is 'Type[__main__.Parent*]'
reveal_type(Child.foo(3))                   # E: Revealed type is 'Type[__main__.Child*]'
reveal_type(Child.foo("..."))               # E: Revealed type is 'builtins.str'
reveal_type(Child.foo(x))                   # E: Revealed type is 'Union[Type[__main__.Child*], builtins.str]'
reveal_type(Child.foo(3)().child_only())    # E: 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))  # E: Revealed type is '__main__.C'
[out]

[case testOptionalIsNotAUnionIfNoStrictOverloadStr]
# flags: -2 --no-strict-optional

from typing import Optional
from m import relpath
a = '' # type: Optional[str]
reveal_type(relpath(a))  # E: Revealed type is 'builtins.str'

[file m.pyi]
from typing import overload
@overload
def relpath(path: str) -> str: ...
@overload
def relpath(path: unicode) -> unicode: ...
[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))  # E: 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)  # E: 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]
# flags: --strict-optional
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:22: error: Overloaded function implementation does not accept all possible arguments of signature 1
main:22: 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)
[out]
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"
main:11: note: Not all union combinations were tried because there are too many unions

[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  # E: Signature of "__add__" incompatible with supertype "A" \
                # N: Overloaded operator methods can't have wider argument types in overrides
     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())  # E: Revealed type is '__main__.Other'
# Runtime type is B, this is why we report the error on overriding.
[builtins fixtures/isinstance.pyi]
[out]

[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:     <2 more similar overloads not shown, out of 5 total overloads>

@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

[case testOverloadedInIter]
from lib import f, g

for fun in [f, g]:
    reveal_type(fun)  # E: 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-full.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 variant: \
                     # N:     def [T] g(x: T, y: int) -> T \
                     # N:     <1 more non-matching overload not shown>
    reveal_type(g(str(), int()))  # E: 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()))  # E: 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()))  # E: 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))  # E: Revealed type is 'builtins.int*'
reveal_type(attr("hi"))  # E: Revealed type is 'builtins.int'
x: Any
reveal_type(attr(x)) # E: Revealed type is 'Any'
attr("hi", 1)  # E: No overload variant of "attr" matches argument types "str", "int" \
               # N: Possible overload variant: \
               # N:     def [T in (int, float)] attr(default: T = ..., blah: int = ...) -> T \
               # N:     <1 more non-matching overload not shown>
[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))  # E: Revealed type is 'builtins.int*'
reveal_type(attr("hi"))  # E: Revealed type is 'builtins.int'
x: Any
reveal_type(attr(x)) # E: Revealed type is 'Any'
attr("hi", 1)  # E: No overload variant of "attr" matches argument types "str", "int" \
               # N: Possible overload variant: \
               # N:     def [T <: int] attr(default: T = ..., blah: int = ...) -> T \
               # N:     <1 more non-matching overload not shown>
[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)      # E: Revealed type is '__main__.Child'
        return children
    else:
        reveal_type(x)      # E: 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)      # E: Revealed type is 'builtins.int'
        return ints
    else:
        reveal_type(x)      # E: Revealed type is 'builtins.float'
        return floats

[builtins fixtures/isinstancelist.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)                   # E: 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)                   # E: Revealed type is 'builtins.int'

c = single_plausible([Other()])  # E: List item 0 has incompatible type "Other"; expected "str"
reveal_type(c)                   # E: Revealed type is 'builtins.str'
[builtins fixtures/list.pyi]
