

-- Basic test cases
-- ----------------


[case testBasicContextInference]
from typing import TypeVar, Generic
T = TypeVar('T')
ab = None # type: A[B]
ao = None # type: A[object]
b = None # type: B

ao = f()
ab = f()
b = f() # E: Incompatible types in assignment (expression has type "A[<nothing>]", variable has type "B")

def f() -> 'A[T]': pass

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

[case testBasicContextInferenceForConstructor]
from typing import TypeVar, Generic
T = TypeVar('T')
ab = None # type: A[B]
ao = None # type: A[object]
b = None # type: B

ao = A()
ab = A()
b = A() # E: Incompatible types in assignment (expression has type "A[<nothing>]", variable has type "B")

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

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

ac = f(b) # E: Argument 1 to "f" has incompatible type "B"; expected "C"
ab = f(c) # E: Argument 1 to "f" has incompatible type "C"; expected "B"

ao = f(b)
ab = f(b)
ao = f(c)
ac = f(c)

def f(a: T) -> 'A[T]':
    pass

class A(Generic[T]): pass

class B: pass
class C: pass


-- Local variables
-- ---------------


[case testInferGenericLocalVariableTypeWithEmptyContext]
from typing import TypeVar, Generic
T = TypeVar('T')
def g() -> None:
    ao = None # type: A[object]
    ab = None # type: A[B]
    o = None # type: object
    b = None # type: B

    x = f(o)
    ab = x # E: Incompatible types in assignment (expression has type "A[object]", variable has type "A[B]")
    ao = x
    y = f(b)
    ao = y # E: Incompatible types in assignment (expression has type "A[B]", variable has type "A[object]")
    ab = y

def f(a: T) -> 'A[T]': pass

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

[case testInferLocalVariableTypeWithUnderspecifiedGenericType]
from typing import TypeVar, Generic
T = TypeVar('T')
def g() -> None:
    x = f() # E: Need type annotation for 'x'

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

[case testInferMultipleLocalVariableTypesWithTupleRvalue]
from typing import TypeVar, Generic
T = TypeVar('T')
def g() -> None:
    ao = None # type: A[object]
    ab = None # type: A[B]
    b = None # type: B
    x, y = f(b), f(b)
    ao = x # E: Incompatible types in assignment (expression has type "A[B]", variable has type "A[object]")
    ao = y # E: Incompatible types in assignment (expression has type "A[B]", variable has type "A[object]")
    ab = x
    ab = y

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

[case testInferMultipleLocalVariableTypesWithArrayRvalueAndNesting]
from typing import TypeVar, List, Generic
T = TypeVar('T')
def h() -> None:
    ao = None # type: A[object]
    ab = None # type: A[B]
    b = None # type: B
    x, y = g(f(b))
    ao = x # E: Incompatible types in assignment (expression has type "A[B]", variable has type "A[object]")
    ao = y # E: Incompatible types in assignment (expression has type "A[B]", variable has type "A[object]")
    ab = x
    ab = y

def f(a: T) -> 'A[T]': pass
def g(a: T) -> List[T]: pass

class A(Generic[T]): pass
class B: pass
[builtins fixtures/for.pyi]
[out]


-- Return types with multiple tvar instances
-- -----------------------------------------


[case testInferenceWithTypeVariableTwiceInReturnType]
from typing import TypeVar, Tuple, Generic
T = TypeVar('T')
b = None # type: B
o = None # type: object
ab = None # type: A[B]
ao = None # type: A[object]

ab, ao = f(b) # Fail
ao, ab = f(b) # Fail

ao, ao = f(b)
ab, ab = f(b)
ao, ao = f(o)

def f(a: T) -> 'Tuple[A[T], A[T]]': pass

class A(Generic[T]): pass
class B: pass
[builtins fixtures/tuple.pyi]
[out]
main:8: error: Incompatible types in assignment (expression has type "A[B]", variable has type "A[object]")
main:9: error: Incompatible types in assignment (expression has type "A[B]", variable has type "A[object]")

[case testInferenceWithTypeVariableTwiceInReturnTypeAndMultipleVariables]
from typing import TypeVar, Tuple, Generic
S = TypeVar('S')
T = TypeVar('T')
b = None # type: B
o = None # type: object
ab = None # type: A[B]
ao = None # type: A[object]

ao, ao, ab = f(b, b)     # Fail
ao, ab, ao = g(b, b)     # Fail
ao, ab, ab, ab = h(b, b) # Fail
ab, ab, ao, ab = h(b, b) # Fail

ao, ab, ab = f(b, b)
ab, ab, ao = g(b, b)
ab, ab, ab, ab = h(b, b)

def f(a: S, b: T) -> 'Tuple[A[S], A[T], A[T]]': pass
def g(a: S, b: T) -> 'Tuple[A[S], A[S], A[T]]': pass
def h(a: S, b: T) -> 'Tuple[A[S], A[S], A[T], A[T]]': pass

class A(Generic[T]): pass
class B: pass
[builtins fixtures/tuple.pyi]
[out]
main:9: error: Incompatible types in assignment (expression has type "A[B]", variable has type "A[object]")
main:10: error: Incompatible types in assignment (expression has type "A[B]", variable has type "A[object]")
main:11: error: Incompatible types in assignment (expression has type "A[B]", variable has type "A[object]")
main:12: error: Incompatible types in assignment (expression has type "A[B]", variable has type "A[object]")


-- Multiple tvar instances in arguments
-- ------------------------------------


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

ab = f(b, o) # E: Argument 2 to "f" has incompatible type "object"; expected "B"
ab = f(o, b) # E: Argument 1 to "f" has incompatible type "object"; expected "B"
ac = f(b, c) # E: Argument 1 to "f" has incompatible type "B"; expected "C"
ac = f(c, b) # E: Argument 2 to "f" has incompatible type "B"; expected "C"

ao = f(b, c)
ao = f(c, b)
ab = f(c, b)

def f(a: T, b: T) -> 'A[T]': pass

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


-- Nested generic function calls
-- -----------------------------


[case testNestedGenericFunctionCall1]
from typing import TypeVar, Generic
T = TypeVar('T')
aab = None # type: A[A[B]]
aao = None # type: A[A[object]]
ao = None # type: A[object]
b = None # type: B
o = None # type: object

aab = f(f(o)) # E: Argument 1 to "f" has incompatible type "object"; expected "B"

aab = f(f(b))
aao = f(f(b))
ao = f(f(b))

def f(a: T) -> 'A[T]': pass

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

[case testNestedGenericFunctionCall2]
from typing import TypeVar, Generic
T = TypeVar('T')
ab = None # type: A[B]
ao = None # type: A[object]
b = None # type: B
o = None # type: object

ab = f(g(o)) # E: Argument 1 to "g" has incompatible type "object"; expected "B"

ab = f(g(b))
ao = f(g(b))

def f(a: T) -> T: pass

def g(a: T) -> 'A[T]': pass

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

[case testNestedGenericFunctionCall3]
from typing import TypeVar, Generic
T = TypeVar('T')
ab = None # type: A[B]
ao = None # type: A[object]
b = None # type: B
o = None # type: object

ab = f(g(o), g(b)) # E: Argument 1 to "g" has incompatible type "object"; expected "B"
ab = f(g(b), g(o)) # E: Argument 1 to "g" has incompatible type "object"; expected "B"

ab = f(g(b), g(b))
ao = f(g(b), g(o))
ao = f(g(o), g(b))

def f(a: T, b: T) -> T:
    pass

def g(a: T) -> 'A[T]': pass

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


-- Method calls
-- ------------


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

ab.g(f(o))        # E: Argument 1 to "f" has incompatible type "object"; expected "B"
ac = f(b).g(f(c)) # E: Incompatible types in assignment (expression has type "A[B]", variable has type "A[C]")
ac = f(c).g(f(b)) # E: Argument 1 to "f" has incompatible type "B"; expected "C"

ab = f(b).g(f(c))
ab.g(f(c))

def f(a: T) -> 'A[T]': pass

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

class B: pass
class C(B): pass


-- List expressions
-- ----------------


[case testEmptyListExpression]
from typing import List
aa = None # type: List[A]
ao = None # type: List[object]
a = None # type: A

a = [] # E: Incompatible types in assignment (expression has type "List[<nothing>]", variable has type "A")

aa = []
ao = []

class A: pass
[builtins fixtures/list.pyi]

[case testSingleItemListExpressions]
from typing import List
aa = None # type: List[A]
ab = None # type: List[B]
ao = None # type: List[object]
a = None # type: A
b = None # type: B

aa = [b] # E: List item 0 has incompatible type "B"; expected "A"
ab = [a] # E: List item 0 has incompatible type "A"; expected "B"

aa = [a]
ab = [b]
ao = [a]
aa = [None]
ao = [None]

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

[case testMultiItemListExpressions]
from typing import List
aa = None # type: List[A]
ab = None # type: List[B]
ao = None # type: List[object]
a = None # type: A
b = None # type: B

ab = [b, a] # E: List item 1 has incompatible type "A"; expected "B"
ab = [a, b] # E: List item 0 has incompatible type "A"; expected "B"

aa = [a, b, a]
ao = [a, b]

class A: pass
class B(A): pass
[builtins fixtures/list.pyi]

[case testLocalVariableInferenceFromEmptyList]
import typing
def f() -> None:
    a = []     # E: Need type annotation for 'a'
    b = [None]
    c = [B()]
    c = [object()] # E: List item 0 has incompatible type "object"; expected "B"
    c = [B()]
class B: pass
[builtins fixtures/list.pyi]
[out]

[case testNestedListExpressions]
from typing import List
aao = None # type: List[List[object]]
aab = None # type: List[List[B]]
ab = None # type: List[B]
b = None # type: B
o = None # type: object

aao = [[o], ab] # E: List item 1 has incompatible type "List[B]"; expected "List[object]"
aab = [[], [o]] # E: List item 0 has incompatible type "object"; expected "B"

aao = [[None], [b], [], [o]]
aab = [[None], [b], []]
aab = [ab, []]

class B: pass
[builtins fixtures/list.pyi]


-- Complex context
-- ---------------


[case testParenthesesAndContext]
from typing import List
l = ([A()]) # type: List[object]
class A: pass
[builtins fixtures/list.pyi]

[case testComplexTypeInferenceWithTuple]
from typing import TypeVar, Tuple, Generic
k = TypeVar('k')
t = TypeVar('t')
v = TypeVar('v')
def f(x: Tuple[k]) -> 'A[k]': pass

d = f((A(),)) # type: A[A[B]]

class A(Generic[t]): pass
class B: pass
class C: pass
class D(Generic[k, v]): pass
[builtins fixtures/list.pyi]


-- Dictionary literals
-- -------------------


[case testDictionaryLiteralInContext]
from typing import Dict, TypeVar, Generic
t = TypeVar('t')
class A(Generic[t]): pass
class B: pass
class C: pass
a_b = A() # type: A[B]
a_c = A() # type: A[C]
d = {A() : a_c,
     a_b : A()} # type: Dict[A[B], A[C]]
[builtins fixtures/dict.pyi]


-- Special cases (regression tests etc.)
-- -------------------------------------


[case testInitializationWithInferredGenericType]
from typing import TypeVar, Generic
T = TypeVar('T')
c = f(A()) # type: C[A] # E: Argument 1 to "f" has incompatible type "A"; expected "C[A]"

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

[case testInferredGenericTypeAsReturnValue]
from typing import TypeVar, Generic
T = TypeVar('T')
def t() -> 'A[B]':
    return f(D()) # E: Argument 1 to "f" has incompatible type "D"; expected "B"
    return A()
    return f(C())

def f(a: T) -> 'A[T]': pass
class A(Generic[T]): pass
class B: pass
class C(B): pass
class D: pass
[out]

[case testIntersectionWithInferredGenericArgument]
from foo import *
[file foo.pyi]
from typing import overload, TypeVar, Generic
T = TypeVar('T')
f(A())

@overload
def f(x: 'A[B]') -> None: pass
@overload
def f(x: 'B') -> None: pass
class A(Generic[T]): pass
class B: pass

[case testInferenceWithAbstractClassContext]
from typing import TypeVar, Generic
from abc import abstractmethod, ABCMeta
t = TypeVar('t')
x = A() # type: I[int]
a_object = A() # type: A[object]
y = a_object # type: I[int] # E: Incompatible types in assignment (expression has type "A[object]", variable has type "I[int]")

class I(Generic[t]):
    @abstractmethod
    def f(self): pass
class A(I[t], Generic[t]):
    def f(self): pass

[case testInferenceWithAbstractClassContext2]
from typing import TypeVar, Generic
from abc import abstractmethod, ABCMeta
t = TypeVar('t')
a = f(A()) # type: A[int]
a_int = A() # type: A[int]
aa = f(a_int)
class I(Generic[t]): pass
class A(I[t], Generic[t]): pass
def f(i: I[t]) -> A[t]: pass

[case testInferenceWithAbstractClassContext3]
from typing import TypeVar, Generic, Iterable
t = TypeVar('t')
class set(Generic[t]):
    def __init__(self, iterable: Iterable[t]) -> None: pass
b = bool()
l = set([b])
l = set([object()]) # E: List item 0 has incompatible type "object"; expected "bool"
[builtins fixtures/for.pyi]


-- Infer generic type in 'Any' context
-- -----------------------------------


[case testInferGenericTypeInAnyContext]
from typing import Any, TypeVar, Generic
s = TypeVar('s')
t = TypeVar('t')
x = [] # type: Any
y = C() # type: Any
class C(Generic[s, t]): pass
[builtins fixtures/list.pyi]


-- Lambdas
-- -------


[case testInferLambdaArgumentTypeUsingContext]
from typing import Callable
f = None # type: Callable[[B], A]
f = lambda x: x.o
f = lambda x: x.x # E: "B" has no attribute "x"
class A: pass
class B:
  o = None # type: A

[case testInferLambdaReturnTypeUsingContext]
from typing import List, Callable
f = None # type: Callable[[], List[A]]
f = lambda: []
f = lambda: [B()]  # E: List item 0 has incompatible type "B"; expected "A"
class A: pass
class B: pass
[builtins fixtures/list.pyi]

[case testInferLambdaTypeUsingContext]
x : str = (lambda x: x + 1)(1)  # E: Incompatible types in assignment (expression has type "int", variable has type "str")
reveal_type((lambda x, y: x + y)(1, 2))  # E: Revealed type is 'builtins.int'
(lambda x, y: x + y)(1, "")  # E: Unsupported operand types for + ("int" and "str")
(lambda *, x, y: x + y)(x=1, y="")  # E: Unsupported operand types for + ("int" and "str")
reveal_type((lambda s, i: s)(i=0, s='x')) # E: Revealed type is 'builtins.str'
reveal_type((lambda s, i: i)(i=0, s='x')) # E: Revealed type is 'builtins.int'
reveal_type((lambda x, s, i: x)(1.0, i=0, s='x')) # E: Revealed type is 'builtins.float'
(lambda x, s, i: x)() # E: Too few arguments
(lambda: 0)(1) # E: Too many arguments
-- varargs are not handled, but it should not crash
reveal_type((lambda *k, s, i: i)(type, i=0, s='x')) # E: Revealed type is 'Any'
reveal_type((lambda s, *k, i: i)(i=0, s='x')) # E: Revealed type is 'Any'
reveal_type((lambda s, i, **k: i)(i=0, s='x')) # E: Revealed type is 'Any'
[builtins fixtures/dict.pyi]

[case testInferLambdaAsGenericFunctionArgument]
from typing import TypeVar, List, Any, Callable
t = TypeVar('t')
class A:
  x = None # type: A
def f(a: List[t], fn: Callable[[t], Any]) -> None: pass
list_a = [] # type: List[A]
f(list_a, lambda a: a.x)
[builtins fixtures/list.pyi]

[case testLambdaWithoutContext]
reveal_type(lambda x: x)  # E: Revealed type is 'def (x: Any) -> Any'
reveal_type(lambda x: 1)  # E: Revealed type is 'def (x: Any) -> builtins.int'

[case testLambdaContextVararg]
from typing import Callable
def f(t: Callable[[str], str]) -> str: ''
f(lambda *_: '')

[case testInvalidContextForLambda]
from typing import Callable
f = lambda x: A() # type: Callable[[], A]
f2 = lambda: A() # type: Callable[[A], A]
class A: pass
[out]
main:2: error: Incompatible types in assignment (expression has type "Callable[[Any], A]", variable has type "Callable[[], A]")
main:2: error: Cannot infer type of lambda
main:3: error: Incompatible types in assignment (expression has type "Callable[[], A]", variable has type "Callable[[A], A]")
main:3: error: Cannot infer type of lambda

[case testEllipsisContextForLambda]
from typing import Callable
f1 = lambda x: 1 # type: Callable[..., int]
f2 = lambda: 1 # type: Callable[..., int]
f3 = lambda *args, **kwargs: 1 # type: Callable[..., int]
f4 = lambda x: x # type: Callable[..., int]
g = lambda x: 1 # type: Callable[..., str]
[builtins fixtures/dict.pyi]
[out]
main:6: error: Incompatible types in assignment (expression has type "Callable[[Any], int]", variable has type "Callable[..., str]")
main:6: error: Incompatible return value type (got "int", expected "str")

[case testEllipsisContextForLambda2]
from typing import TypeVar, Callable
T = TypeVar('T')
def foo(arg: Callable[..., T]) -> None: pass
foo(lambda: 1)

[case testLambdaNoneInContext]
from typing import Callable
def f(x: Callable[[], None]) -> None: pass
def g(x: Callable[[], int]) -> None: pass
f(lambda: None)
g(lambda: None)

[case testIsinstanceInInferredLambda]
from typing import TypeVar, Callable
T = TypeVar('T')
S = TypeVar('S')
class A: pass
class B(A): pass
class C(A): pass
def f(func: Callable[[T], S], *z: T, r: S = None) -> S: pass
f(lambda x: 0 if isinstance(x, B) else 1) # E: Cannot infer type argument 1 of "f"
f(lambda x: 0 if isinstance(x, B) else 1, A())() # E: "int" not callable
f(lambda x: x if isinstance(x, B) else B(), A(), r=B())() # E: "B" not callable
f( # E: Argument 1 to "f" has incompatible type "Callable[[A], A]"; expected "Callable[[A], B]"
    lambda x: B() if isinstance(x, B) else x, # E: Incompatible return value type (got "A", expected "B")
    A(), r=B())
[builtins fixtures/isinstance.pyi]


-- Overloads + generic functions
-- -----------------------------


[case testMapWithOverloadedFunc]
from foo import *
[file foo.pyi]
from typing import TypeVar, Callable, List, overload, Any
t = TypeVar('t')
s = TypeVar('s')
def map(f: Callable[[t], s], seq: List[t]) -> List[s]: pass

@overload
def g(o: object) -> 'B': pass
@overload
def g(o: 'A', x: Any = None) -> 'B': pass

class A: pass
class B: pass

m = map(g, [A()])
b = m # type: List[B]
a = m # type: List[A] # E: Incompatible types in assignment (expression has type "List[B]", variable has type "List[A]")
[builtins fixtures/list.pyi]


-- Boolean operators
-- -----------------


[case testOrOperationInferredFromContext]
from typing import List
a, b, c = None, None, None # type: (List[A], List[B], List[C])
a = a or []
a = [] or a
b = b or [C()]
a = a or b # E: Incompatible types in assignment (expression has type "Union[List[A], List[B]]", variable has type "List[A]")
b = b or c # E: Incompatible types in assignment (expression has type "Union[List[B], List[C]]", variable has type "List[B]")

class A: pass
class B: pass
class C(B): pass
[builtins fixtures/list.pyi]


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


[case testSomeTypeVarsInferredFromContext]
from typing import List, TypeVar
t = TypeVar('t')
s = TypeVar('s')
# Some type variables can be inferred using context, but not all of them.
a = None # type: List[A]
a = f(A(), B())
a = f(B(), B()) # E: Argument 1 to "f" has incompatible type "B"; expected "A"
def f(a: s, b: t) -> List[s]: pass
class A: pass
class B: pass
[builtins fixtures/list.pyi]

[case testSomeTypeVarsInferredFromContext2]
from typing import List, TypeVar
s = TypeVar('s')
t = TypeVar('t')
# Like testSomeTypeVarsInferredFromContext, but tvars in different order.
a = None # type: List[A]
a = f(A(), B())
a = f(B(), B()) # E: Argument 1 to "f" has incompatible type "B"; expected "A"
def f(a: s, b: t) -> List[s]: pass
class A: pass
class B: pass
[builtins fixtures/list.pyi]

[case testLambdaInListAndHigherOrderFunction]
from typing import TypeVar, Callable, List
t = TypeVar('t')
s = TypeVar('s')
map(
  [lambda x: x], [])
def map(f: List[Callable[[t], s]], a: List[t]) -> List[s]: pass
class A: pass
[builtins fixtures/list.pyi]
[out]

[case testChainedAssignmentInferenceContexts]
from typing import List
i = None # type: List[int]
s = None # type: List[str]
i = i = []
i = s = [] # E: Incompatible types in assignment (expression has type "List[str]", variable has type "List[int]")
[builtins fixtures/list.pyi]

[case testContextForAttributeDeclaredInInit]
from typing import List
class A:
  def __init__(self):
    self.x = [] # type: List[int]
a = A()
a.x = []
a.x = [1]
a.x = [''] # E: List item 0 has incompatible type "str"; expected "int"
[builtins fixtures/list.pyi]

[case testListMultiplyInContext]
from typing import List
a = None  # type: List[int]
a = [None] * 3
a = [''] * 3 # E: List item 0 has incompatible type "str"; expected "int"
[builtins fixtures/list.pyi]

[case testUnionTypeContext]
from typing import Union, List, TypeVar
T = TypeVar('T')
def f(x: Union[List[T], str]) -> None: pass
f([1])
f('')
f(1) # E: Argument 1 to "f" has incompatible type "int"; expected "Union[List[<nothing>], str]"
[builtins fixtures/isinstancelist.pyi]

[case testIgnoringInferenceContext]
from typing import TypeVar, List
T = TypeVar('T')
def f(x: List[T]) -> T: pass
def g(y: object) -> None: pass
a = [1]
g(f(a))
[builtins fixtures/list.pyi]

[case testStar2Context]
from typing import Any, Dict, Tuple, Iterable
def f1(iterable: Iterable[Tuple[str, Any]] = None) -> None:
    f2(**dict(iterable))
def f2(iterable: Iterable[Tuple[str, Any]], **kw: Any) -> None:
    pass
[builtins fixtures/dict.pyi]
[out]

[case testInferenceInGenericFunction]
from typing import TypeVar, List
T = TypeVar('T')
def f(a: T) -> None:
    l = []  # type: List[T]
    l.append(a)
    l.append(1) # E: Argument 1 to "append" of "list" has incompatible type "int"; expected "T"
[builtins fixtures/list.pyi]
[out]

[case testInferenceInGenericClass]
from typing import TypeVar, Generic, List
S = TypeVar('S')
T = TypeVar('T')
class A(Generic[S]):
    def f(self, a: T, b: S) -> None:
        l = []  # type: List[T]
        l.append(a)
        l.append(b) # E: Argument 1 to "append" of "list" has incompatible type "S"; expected "T"
[builtins fixtures/list.pyi]
[out]

[case testLambdaInGenericFunction]
from typing import TypeVar, Callable
T = TypeVar('T')
S = TypeVar('S')
def f(a: T, b: S) -> None:
    c = lambda x: x  # type: Callable[[T], S]
[out]
main:5: error: Incompatible types in assignment (expression has type "Callable[[T], T]", variable has type "Callable[[T], S]")
main:5: error: Incompatible return value type (got "T", expected "S")

[case testLambdaInGenericClass]
from typing import TypeVar, Callable, Generic
T = TypeVar('T')
S = TypeVar('S')
class A(Generic[T]):
    def f(self, b: S) -> None:
        c = lambda x: x  # type: Callable[[T], S]
[out]
main:6: error: Incompatible types in assignment (expression has type "Callable[[T], T]", variable has type "Callable[[T], S]")
main:6: error: Incompatible return value type (got "T", expected "S")

[case testRevealTypeContext]
from typing import TypeVar, Callable, Generic
T = TypeVar('T')
class A(Generic[T]):
    pass
reveal_type(A()) # E: Revealed type is '__main__.A[<nothing>]'
b = reveal_type(A())  # type: A[int] # E: Revealed type is '__main__.A[builtins.int]'

[case testUnionWithGenericTypeItemContext]
from typing import TypeVar, Union, List

T = TypeVar('T')

def f(x: Union[T, List[int]]) -> Union[T, List[int]]: pass
reveal_type(f(1)) # E: Revealed type is 'Union[builtins.int*, builtins.list[builtins.int]]'
reveal_type(f([])) # E: Revealed type is 'builtins.list[builtins.int]'
reveal_type(f(None)) # E: Revealed type is 'builtins.list[builtins.int]'
[builtins fixtures/list.pyi]

[case testUnionWithGenericTypeItemContextAndStrictOptional]
# flags: --strict-optional
from typing import TypeVar, Union, List

T = TypeVar('T')

def f(x: Union[T, List[int]]) -> Union[T, List[int]]: pass
reveal_type(f(1)) # E: Revealed type is 'Union[builtins.int*, builtins.list[builtins.int]]'
reveal_type(f([])) # E: Revealed type is 'builtins.list[builtins.int]'
reveal_type(f(None)) # E: Revealed type is 'Union[None, builtins.list[builtins.int]]'
[builtins fixtures/list.pyi]

[case testUnionWithGenericTypeItemContextInMethod]
from typing import TypeVar, Union, List, Generic

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

class C(Generic[T]):
    def f(self, x: Union[T, S]) -> Union[T, S]: pass

c = C[List[int]]()
reveal_type(c.f('')) # E: Revealed type is 'Union[builtins.list[builtins.int], builtins.str*]'
reveal_type(c.f([1])) # E: Revealed type is 'builtins.list[builtins.int]'
reveal_type(c.f([])) # E: Revealed type is 'builtins.list[builtins.int]'
reveal_type(c.f(None)) # E: Revealed type is 'builtins.list[builtins.int]'
[builtins fixtures/list.pyi]

[case testGenericMethodCalledInGenericContext]
from typing import TypeVar, Generic

_KT = TypeVar('_KT')
_VT = TypeVar('_VT')
_T = TypeVar('_T')

class M(Generic[_KT, _VT]):
    def get(self, k: _KT, default: _T) -> _T: ...

def f(d: M[_KT, _VT], k: _KT) -> _VT:
    return d.get(k, None)  # E: "get" of "M" does not return a value

[case testGenericMethodCalledInGenericContext2]
from typing import TypeVar, Generic, Union

_KT = TypeVar('_KT')
_VT = TypeVar('_VT')
_T = TypeVar('_T')

class M(Generic[_KT, _VT]):
    def get(self, k: _KT, default: _T) -> Union[_VT, _T]: ...

def f(d: M[_KT, _VT], k: _KT) -> Union[_VT, None]:
    return d.get(k, None)

[case testLambdaDeferredCrash]
from typing import Callable

class C:
    def f(self) -> None:
        g: Callable[[], int] = lambda: 1 or self.x
        self.x = int()
