[case testSimpleTypeAlias]
import typing
i = int
def f(x: i) -> None: pass
f(1)
f('') # E: Argument 1 to "f" has incompatible type "str"; expected "int"

[case testUnionTypeAlias]
from typing import Union
U = Union[int, str]
def f(x: U) -> None: pass
f(1)
f('')
f(()) # E: Argument 1 to "f" has incompatible type "Tuple[]"; expected "Union[int, str]"

[case testTupleTypeAlias]
from typing import Tuple
T = Tuple[int, str]
def f(x: T) -> None: pass
f((1, 'x'))
f(1) # E: Argument 1 to "f" has incompatible type "int"; expected "Tuple[int, str]"

[case testCallableTypeAlias]
from typing import Callable
A = Callable[[int], None]
f = None  # type: A
f(1)
f('') # E: Argument 1 has incompatible type "str"; expected "int"

[case testListTypeAlias]
from typing import List
A = List[int]
def f(x: A) -> None: pass
f([1])
f(['x']) # E: List item 0 has incompatible type "str"; expected "int"
[builtins fixtures/list.pyi]
[out]

[case testAnyTypeAlias]
from typing import Any
A = Any
def f(x: A) -> None:
    x.foo()
f(1)
f('x')

[case testImportUnionAlias]
import typing
from _m import U
def f(x: U) -> None: pass
f(1)
f('x')
f(()) # E: Argument 1 to "f" has incompatible type "Tuple[]"; expected "Union[int, str]"
[file _m.py]
from typing import Union
U = Union[int, str]
[builtins fixtures/tuple.pyi]

[case testProhibitReassigningAliases]
A = float
A = int  # E: Cannot assign multiple types to name "A" without an explicit "Type[...]" annotation
[out]

[case testProhibitReassigningSubscriptedAliases]
from typing import Callable
A = Callable[[], float]
A = Callable[[], int]  # E: Cannot assign multiple types to name "A" without an explicit "Type[...]" annotation \
                       # E: Value of type "int" is not indexable
                       # the second error is because of `Callable = 0` in lib-stub/typing.pyi
[builtins fixtures/list.pyi]
[out]

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

A = Tuple[T, T]
A = Union[T, int]  # E: Cannot assign multiple types to name "A" without an explicit "Type[...]" annotation \
                   # E: Value of type "int" is not indexable
                   # the second error is because of `Union = 0` in lib-stub/typing.pyi
[out]

[case testProhibitUsingVariablesAsTypesAndAllowAliasesAsTypes]
from typing import TypeVar, Sequence, Type
T = TypeVar('T')

A: Type[float] = int
A = float  # OK
x: A  # E: Invalid type "__main__.A"
def bad(tp: A) -> None:  # E: Invalid type "__main__.A"
    pass

Alias = int
GenAlias = Sequence[T]
def fun(x: Alias) -> GenAlias[int]: pass
[out]

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

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

    a: X[T]
    b: A = a
    c: A[T] = a
    d: A[int] = a # E: Incompatible types in assignment (expression has type "X[T]", variable has type "X[int]")

    def g(self) -> None:
        a: X[T]
        b: X.A = a
        c: X.A[T] = a
        d: X.A[int] = a  # E: Incompatible types in assignment (expression has type "X[T]", variable has type "X[int]")

def g(arg: X[int]) -> None:
    p: X[int] = arg.f()
    q: X.A = arg.f()
    r: X.A[str] = arg.f() # E: Incompatible types in assignment (expression has type "X[int]", variable has type "X[str]")
[out]

[case testProhibitBoundTypeVariableReuseForAliases]
from typing import TypeVar, Generic, List
T = TypeVar('T')
class C(Generic[T]):
    A = List[T] # E: Can't use bound type variable "T" to define generic alias

x: C.A
reveal_type(x) # E: Revealed type is 'builtins.list[Any]'

def f(x: T) -> T:
    A = List[T] # E: Can't use bound type variable "T" to define generic alias
    return x
[builtins fixtures/list.pyi]
[out]

[case testTypeAliasInBuiltins]
def f(x: bytes): pass
bytes
f(1) # E: Argument 1 to "f" has incompatible type "int"; expected "str"
[builtins fixtures/alias.pyi]

[case testEmptyTupleTypeAlias]
from typing import Tuple, Callable
EmptyTuple = Tuple[()]
x = None # type: EmptyTuple
reveal_type(x)  # E: Revealed type is 'Tuple[]'

EmptyTupleCallable = Callable[[Tuple[()]], None]
f = None # type: EmptyTupleCallable
reveal_type(f)  # E: Revealed type is 'def (Tuple[])'
[builtins fixtures/list.pyi]

[case testForwardTypeAlias]
def f(p: 'Alias') -> None:
    pass

reveal_type(f) # E: Revealed type is 'def (p: builtins.int)'
Alias = int
[out]

[case testForwardTypeAliasGeneric]
from typing import TypeVar, Tuple
def f(p: 'Alias[str]') -> None:
    pass

reveal_type(f) # E: Revealed type is 'def (p: Tuple[builtins.int, builtins.str])'
T = TypeVar('T')
Alias = Tuple[int, T]
[out]

[case testRecursiveAliasesErrors1]
from typing import Type, Callable, Union

A = Union[A, int]
B = Callable[[B], int]
C = Type[C]
[out]
main:3: error: Recursive types not fully supported yet, nested types replaced with "Any"
main:4: error: Recursive types not fully supported yet, nested types replaced with "Any"
main:5: error: Recursive types not fully supported yet, nested types replaced with "Any"

[case testRecursiveAliasesErrors2]
from typing import Type, Callable, Union

A = Union[B, int]
B = Callable[[C], int]
C = Type[A]
[out]
main:3: error: Recursive types not fully supported yet, nested types replaced with "Any"
main:4: error: Recursive types not fully supported yet, nested types replaced with "Any"
main:5: error: Recursive types not fully supported yet, nested types replaced with "Any"

[case testDoubleForwardAlias]
from typing import List
x: A
A = List[B]
B = List[int]
reveal_type(x) # E: Revealed type is 'builtins.list[builtins.list[builtins.int]]'
[builtins fixtures/list.pyi]
[out]

[case testDoubleForwardAliasWithNamedTuple]
from typing import List, NamedTuple
x: A
A = List[B]
class B(NamedTuple):
    x: str
reveal_type(x[0].x) # E: Revealed type is 'builtins.str'
[builtins fixtures/list.pyi]
[out]

[case testJSONAliasApproximation]
from typing import List, Union, Dict
x: JSON
JSON = Union[int, str, List[JSON], Dict[str, JSON]] # type: ignore
reveal_type(x) # E: Revealed type is 'Union[builtins.int, builtins.str, builtins.list[Any], builtins.dict[builtins.str, Any]]'
if isinstance(x, list):
    reveal_type(x) # E: Revealed type is 'builtins.list[Any]'
[builtins fixtures/isinstancelist.pyi]
[out]

[case testProhibitedForwardRefToTypeVar]
from typing import TypeVar, List

a: List[T]

T = TypeVar('T')
[builtins fixtures/list.pyi]
[out]
main:3: error: Invalid type "__main__.T"
main:3: note: Forward references to type variables are prohibited

[case testUnsupportedForwardRef]
from typing import List, TypeVar

T = TypeVar('T')

def f(x: T) -> None:
    y: A[T]  # E: Unsupported forward reference to "A"

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

[case testUnsupportedForwardRef2]
from typing import List, TypeVar

def f() -> None:
    X = List[int]
    x: A[X]  # E: Unsupported forward reference to "A"

T = TypeVar('T')
A = List[T]
[builtins fixtures/list.pyi]
[out]

[case testNoneAlias]
from typing import Union
void = type(None)
x: void
reveal_type(x)  # E: Revealed type is 'None'
y: Union[int, void]
reveal_type(y)  # E: Revealed type is 'Union[builtins.int, None]'
[builtins fixtures/bool.pyi]

[case testNoneAliasStrict]
# flags: --strict-optional
from typing import Optional, Union
void = type(None)
x: int
y: Union[int, void]
z: Optional[int]
x = y  # E: Incompatible types in assignment (expression has type "Optional[int]", variable has type "int")
y = z
[builtins fixtures/bool.pyi]

[case testAliasToTupleAndCallable]
from typing import Callable, Tuple
C = Callable
T = Tuple
c: C
t: T
reveal_type(c)  # E: Revealed type is 'def (*Any, **Any) -> Any'
reveal_type(t)  # E: Revealed type is 'builtins.tuple[Any]'
bad: C[int]  # E: Bad number of arguments for type alias, expected: 0, given: 1
also_bad: T[int]  # E: Bad number of arguments for type alias, expected: 0, given: 1
[builtins fixtures/tuple.pyi]
[out]

[case testAliasRefOnClass]
from typing import Generic, TypeVar, Type

T = TypeVar('T')
class C(Generic[T]):
    pass

class N:
    A = C[T]
    B = C[int]

x: N.A[C]
reveal_type(x)  # E: Revealed type is '__main__.C[__main__.C[Any]]'

xx = N.A[C]()
reveal_type(xx)  # E: Revealed type is '__main__.C[__main__.C*[Any]]'

y = N.A()
reveal_type(y)  # E: Revealed type is '__main__.C[Any]'

M = N
b = M.A[int]()
reveal_type(b)  # E: Revealed type is '__main__.C[builtins.int*]'

n: Type[N]
w = n.B()
reveal_type(w)  # E: Revealed type is '__main__.C[builtins.int]'
[out]

[case testTypeAliasesToNamedTuple]
from nt import C, D, E

A1 = C
A2 = D
A3 = E

class Cls:
    A1 = C
    A2 = D
    A3 = E

A1('no')  # E: Argument 1 to "C" has incompatible type "str"; expected "int"
a1 = A1(1)
reveal_type(a1)  # E: Revealed type is 'Tuple[builtins.int, fallback=nt.C]'

A2(0)  # E: Argument 1 to "D" has incompatible type "int"; expected "str"
a2 = A2('yes')
reveal_type(a2)  # E: Revealed type is 'Tuple[builtins.str, fallback=nt.D]'

a3 = A3()
reveal_type(a3)  # E: Revealed type is 'Tuple[builtins.int, builtins.str, fallback=nt.E]'

Cls.A1('no')  # E: Argument 1 has incompatible type "str"; expected "int"
ca1 = Cls.A1(1)
reveal_type(ca1)  # E: Revealed type is 'Tuple[builtins.int, fallback=nt.C]'

Cls.A2(0)  # E: Argument 1 has incompatible type "int"; expected "str"
ca2 = Cls.A2('yes')
reveal_type(ca2)  # E: Revealed type is 'Tuple[builtins.str, fallback=nt.D]'

ca3 = Cls.A3()
reveal_type(ca3)  # E: Revealed type is 'Tuple[builtins.int, builtins.str, fallback=nt.E]'
[file nt.pyi]
from typing import NamedTuple, Tuple

class C(NamedTuple):
    x: int

D = NamedTuple('D', [('y', str)])

class E(Tuple[int, str]):
    pass
[builtins fixtures/tuple.pyi]
[out]

[case testTypeAliasesToAny]
from typing import Any

A = Any
A # this should not fail
[out]

[case testDoubleImportsOfAnAlias]
from b import *
from c import *
[file b.py]
from a import A
[file c.py]
from a import A
[file a.py]
A = int
[out]

[case testDoubleImportsOfAnAlias2]
from b import A
from c import A
[file b.py]
from a import A
[file c.py]
from a import A
[file a.py]
A = int
[out]

[case testDoubleImportsOfAnAlias3]
from b import *
from c import *
[file b.py]
from a import A
[file c.py]
from a import A
[file a.py]
from typing import Union
A = Union[None]
[out]

[case testAliasToClassMethod]
from typing import TypeVar, Generic, Union, Type

T = TypeVar('T', bound=C)

MYPY = False
if MYPY:
    test = classmethod

class C:
    @test
    def meth(cls: Type[T], arg: int) -> Union[T, int]: ...

class D(C): ...

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

[case testFlexibleAlias1]
from typing import TypeVar, List, Tuple
from mypy_extensions import FlexibleAlias

T = TypeVar('T')
U = TypeVar('U')

AnInt = FlexibleAlias[T, int]

x: AnInt[str]
reveal_type(x)  # E: Revealed type is 'builtins.int'

TwoArgs = FlexibleAlias[Tuple[T, U], bool]
TwoArgs2 = FlexibleAlias[Tuple[T, U], List[U]]

def welp(x: TwoArgs[str, int]) -> None:
    reveal_type(x)  # E: Revealed type is 'builtins.bool'

def welp2(x: TwoArgs2[str, int]) -> None:
    reveal_type(x)  # E: Revealed type is 'builtins.list[builtins.int]'


Id = FlexibleAlias[T, T]

def take_id(x: Id[int]) -> None:
    reveal_type(x)  # E: Revealed type is 'builtins.int'

def id(x: Id[T]) -> T:
    return x

# TODO: This doesn't work and maybe it should?
# Indirection = AnInt[T]
# y: Indirection[str]
# reveal_type(y)  # E : Revealed type is 'builtins.int'

# But this does
Indirection2 = FlexibleAlias[T, AnInt[T]]
z: Indirection2[str]
reveal_type(z)  # E: Revealed type is 'builtins.int'

Indirection3 = FlexibleAlias[Tuple[T, U], AnInt[T]]
w: Indirection3[str, int]
reveal_type(w)  # E: Revealed type is 'builtins.int'

[builtins fixtures/dict.pyi]

[case testFlexibleAlias2]
# flags: --always-true=BOGUS
from typing import TypeVar, Any
from mypy_extensions import FlexibleAlias

T = TypeVar('T')

BOGUS = True
if BOGUS:
    Bogus = FlexibleAlias[T, Any]
else:
    Bogus = FlexibleAlias[T, T]

class A:
    x: Bogus[str]

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

def foo(x: Bogus[int]) -> None:
    reveal_type(x)  # E: Revealed type is 'Any'

[builtins fixtures/dict.pyi]

[case testFlexibleAlias3]
# flags: --always-false=BOGUS
from typing import TypeVar, Any
from mypy_extensions import FlexibleAlias

T = TypeVar('T')

BOGUS = True
if BOGUS:
    Bogus = FlexibleAlias[T, Any]
else:
    Bogus = FlexibleAlias[T, T]

class A:
    x: Bogus[str]

reveal_type(A().x)  # E: Revealed type is 'builtins.str'

def foo(x: Bogus[int]) -> None:
    reveal_type(x)  # E: Revealed type is 'builtins.int'

[builtins fixtures/dict.pyi]
