[case testForcedAssignment]
x = 1 # type: object
y = 1
y = x # E: Incompatible types in assignment (expression has type "object", variable has type "int")
x = 2
y = x

[case testJoinAny]
from typing import List, Any

x = None # type: List[Any]

def foo() -> List[int]: pass
def bar() -> List[str]: pass

if bool():
    x = foo()
else:
    x = bar()

x * 2
[builtins fixtures/list.pyi]

[case testGeneratorExpressionTypes]
class A: y = 1
x = [A()]
y = [x]

z = [1,2]
z = [a.y for b in y for a in b]
[builtins fixtures/list.pyi]

[case testIsinstanceNestedTuple]
from typing import Union, List, Tuple, Dict

def f(x: Union[int, str, List]) -> None:
    if isinstance(x, (str, (int,))):
        reveal_type(x)  # E: Revealed type is 'Union[builtins.int, builtins.str]'
        x[1]  # E: Value of type "Union[int, str]" is not indexable
    else:
        reveal_type(x)  # E: Revealed type is 'builtins.list[Any]'
        x[1]
    reveal_type(x)  # E: Revealed type is 'Union[builtins.int, builtins.str, builtins.list[Any]]'
    if isinstance(x, (str, (list,))):
        reveal_type(x)  # E: Revealed type is 'Union[builtins.str, builtins.list[Any]]'
        x[1]
    reveal_type(x)  # E: Revealed type is 'Union[builtins.int, builtins.str, builtins.list[Any]]'
[builtins fixtures/isinstancelist.pyi]

[case testClassAttributeInitialization-skip]
class A:
    x = None # type: int
    def __init__(self) -> None:
        self.y = None # type: int
        z = self.x
        w = self.y

[case testAssignmentSubtypes-skip]
from typing import Union

def foo(x: Union[str, int]):
    if isinstance(x, int):
        x = 'a'
    x + 'a'         # Works in the current code
    z = x           # We probably want this to be of type str.
    y = [x]         # But what type should this be?
    y[0] + 'a'      #  (1) Should this work?
    y + [1]         #  (2) Or this?
    z = 1           # Also, is this valid?

x = None # type: int
y = [x]
[builtins fixtures/isinstancelist.pyi]

[case testFunctionDefaultArgs]
class A: pass
class B(A): y = 1

x =  A()

def foo(x: A = B()):
    x.y   # E: "A" has no attribute "y"
[builtins fixtures/isinstance.pyi]

[case testIsinstanceFancyConditionals]
class A: pass

class B(A):
    y = 1

x =  A()
if isinstance(x, B):
    x.y
while isinstance(x, B):
    x.y
while isinstance(x, B):
    x.y
    x = B()
[builtins fixtures/isinstance.pyi]

[case testSubtypingWithAny]
class A:
    y = 1

class B(A):
    z = 1

def foo(): pass

x = A()
x = B()
x.z
x = foo()
x.z          # E: "A" has no attribute "z"
x.y

[case testSingleMultiAssignment-skip]
x = 'a'
(x, ) = ('a',)

[case testUnionMultiAssignment]
from typing import Union
x = None # type: Union[int, str]
x = 1
x = 'a'
x + 1    # E: Unsupported operand types for + ("str" and "int")
x = 1
(x, y) = ('a', 1)
x + 1    # E: Unsupported operand types for + ("str" and "int")
[builtins fixtures/isinstancelist.pyi]

[case testUnionIfZigzag]
from typing import Union

def f(x: Union[int, str]) -> None:
    x = 1
    if x:
        x = 'a'
        x = 1
    x + 1
[builtins fixtures/isinstancelist.pyi]

[case testTwoLoopsUnion]
from typing import Union

def foo() -> Union[int, str]: pass

def bar() -> None:
    x = foo()
    if isinstance(x, int):
        return
    while bool():
        x + 'a'
        while bool():
            x = foo()
            if bool():
                return
            x = 'a'
    x + 'a'
[builtins fixtures/isinstancelist.pyi]

[case testComplicatedBlocks]
from typing import Union

def foo() -> Union[int, str]: pass

def bar() -> None:
    x = foo()
    if isinstance(x, int):
        return
    while bool():
        x + 'a'
        while bool():
            x = foo()
            if bool():
                return
            x = 'a'
    x + 'a'

    x = foo()
    if isinstance(x, int):
        return
    while bool():
        x + 'a'
        while bool():
            x + 'a'         # E: Unsupported operand types for + ("int" and "str") \
                            # N: Left operand is of type "Union[int, str]"
            x = foo()
            if bool():
                continue
            x = 'a'
        x = 'a'
    x + 'a'
[builtins fixtures/isinstancelist.pyi]

[case testUnionTryExcept]
class A:
    y = A()

class B(A):
    z = 1

x = A()
x = B()
x.z
try:
    x.z
    x = A()
    x = B()
    x.z
except:
    pass
x.z           # E: "A" has no attribute "z"

[case testUnionTryExcept2]
class A:
    y = A()

class B(A):
    z = 1

x = A()
try:
    x.z # E: "A" has no attribute "z"
    x = A()
    x = B()
    x.z
except:
    x.z # E: "A" has no attribute "z"
    x = B()
    x.z
else:
    x = B()
x.z

[case testUnionTryExcept3]
class A:
    y = A()

class B(A):
    z = 1

x = A()
x = B()
try:
    raise BaseException()
    x = A()
except:
    pass
x.z
x = B()
try:
    x = A()
    raise BaseException()
except:
    pass
x.z           # E: "A" has no attribute "z"
x = B()
try:
    pass
except:
    x = A()
    raise BaseException()
x.z
try:
    x = A()
except:
    pass
x.z           # E: "A" has no attribute "z"
x = B()
try:
    pass
except:
    x = A()
x.z           # E: "A" has no attribute "z"
[builtins fixtures/exception.pyi]

[case testUnionTryExcept4]
class A: pass

class B(A):
    z = 1

x = A()
while bool():
    try:
        x.z # E: "A" has no attribute "z"
        x = A()
    except:
        x = B()
    else:
        x = B()
    x.z
[builtins fixtures/exception.pyi]

[case testUnionTryFinally]
class A: pass

class B(A):
    b = 1

x = A()
x = B()
try:
    x = A()
    x.b # E: "A" has no attribute "b"
    x = B()
finally:
    x.b  # E: "A" has no attribute "b"
x.b

[case testUnionTryFinally2]
class A: pass

class B(A):
    b = 1

x = A()
x = B()
try:
    x = A()
    x = B()
except:
    pass
finally:
    pass
x.b      # E: "A" has no attribute "b"

[case testUnionTryFinally3]
class A: pass

class B(A):
    b = 1

x = A()
x = B()
try:
    x = A()
    x = B()
except:
    pass
finally:
    x = B()
x.b

[case testUnionTryFinally4]
class A: pass

class B(A):
    b = 1

while 2:
    x = A()
    x = B()
    try:
        x = A()
        x = B()
    except:
        pass
    finally:
        x.b     # E: "A" has no attribute "b"
        if not isinstance(x, B):
            break
    x.b
[builtins fixtures/isinstancelist.pyi]

[case testUnionTryFinally5]
class A: pass

class B(A):
    b = 1

while 2:
    x = A()
    try:
        x = A()
        x = B()
    finally:
        x.b    # E: "A" has no attribute "b"
        break
        x.b
    x.b

[case testUnionTryFinally6]
class A: pass

class B(A):
    b = 1

def f() -> int:
    x = B()  # type: A
    try:
        x = B()
    except:
        x = A()
        # An exception could occur here
        x = B()
    finally:
        return x.b # E: "A" has no attribute "b"

[case testUnionListIsinstance]
from typing import Union, List

def f(x: Union[List[int], List[str], int]) -> None:
    if isinstance(x, list):
        a = x[0]
        if isinstance(a, int):
            a + 1
            a + 'x' # E: Unsupported operand types for + ("int" and "str")

        # type of a?
        reveal_type(x) # E: Revealed type is 'Union[builtins.list[builtins.int], builtins.list[builtins.str]]'
        x + 1 # E: Unsupported operand types for + ("List[int]" and "int") \
              # E: Unsupported operand types for + ("List[str]" and "int") \
              # N: Left operand is of type "Union[List[int], List[str]]"
    else:
        x[0] # E: Value of type "int" is not indexable
        x + 1
    x[0] # E: Value of type "Union[List[int], List[str], int]" is not indexable
    x + 1 # E: Unsupported operand types for + ("List[int]" and "int") \
          # E: Unsupported operand types for + ("List[str]" and "int") \
          # N: Left operand is of type "Union[List[int], List[str], int]"
[builtins fixtures/isinstancelist.pyi]

[case testUnionListIsinstance2]
from typing import Union, List

class A:
    a = 1

class B: pass
class C: pass

def g(x: Union[A, B]) -> A: pass
def h(x: C) -> A: pass
def f(x: Union[A, B, C]) -> None:
    if isinstance(x, C):
        x = h(x)
    else:
        x = g(x)
    x.a
[builtins fixtures/isinstancelist.pyi]

[case testUnionStrictDefnBasic]
from typing import Union

def foo() -> Union[int, str]: pass

x = foo()
x = 1
x = x + 1
x = foo()
x = x + 1                # E: Unsupported operand types for + ("str" and "int") \
                         # N: Left operand is of type "Union[int, str]"
if isinstance(x, str):
   x = x + 1             # E: Unsupported operand types for + ("str" and "int")
   x = 1
   x = x + 1
[builtins fixtures/isinstancelist.pyi]

[case testSubtypeRedefinitionBasic]
from typing import Union

class A: pass

class B(A):
    y = 1

x = A()
x.y        # E: "A" has no attribute "y"
x = B()
x.y        # OK: x is known to be a B
[builtins fixtures/isinstancelist.pyi]

[case testIsInstanceBasic]
from typing import Union
x = None # type: Union[int, str]
if isinstance(x, str):
    x = x + 1   # E: Unsupported operand types for + ("str" and "int")
    x = x + 'a'
else:
    x = x + 'a' # E: Unsupported operand types for + ("int" and "str")
    x = x + 1
[builtins fixtures/isinstancelist.pyi]

[case testIsInstanceIndexing]
from typing import Union
x = None # type: Union[int, str]
j = [x]
if isinstance(j[0], str):
    j[0] = j[0] + 'a'
    j[0] = j[0] + 1   # E: Unsupported operand types for + ("str" and "int")
else:
    j[0] = j[0] + 'a' # E: Unsupported operand types for + ("int" and "str")
    j[0] = j[0] + 1
[builtins fixtures/isinstancelist.pyi]

[case testIsInstanceSubClassMember]
from typing import Union

class Animal: pass

class Dog(Animal):
    paws = 4  # type: Union[int, str]

    def bark(self): pass

class House:
    pet = None  # type: Animal

h = House()
h.pet = Dog()

while bool():
    if isinstance(h.pet, Dog):
        if isinstance(h.pet.paws, str):
            x = h.pet.paws + 'a'
        y = h.pet.paws + 1   # E: Unsupported operand types for + ("str" and "int") \
                             # N: Left operand is of type "Union[int, str]"
        z = h.pet.paws + 'a' # E: Unsupported operand types for + ("int" and "str") \
                             # N: Left operand is of type "Union[int, str]"
        if isinstance(h.pet.paws, str):
            x = h.pet.paws + 'a'
            break
        y = h.pet.paws + 1
        z = h.pet.paws + 'a' # E: Unsupported operand types for + ("int" and "str")
[builtins fixtures/isinstancelist.pyi]

[case testIsInstanceSubClassReset]
class A:
    pass

class B(A):
    b = 1

class C:
    a = A()

x = C()
x.a.b                   # E: "A" has no attribute "b"
if isinstance(x.a, B):
    x.a.b
    x = C()
    x.a.b               # E: "A" has no attribute "b"
[builtins fixtures/isinstance.pyi]

[case testIsinstanceTuple]
from typing import Union

class A: pass

class B:
    def method2(self, arg: int):
        return 123

class C:
    def method2(self, arg: int):
        return 456

    def method3(self, arg: str):
        return 'abc'

v = A() # type: Union[A, B, C]

if isinstance(v, (B, C)):
    v.method2(123)
    v.method3('xyz') # E: Item "B" of "Union[B, C]" has no attribute "method3"
[builtins fixtures/isinstance.pyi]

[case testIsinstanceNeverWidens]
from typing import Union

class A: pass
class B: pass
class C: pass

a = A()  # type: A
assert isinstance(a, (A, B))
reveal_type(a)  # E: Revealed type is '__main__.A'

b = A()  # type: Union[A, B]
assert isinstance(b, (A, B, C))
reveal_type(b)  # E: Revealed type is 'Union[__main__.A, __main__.B]'
[builtins fixtures/isinstance.pyi]

[case testMemberAssignmentChanges-skip]
from typing import Union

class Dog:
    paws = 1  # type: Union[int, str]

pet = Dog()

pet.paws + 'a'  # E: moo
pet.paws = 'a'
pet.paws + 'a'
pet.paws = 1
pet.paws + 1
[builtins fixtures/isinstancelist.pyi]

[case testIsInstanceSubClassMemberHard-skip]
from typing import Union

class Animal:
    pass

class Dog(Animal):
    paws = 4  # type: Union[int, str]

    def bark(self): pass

class House:
    pet = None  # type: Animal

h = House()
h.pet = Dog()

if isinstance(h.pet, Dog):
    if isinstance(h.pet.paws, str):
        for i in [1]:
            h.pet.paws + 'a'
            if bool():
                break
            h.pet.paws = 1
            h.pet.paws + 1

    if isinstance(h.pet.paws, str):
        h.pet.paws + 'a'
    else:
        h.pet.paws + 1
[builtins fixtures/isinstancelist.pyi]

[case testIsInstanceReturn]
from typing import Union

def foo() -> None:
    x = 1 # type: Union[int, str]
    if isinstance(x, int):
        return
    y = x + 'asdad'

def bar() -> None:
    x = 1 # type: Union[int, str]
    if isinstance(x, int):
        return
    else:
        pass
    y = x + 'asdad'

foo()
[builtins fixtures/isinstancelist.pyi]

[case testIsInstanceBadBreak]
from typing import Union

def foo() -> None:
    x = None # type: Union[int, str]
    if isinstance(x, int):
        for z in [1,2]:
            break
    else:
        pass
    y = x + 'asdad'    # E: Unsupported operand types for + ("int" and "str") \
                       # N: Left operand is of type "Union[int, str]"

foo()
[builtins fixtures/isinstancelist.pyi]

[case testIsInstanceThreeUnion]
from typing import Union, List

x = None # type: Union[int, str, List[int]]

while bool():
    if isinstance(x, int):
        x + 1
    elif isinstance(x, str):
        x + 'a'
    else:
        x + [1]
    x + 'a'           # E: Unsupported operand types for + ("int" and "str") \
                      # E: Unsupported operand types for + ("List[int]" and "str") \
                      # N: Left operand is of type "Union[int, str, List[int]]"

x + [1]               # E: Unsupported operand types for + ("int" and "List[int]") \
                      # E: Unsupported operand types for + ("str" and "List[int]") \
                      # N: Left operand is of type "Union[int, str, List[int]]"
[builtins fixtures/isinstancelist.pyi]

[case testIsInstanceThreeUnion2]
from typing import Union, List
x = None # type: Union[int, str, List[int]]
while bool():
    if isinstance(x, int):
        x + 1
        break
    elif isinstance(x, str):
        x + 'a'
        break
    x + [1]
    x + 'a'           # E: Unsupported operand types for + ("List[int]" and "str")
x + [1]               # E: Unsupported operand types for + ("int" and "List[int]") \
                      # E: Unsupported operand types for + ("str" and "List[int]") \
                      # N: Left operand is of type "Union[int, str, List[int]]"
[builtins fixtures/isinstancelist.pyi]

[case testIsInstanceThreeUnion3]
from typing import Union, List

while bool():
    x = None # type: Union[int, str, List[int]]
    x = 1
    if isinstance(x, int):
        x + 1
        break
    elif isinstance(x, str):
        x + 'a'
        break
    x + [1]           # These lines aren't reached because x was an int
    x + 'a'
x + [1]               # E: Unsupported operand types for + ("int" and "List[int]") \
                      # E: Unsupported operand types for + ("str" and "List[int]") \
                      # N: Left operand is of type "Union[int, str, List[int]]"
[builtins fixtures/isinstancelist.pyi]

[case testRemovingTypeRepeatedly]
from typing import Union

def foo() -> Union[int, str]: pass

for i in [1, 2]:
    x = foo()
    x + 'a'                 # E: Unsupported operand types for + ("int" and "str") \
                            # N: Left operand is of type "Union[int, str]"
    if isinstance(x, int):
        break
    x + 'a'

    x = foo()
    x + 'a'                 # E: Unsupported operand types for + ("int" and "str") \
                            # N: Left operand is of type "Union[int, str]"
    if isinstance(x, int):
        break
    x + 'a'

    x = foo()
    x + 'a'                 # E: Unsupported operand types for + ("int" and "str") \
                            # N: Left operand is of type "Union[int, str]"
    if isinstance(x, int):
        break
    x + 'a'

x + 'a'                    # E: Unsupported operand types for + ("int" and "str") \
                            # N: Left operand is of type "Union[int, str]"
[builtins fixtures/isinstancelist.pyi]

[case testModifyRepeatedly]
from typing import Union

def foo() -> Union[int, str]: pass

x = foo()
x + 1     # E: Unsupported operand types for + ("str" and "int") \
          # N: Left operand is of type "Union[int, str]"
x + 'a'   # E: Unsupported operand types for + ("int" and "str") \
          # N: Left operand is of type "Union[int, str]"

x = 1
x + 1
x + 'a'   # E: Unsupported operand types for + ("int" and "str")

x = 'a'
x + 1     # E: Unsupported operand types for + ("str" and "int")
x + 'a'

x = foo()
x + 1     # E: Unsupported operand types for + ("str" and "int") \
          # N: Left operand is of type "Union[int, str]"
x + 'a'   # E: Unsupported operand types for + ("int" and "str") \
          # N: Left operand is of type "Union[int, str]"
[builtins fixtures/isinstancelist.pyi]

[case testModifyLoop]
from typing import Union

def foo() -> Union[int, str]: pass

x = foo()
x + 1      # E: Unsupported operand types for + ("str" and "int") \
           # N: Left operand is of type "Union[int, str]"
x = 'a'
x + 1      # E: Unsupported operand types for + ("str" and "int")
x = 1
x + 1

while bool():
      x + 1    # E: Unsupported operand types for + ("str" and "int") \
               # N: Left operand is of type "Union[int, str]"
      x = 'a'
[builtins fixtures/isinstancelist.pyi]

[case testModifyLoop2]
from typing import Union

def foo() -> Union[int, str]: pass

x = foo()
x + 1      # E: Unsupported operand types for + ("str" and "int") \
           # N: Left operand is of type "Union[int, str]"
x = 'a'
x + 1      # E: Unsupported operand types for + ("str" and "int")
x = 1
x + 1

for i in [1]:
      x = 'a'

x + 1    # E: Unsupported operand types for + ("str" and "int") \
         # N: Left operand is of type "Union[int, str]"
[builtins fixtures/isinstancelist.pyi]

[case testModifyLoop3]
from typing import Union

def foo() -> Union[int, str]: pass

x = foo()
x = 1

while bool():
    x + 1
    x = 'a'
    break
else:
    x + 1
x + 1      # E: Unsupported operand types for + ("str" and "int") \
           # N: Left operand is of type "Union[int, str]"
x = 1
for y in [1]:
    x + 1
    x = 'a'
    break
else:
    x + 1
x + 1      # E: Unsupported operand types for + ("str" and "int") \
           # N: Left operand is of type "Union[int, str]"
[builtins fixtures/isinstancelist.pyi]

[case testModifyLoopWhile4]
from typing import Union

def foo() -> Union[int, str]: pass

x = foo()
x = 1

while bool():
    x + 1
    if bool():
        x = 'a'
        break
else:
    x + 1
    x = 'a'
x + 'a'
x = 1
while bool():
    x + 1 # E: Unsupported operand types for + ("str" and "int") \
          # N: Left operand is of type "Union[int, str]"
    if bool():
        x = 'a'
        continue
else:
    x + 1 # E: Unsupported operand types for + ("str" and "int") \
          # N: Left operand is of type "Union[int, str]"
    x = 'a'
x + 'a'
[builtins fixtures/isinstancelist.pyi]

[case testModifyLoopFor4]
from typing import Union

def foo() -> Union[int, str]: pass

x = foo()
x = 1

for y in [1]:
    x + 1
    if bool():
        x = 'a'
        break
else:
    x + 1
    x = 'a'
x + 'a'
x = 1
for y in [1]:
    x + 1 # E: Unsupported operand types for + ("str" and "int") \
          # N: Left operand is of type "Union[int, str]"
    if bool():
        x = 'a'
        continue
else:
    x + 1 # E: Unsupported operand types for + ("str" and "int") \
          # N: Left operand is of type "Union[int, str]"
    x = 'a'
x + 'a'
[builtins fixtures/isinstancelist.pyi]

[case testModifyNestedLoop]
from typing import Union

def foo() -> Union[int, str]: pass

x = foo()
x = 1

for y in [1]:
    for z in [1]:
        break
    else:
        x = 'a'
        break
else:
    x + 1
x + 1 # E: Unsupported operand types for + ("str" and "int") \
      # N: Left operand is of type "Union[int, str]"
x = 1
while bool():
    while bool():
        break
    else:
        x = 'a'
        break
else:
    x + 1
x + 1 # E: Unsupported operand types for + ("str" and "int") \
      # N: Left operand is of type "Union[int, str]"
[builtins fixtures/isinstancelist.pyi]

[case testModifyLoopLong]
from typing import Union

class A: a = 1

def foo() -> Union[int, str, A]: pass

def bar() -> None:
    x = foo()
    x + 1  # E: Unsupported operand types for + ("str" and "int") \
           # E: Unsupported left operand type for + ("A") \
           # N: Left operand is of type "Union[int, str, A]"
    if isinstance(x, A):
       x.a
    else:
       if isinstance(x, int):
          x + 1
          x + 'a'  # E: Unsupported operand types for + ("int" and "str")
       else:
          x + 'a'
          x.a      # E: "str" has no attribute "a"
       x = A()

    if isinstance(x, str):
       x + 'a'
    else:
       while bool():
          if isinstance(x, int):
             x + 1
          else:
             x.a
          break
       while bool():
          if isinstance(x, int):
             x + 1
          else:
             x.a
          continue

       while bool():
          if isinstance(x, int):
             x + 1
          else:
             x.a     # E: Item "str" of "Union[str, A]" has no attribute "a"
          x = 'a'
[builtins fixtures/isinstancelist.pyi]

[case testWhileExitCondition1]
from typing import Union
x = 1  # type: Union[int, str]
while isinstance(x, int):
    if bool():
        continue
    x = 'a'
else:
    reveal_type(x)  # E: Revealed type is 'builtins.str'
reveal_type(x)  # E: Revealed type is 'builtins.str'
[builtins fixtures/isinstance.pyi]

[case testWhileExitCondition2]
from typing import Union
x = 1  # type: Union[int, str]
while isinstance(x, int):
    if bool():
        break
    x = 'a'
else:
    reveal_type(x)  # E: Revealed type is 'builtins.str'
reveal_type(x)  # E: Revealed type is 'Union[builtins.int, builtins.str]'
[builtins fixtures/isinstance.pyi]

[case testWhileLinkedList]
from typing import Union
LinkedList = Union['Cons', 'Nil']
class Nil: pass
class Cons:
    tail = None  # type: LinkedList
def last(x: LinkedList) -> Nil:
    while isinstance(x, Cons):
        x = x.tail
    return x
[builtins fixtures/isinstance.pyi]

[case testReturnAndFlow]
def foo() -> int:
    return 1 and 2
    return 'a'
[case testCastIsinstance]
from typing import Union

def foo() -> Union[int, str]: pass

x = foo()
y = 1 # type: int

if isinstance(x, str):
    x = y
x + 1
x + 'a'   # E: Unsupported operand types for + ("int" and "str")
[builtins fixtures/isinstancelist.pyi]

[case testUnreachableCode]
x = 1 # type: int

while bool():
    x = 'a'           # E: Incompatible types in assignment (expression has type "str", variable has type "int")
    break
    x = 'a'           # Note: no error because unreachable code
[builtins fixtures/isinstancelist.pyi]

[case testUnreachableCode2]
x = 1
while bool():
    try:
        pass
    except:
        continue
    else:
        continue
    x + 'a'
[builtins fixtures/isinstance.pyi]

[case testUnreachableWhileTrue]
def f(x: int) -> None:
    while True:
        if x:
            return
    1()
[builtins fixtures/bool.pyi]

[case testUnreachableAssertFalse]
def f() -> None:
    assert False
    1()
[builtins fixtures/bool.pyi]

[case testUnreachableAssertFalse2]
def f() -> None:
    # The old parser doesn't understand the syntax below
    assert False, "hi"
    1()
[builtins fixtures/bool.pyi]

[case testUnreachableReturnOrAssertFalse]
def f(x: int) -> int:
    if x:
        return x
    else:
        assert False
    1()
[builtins fixtures/bool.pyi]

[case testUnreachableTryExcept]
def f() -> None:
    try:
        f()
        return
    except BaseException:
        return
    1()
[builtins fixtures/exception.pyi]

[case testUnreachableTryExceptElse]
def f() -> None:
    try:
        f()
    except BaseException:
        return
    else:
        return
    1()
[builtins fixtures/exception.pyi]

[case testUnreachableTryReturnFinally1]
def f() -> None:
    try:
        return
    finally:
        pass
    1()

[case testUnreachableTryReturnFinally2]
def f() -> None:
    try:
        pass
    finally:
        return
    1()

[case testUnreachableTryReturnExceptRaise]
def f() -> None:
    try:
        return
    except:
        raise
    1()

[case testUnreachableReturnLambda]
from typing import Callable
def g(t: Callable[[int], int]) -> int: pass
def f() -> int:
    return g(lambda x: x)
    1()

[case testIsinstanceAnd]
class A: pass

class B(A):
    flag = 1

x = B() # type: A

if isinstance(x, B) and 1:
   x.flag
[builtins fixtures/isinstancelist.pyi]

[case testIsinstanceShortcircuit]
class A:
    pass

class B(A):
    flag = 1

x = B() # type: A

if isinstance(x, B) and x.flag:
    pass
if isinstance(x, B) or x.flag: # E: "A" has no attribute "flag"
    pass
if not isinstance(x, B) or x.flag:
    pass
if not isinstance(x, B) and x.flag: # E: "A" has no attribute "flag"
    pass
[builtins fixtures/isinstancelist.pyi]

[case testIsinstanceExpression]
class A:
    pass

class B(A):
    flag = 1

x = B() # type: A

x.flag if isinstance(x, B) else 0
0 if not isinstance(x, B) else x.flag
0 if isinstance(x, B) else x.flag # E: "A" has no attribute "flag"
[builtins fixtures/isinstancelist.pyi]

[case testIsinstanceMultiAnd]
class A: pass

class B(A):
    flag = 1

class C(A):
    glaf = 1

x = B() # type: A
y = C() # type: A

if isinstance(x, B) and isinstance(y, C):
    x.flag += 1
    y.glaf += 1
    x() # E: "B" not callable
    y() # E: "C" not callable
else:
    x() # E: "A" not callable
    y() # E: "A" not callable
[builtins fixtures/isinstancelist.pyi]

[case testIsinstanceMultiAndSpecialCase]
class A: pass

class B(A):
    flag = 1

class C(A):
    glaf = 1

x = B() # type: A
y = C() # type: A

if isinstance(x, B) and isinstance(y, int):
    1() # type checking skipped
if isinstance(y, int) and isinstance(x, B):
    1() # type checking skipped
if isinstance(y, int) and y > 42:
    1() # type checking skipped
[builtins fixtures/isinstancelist.pyi]

[case testReturnWithCallExprAndIsinstance]
from typing import Union

def f(x: Union[int, str]) -> None:
    if not isinstance(x, int):
        return foo()
    x()  # E: "int" not callable

def foo(): pass
[builtins fixtures/isinstancelist.pyi]

[case testIsinstanceOr1]
from typing import Optional

def f(a: bool, x: object) -> Optional[int]:
    if a or not isinstance(x, int):
        return None
    reveal_type(x) # E: Revealed type is 'builtins.int'
    return x
[builtins fixtures/isinstance.pyi]

[case testIsinstanceOr2]
from typing import Optional

def g(a: bool, x: object) -> Optional[int]:
    if not isinstance(x, int) or a:
        return None
    reveal_type(x) # E: Revealed type is 'builtins.int'
    return x
[builtins fixtures/isinstance.pyi]

[case testIsinstanceOr3]
from typing import Optional

def h(a: bool, x: object) -> Optional[int]:
    if a or isinstance(x, int):
        return None
    return x # E: Incompatible return value type (got "object", expected "Optional[int]")
[builtins fixtures/isinstance.pyi]

[case testIsinstanceWithOverlappingUnionType]
from typing import Union

def f(x: Union[float, int]) -> None:
    if isinstance(x, float):
        pass
    if not isinstance(x, int):
        f(x)
[builtins fixtures/isinstance.pyi]

[case testIsinstanceWithOverlappingUnionType2]
from typing import Union

class A: pass
class B(A): pass

def f(x: Union[A, B]) -> None:
    if isinstance(x, A):
        pass
    if not isinstance(x, B):
        f(x)
[builtins fixtures/isinstance.pyi]

[case testIsinstanceOfSuperclass]
class A: pass
class B(A): pass

x = B()
if isinstance(x, A):
    reveal_type(x)  # E: Revealed type is '__main__.B'
if not isinstance(x, A):
    reveal_type(x)  # unreachable
    x = A()
reveal_type(x)  # E: Revealed type is '__main__.B'
[builtins fixtures/isinstance.pyi]

[case testIsinstanceOfNonoverlapping]
class A: pass
class B: pass

x = B()
if isinstance(x, A):
    reveal_type(x)  # unreachable
else:
    reveal_type(x)  # E: Revealed type is '__main__.B'
reveal_type(x)  # E: Revealed type is '__main__.B'
[builtins fixtures/isinstance.pyi]

[case testAssertIsinstance]
def f(x: object):
    assert isinstance(x, int)
    y = 0 # type: int
    y = x
[builtins fixtures/isinstance.pyi]

[case testUnionAssertIsinstance]
from typing import Union

def f(x: Union[str, int]):
    assert isinstance(x, int)
    y = 0 # type: int
    y = x
[builtins fixtures/isinstance.pyi]

[case testAnyAssertIsinstance]
from typing import Any

def f(x: Any):
    assert isinstance(x, int)  # this should narrow x to type int
    x + "foo"  # E: Unsupported operand types for + ("int" and "str")
[builtins fixtures/isinstance.pyi]

[case testIsinstanceOfGenericClassRetainsParameters]
from typing import List, Union

def f(x: Union[List[int], str]) -> None:
    if isinstance(x, list):
        x[0]() # E: "int" not callable
    else:
        reveal_type(x) # E: Revealed type is 'builtins.str'
    reveal_type(x) # E: Revealed type is 'Union[builtins.list[builtins.int], builtins.str]'
[builtins fixtures/isinstancelist.pyi]

[case testIsinstanceOrIsinstance]
class A: pass

class B(A):
    flag = 1

class C(A):
    flag = 2

x1 = A()
if isinstance(x1, B) or isinstance(x1, C):
    reveal_type(x1) # E: Revealed type is 'Union[__main__.B, __main__.C]'
    f = x1.flag  # type: int
else:
    reveal_type(x1) # E: Revealed type is '__main__.A'
    f = 0
reveal_type(x1) # E: Revealed type is '__main__.A'
x2 = A()
if isinstance(x2, A) or isinstance(x2, C):
    reveal_type(x2) # E: Revealed type is '__main__.A'
    f = x2.flag # E: "A" has no attribute "flag"
else:
    # unreachable
    1()
reveal_type(x2) # E: Revealed type is '__main__.A'
[builtins fixtures/isinstance.pyi]

[case testComprehensionIsInstance]
from typing import List, Union
a = [] # type: List[Union[int, str]]
l = [x for x in a if isinstance(x, int)]
g = (x for x in a if isinstance(x, int))
d = {0: x for x in a if isinstance(x, int)}
reveal_type(l) # E: Revealed type is 'builtins.list[builtins.int*]'
reveal_type(g) # E: Revealed type is 'typing.Generator[builtins.int*, None, None]'
reveal_type(d) # E: Revealed type is 'builtins.dict[builtins.int*, builtins.int*]'
[builtins fixtures/isinstancelist.pyi]

[case testIsinstanceInWrongOrderInBooleanOp]
class A:
    m = 1

def f(x: object) -> None:
    if x.m and isinstance(x, A) or False:  # E: "object" has no attribute "m"
        pass
[builtins fixtures/isinstance.pyi]

[case testIsinstanceAndOr]
class A:
    a = None  # type: A

def f(x: object) -> None:
    b = isinstance(x, A) and x.a or A()
    reveal_type(b)  # E: Revealed type is '__main__.A'
[builtins fixtures/isinstance.pyi]

[case testIsInstanceWithUnknownType]
from typing import Union

def f(x: Union[int, str], typ: type) -> None:
    if isinstance(x, (typ, int)):
        x + 1  # E: Unsupported operand types for + ("str" and "int") \
               # N: Left operand is of type "Union[int, str]"
        reveal_type(x)  # E: Revealed type is 'Union[builtins.int, builtins.str]'
    else:
        reveal_type(x)  # E: Revealed type is 'builtins.str'
    reveal_type(x) # E: Revealed type is 'Union[builtins.int, builtins.str]'
[builtins fixtures/isinstancelist.pyi]

[case testIsInstanceWithBoundedType]
from typing import Union, Type

class A: pass

def f(x: Union[int, A], a: Type[A]) -> None:
    if isinstance(x, (a, int)):
        reveal_type(x)  # E: Revealed type is 'Union[builtins.int, __main__.A]'
    else:
        reveal_type(x)  # E: Revealed type is '__main__.A'
    reveal_type(x) # E: Revealed type is 'Union[builtins.int, __main__.A]'
[builtins fixtures/isinstancelist.pyi]

[case testIsInstanceWithEmtpy2ndArg]
from typing import Union

def f(x: Union[int, str]) -> None:
    if isinstance(x, ()):
        reveal_type(x)  # E: Revealed type is 'Union[builtins.int, builtins.str]'
    else:
        reveal_type(x)  # E: Revealed type is 'Union[builtins.int, builtins.str]'
[builtins fixtures/isinstancelist.pyi]

[case testIsInstanceWithTypeObject]
from typing import Union, Type

class A: pass

def f(x: Union[int, A], a: Type[A]) -> None:
    if isinstance(x, a):
        reveal_type(x)  # E: Revealed type is '__main__.A'
    elif isinstance(x, int):
        reveal_type(x)  # E: Revealed type is 'builtins.int'
    else:
        reveal_type(x)  # E: Revealed type is '__main__.A'
    reveal_type(x)  # E: Revealed type is 'Union[builtins.int, __main__.A]'
[builtins fixtures/isinstancelist.pyi]

[case testIssubclassUnreachable]
from typing import Type, Sequence, Union

x: Type[str]
if issubclass(x, int):
    reveal_type(x)  # unreachable block

class X: pass
class Y(X): pass
class Z(X): pass

a: Union[Type[Y], Type[Z]]
if issubclass(a, X):
    reveal_type(a)  # E: Revealed type is 'Union[Type[__main__.Y], Type[__main__.Z]]'
else:
    reveal_type(a)  # unreachable block
[builtins fixtures/isinstancelist.pyi]

[case testIssubclasDestructuringUnions1]
from typing import Union, List, Tuple, Dict, Type
def f(x: Union[Type[int], Type[str], Type[List]]) -> None:
    if issubclass(x, (str, (int,))):
        reveal_type(x)  # E: Revealed type is 'Union[Type[builtins.int], Type[builtins.str]]'
        reveal_type(x())  # E: Revealed type is 'Union[builtins.int, builtins.str]'
        x()[1]  # E: Value of type "Union[int, str]" is not indexable
    else:
        reveal_type(x)  # E: Revealed type is 'Type[builtins.list[Any]]'
        reveal_type(x())  # E: Revealed type is 'builtins.list[Any]'
        x()[1]
    reveal_type(x)  # E: Revealed type is 'Union[Type[builtins.int], Type[builtins.str], Type[builtins.list[Any]]]'
    reveal_type(x())  # E: Revealed type is 'Union[builtins.int, builtins.str, builtins.list[Any]]'
    if issubclass(x, (str, (list,))):
        reveal_type(x)  # E: Revealed type is 'Union[Type[builtins.str], Type[builtins.list[Any]]]'
        reveal_type(x())  # E: Revealed type is 'Union[builtins.str, builtins.list[Any]]'
        x()[1]
    reveal_type(x)  # E: Revealed type is 'Union[Type[builtins.int], Type[builtins.str], Type[builtins.list[Any]]]'
    reveal_type(x())  # E: Revealed type is 'Union[builtins.int, builtins.str, builtins.list[Any]]'
[builtins fixtures/isinstancelist.pyi]

[case testIssubclasDestructuringUnions2]
from typing import Union, List, Tuple, Dict, Type

def f(x: Type[Union[int, str, List]]) -> None:
    if issubclass(x, (str, (int,))):
        reveal_type(x)  # E: Revealed type is 'Union[Type[builtins.int], Type[builtins.str]]'
        reveal_type(x())  # E: Revealed type is 'Union[builtins.int, builtins.str]'
        x()[1]  # E: Value of type "Union[int, str]" is not indexable
    else:
        reveal_type(x)  # E: Revealed type is 'Type[builtins.list[Any]]'
        reveal_type(x())  # E: Revealed type is 'builtins.list[Any]'
        x()[1]
    reveal_type(x)  # E: Revealed type is 'Union[Type[builtins.int], Type[builtins.str], Type[builtins.list[Any]]]'
    reveal_type(x())  # E: Revealed type is 'Union[builtins.int, builtins.str, builtins.list[Any]]'
    if issubclass(x, (str, (list,))):
        reveal_type(x)  # E: Revealed type is 'Union[Type[builtins.str], Type[builtins.list[Any]]]'
        reveal_type(x())  # E: Revealed type is 'Union[builtins.str, builtins.list[Any]]'
        x()[1]
    reveal_type(x)  # E: Revealed type is 'Union[Type[builtins.int], Type[builtins.str], Type[builtins.list[Any]]]'
    reveal_type(x())  # E: Revealed type is 'Union[builtins.int, builtins.str, builtins.list[Any]]'
[builtins fixtures/isinstancelist.pyi]

[case testIssubclasDestructuringUnions3]
from typing import Union, List, Tuple, Dict, Type

def f(x: Type[Union[int, str, List]]) -> None:
    reveal_type(x)  # E: Revealed type is 'Union[Type[builtins.int], Type[builtins.str], Type[builtins.list[Any]]]'
    reveal_type(x())  # E: Revealed type is 'Union[builtins.int, builtins.str, builtins.list[Any]]'
    if issubclass(x, (str, (int,))):
        reveal_type(x)  # E: Revealed type is 'Union[Type[builtins.int], Type[builtins.str]]'
        reveal_type(x())  # E: Revealed type is 'Union[builtins.int, builtins.str]'
        x()[1]  # E: Value of type "Union[int, str]" is not indexable
    else:
        reveal_type(x)  # E: Revealed type is 'Type[builtins.list[Any]]'
        reveal_type(x())  # E: Revealed type is 'builtins.list[Any]'
        x()[1]
    reveal_type(x)  # E: Revealed type is 'Union[Type[builtins.int], Type[builtins.str], Type[builtins.list[Any]]]'
    reveal_type(x())  # E: Revealed type is 'Union[builtins.int, builtins.str, builtins.list[Any]]'
    if issubclass(x, (str, (list,))):
        reveal_type(x)  # E: Revealed type is 'Union[Type[builtins.str], Type[builtins.list[Any]]]'
        reveal_type(x())  # E: Revealed type is 'Union[builtins.str, builtins.list[Any]]'
        x()[1]
    reveal_type(x)  # E: Revealed type is 'Union[Type[builtins.int], Type[builtins.str], Type[builtins.list[Any]]]'
    reveal_type(x())  # E: Revealed type is 'Union[builtins.int, builtins.str, builtins.list[Any]]'
[builtins fixtures/isinstancelist.pyi]

[case testIssubclass]
from typing import Type, ClassVar

class Goblin:
    level: int

class GoblinAmbusher(Goblin):
    job: ClassVar[str] = 'Ranger'

def test_issubclass(cls: Type[Goblin]) -> None:
    if issubclass(cls, GoblinAmbusher):
        reveal_type(cls)  # E: Revealed type is 'Type[__main__.GoblinAmbusher]'
        cls.level
        cls.job
        ga = cls()
        ga.level = 15
        ga.job
        ga.job = "Warrior"  # E: Cannot assign to class variable "job" via instance
    else:
        reveal_type(cls)  # E: Revealed type is 'Type[__main__.Goblin]'
        cls.level
        cls.job  # E: "Type[Goblin]" has no attribute "job"
        g = cls()
        g.level = 15
        g.job  # E: "Goblin" has no attribute "job"
[builtins fixtures/isinstancelist.pyi]

[case testIssubclassDeepHierarchy]
from typing import Type, ClassVar

class Mob: pass

class Goblin(Mob):
    level: int

class GoblinAmbusher(Goblin):
    job: ClassVar[str] = 'Ranger'

def test_issubclass(cls: Type[Mob]) -> None:
    if issubclass(cls, Goblin):
        reveal_type(cls)  # E: Revealed type is 'Type[__main__.Goblin]'
        cls.level
        cls.job  # E: "Type[Goblin]" has no attribute "job"
        g = cls()
        g.level = 15
        g.job  # E: "Goblin" has no attribute "job"
        if issubclass(cls, GoblinAmbusher):
            reveal_type(cls)  # E: Revealed type is 'Type[__main__.GoblinAmbusher]'
            cls.level
            cls.job
            g = cls()
            g.level = 15
            g.job
            g.job = 'Warrior' # E: Cannot assign to class variable "job" via instance
    else:
        reveal_type(cls)  # E: Revealed type is 'Type[__main__.Mob]'
        cls.job  # E: "Type[Mob]" has no attribute "job"
        cls.level  # E: "Type[Mob]" has no attribute "level"
        m = cls()
        m.level = 15  # E: "Mob" has no attribute "level"
        m.job  # E: "Mob" has no attribute "job"
        if issubclass(cls, GoblinAmbusher):
            reveal_type(cls)  # E: Revealed type is 'Type[__main__.GoblinAmbusher]'
            cls.job
            cls.level
            ga = cls()
            ga.level = 15
            ga.job
            ga.job = 'Warrior' # E: Cannot assign to class variable "job" via instance

    if issubclass(cls, GoblinAmbusher):
        reveal_type(cls)  # E: Revealed type is 'Type[__main__.GoblinAmbusher]'
        cls.level
        cls.job
        ga = cls()
        ga.level = 15
        ga.job
        ga.job = "Warrior"  # E: Cannot assign to class variable "job" via instance
[builtins fixtures/isinstancelist.pyi]

[case testIssubclassTuple]
from typing import Type, ClassVar

class Mob: pass

class Goblin(Mob):
    level: int

class GoblinAmbusher(Goblin):
    job: ClassVar[str] = 'Ranger'

class GoblinDigger(Goblin):
    job: ClassVar[str] = 'Thief'

def test_issubclass(cls: Type[Mob]) -> None:
    if issubclass(cls, (Goblin, GoblinAmbusher)):
        reveal_type(cls)  # E: Revealed type is 'Type[__main__.Goblin]'
        cls.level
        cls.job  # E: "Type[Goblin]" has no attribute "job"
        g = cls()
        g.level = 15
        g.job  # E: "Goblin" has no attribute "job"
        if issubclass(cls, GoblinAmbusher):
            cls.level
            reveal_type(cls)  # E: Revealed type is 'Type[__main__.GoblinAmbusher]'
            cls.job
            ga = cls()
            ga.level = 15
            ga.job
            ga.job = "Warrior"  # E: Cannot assign to class variable "job" via instance
    else:
        reveal_type(cls)  # E: Revealed type is 'Type[__main__.Mob]'
        cls.job  # E: "Type[Mob]" has no attribute "job"
        cls.level  # E: "Type[Mob]" has no attribute "level"
        m = cls()
        m.level = 15  # E: "Mob" has no attribute "level"
        m.job  # E: "Mob" has no attribute "job"
        if issubclass(cls, GoblinAmbusher):
            reveal_type(cls)  # E: Revealed type is 'Type[__main__.GoblinAmbusher]'
            cls.job
            cls.level
            ga = cls()
            ga.level = 15
            ga.job
            ga.job = "Warrior"  # E: Cannot assign to class variable "job" via instance

    if issubclass(cls, (GoblinDigger, GoblinAmbusher)):
        reveal_type(cls)  # E: Revealed type is 'Union[Type[__main__.GoblinDigger], Type[__main__.GoblinAmbusher]]'
        cls.level
        cls.job
        g = cls()
        g.level = 15
        g.job
        g.job = "Warrior" # E: Cannot assign to class variable "job" via instance
[builtins fixtures/isinstancelist.pyi]

[case testIssubclassBuiltins]
from typing import List, Type

class MyList(List): pass
class MyIntList(List[int]): pass

def f(cls: Type[object]) -> None:
    if issubclass(cls, MyList):
        reveal_type(cls)  # E: Revealed type is 'Type[__main__.MyList]'
        cls()[0]
    else:
        reveal_type(cls)  # E: Revealed type is 'Type[builtins.object]'
        cls()[0]  # E: Value of type "object" is not indexable

    if issubclass(cls, MyIntList):
        reveal_type(cls)  # E: Revealed type is 'Type[__main__.MyIntList]'
        cls()[0] + 1
[builtins fixtures/isinstancelist.pyi]

[case testIsinstanceTypeArgs]
from typing import Iterable, TypeVar
x = 1
T = TypeVar('T')

isinstance(x, Iterable)
isinstance(x, Iterable[int])  # E: Parameterized generics cannot be used with class or instance checks
isinstance(x, Iterable[T])  # E: Parameterized generics cannot be used with class or instance checks
isinstance(x, (int, Iterable[int]))  # E: Parameterized generics cannot be used with class or instance checks
isinstance(x, (int, (str, Iterable[int])))  # E: Parameterized generics cannot be used with class or instance checks
[builtins fixtures/isinstancelist.pyi]

[case testIsinstanceTypeArgsAliases]
from typing import Iterable, TypeVar
x = 1
T = TypeVar('T')
It = Iterable
It2 = Iterable[T]

isinstance(x, It[int])  # E: Parameterized generics cannot be used with class or instance checks
isinstance(x, It)
isinstance(x, It2[int])  # E: Parameterized generics cannot be used with class or instance checks
isinstance(x, It2)  # E: Parameterized generics cannot be used with class or instance checks
[builtins fixtures/isinstance.pyi]

[case testIssubclassTypeArgs]
from typing import Iterable, TypeVar
x = int
T = TypeVar('T')
issubclass(x, Iterable)
issubclass(x, Iterable[int])  # E: Parameterized generics cannot be used with class or instance checks
issubclass(x, Iterable[T])  # E: Parameterized generics cannot be used with class or instance checks
issubclass(x, (int, Iterable[int]))  # E: Parameterized generics cannot be used with class or instance checks
[builtins fixtures/isinstance.pyi]

[case testIsinstanceAndNarrowTypeVariable]
from typing import TypeVar

class A: pass
class B(A): pass

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

def f(x: T) -> None:
    if isinstance(x, B):
        reveal_type(x) # E: Revealed type is '__main__.B'
    else:
        reveal_type(x) # E: Revealed type is 'T`-1'
    reveal_type(x) # E: Revealed type is 'T`-1'
[builtins fixtures/isinstance.pyi]

[case testIsinstanceAndTypeType]
from typing import Type
def f(x: Type[int]) -> None:
    if isinstance(x, type):
        reveal_type(x) # E: Revealed type is 'Type[builtins.int]'
    else:
        reveal_type(x)  # Unreachable
    reveal_type(x) # E: Revealed type is 'Type[builtins.int]'
[builtins fixtures/isinstance.pyi]

[case testIsinstanceVariableSubstitution]
T = (int, str)
U = (list, T)
x: object = None

if isinstance(x, T):
    reveal_type(x)  # E: Revealed type is 'Union[builtins.int, builtins.str]'

if isinstance(x, U):
    reveal_type(x)  # E: Revealed type is 'Union[builtins.list[Any], builtins.int, builtins.str]'

if isinstance(x, (set, (list, T))):
    reveal_type(x)  # E: Revealed type is 'Union[builtins.set[Any], builtins.list[Any], builtins.int, builtins.str]'
[builtins fixtures/isinstancelist.pyi]

[case testIsInstanceTooFewArgs]
isinstance() # E: Too few arguments for "isinstance"
x: object
if isinstance(): # E: Too few arguments for "isinstance"
    x = 1
    reveal_type(x) # E: Revealed type is 'builtins.int'
if isinstance(x): # E: Too few arguments for "isinstance"
    x = 1
    reveal_type(x) # E: Revealed type is 'builtins.int'
[builtins fixtures/isinstancelist.pyi]

[case testIsInstanceTooManyArgs]
isinstance(1, 1, 1) # E: Too many arguments for "isinstance" \
         # E: Argument 2 to "isinstance" has incompatible type "int"; expected "Union[type, Tuple[Any, ...]]"
x: object
if isinstance(x, str, 1): # E: Too many arguments for "isinstance"
    reveal_type(x) # E: Revealed type is 'builtins.object'
    x = 1
    reveal_type(x) # E: Revealed type is 'builtins.int'
[builtins fixtures/isinstancelist.pyi]

[case testIsinstanceNarrowAny]
from typing import Any

def narrow_any_to_str_then_reassign_to_int() -> None:
    v = 1 # type: Any

    if isinstance(v, str):
        reveal_type(v)  # E: Revealed type is 'builtins.str'
        v = 2
        reveal_type(v)  # E: Revealed type is 'Any'

[builtins fixtures/isinstance.pyi]

[case testNarrowTypeAfterInList]
# flags: --strict-optional
from typing import List, Optional

x: List[int]
y: Optional[int]

if y in x:
    reveal_type(y)  # E: Revealed type is 'builtins.int'
else:
    reveal_type(y)  # E: Revealed type is 'Union[builtins.int, None]'
if y not in x:
    reveal_type(y)  # E: Revealed type is 'Union[builtins.int, None]'
else:
    reveal_type(y)  # E: Revealed type is 'builtins.int'
[builtins fixtures/list.pyi]
[out]

[case testNarrowTypeAfterInListOfOptional]
# flags: --strict-optional
from typing import List, Optional

x: List[Optional[int]]
y: Optional[int]

if y not in x:
    reveal_type(y)  # E: Revealed type is 'Union[builtins.int, None]'
else:
    reveal_type(y)  # E: Revealed type is 'Union[builtins.int, None]'
[builtins fixtures/list.pyi]
[out]

[case testNarrowTypeAfterInListNonOverlapping]
# flags: --strict-optional
from typing import List, Optional

x: List[str]
y: Optional[int]

if y in x:
    reveal_type(y)  # E: Revealed type is 'Union[builtins.int, None]'
else:
    reveal_type(y)  # E: Revealed type is 'Union[builtins.int, None]'
[builtins fixtures/list.pyi]
[out]

[case testNarrowTypeAfterInListNested]
# flags: --strict-optional
from typing import List, Optional, Any

x: Optional[int]
lst: Optional[List[int]]
nested_any: List[List[Any]]

if lst in nested_any:
    reveal_type(lst) # E: Revealed type is 'builtins.list[builtins.int]'
if x in nested_any:
    reveal_type(x) # E: Revealed type is 'Union[builtins.int, None]'
[builtins fixtures/list.pyi]
[out]

[case testNarrowTypeAfterInTuple]
# flags: --strict-optional
from typing import Optional
class A: pass
class B(A): pass
class C(A): pass

y: Optional[B]
if y in (B(), C()):
    reveal_type(y) # E: Revealed type is '__main__.B'
else:
    reveal_type(y) # E: Revealed type is 'Union[__main__.B, None]'
[builtins fixtures/tuple.pyi]
[out]

[case testNarrowTypeAfterInNamedTuple]
# flags: --strict-optional
from typing import NamedTuple, Optional
class NT(NamedTuple):
    x: int
    y: int
nt: NT

y: Optional[int]
if y not in nt:
    reveal_type(y) # E: Revealed type is 'Union[builtins.int, None]'
else:
    reveal_type(y) # E: Revealed type is 'builtins.int'
[builtins fixtures/tuple.pyi]
[out]

[case testNarrowTypeAfterInDict]
# flags: --strict-optional
from typing import Dict, Optional
x: Dict[str, int]
y: Optional[str]

if y in x:
    reveal_type(y) # E: Revealed type is 'builtins.str'
else:
    reveal_type(y) # E: Revealed type is 'Union[builtins.str, None]'
if y not in x:
    reveal_type(y) # E: Revealed type is 'Union[builtins.str, None]'
else:
    reveal_type(y) # E: Revealed type is 'builtins.str'
[builtins fixtures/dict.pyi]
[out]

[case testNarrowTypeAfterInList_python2]
# flags: --strict-optional
from typing import List, Optional

x = []  # type: List[int]
y = None  # type: Optional[int]

# TODO: Fix running tests on Python 2: "Iterator[int]" has no attribute "next"
if y in x:  # type: ignore
    reveal_type(y)  # E: Revealed type is 'builtins.int'
else:
    reveal_type(y)  # E: Revealed type is 'Union[builtins.int, None]'
if y not in x:  # type: ignore
    reveal_type(y)  # E: Revealed type is 'Union[builtins.int, None]'
else:
    reveal_type(y)  # E: Revealed type is 'builtins.int'

[builtins_py2 fixtures/python2.pyi]
[out]

[case testNarrowTypeAfterInNoAnyOrObject]
# flags: --strict-optional
from typing import Any, List, Optional
x: List[Any]
z: List[object]

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

if y not in z:
    reveal_type(y) # E: Revealed type is 'Union[builtins.int, None]'
else:
    reveal_type(y) # E: Revealed type is 'Union[builtins.int, None]'
[typing fixtures/typing-full.pyi]
[builtins fixtures/list.pyi]
[out]

[case testNarrowTypeAfterInUserDefined]
# flags: --strict-optional
from typing import Container, Optional

class C(Container[int]):
    def __contains__(self, item: object) -> bool:
        return item is 'surprise'

y: Optional[int]
# We never trust user defined types
if y in C():
    reveal_type(y) # E: Revealed type is 'Union[builtins.int, None]'
else:
    reveal_type(y) # E: Revealed type is 'Union[builtins.int, None]'
if y not in C():
    reveal_type(y) # E: Revealed type is 'Union[builtins.int, None]'
else:
    reveal_type(y) # E: Revealed type is 'Union[builtins.int, None]'
[typing fixtures/typing-full.pyi]
[builtins fixtures/list.pyi]
[out]

[case testNarrowTypeAfterInSet]
# flags: --strict-optional
from typing import Optional, Set
s: Set[str]

y: Optional[str]
if y in {'a', 'b', 'c'}:
    reveal_type(y) # E: Revealed type is 'builtins.str'
else:
    reveal_type(y) # E: Revealed type is 'Union[builtins.str, None]'
if y not in s:
    reveal_type(y) # E: Revealed type is 'Union[builtins.str, None]'
else:
    reveal_type(y) # E: Revealed type is 'builtins.str'
[builtins fixtures/set.pyi]
[out]

[case testNarrowTypeAfterInTypedDict]
# flags: --strict-optional
from typing import Optional
from mypy_extensions import TypedDict
class TD(TypedDict):
    a: int
    b: str
td: TD

def f() -> None:
    x: Optional[str]
    if x not in td:
        return
    reveal_type(x) # E: Revealed type is 'builtins.str'
[typing fixtures/typing-full.pyi]
[builtins fixtures/dict.pyi]
[out]

[case testIsinstanceWidensWithAnyArg]
from typing import Any
class A: ...
B: Any
x: A
x.foo()  # E: "A" has no attribute "foo"
assert isinstance(x, B)
x.foo()
reveal_type(x)  # E: Revealed type is 'Any'
[builtins fixtures/isinstance.pyi]

[case testIsinstanceWidensUnionWithAnyArg]
from typing import Any, Union
class A: ...
B: Any
x: Union[A, B]
reveal_type(x)  # E: Revealed type is 'Union[__main__.A, Any]'
assert isinstance(x, B)
reveal_type(x)  # E: Revealed type is 'Any'
[builtins fixtures/isinstance.pyi]

[case testIsinstanceIgnoredImport]
from typing import Union
from foo import A  # type: ignore
def f(x: Union[A, str]) -> None:
    x.method_only_in_a()  # E: Item "str" of "Union[Any, str]" has no attribute "method_only_in_a"
    if isinstance(x, A):
        x.method_only_in_a()
[builtins fixtures/isinstance.pyi]

[case testIsInstanceInitialNoneCheckSkipsImpossibleCasesNoStrictOptional]
# flags: --strict-optional
from typing import Optional, Union

class A: pass

def foo1(x: Union[A, str, None]) -> None:
    if x is None:
        reveal_type(x)      # E: Revealed type is 'None'
    elif isinstance(x, A):
        reveal_type(x)      # E: Revealed type is '__main__.A'
    else:
        reveal_type(x)      # E: Revealed type is 'builtins.str'

def foo2(x: Optional[str]) -> None:
    if x is None:
        reveal_type(x)      # E: Revealed type is 'None'
    elif isinstance(x, A):
        reveal_type(x)
    else:
        reveal_type(x)      # E: Revealed type is 'builtins.str'
[builtins fixtures/isinstance.pyi]

[case testIsInstanceInitialNoneCheckSkipsImpossibleCasesInNoStrictOptional]
# flags: --no-strict-optional
from typing import Optional, Union

class A: pass

def foo1(x: Union[A, str, None]) -> None:
    if x is None:
        # Since None is a subtype of all types in no-strict-optional,
        # we can't really narrow the type here
        reveal_type(x)      # E: Revealed type is 'Union[__main__.A, builtins.str, None]'
    elif isinstance(x, A):
        # Note that Union[None, A] == A in no-strict-optional
        reveal_type(x)      # E: Revealed type is '__main__.A'
    else:
        reveal_type(x)      # E: Revealed type is 'builtins.str'

def foo2(x: Optional[str]) -> None:
    if x is None:
        reveal_type(x)      # E: Revealed type is 'Union[builtins.str, None]'
    elif isinstance(x, A):
        # Mypy should, however, be able to skip impossible cases
        reveal_type(x)
    else:
        reveal_type(x)      # E: Revealed type is 'Union[builtins.str, None]'
[builtins fixtures/isinstance.pyi]

[case testNoneCheckDoesNotNarrowWhenUsingTypeVars]
# flags: --strict-optional

# Note: this test (and the following one) are testing checker.conditional_type_map:
# if you set the 'prohibit_none_typevar_overlap' keyword argument to False when calling
# 'is_overlapping_types', the binder will incorrectly infer that 'out' has a type of
# Union[T, None] after the if statement.

from typing import TypeVar

T = TypeVar('T')

def foo(x: T) -> T:
    out = None
    out = x
    if out is None:
        pass
    return out
[builtins fixtures/isinstance.pyi]

[case testNoneCheckDoesNotNarrowWhenUsingTypeVarsNoStrictOptional]
# flags: --no-strict-optional
from typing import TypeVar

T = TypeVar('T')

def foo(x: T) -> T:
    out = None
    out = x
    if out is None:
        pass
    return out
[builtins fixtures/isinstance.pyi]

[case testNoneAndGenericTypesOverlapNoStrictOptional]
# flags: --no-strict-optional
from typing import Union, Optional, List

# Note: this test is indirectly making sure meet.is_overlapping_types
# correctly ignores 'None' in unions.

def foo(x: Optional[List[str]]) -> None:
    reveal_type(x)                  # E: Revealed type is 'Union[builtins.list[builtins.str], None]'
    assert isinstance(x, list)
    reveal_type(x)                  # E: Revealed type is 'builtins.list[builtins.str]'

def bar(x: Union[List[str], List[int], None]) -> None:
    reveal_type(x)                  # E: Revealed type is 'Union[builtins.list[builtins.str], builtins.list[builtins.int], None]'
    assert isinstance(x, list)
    reveal_type(x)                  # E: Revealed type is 'Union[builtins.list[builtins.str], builtins.list[builtins.int]]'
[builtins fixtures/isinstancelist.pyi]

[case testNoneAndGenericTypesOverlapStrictOptional]
# flags: --strict-optional
from typing import Union, Optional, List

# This test is the same as the one above, except for strict-optional.
# It isn't testing anything explicitly and mostly exists for the sake 
# of completeness.

def foo(x: Optional[List[str]]) -> None:
    reveal_type(x)                  # E: Revealed type is 'Union[builtins.list[builtins.str], None]'
    assert isinstance(x, list)
    reveal_type(x)                  # E: Revealed type is 'builtins.list[builtins.str]'

def bar(x: Union[List[str], List[int], None]) -> None:
    reveal_type(x)                  # E: Revealed type is 'Union[builtins.list[builtins.str], builtins.list[builtins.int], None]'
    assert isinstance(x, list)
    reveal_type(x)                  # E: Revealed type is 'Union[builtins.list[builtins.str], builtins.list[builtins.int]]'
[builtins fixtures/isinstancelist.pyi]

