-- Simple generic types
-- --------------------


[case testGenericMethodReturnType]
from typing import TypeVar, Generic
T = TypeVar('T')
a, b, c = None, None, None # type: (A[B], B, C)
c = a.f() # Fail
b = a.f()

class A(Generic[T]):
    def f(self) -> T: pass

class B: pass
class C: pass
[out]
main:4: error: Incompatible types in assignment (expression has type "B", variable has type "C")

[case testGenericMethodArgument]
from typing import TypeVar, Generic
T = TypeVar('T')
a.f(c) # Fail
a.f(b)

a = None # type: A[B]
b = None # type: B
c = None # type: C

class A(Generic[T]):
    def f(self, a: T) -> None: pass

class B: pass
class C: pass
[out]
main:3: error: Argument 1 to "f" of "A" has incompatible type "C"; expected "B"

[case testGenericMemberVariable]
from typing import TypeVar, Generic
T = TypeVar('T')
class A(Generic[T]):
    def __init__(self, v: T) -> None:
        self.v = v

a, b, c = None, None, None # type: (A[B], B, C)
a.v = c # Fail
a.v = b

class B: pass
class C: pass
[out]
main:8: error: Incompatible types in assignment (expression has type "C", variable has type "B")

[case testGenericMemberVariable]
from typing import TypeVar, Generic
T = TypeVar('T')
a, b, c = None, None, None # type: (A[B], B, C)
a.v = c # Fail
a.v = b

class A(Generic[T]):
    v = None # type: T
class B: pass
class C: pass
[out]
main:4: error: Incompatible types in assignment (expression has type "C", variable has type "B")

[case testSimpleGenericSubtyping]
from typing import TypeVar, Generic
T = TypeVar('T')
b, bb, c = None, None, None # type: (A[B], A[B], A[C])
c = b # Fail
b = c # Fail

b = b
b = bb

class A(Generic[T]): pass
class B: pass
class C(B): pass
[out]
main:4: error: Incompatible types in assignment (expression has type "A[B]", variable has type "A[C]")
main:5: error: Incompatible types in assignment (expression has type "A[C]", variable has type "A[B]")

[case testGenericTypeCompatibilityWithAny]
from typing import Any, TypeVar, Generic
T = TypeVar('T')
b, c, d = None, None, None # type: (A[B], A[C], A[Any])

b = d
c = d
d = b
d = c

class A(Generic[T]): pass
class B: pass
class C(B): pass
[out]

[case testTypeVariableAsTypeArgument]
from typing import TypeVar, Generic
T = TypeVar('T')
a = None # type: A[B]
b = None # type: A[B]
c = None # type: A[C]

a.v = c # Fail
c = a.v # Fail
a.v = b
b = a.v

class A(Generic[T]):
    v = None # type: A[T]

class B: pass
class C: pass
[out]
main:7: error: Incompatible types in assignment (expression has type "A[C]", variable has type "A[B]")
main:8: error: Incompatible types in assignment (expression has type "A[B]", variable has type "A[C]")

[case testMultipleGenericTypeParametersWithMemberVars]
from typing import TypeVar, Generic
S = TypeVar('S')
T = TypeVar('T')
a = None # type: A[B, C]
s = None # type: B
t = None # type: C

t = a.s # Fail
s = a.t # Fail

s = a.s
t = a.t

class A(Generic[S, T]):
    s = None # type: S
    t = None # type: T
class B: pass
class C: pass
[out]
main:8: error: Incompatible types in assignment (expression has type "B", variable has type "C")
main:9: error: Incompatible types in assignment (expression has type "C", variable has type "B")

[case testMultipleGenericTypeParametersWithMethods]
from typing import TypeVar, Generic
S = TypeVar('S')
T = TypeVar('T')
a = None # type: A[B, C]
s = None # type: B
t = None # type: C

a.f(s, s) # Fail
a.f(t, t) # Fail
a.f(s, t)

class A(Generic[S, T]):
    def f(self, s: S, t: T) -> None: pass
class B: pass
class C: pass
[out]
main:8: error: Argument 2 to "f" of "A" has incompatible type "B"; expected "C"
main:9: error: Argument 1 to "f" of "A" has incompatible type "C"; expected "B"

[case testMultipleGenericTypeParametersAndSubtyping]
from typing import TypeVar, Generic
S = TypeVar('S')
T = TypeVar('T')
bc = None # type: A[B, C]
bb = None # type: A[B, B]
cb = None # type: A[C, B]

bb = bc # Fail
bb = cb # Fail
bc = bb # Fail

bb = bb
bc = bc

class A(Generic[S, T]):
    s = None # type: S
    t = None # type: T

class B: pass
class C(B):pass
[out]
main:8: error: Incompatible types in assignment (expression has type "A[B, C]", variable has type "A[B, B]")
main:9: error: Incompatible types in assignment (expression has type "A[C, B]", variable has type "A[B, B]")
main:10: error: Incompatible types in assignment (expression has type "A[B, B]", variable has type "A[B, C]")


-- Simple generic type bodies
-- --------------------------


[case testGenericTypeBody1]
from typing import TypeVar, Generic
T = TypeVar('T')
class A(Generic[T]):
    a = None # type: T

    def f(self, b: T) -> T:
        self.f(x)     # Fail
        d = self # type: A[B] # Fail
        self.a = self.f(self.a)
        return self.a
        c = self # type: A[T]
x = None # type: B
class B: pass
[out]
main:7: error: Argument 1 to "f" of "A" has incompatible type "B"; expected "T"
main:8: error: Incompatible types in assignment (expression has type "A[T]", variable has type "A[B]")

[case testGenericTypeBodyWithMultipleVariables]
from typing import TypeVar, Generic
S = TypeVar('S')
T = TypeVar('T')
class A(Generic[S, T]):
    def f(self) -> None:
        s = None # type: S
        t = None # type: T
        s = t # Fail
        t = s # Fail
        a = self # type: A[S, B] # Fail
        b = self # type: A[T, T] # Fail
        c = self # type: A[S, T]
        t = t

class B: pass
[out]
main:8: error: Incompatible types in assignment (expression has type "T", variable has type "S")
main:9: error: Incompatible types in assignment (expression has type "S", variable has type "T")
main:10: error: Incompatible types in assignment (expression has type "A[S, T]", variable has type "A[S, B]")
main:11: error: Incompatible types in assignment (expression has type "A[S, T]", variable has type "A[T, T]")

[case testCompatibilityOfNoneWithTypeVar]
from typing import TypeVar, Generic
T = TypeVar('T')
class A(Generic[T]):
    def f(self) -> None:
        a = None # type: T
        a = None
[out]

[case testCompatibilityOfTypeVarWithObject]
from typing import TypeVar, Generic
T = TypeVar('T')
class A(Generic[T]):
    def f(self) -> T:
        a = object() # type: T  # Fail
        a = object()    # Fail
        b = self.f() # type: object
        b = self.f()
        return None
[out]
main:5: error: Incompatible types in assignment (expression has type "object", variable has type "T")
main:6: error: Incompatible types in assignment (expression has type "object", variable has type "T")


-- Operations with generic types
-- -----------------------------


[case testGenericOperations]
from typing import TypeVar, Generic
S = TypeVar('S')
T = TypeVar('T')
a = None # type: A[B, C]
b = None # type: B
c = None # type: C

b = a + b # Fail
c = a + c # Fail
c = a[c]  # Fail
b = a[b]  # Fail

c = a + b
b = a[c]

class A(Generic[S, T]):
    def __add__(self, a: S) -> T: pass
    def __getitem__(self, i: T) -> S: pass

class B: pass
class C: pass
[out]
main:8: error: Incompatible types in assignment (expression has type "C", variable has type "B")
main:9: error: Unsupported operand types for + ("A[B, C]" and "C")
main:10: error: Incompatible types in assignment (expression has type "B", variable has type "C")
main:11: error: Invalid index type "B" for "A[B, C]"; expected type "C"

[case testOperatorAssignmentWithIndexLvalue1]
from typing import TypeVar, Generic
T = TypeVar('T')
b = None # type: B
c = None # type: C
ac = None # type: A[C]

ac[b] += b # Fail
ac[c] += c # Fail
ac[b] += c
ac[b] = ac[b] + c

class A(Generic[T]):
    def __getitem__(self, i: 'B') -> T: pass
    def __setitem__(self, i: 'B', v: T) -> None: pass

class B: pass
class C:
    def __add__(self, o: 'C') -> 'C': pass
[out]
main:7: error: Unsupported operand types for + ("C" and "B")
main:8: error: Invalid index type "C" for "A[C]"; expected type "B"

[case testOperatorAssignmentWithIndexLvalue2]
from typing import TypeVar, Generic
T = TypeVar('T')
b = None # type: B
c = None # type: C
ac = None # type: A[C]

ac[b] += c        # Fail
ac[c] += c        # Fail
ac[b] = ac[b] + c # Fail

class A(Generic[T]):
    def __getitem__(self, i: 'B') -> T: pass
    def __setitem__(self, i: 'C', v: T) -> None: pass

class B: pass
class C:
    def __add__(self, o: 'C') -> 'C': pass
[out]
main:7: error: Invalid index type "B" for "A[C]"; expected type "C"
main:8: error: Invalid index type "C" for "A[C]"; expected type "B"
main:9: error: Invalid index type "B" for "A[C]"; expected type "C"


-- Nested generic types
-- --------------------


[case testNestedGenericTypes]
from typing import TypeVar, Generic
T = TypeVar('T')
aab = None # type: A[A[B]]
aac = None # type: A[A[C]]
ab = None # type: A[B]
ac = None # type: A[C]

ac = aab.x # Fail
ac.y = aab # Fail

ab = aab.x
ac = aac.x
ab.y = aab
ac.y = aac

class A(Generic[T]):
    x = None # type: T
    y = None # type: A[A[T]]

class B:
    pass
class C:
    pass
[out]
main:8: error: Incompatible types in assignment (expression has type "A[B]", variable has type "A[C]")
main:9: error: Incompatible types in assignment (expression has type "A[A[B]]", variable has type "A[A[C]]")


-- Generic functions
-- -----------------


[case testTypeCheckingGenericFunctionBody]
from typing import TypeVar, Generic
S = TypeVar('S')
T = TypeVar('T')
class A: pass
class p(Generic[T, S]):
    def __init__(self, t: T, a: S) -> None: pass
def f(s: S, t: T) -> p[T, A]:
    a = t # type: S # E: Incompatible types in assignment (expression has type "T", variable has type "S")
    s = t           # E: Incompatible types in assignment (expression has type "T", variable has type "S")
    p_s_a = None  # type: p[S, A]
    if s:
        return p_s_a # E: Incompatible return value type (got "p[S, A]", expected "p[T, A]")
    b = t # type: T
    c = s # type: S
    p_t_a = None  # type: p[T, A]
    return p_t_a
[out]

[case testTypeCheckingGenericMethodBody]
from typing import TypeVar, Generic
T = TypeVar('T')
S = TypeVar('S')
class p(Generic[T, S]):
    def __init__(self, t: T, a: S) -> None: pass
class A(Generic[T]):
    def f(self, s: S, t: T) -> p[S, T]:
        s = t # E: Incompatible types in assignment (expression has type "T", variable has type "S")
        p_s_s = None  # type: p[S, S]
        if s:
            return p_s_s # E: Incompatible return value type (got "p[S, S]", expected "p[S, T]")
        p_t_t = None  # type: p[T, T]
        if t:
            return p_t_t # E: Incompatible return value type (got "p[T, T]", expected "p[S, T]")
        t = t
        s = s
        p_s_t = None  # type: p[S, T]
        return p_s_t
[out]

[case testProhibitTypeApplicationToGenericFunctions]
from typing import TypeVar
T = TypeVar('T')
def f(x: T) -> T: pass

y = f[int]  # E: Type application is only supported for generic classes
[out]


-- Generic types in expressions
-- ----------------------------


[case testTypeApplicationArgs]
from typing import TypeVar, Generic
T = TypeVar('T')
class Node(Generic[T]):
    def __init__(self, x: T) -> None:
        ...
Node[int]()  # E: Too few arguments for "Node"
Node[int](1, 1, 1)  # E: Too many arguments for "Node"
[out]

[case testTypeApplicationTvars]
from typing import TypeVar, Generic
T = TypeVar('T')
S = TypeVar('S')
class A(Generic[T, S]): pass
A[int]()  # E: Type application has too few types (2 expected)
A[int, str, int]() # E: Type application has too many types (2 expected)
[out]

[case testInvalidTypeApplicationType]
a = None # type: A
class A: pass
a[A]()  # E: Value of type "A" is not indexable
A[A]()  # E: The type "Type[A]" is not generic and not indexable
[out]

[case testTypeApplicationArgTypes]
from typing import TypeVar, Generic
T = TypeVar('T')
class Node(Generic[T]):
    def __init__(self, x: T) -> None:
        ...

Node[int](1)
Node[int]('a')  # E: Argument 1 to "Node" has incompatible type "str"; expected "int"

class Dummy(Generic[T]):
    def meth(self, x: T) -> None:
        ...
    def methout(self) -> T:
        ...

Dummy[int]().meth(1)
Dummy[int]().meth('a')  # E: Argument 1 to "meth" of "Dummy" has incompatible type "str"; expected "int"
reveal_type(Dummy[int]())  # E: Revealed type is '__main__.Dummy[builtins.int*]'
reveal_type(Dummy[int]().methout())  # E: Revealed type is 'builtins.int*'
[out]

[case testTypeApplicationArgTypesSubclasses]
from typing import TypeVar, Generic
T = TypeVar('T')
S = TypeVar('S')
class C(Generic[T, S]):
    def __init__(self, x: T, y: S) -> None:
        ...

class D(C[int, T]): ...

D[str](1, 'a')
D[str](1, 1)  # E: Argument 2 to "D" has incompatible type "int"; expected "str"

class E(D[str]): ...
E(1, 'a')
E(1, 1)  # E: Argument 2 to "E" has incompatible type "int"; expected "str"
[out]

[case testTypeApplicationAlias]
from typing import TypeVar, Generic
T = TypeVar('T')
class Node(Generic[T]):
    def __init__(self, x: T) -> None:
        ...

Alias = Node
Alias[int](1)
Alias[int]("a")  # E: Argument 1 to "Node" has incompatible type "str"; expected "int"
[out]

[case testTypeApplicationCrash]
type[int] # this was crashing, see #2302 (comment)  # E: The type "Type[type]" is not generic and not indexable
[out]


-- Generic type aliases
-- --------------------

[case testGenericTypeAliasesBasic]
from typing import TypeVar, Generic
T = TypeVar('T')
S = TypeVar('S')
class Node(Generic[T, S]):
    def __init__(self, x: T, y: S) -> None:
        ...

IntNode = Node[int, S]
IntIntNode = Node[int, int]
SameNode = Node[T, T]

n = Node(1, 1) # type: IntIntNode
n1 = Node(1, 'a') # type: IntIntNode # E: Argument 2 to "Node" has incompatible type "str"; expected "int"

m = Node(1, 1) # type: IntNode
m1 = Node('x', 1) # type: IntNode # E: Argument 1 to "Node" has incompatible type "str"; expected "int"
m2 = Node(1, 1) # type: IntNode[str] # E: Argument 2 to "Node" has incompatible type "int"; expected "str"

s = Node(1, 1) # type: SameNode[int]
reveal_type(s) # E: Revealed type is '__main__.Node[builtins.int, builtins.int]'
s1 = Node(1, 'x') # type: SameNode[int] # E: Argument 2 to "Node" has incompatible type "str"; expected "int"

[out]

[case testGenericTypeAliasesBasic2]
from typing import TypeVar, Generic
T = TypeVar('T')
S = TypeVar('S')
class Node(Generic[T, S]):
    def __init__(self, x: T, y: S) -> None:
        ...

IntNode = Node[int, S]
IntIntNode = Node[int, int]
SameNode = Node[T, T]

def output_bad() -> IntNode[str]:
    return Node(1, 1) # Eroor - bad return type, see out

def input(x: IntNode[str]) -> None:
    pass
input(Node(1, 's'))
input(Node(1, 1)) # E: Argument 2 to "Node" has incompatible type "int"; expected "str"

def output() -> IntNode[str]:
    return Node(1, 'x')
reveal_type(output()) # E: Revealed type is '__main__.Node[builtins.int, builtins.str]'

def func(x: IntNode[T]) -> IntNode[T]:
    return x
reveal_type(func) # E: Revealed type is 'def [T] (x: __main__.Node[builtins.int, T`-1]) -> __main__.Node[builtins.int, T`-1]'

func(1) # E: Argument 1 to "func" has incompatible type "int"; expected "Node[int, <nothing>]"
func(Node('x', 1)) # E: Argument 1 to "Node" has incompatible type "str"; expected "int"
reveal_type(func(Node(1, 'x'))) # E: Revealed type is '__main__.Node[builtins.int, builtins.str*]'

def func2(x: SameNode[T]) -> SameNode[T]:
    return x
reveal_type(func2) # E: Revealed type is 'def [T] (x: __main__.Node[T`-1, T`-1]) -> __main__.Node[T`-1, T`-1]'

func2(Node(1, 'x')) # E: Cannot infer type argument 1 of "func2"
y = func2(Node('x', 'x'))
reveal_type(y) # E: Revealed type is '__main__.Node[builtins.str*, builtins.str*]'

def wrap(x: T) -> IntNode[T]:
    return Node(1, x)

z = None # type: str
reveal_type(wrap(z)) # E: Revealed type is '__main__.Node[builtins.int, builtins.str*]'

[out]
main:13: error: Argument 2 to "Node" has incompatible type "int"; expected "str"

[case testGenericTypeAliasesWrongAliases]
# flags: --show-column-numbers --python-version 3.6 --no-strict-optional
from typing import TypeVar, Generic, List, Callable, Tuple, Union
T = TypeVar('T')
S = TypeVar('S')
class Node(Generic[T, S]):
    def __init__(self, x: T, y: S) -> None:
        ...

A = Node[T] # Error
B = Node[T, T]
C = Node[T, T, T] # Error
D = Node[T, S]
E = Node[Node[T, T], List[T]]

F = Node[List[T, T], S] # Error
G = Callable[..., List[T, T]] # Error
H = Union[int, Tuple[T, Node[T]]] # Error
h: H # Error
h1: H[int, str] # Two errors here, wrong number of args for H, and for Node

x = None # type: D[int, str]
reveal_type(x)
y = None # type: E[int]
reveal_type(y)

X = T # Error

[builtins fixtures/list.pyi]
[out]
main:9:5: error: "Node" expects 2 type arguments, but 1 given
main:11:5: error: "Node" expects 2 type arguments, but 3 given
main:15:10: error: "list" expects 1 type argument, but 2 given
main:16:19: error: "list" expects 1 type argument, but 2 given
main:17:25: error: "Node" expects 2 type arguments, but 1 given
main:18:4: error: "Node" expects 2 type arguments, but 1 given
main:19:5: error: Bad number of arguments for type alias, expected: 1, given: 2
main:19:5: error: "Node" expects 2 type arguments, but 1 given
main:22:1: error: Revealed type is '__main__.Node[builtins.int, builtins.str]'
main:24:1: error: Revealed type is '__main__.Node[__main__.Node[builtins.int, builtins.int], builtins.list[builtins.int]]'
main:26:5: error: Type variable "__main__.T" is invalid as target for type alias

[case testGenericTypeAliasesForAliases]
from typing import TypeVar, Generic, List, Union
T = TypeVar('T')
S = TypeVar('S')

class Node(Generic[T, S]):
    def __init__(self, x: T, y: S) -> None:
        pass

ListedNode = Node[List[T], List[S]]
Second = ListedNode[int, T]
Third = Union[int, Second[str]]

def f2(x: T) -> Second[T]:
    return Node([1], [x])
reveal_type(f2('a')) # E: Revealed type is '__main__.Node[builtins.list[builtins.int], builtins.list[builtins.str*]]'

def f3() -> Third:
    return Node([1], ['x'])
reveal_type(f3()) # E: Revealed type is 'Union[builtins.int, __main__.Node[builtins.list[builtins.int], builtins.list[builtins.str]]]'

[builtins fixtures/list.pyi]

[case testGenericTypeAliasesAny]
from typing import TypeVar, Generic
T = TypeVar('T')
S = TypeVar('S')
class Node(Generic[T, S]):
    def __init__(self, x: T, y: S) -> None:
        self.x = x
        self.y = y

IntNode = Node[int, S]
AnyNode = Node[S, T]

def output() -> IntNode[str]:
    return Node(1, 'x')
x = output() # type: IntNode # This is OK (implicit Any)

y = None # type: IntNode
y.x = 1
y.x = 'x' # E: Incompatible types in assignment (expression has type "str", variable has type "int")
y.y = 1 # Both are OK (implicit Any)
y.y = 'x'

z = Node(1, 'x') # type: AnyNode
reveal_type(z) # E: Revealed type is '__main__.Node[Any, Any]'

[out]

[case testGenericTypeAliasesAcessingMethods]
from typing import TypeVar, Generic, List
T = TypeVar('T')
class Node(Generic[T]):
    def __init__(self, x: T) -> None:
        self.x = x
    def meth(self) -> T:
        return self.x

ListedNode = Node[List[T]]
l = None # type: ListedNode[int]
l.x.append(1)
l.meth().append(1)
reveal_type(l.meth()) # E: Revealed type is 'builtins.list*[builtins.int]'
l.meth().append('x') # E: Argument 1 to "append" of "list" has incompatible type "str"; expected "int"

ListedNode[str]([]).x = 1 # E: Incompatible types in assignment (expression has type "int", variable has type "List[str]")

[builtins fixtures/list.pyi]

[case testGenericTypeAliasesSubclassing]
from typing import TypeVar, Generic, Tuple, List
T = TypeVar('T')
class Node(Generic[T]):
    def __init__(self, x: T) -> None:
        ...

TupledNode = Node[Tuple[T, T]]

class D(TupledNode[T]):
    ...
class L(List[TupledNode[T]]):
    ...

def f_bad(x: T) -> D[T]:
    return D(1)  # Error, see out

L[int]().append(Node((1, 1)))
L[int]().append(5) # E: Argument 1 to "append" of "list" has incompatible type "int"; expected "Node[Tuple[int, int]]"

x = D((1, 1)) # type: D[int]
y = D(5) # type: D[int] # E: Argument 1 to "D" has incompatible type "int"; expected "Tuple[int, int]"

def f(x: T) -> D[T]:
    return D((x, x))
reveal_type(f('a'))  # E: Revealed type is '__main__.D[builtins.str*]'

[builtins fixtures/list.pyi]
[out]
main:15: error: Argument 1 to "D" has incompatible type "int"; expected "Tuple[T, T]"

[case testGenericTypeAliasesSubclassingBad]
from typing import TypeVar, Generic, Tuple, Union
T = TypeVar('T')
class Node(Generic[T]):
    def __init__(self, x: T) -> None:
        ...

TupledNode = Node[Tuple[T, T]]
UNode = Union[int, Node[T]]

class C(TupledNode): ... # Same as TupledNode[Any]
class D(TupledNode[T]): ...
class E(Generic[T], UNode[T]): ... # E: Invalid base class

reveal_type(D((1, 1))) # E: Revealed type is '__main__.D[builtins.int*]'
[builtins fixtures/list.pyi]

[case testGenericTypeAliasesUnion]
from typing import TypeVar, Generic, Union, Any
T = TypeVar('T')
class Node(Generic[T]):
    def __init__(self, x: T) -> None:
        self.x = x

UNode = Union[int, Node[T]]
x = 1 # type: UNode[int]

x + 1 # E: Unsupported left operand type for + ("Node[int]") \
      # N: Left operand is of type "Union[int, Node[int]]"
if not isinstance(x, Node):
    x + 1

if not isinstance(x, int):
   x.x = 1
   x.x = 'a' # E: Incompatible types in assignment (expression has type "str", variable has type "int")

def f(x: T) -> UNode[T]:
    if 1:
        return Node(x)
    else:
        return 1

reveal_type(f(1)) # E: Revealed type is 'Union[builtins.int, __main__.Node[builtins.int*]]'

TNode = Union[T, Node[int]]
s = 1 # type: TNode[str] # E: Incompatible types in assignment (expression has type "int", variable has type "Union[str, Node[int]]")

if not isinstance(s, str):
    s.x = 1

z = None # type: TNode # Same as TNode[Any]
z.x
z.foo() # E: Item "Node[int]" of "Union[Any, Node[int]]" has no attribute "foo"

[builtins fixtures/isinstance.pyi]

[case testGenericTypeAliasesTuple]
from typing import TypeVar, Tuple
T = TypeVar('T')

SameTP = Tuple[T, T]
IntTP = Tuple[int, T]

def f1(x: T) -> SameTP[T]:
    return x, x

a, b, c = f1(1) # E: Need more than 2 values to unpack (3 expected)
x, y = f1(1)
reveal_type(x) # E: Revealed type is 'builtins.int'

def f2(x: IntTP[T]) -> IntTP[T]:
    return x

f2((1, 2, 3)) # E: Argument 1 to "f2" has incompatible type "Tuple[int, int, int]"; expected "Tuple[int, <nothing>]"
reveal_type(f2((1, 'x'))) # E: Revealed type is 'Tuple[builtins.int, builtins.str*]'

[builtins fixtures/for.pyi]

[case testGenericTypeAliasesCallable]
from typing import TypeVar, Generic, Callable
T = TypeVar('T')
class Node(Generic[T]):
    def __init__(self, x: T) -> None:
        ...

BadC = Callable[T] # E: Please use "Callable[[<parameters>], <return type>]" or "Callable"

C = Callable[..., T]
C2 = Callable[[T, T], Node[T]]

def make_cb(x: T) -> C[T]:
    return lambda *args: x

reveal_type(make_cb(1)) # E: Revealed type is 'def (*Any, **Any) -> builtins.int*'

def use_cb(arg: T, cb: C2[T]) -> Node[T]:
    return cb(arg, arg)

use_cb(1, 1) # E: Argument 2 to "use_cb" has incompatible type "int"; expected "Callable[[int, int], Node[int]]"
my_cb = None # type: C2[int]
use_cb('x', my_cb) # E: Argument 2 to "use_cb" has incompatible type "Callable[[int, int], Node[int]]"; expected "Callable[[str, str], Node[str]]"
reveal_type(use_cb(1, my_cb)) # E: Revealed type is '__main__.Node[builtins.int]'

[out]

[case testGenericTypeAliasesPEPBasedExample]
from typing import TypeVar, List, Tuple
T = TypeVar('T', int, bool)

Vec = List[Tuple[T, T]]

vec = []  # type: Vec[bool]
vec.append('x') # E: Argument 1 to "append" of "list" has incompatible type "str"; expected "Tuple[bool, bool]"
reveal_type(vec[0]) # E: Revealed type is 'Tuple[builtins.bool, builtins.bool]'

def fun1(v: Vec[T]) -> T:
    return v[0][0]
def fun2(v: Vec[T], scale: T) -> Vec[T]:
    return v

reveal_type(fun1([(1, 1)])) # E: Revealed type is 'builtins.int*'
fun1(1) # E: Argument 1 to "fun1" has incompatible type "int"; expected "List[Tuple[int, int]]"
fun1([(1, 'x')]) # E: Cannot infer type argument 1 of "fun1"

reveal_type(fun2([(1, 1)], 1)) # E: Revealed type is 'builtins.list[Tuple[builtins.int*, builtins.int*]]'
fun2([('x', 'x')], 'x') # E: Value of type variable "T" of "fun2" cannot be "str"

[builtins fixtures/list.pyi]

[case testGenericTypeAliasesImporting]
from typing import TypeVar
from a import Node, TupledNode
T = TypeVar('T')

n = None # type: TupledNode[int]
n.x = 1
n.y = (1, 1)
n.y = 'x' # E: Incompatible types in assignment (expression has type "str", variable has type "Tuple[int, int]")

def f(x: Node[T, T]) -> TupledNode[T]:
    return Node(x.x, (x.x, x.x))

f(1) # E: Argument 1 to "f" has incompatible type "int"; expected "Node[<nothing>, <nothing>]"
f(Node(1, 'x')) # E: Cannot infer type argument 1 of "f"
reveal_type(Node('x', 'x')) # E: Revealed type is 'a.Node[builtins.str*, builtins.str*]'

[file a.py]
from typing import TypeVar, Generic, Tuple
T = TypeVar('T')
S = TypeVar('S')
class Node(Generic[T, S]):
    def __init__(self, x: T, y: S) -> None:
        self.x = x
        self.y = y

TupledNode = Node[T, Tuple[T, T]]

[builtins fixtures/list.pyi]

[case testGenericTypeAliasesImportingWithoutTypeVar]
from typing import Tuple
from lib import Transform

def int_tf(m: int) -> Transform[int, str]:
    def transform(i: int, pos: int) -> Tuple[int, str]:
        pass
    return transform

var: Transform[int, str]
reveal_type(var)  # E: Revealed type is 'def (builtins.int, builtins.int) -> Tuple[builtins.int, builtins.str]'
[file lib.py]
from typing import Callable, TypeVar, Tuple

T = TypeVar('T')
R = TypeVar('R')

Transform = Callable[[T, int], Tuple[T, R]]
[out]

[case testGenericTypeAliasesImportingWithoutTypeVarError]
from a import Alias
x: Alias[int, str]  # E: Bad number of arguments for type alias, expected: 1, given: 2
reveal_type(x)  # E: Revealed type is 'builtins.list[builtins.list[Any]]'

[file a.py]
from typing import TypeVar, List
T = TypeVar('T')

Alias = List[List[T]]
[builtins fixtures/list.pyi]
[out]

[case testGenericAliasWithTypeVarsFromDifferentModules]
from mod import Alias, TypeVar

S = TypeVar('S')
NewAlias = Alias[int, int, S, S]
class C: pass

x: NewAlias[str]
reveal_type(x)  # E: Revealed type is 'builtins.list[Tuple[builtins.int, builtins.int, builtins.str, builtins.str]]'
y: Alias[int, str, C, C]
reveal_type(y)  # E: Revealed type is 'builtins.list[Tuple[builtins.int, builtins.str, __main__.C, __main__.C]]'

[file mod.py]
from typing import TypeVar, List, Tuple
import a
import b
T = TypeVar('T')
Alias = List[Tuple[T, a.T, b.T, b.B.T]]  # alias_tvars here will be ['T', 'a.T', 'b.T', 'b.B.T']

[file a.py]
from typing import TypeVar
T = TypeVar('T')

[file b.py]
from typing import TypeVar

T = TypeVar('T')
class B:
    T = TypeVar('T')
[builtins fixtures/list.pyi]
[out]

[case testTypeAliasesResultingInPlainInstance]
from typing import Optional, Union

O = Optional[int]
U = Union[int]

x: O
y: U

reveal_type(x)  # E: Revealed type is 'Union[builtins.int, None]'
reveal_type(y)  # E: Revealed type is 'builtins.int'

U[int]  # E: Type application targets a non-generic function or class
O[int]  # E: Bad number of arguments for type alias, expected: 0, given: 1  # E: Type application is only supported for generic classes
[out]

[case testAliasesInClassBodyNormalVsSubscripted]
from typing import Union, Type, Iterable

class A: pass
class B(A): pass
class C:
    a = A  # This is a variable
    b = Union[int, str]  # This is an alias
    c: Type[object] = Iterable[int]  # This is however also a variable
    a = B
    b = int  # E: Cannot assign multiple types to name "b" without an explicit "Type[...]" annotation
    c = int
    def f(self, x: a) -> None: pass  # E: Invalid type "__main__.C.a"
    def g(self, x: b) -> None: pass
    def h(self, x: c) -> None: pass  # E: Invalid type "__main__.C.c"
    x: b
    reveal_type(x)  # E: Revealed type is 'Union[builtins.int, builtins.str]'
[out]

[case testGenericTypeAliasesRuntimeExpressionsInstance]
from typing import TypeVar, Generic
T = TypeVar('T')
S = TypeVar('S')
class Node(Generic[T, S]):
    def __init__(self, x: T, y: S) -> None:
        ...

IntNode = Node[int, T]
IntNode[int](1, 1)
IntNode[int](1, 'a')  # E: Argument 2 to "Node" has incompatible type "str"; expected "int"

SameNode = Node[T, T]
ff = SameNode[T](1, 1)  # E: Need type annotation for 'ff'
a = SameNode(1, 'x')
reveal_type(a) # E: Revealed type is '__main__.Node[Any, Any]'
b = SameNode[int](1, 1)
reveal_type(b) # E: Revealed type is '__main__.Node[builtins.int*, builtins.int*]'
SameNode[int](1, 'x') # E: Argument 2 to "Node" has incompatible type "str"; expected "int"

[out]

[case testGenericTypeAliasesRuntimeExpressionsOther]
from typing import TypeVar, Union, Tuple, Callable, Any
T = TypeVar('T')

CA = Callable[[T], int]
TA = Tuple[T, int]
UA = Union[T, int]

cs = CA + 1 # E: The type alias to Callable is invalid in runtime context
reveal_type(cs) # E: Revealed type is 'Any'

ts = TA() # E: The type alias to Tuple is invalid in runtime context
reveal_type(ts) # E: Revealed type is 'Any'

us = UA.x # E: The type alias to Union is invalid in runtime context
reveal_type(us) # E: Revealed type is 'Any'

xx = CA[str] + 1  # E: Type application is only supported for generic classes
yy = TA[str]()  # E: Type application is only supported for generic classes
zz = UA[str].x  # E: Type application is only supported for generic classes

[out]

[case testGenericTypeAliasesTypeVarBinding]
from typing import TypeVar, Generic, List
T = TypeVar('T')
S = TypeVar('S')

class A(Generic[T, S]):
    def __init__(self, x: T, y: S) -> None: ...

class B(Generic[T, S]):
    def __init__(self, x: List[T], y: List[S]) -> None: ...

SameA = A[T, T]
SameB = B[T, T]

class C(Generic[T]):
    a = None # type: SameA[T]
    b = SameB[T]([], [])

reveal_type(C[int]().a) # E: Revealed type is '__main__.A[builtins.int*, builtins.int*]'
reveal_type(C[str]().b) # E: Revealed type is '__main__.B[builtins.str*, builtins.str*]'

[builtins fixtures/list.pyi]

[case testGenericTypeAliasesTypeVarConstraints]
# flags: --show-column-numbers --no-strict-optional
from typing import TypeVar, Generic
T = TypeVar('T', int, list)
S = TypeVar('S', int, list)

class A(Generic[T, S]):
    def __init__(self, x: T, y: S) -> None: ...

BadA = A[str, T]  # One error here
SameA = A[T, T]

x = None # type: SameA[int]
y = None # type: SameA[str] # Two errors here, for both args of A

[builtins fixtures/list.pyi]
[out]
main:9:8: error: Value of type variable "T" of "A" cannot be "str"
main:13: error: Value of type variable "T" of "A" cannot be "str"
main:13: error: Value of type variable "S" of "A" cannot be "str"

[case testGenericTypeAliasesIgnoredPotentialAlias]
class A: ...
Bad = A[int] # type: ignore

reveal_type(Bad) # E: Revealed type is 'Any'
[out]

[case testNoSubscriptionOfBuiltinAliases]
from typing import List, TypeVar

list[int]() # E: "list" is not subscriptable

ListAlias = List
def fun() -> ListAlias[int]:
    pass

reveal_type(fun())  # E: Revealed type is 'builtins.list[builtins.int]'

BuiltinAlias = list
BuiltinAlias[int]() # E: "list" is not subscriptable

#check that error is reported only once, and type is still stored
T = TypeVar('T')
BadGenList = list[T] # E: "list" is not subscriptable

reveal_type(BadGenList[int]()) # E: Revealed type is 'builtins.list[builtins.int*]'
reveal_type(BadGenList()) # E: Revealed type is 'builtins.list[Any]'

[builtins fixtures/list.pyi]
[out]

[case testImportedTypeAliasInRuntimeContext]
from m import Alias

n = Alias[int]([1])
reveal_type(n)  # E: Revealed type is 'm.Node[builtins.list*[builtins.int]]'
bad = Alias[str]([1])  # E: List item 0 has incompatible type "int"; expected "str"

n2 = Alias([1]) # Same as Node[List[Any]]
reveal_type(n2)  # E: Revealed type is 'm.Node[builtins.list*[Any]]'
[file m.py]
from typing import TypeVar, Generic, List
T = TypeVar('T')

class Node(Generic[T]):
    def __init__(self, x: T) -> None:
        self.x = x

Alias = Node[List[T]]
[builtins fixtures/list.pyi]
[out]

-- Simplified declaration of generics
-- ----------------------------------

[case testSimplifiedGenericSimple]
from typing import TypeVar, Generic
T = TypeVar('T')
S = TypeVar('S')
class B(Generic[T]):
    def b(self) -> T: ...

class C(Generic[T]):
    def c(self) -> T: ...

class D(B[T], C[S]): ...

reveal_type(D[str, int]().b()) # E: Revealed type is 'builtins.str*'
reveal_type(D[str, int]().c()) # E: Revealed type is 'builtins.int*'
[builtins fixtures/list.pyi]
[out]

[case testSimplifiedGenericCallable]
from typing import TypeVar, Generic, Callable
T = TypeVar('T')
S = TypeVar('S')
class B(Generic[T]):
    def b(self) -> T: ...

class D(B[Callable[[T], S]]): ...

reveal_type(D[str, int]().b()) # E: Revealed type is 'def (builtins.str*) -> builtins.int*'
[builtins fixtures/list.pyi]
[out]

[case testSimplifiedGenericComplex]
from typing import TypeVar, Generic, Tuple
T = TypeVar('T')
S = TypeVar('S')
U = TypeVar('U')

class A(Generic[T, S]):
    pass

class B(Generic[T, S]):
    def m(self) -> Tuple[T, S]:
        pass

class C(A[S, B[T, int]], B[U, A[int, T]]):
    pass

c = C[object, int, str]()
reveal_type(c.m()) # E: Revealed type is 'Tuple[builtins.str*, __main__.A*[builtins.int, builtins.int*]]'
[builtins fixtures/tuple.pyi]
[out]


[case testSimplifiedGenericOrder]
from typing import TypeVar, Generic
T = TypeVar('T')
S = TypeVar('S')

class B(Generic[T]):
    def b(self) -> T: ...

class C(Generic[T]):
    def c(self) -> T: ...

class D(B[T], C[S], Generic[S, T]): ...

reveal_type(D[str, int]().b()) # E: Revealed type is 'builtins.int*'
reveal_type(D[str, int]().c()) # E: Revealed type is 'builtins.str*'
[builtins fixtures/list.pyi]
[out]

[case testSimplifiedGenericDuplicate]
from typing import TypeVar, Generic
T = TypeVar('T')

class A(Generic[T, T]): # E: Duplicate type variables in Generic[...] or Protocol[...]
    pass

a = A[int]()
[builtins fixtures/list.pyi]
[out]

[case testSimplifiedGenericNotAll]
from typing import TypeVar, Generic
T = TypeVar('T')
S = TypeVar('S')

class A(Generic[T]):
    pass
class B(Generic[T]):
    pass

class C(A[T], B[S], Generic[T]): # E: If Generic[...] or Protocol[...] is present it should list all type variables
    pass

c = C[int, str]()
[builtins fixtures/list.pyi]
[out]

[case testSimplifiedGenericInvalid]
from typing import TypeVar, Generic
T = TypeVar('T')

class A(Generic[T]):
    pass

class B(A[S]): # E: Name 'S' is not defined
    pass
[builtins fixtures/list.pyi]
[out]


-- Multiple assignment with lists
-- ------------------------------


[case testMultipleAssignmentWithLists]
from typing import List
class A: pass
class B: pass
class B2(B): pass
a = None # type: A
b = None # type: B
b2 = None # type: B2

list_a = [a]
list_b = [b]
list_b2 = [b2]

a, b = list_a   # E: Incompatible types in assignment (expression has type "A", variable has type "B")
b, a = list_a   # E: Incompatible types in assignment (expression has type "A", variable has type "B")
b2, b2 = list_b # E: Incompatible types in assignment (expression has type "B", variable has type "B2")

a, a = list_a
b, b2, b = list_b2
[builtins fixtures/for.pyi]

[case testMultipleAssignmentWithListsInInitialization]
from typing import List
class A: pass
list_object = [object()]
list_a = [A()]
a, b = list_object # type: (A, object) # E: Incompatible types in assignment (expression has type "object", variable has type "A")
c, d = list_object # type: (object, A) # E: Incompatible types in assignment (expression has type "object", variable has type "A")
e, f = list_a # type: (A, object)
[builtins fixtures/for.pyi]

[case testMultipleAssignmentWithListAndIndexing]
from typing import List
a = None # type: List[A]
b = None # type: List[int]

a[1], b[1] = a # E: Incompatible types in assignment (expression has type "A", target has type "int")
a[1], a[2] = a

class A: pass
[file builtins.py]
from typing import TypeVar, Generic, Iterable
T = TypeVar('T')
class object: pass
class list(Iterable[T]):
  def __setitem__(self, x: int, v: T) -> None: pass
class int: pass
class type: pass
class tuple: pass
class function: pass
class str: pass

[case testMultipleAssignmentWithIterable]
from typing import Iterable, TypeVar
a = None  # type: int
b = None  # type: str
T = TypeVar('T')

def f(x: T) -> Iterable[T]: pass

a, b = f(a)   # E: Incompatible types in assignment (expression has type "int", variable has type "str")
b, b = f(a)   # E: Incompatible types in assignment (expression has type "int", variable has type "str")
a, a = f(a)
b, b = f(b)
[builtins fixtures/for.pyi]


-- Error messages
-- --------------


[case testErrorWithLongGenericTypeName]
from typing import TypeVar, Generic
B = TypeVar('B')
C = TypeVar('C')
D = TypeVar('D')
E = TypeVar('E')
F = TypeVar('F')
G = TypeVar('G')
H = TypeVar('H')
I = TypeVar('I')
J = TypeVar('J')
K = TypeVar('K')
L = TypeVar('L')
M = TypeVar('M')
N = TypeVar('N')
O = TypeVar('O')
P = TypeVar('P')
Q = TypeVar('Q')
R = TypeVar('R')
S = TypeVar('S')
T = TypeVar('T')
U = TypeVar('U')
V = TypeVar('V')
W = TypeVar('W')
X = TypeVar('X')
Y = TypeVar('Y')
Z = TypeVar('Z')
class OO: pass
a = None # type: A[object, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object, object]

f(a) # E: Argument 1 to "f" has incompatible type "A[...]"; expected "OO"

def f(a: OO) -> None:
    pass
class A(Generic[B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]): pass

[case testErrorWithShorterGenericTypeName]
from typing import TypeVar, Generic
S = TypeVar('S')
T = TypeVar('T')
a = None # type: A[object, B]
f(a) # E: Argument 1 to "f" has incompatible type "A[object, B]"; expected "B"

def f(a: 'B') -> None: pass
class A(Generic[S, T]): pass
class B: pass

[case testErrorWithShorterGenericTypeName2]
from typing import Callable, TypeVar, Generic
S = TypeVar('S')
T = TypeVar('T')
a = None # type: A[object, Callable[[], None]]
f(a) # E: Argument 1 to "f" has incompatible type "A[object, Callable[[], None]]"; expected "B"

def f(a: 'B') -> None: pass
class A(Generic[S, T]): pass
class B: pass


-- Overloads + generics
-- --------------------


[case testGenericArgumentInOverload]
from foo import *
[file foo.pyi]
from typing import overload, List
class A: pass
class B: pass
a, b = None, None # type: (A, B)

@overload
def f(a: List[A]) -> A: pass
@overload
def f(a: B) -> B: pass

b = f([a]) # E: Incompatible types in assignment (expression has type "A", variable has type "B")
a = f([b]) # E: List item 0 has incompatible type "B"; expected "A"
a = f(b)   # E: Incompatible types in assignment (expression has type "B", variable has type "A")

a = f([a])
b = f(b)
[builtins fixtures/list.pyi]

[case testGenericFunctionAsOverloadItem]
from foo import *
[file foo.pyi]
from typing import overload, TypeVar, List
T = TypeVar('T')
class A: pass
class B: pass

@overload
def f(a: B) -> B: pass
@overload
def f(a: List[T]) -> T: pass

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(b)   # E: Incompatible types in assignment (expression has type "B", variable has type "A")

a = f([a])
b = f([b])
b = f(b)
[builtins fixtures/list.pyi]


-- Type variable scoping
-- ---------------------


[case testLocalTypeVariable]
from typing import TypeVar
def f() -> None:
    T = TypeVar('T')
    def g(x: T) -> T: pass
    a = g(1)
    a = 1
    a = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int")
[out]

[case testClassLevelTypeVariable]
from typing import TypeVar
class A:
    T = TypeVar('T')
    def g(self, x: T) -> T: pass
a = A().g(1)
a = 1
a = '' # E: Incompatible types in assignment (expression has type "str", variable has type "int")

[case testGenericInnerClass]
from typing import TypeVar, Generic
T = TypeVar('T')
class A:
    class B(Generic[T]):
        def meth(self) -> T:  ...
    B[int]()
    reveal_type(B[int]().meth) # E: Revealed type is 'def () -> builtins.int*'

A.B[int]()
reveal_type(A.B[int]().meth) # E: Revealed type is 'def () -> builtins.int*'

[case testGenericClassInnerFunctionTypeVariable]
from typing import TypeVar, Generic
T = TypeVar('T')
class A(Generic[T]):
    def __init__(self, a: T) -> None:
        self.a = a
    def f(self, n: int) -> None:
        def g(a: T):
            self.a = a
        g(self.a)
        g(n) # E: Argument 1 to "g" has incompatible type "int"; expected "T"

[case testFunctionInGenericInnerClassTypeVariable]
from typing import TypeVar, Generic

T = TypeVar('T')
class Outer(Generic[T]):
    class Inner:
        x: T  # E: Invalid type "__main__.T"
        def f(self, x: T) -> T: ...  # E: Type variable 'T' is bound by an outer class
        def g(self) -> None:
            y: T  # E: Invalid type "__main__.T"


-- Callable subtyping with generic functions
-- -----------------------------------------


[case testSubtypingWithGenericFunctions]
from typing import TypeVar
A = TypeVar('A')
B = TypeVar('B')

def f1(x: A) -> A: ...
def f2(x: A) -> B: ...
def f3(x: B) -> B: ...
def f4(x: int) -> A: ...

y1 = f1
y1 = f1
y1 = f2
y1 = f3
y1 = f4 # E: Incompatible types in assignment (expression has type "Callable[[int], A]", variable has type "Callable[[A], A]")

y2 = f2
y2 = f2
y2 = f1 # E: Incompatible types in assignment (expression has type "Callable[[A], A]", variable has type "Callable[[A], B]")
y2 = f3 # E: Incompatible types in assignment (expression has type "Callable[[B], B]", variable has type "Callable[[A], B]")
y2 = f4 # E: Incompatible types in assignment (expression has type "Callable[[int], A]", variable has type "Callable[[A], B]")

y3 = f3
y3 = f3
y3 = f1
y3 = f2
y3 = f4 # E: Incompatible types in assignment (expression has type "Callable[[int], A]", variable has type "Callable[[B], B]")

y4 = f4
y4 = f4
y4 = f1 # E: Incompatible types in assignment (expression has type "Callable[[A], A]", variable has type "Callable[[int], A]")
y4 = f2
y4 = f3 # E: Incompatible types in assignment (expression has type "Callable[[B], B]", variable has type "Callable[[int], A]")

[case testSubtypingWithGenericInnerFunctions]
from typing import TypeVar
A = TypeVar('A')
B = TypeVar('B')
T = TypeVar('T')
def outer(t: T) -> None:
    def f1(x: A) -> A: ...
    def f2(x: A) -> B: ...
    def f3(x: T) -> A: ...
    def f4(x: A) -> T: ...
    def f5(x: T) -> T: ...

    y1 = f1
    y1 = f2
    y1 = f3 # E: Incompatible types in assignment (expression has type "Callable[[T], A]", variable has type "Callable[[A], A]")
    y1 = f4 # E: Incompatible types in assignment (expression has type "Callable[[A], T]", variable has type "Callable[[A], A]")
    y1 = f5 # E: Incompatible types in assignment (expression has type "Callable[[T], T]", variable has type "Callable[[A], A]")

    y2 = f2
    y2 = f1 # E: Incompatible types in assignment (expression has type "Callable[[A], A]", variable has type "Callable[[A], B]")

    y3 = f3
    y3 = f1 # E: Incompatible types in assignment (expression has type "Callable[[A], A]", variable has type "Callable[[T], A]")
    y3 = f2
    y3 = f4 # E: Incompatible types in assignment (expression has type "Callable[[A], T]", variable has type "Callable[[T], A]")
    y3 = f5 # E: Incompatible types in assignment (expression has type "Callable[[T], T]", variable has type "Callable[[T], A]")

    y4 = f4
    y4 = f1 # E: Incompatible types in assignment (expression has type "Callable[[A], A]", variable has type "Callable[[A], T]")
    y4 = f2
    y4 = f3 # E: Incompatible types in assignment (expression has type "Callable[[T], A]", variable has type "Callable[[A], T]")
    y4 = f5 # E: Incompatible types in assignment (expression has type "Callable[[T], T]", variable has type "Callable[[A], T]")

    y5 = f5
    y5 = f1
    y5 = f2
    y5 = f3
    y5 = f4
[out]

[case testSubtypingWithGenericFunctionUsingTypevarWithValues]
from typing import TypeVar, Callable
T = TypeVar('T', int, str)
def f(x: T) -> T: pass
def g1(f: Callable[[str], str]) -> None: pass
g1(f)
def g2(f: Callable[[int], int]) -> None: pass
g2(f)
def g3(f: Callable[[object], object]) -> None: pass
g3(f) # E: Argument 1 to "g3" has incompatible type "Callable[[T], T]"; \
           expected "Callable[[object], object]"

[case testSubtypingWithGenericFunctionUsingTypevarWithValues2-skip]
from typing import TypeVar, Callable
T = TypeVar('T', int, str)
def f(x: T) -> T: pass
g = f
g = f


--Operations on type variable types
-- ---------------------------------


[case testTypeVariableTypeEquality]
from typing import TypeVar
T = TypeVar('T')
def f(a: T, b: T) -> T:
    a.__ne__(b)
    if a == b:
        return a
    else:
        return b
[builtins fixtures/ops.pyi]

[case testTypeVariableTypeIs]
from typing import TypeVar
T = TypeVar('T')
def f(a: T, b: T) -> T:
    if a is b or a is 1:
        return a
    else:
        return b
[builtins fixtures/ops.pyi]

[case testTypeVarLessThan]
from typing import TypeVar
T = TypeVar('T')
def f(a: T, b: T) -> T:
    if a < b:  # E: Unsupported left operand type for < ("T")
        return a
    else:
        return b
[builtins fixtures/ops.pyi]

[case testTypeVarReversibleOperator]
from typing import TypeVar
class A:
    def __mul__(cls, other: int) -> str: return ""
T = TypeVar("T", bound=A)
def f(x: T) -> str:
    return reveal_type(x * 0)  # E: Revealed type is 'builtins.str'

[case testTypeVarReversibleOperatorTuple]
from typing import TypeVar, Tuple
class A(Tuple[int, int]):
    def __mul__(cls, other: Tuple[int, int]) -> str: return ""
T = TypeVar("T", bound=A)
def f(x: T) -> str:
    return reveal_type(x * (1, 2) )  # E: Revealed type is 'builtins.str'

[builtins fixtures/tuple.pyi]


-- Subtyping generic callables
-- ---------------------------

[case testSubtypingGenericTypeObject]
from typing import Callable, Generic, TypeVar
T = TypeVar('T')
class C(Generic[T]):
    def __init__(self) -> None: pass
x = C # type: Callable[[], C[int]]
y = C # type: Callable[[], int] # E: Incompatible types in assignment (expression has type "Type[C[Any]]", variable has type "Callable[[], int]")


-- Special cases
-- -------------


[case testIdentityHigherOrderFunction]
from typing import Callable, TypeVar
A = TypeVar('A')
B = TypeVar('B')
def square(n: int) -> int:
    return n
def id(f: Callable[[A], B]) -> Callable[[A], B]:
    return f
g = id(square)
g(1)
g('x')  # E: Argument 1 has incompatible type "str"; expected "int"


[case testIdentityHigherOrderFunction2]
from typing import Callable, TypeVar
A = TypeVar('A')
def voidify(n: int) -> None: pass
def identity(f: Callable[[A], None]) -> Callable[[A], None]:
    return f
identity(voidify)(3)

[case testIdentityHigherOrderFunction3]
from typing import Callable, TypeVar
A = TypeVar('A')
B = TypeVar('B')
def fn(n: B) -> None: pass
def identity(f: A) -> A:
    return f
identity(fn)
identity(fn)('x')

[case testTypeVariableUnionAndCallableInTypeInference]
from typing import Union, Callable, TypeVar
T = TypeVar('T')
def f(x: T, y: Union[T, Callable[[T], None]]) -> None: pass
f('', '')

[case testGenericFunctionsWithUnalignedIds]
from typing import TypeVar
A = TypeVar('A')
B = TypeVar('B')
def f1(x: int, y: A) -> A: ...
def f2(x: int, y: A) -> B: ...
def f3(x: A, y: B) -> B: ...
g = f1
g = f2
g = f3

[case testTypeVariableWithContainerAndTuple]
from typing import TypeVar, Container
T = TypeVar('T')
def f(x: Container[T]) -> T: ...
reveal_type(f((1, 2))) # E: Revealed type is 'builtins.int*'
[typing fixtures/typing-full.pyi]

[case testClassMethodInGenericClassWithGenericConstructorArg]
from typing import TypeVar, Generic
T = TypeVar('T')
class A(Generic[T]):
    def __init__(self, a: T) -> None: pass
    @classmethod
    def f(cls) -> None: pass
[builtins fixtures/classmethod.pyi]

[case testClassMethodInClassWithGenericConstructor]
from typing import TypeVar, Generic
T = TypeVar('T')
class A:
    def __init__(self, a: T) -> None: pass
    @classmethod
    def f(cls) -> None: pass
[builtins fixtures/classmethod.pyi]

[case testGenericOperatorMethodOverlapping]
from typing import TypeVar, Generic, Tuple
T = TypeVar('T')
T2 = TypeVar('T2')
S = TypeVar('S', bound=str)
S2 = TypeVar('S2', bound=str)
class G(Generic[T]):
    pass
class A:
    def __or__(self, x: G[T]) -> G[T]: pass
    def __ior__(self, x: G[T2]) -> G[T2]: pass
class B:
    def __or__(self, x: G[T]) -> G[T]: pass
    def __ior__(self, x: G[S]) -> G[S]: pass \
        # E: Signatures of "__ior__" and "__or__" are incompatible
class C:
    def __or__(self, x: G[S]) -> G[S]: pass
    def __ior__(self, x: G[S2]) -> G[S2]: pass

[case testGenericOperatorMethodOverlapping2]
from typing import TypeVar, Generic, Tuple
X = TypeVar('X')
T = TypeVar('T', int, str)
T2 = TypeVar('T2', int, str)
S = TypeVar('S', float, str)
S2 = TypeVar('S2', float, str)
class G(Generic[X]):
    pass
class A:
    def __or__(self, x: G[T]) -> G[T]: pass
    def __ior__(self, x: G[T2]) -> G[T2]: pass
class B:
    def __or__(self, x: G[T]) -> G[T]: pass
    def __ior__(self, x: G[S]) -> G[S]: pass \
        # E: Signatures of "__ior__" and "__or__" are incompatible
class C:
    def __or__(self, x: G[S]) -> G[S]: pass
    def __ior__(self, x: G[S2]) -> G[S2]: pass
class D:
    def __or__(self, x: G[X]) -> G[X]: pass
    def __ior__(self, x: G[S2]) -> G[S2]: pass \
        # E: Signatures of "__ior__" and "__or__" are incompatible

[case testConstraintInferenceForAnyAgainstTypeT]
from typing import Type, Any, TypeVar

T = TypeVar('T')

def f(c: Type[T]) -> T: ...

x: Any
reveal_type(f(x))  # E: Revealed type is 'Any'

[case testCallTypeTWithGenericBound]
from typing import Generic, TypeVar, Type
T = TypeVar('T')
S = TypeVar('S', bound='A')

class A(Generic[T]): pass

def f(cls: Type[S]) -> None:
    cls()

[case testQualifiedTypeVariableName]
import b
def f(x: b.T) -> b.T: return x
reveal_type(f)
reveal_type(b.g)
[file b.py]
from typing import TypeVar
T = TypeVar('T')
def g(x: T) -> T: return x
[out]
main:3: error: Revealed type is 'def [b.T] (x: b.T`-1) -> b.T`-1'
main:4: error: Revealed type is 'def [T] (x: T`-1) -> T`-1'

[case testPartiallyQualifiedTypeVariableName]
from p import b
def f(x: b.T) -> b.T: return x
reveal_type(f)
reveal_type(b.g)
[file p/__init__.py]
[file p/b.py]
from typing import TypeVar
T = TypeVar('T')
def g(x: T) -> T: return x
[out]
main:3: error: Revealed type is 'def [b.T] (x: b.T`-1) -> b.T`-1'
main:4: error: Revealed type is 'def [T] (x: T`-1) -> T`-1'
