blob: f6fd27e59e4d401110d1d8a1426a65a898287d71 [file] [log] [blame] [edit]
-- Type checking of union types
[case testUnion1]
from typing import Union
def f(x: Union[int, str]) -> None:
if isinstance(x, int):
y = 1
y = x
elif isinstance(x, str):
z = 'a'
z = x
[builtins fixtures/isinstance.pyi]
[case testUnion2]
from typing import Union
def f(x: Union[int, str]) -> None:
if isinstance(x, int):
y = 1
y = x
else:
z = 'a'
z = x
[builtins fixtures/isinstance.pyi]
[case testUnion3]
from typing import Union
def f(x: Union[int, str]) -> None:
if isinstance(x, int):
y = 1
if int():
y = x
else:
z = 2
if int():
z = x # E: Incompatible types in assignment (expression has type "str", variable has type "int")
[builtins fixtures/isinstance.pyi]
[out]
[case testUnionAnyIsInstance]
from typing import Any, Union
def func(v: Union[int, Any]) -> None:
if isinstance(v, int):
reveal_type(v) # N: Revealed type is "builtins.int"
else:
reveal_type(v) # N: Revealed type is "Any"
[builtins fixtures/isinstance.pyi]
[out]
[case testUnionAttributeAccess]
from typing import Union
class A: y = 1
class B: y = 2
class C: pass
class D: pass
u: Union[A, C, D]
v: Union[C, D]
w: Union[A, B]
x: Union[A, C]
y: int
z: str
if int():
y = w.y
v.y # E: Item "C" of "Union[C, D]" has no attribute "y" \
# E: Item "D" of "Union[C, D]" has no attribute "y"
u.y # E: Item "C" of "Union[A, C, D]" has no attribute "y" \
# E: Item "D" of "Union[A, C, D]" has no attribute "y"
if int():
z = w.y # E: Incompatible types in assignment (expression has type "int", variable has type "str")
w.y = 'a' # E: Incompatible types in assignment (expression has type "str", variable has type "int")
if int():
y = x.y # E: Item "C" of "Union[A, C]" has no attribute "y"
zz = x.y # E: Item "C" of "Union[A, C]" has no attribute "y"
if int():
z = zz # E: Incompatible types in assignment (expression has type "Union[int, Any]", variable has type "str")
[builtins fixtures/isinstance.pyi]
[case testUnionMethodCalls]
from typing import Union
class A:
def foo(self) -> int: pass
class B:
def foo(self) -> int: pass
class C:
def foo(self) -> str: pass
x: Union[A, B]
y: Union[A, C]
i: int
x.foo()
y.foo()
i = x.foo()
if int():
i = y.foo() # E: Incompatible types in assignment (expression has type "Union[int, str]", variable has type "int")
[builtins fixtures/isinstance.pyi]
[case testUnionIndexing]
from typing import Union, List
x: Union[List[int], str]
x[2]
x[2] + 1 # E: Unsupported operand types for + ("str" and "int") \
# N: Left operand is of type "Union[int, str]"
[builtins fixtures/isinstancelist.pyi]
[case testUnionAsOverloadArg]
from foo import *
x = 0
if int():
x = f(1)
if int():
x = f('')
s = ''
if int():
s = f(int)
if int():
s = f(1) # E: Incompatible types in assignment (expression has type "int", variable has type "str")
if int():
x = f(int) # E: Incompatible types in assignment (expression has type "str", variable has type "int")
[file foo.pyi]
from typing import Union, overload
@overload
def f(x: Union[int, str]) -> int: pass
@overload
def f(x: type) -> str: pass
[case testUnionWithNoneItem]
# flags: --no-strict-optional
from typing import Union
def f() -> Union[int, None]: pass
x = 1
x = f()
[case testUnionWithEllipsis]
from typing import Union
def f(x: Union[int, EllipsisType]) -> int:
if x is Ellipsis:
reveal_type(x) # N: Revealed type is "builtins.ellipsis"
x = 1
reveal_type(x) # N: Revealed type is "builtins.int"
return x
[builtins fixtures/isinstancelist.pyi]
[case testOptional]
from typing import Optional
def f(x: Optional[int]) -> None: pass
f(1)
f(None)
f('') # E: Argument 1 to "f" has incompatible type "str"; expected "Optional[int]"
[case testUnionWithNoReturn]
from typing import Union, NoReturn
def f() -> Union[int, NoReturn]: ...
reveal_type(f()) # N: Revealed type is "builtins.int"
[case testUnionSimplificationGenericFunction]
from typing import TypeVar, Union, List
T = TypeVar('T')
def f(x: List[T]) -> Union[T, int]: pass
def g(y: str) -> None: pass
a = f([1])
g(a) # E: Argument 1 to "g" has incompatible type "int"; expected "str"
[builtins fixtures/list.pyi]
[case testUnionSimplificationGenericClass]
from typing import TypeVar, Union, Generic
T = TypeVar('T')
U = TypeVar('U')
class C(Generic[T, U]):
def f(self, x: str) -> Union[T, U]: pass
a = C() # type: C[int, int]
b = a.f('a')
a.f(b) # E: Argument 1 to "f" of "C" has incompatible type "int"; expected "str"
[case testUnionOrderEquivalence]
from typing import Union
def foo(): pass
S = str
T = int
if foo():
def f(x: Union[int, str]) -> None: pass
elif foo():
def f(x: Union[str, int]) -> None: pass
elif foo():
def f(x: Union[int, str, int, int, str]) -> None: pass
elif foo():
def f(x: Union[int, str, float]) -> None: pass # E: All conditional function variants must have identical signatures \
# N: Original: \
# N: def f(x: Union[int, str]) -> None \
# N: Redefinition: \
# N: def f(x: Union[int, str, float]) -> None
elif foo():
def f(x: Union[S, T]) -> None: pass
elif foo():
def f(x: Union[str]) -> None: pass # E: All conditional function variants must have identical signatures \
# N: Original: \
# N: def f(x: Union[int, str]) -> None \
# N: Redefinition: \
# N: def f(x: str) -> None
else:
def f(x: Union[Union[int, T], Union[S, T], str]) -> None: pass
# Checks bidirectionality of testing. The first definition of g is consistent with
# the second, but not vice-versa.
if foo():
def g(x: Union[int, str, bytes]) -> None: pass
else:
def g(x: Union[int, str]) -> None: pass # E: All conditional function variants must have identical signatures \
# N: Original: \
# N: def g(x: Union[int, str, bytes]) -> None \
# N: Redefinition: \
# N: def g(x: Union[int, str]) -> None
[case testUnionSimplificationSpecialCases]
# flags: --no-strict-optional
from typing import Any, TypeVar, Union
class C(Any): pass
T = TypeVar('T')
S = TypeVar('S')
def u(x: T, y: S) -> Union[S, T]: pass
a = None # type: Any
reveal_type(u(C(), None)) # N: Revealed type is "__main__.C"
reveal_type(u(None, C())) # N: Revealed type is "__main__.C"
reveal_type(u(C(), a)) # N: Revealed type is "Union[Any, __main__.C]"
reveal_type(u(a, C())) # N: Revealed type is "Union[__main__.C, Any]"
reveal_type(u(C(), C())) # N: Revealed type is "__main__.C"
reveal_type(u(a, a)) # N: Revealed type is "Any"
[case testUnionSimplificationSpecialCase2]
from typing import Any, TypeVar, Union
class C(Any): pass
T = TypeVar('T')
S = TypeVar('S')
def u(x: T, y: S) -> Union[S, T]: pass
def f(x: T) -> None:
reveal_type(u(C(), x)) # N: Revealed type is "Union[T`-1, __main__.C]"
reveal_type(u(x, C())) # N: Revealed type is "Union[__main__.C, T`-1]"
[case testUnionSimplificationSpecialCase3]
from typing import Any, TypeVar, Generic, Union
class C(Any): pass
V = TypeVar('V')
T = TypeVar('T')
class M(Generic[V]):
def get(self, default: T) -> Union[V, T]: ...
def f(x: M[C]) -> None:
y = x.get(None)
reveal_type(y) # N: Revealed type is "Union[__main__.C, None]"
[case testUnionSimplificationSpecialCases2]
# flags: --no-strict-optional
from typing import Any, TypeVar, Union
class C(Any): pass
T = TypeVar('T')
S = TypeVar('S')
def u(x: T, y: S) -> Union[S, T]: pass
a = None # type: Any
# Base-class-Any and None, simplify
reveal_type(u(C(), None)) # N: Revealed type is "__main__.C"
reveal_type(u(None, C())) # N: Revealed type is "__main__.C"
# Normal instance type and None, simplify
reveal_type(u(1, None)) # N: Revealed type is "builtins.int"
reveal_type(u(None, 1)) # N: Revealed type is "builtins.int"
# Normal instance type and base-class-Any, no simplification
reveal_type(u(C(), 1)) # N: Revealed type is "Union[builtins.int, __main__.C]"
reveal_type(u(1, C())) # N: Revealed type is "Union[__main__.C, builtins.int]"
# Normal instance type and Any, no simplification
reveal_type(u(1, a)) # N: Revealed type is "Union[Any, builtins.int]"
reveal_type(u(a, 1)) # N: Revealed type is "Union[builtins.int, Any]"
# Any and base-class-Any, no simplification
reveal_type(u(C(), a)) # N: Revealed type is "Union[Any, __main__.C]"
reveal_type(u(a, C())) # N: Revealed type is "Union[__main__.C, Any]"
# Two normal instance types, simplify
reveal_type(u(1, object())) # N: Revealed type is "builtins.object"
reveal_type(u(object(), 1)) # N: Revealed type is "builtins.object"
# Two normal instance types, no simplification
reveal_type(u(1, '')) # N: Revealed type is "Union[builtins.str, builtins.int]"
reveal_type(u('', 1)) # N: Revealed type is "Union[builtins.int, builtins.str]"
[case testUnionSimplificationWithDuplicateItems]
from typing import Any, TypeVar, Union
class C(Any): pass
T = TypeVar('T')
S = TypeVar('S')
R = TypeVar('R')
def u(x: T, y: S, z: R) -> Union[R, S, T]: pass
a: Any
reveal_type(u(1, 1, 1)) # N: Revealed type is "builtins.int"
reveal_type(u(C(), C(), None)) # N: Revealed type is "Union[None, __main__.C]"
reveal_type(u(a, a, 1)) # N: Revealed type is "Union[builtins.int, Any]"
reveal_type(u(a, C(), a)) # N: Revealed type is "Union[Any, __main__.C]"
reveal_type(u('', 1, 1)) # N: Revealed type is "Union[builtins.int, builtins.str]"
[case testUnionAndBinaryOperation]
from typing import Union
class A: pass
def f(x: Union[int, str, A]):
x + object() # E: Unsupported left operand type for + ("A") \
# N: Left operand is of type "Union[int, str, A]" \
# E: Unsupported operand types for + ("int" and "object") \
# E: Unsupported operand types for + ("str" and "object")
[builtins fixtures/primitives.pyi]
[case testNarrowingDownNamedTupleUnion]
from typing import NamedTuple, Union
A = NamedTuple('A', [('y', int)])
B = NamedTuple('B', [('x', int)])
C = NamedTuple('C', [('x', int)])
def foo(a: Union[A, B, C]):
if isinstance(a, (B, C)):
reveal_type(a) # N: Revealed type is "Union[Tuple[builtins.int, fallback=__main__.B], Tuple[builtins.int, fallback=__main__.C]]"
a.x
a.y # E: Item "B" of "Union[B, C]" has no attribute "y" \
# E: Item "C" of "Union[B, C]" has no attribute "y"
b = a # type: Union[B, C]
[builtins fixtures/isinstance.pyi]
[case testSimplifyingUnionAndTypePromotions]
from typing import TypeVar, Union
T = TypeVar('T')
S = TypeVar('S')
def u(x: T, y: S) -> Union[T, S]: pass
reveal_type(u(1, 2.3)) # N: Revealed type is "Union[builtins.int, builtins.float]"
reveal_type(u(2.3, 1)) # N: Revealed type is "Union[builtins.float, builtins.int]"
reveal_type(u(False, 2.2)) # N: Revealed type is "Union[builtins.bool, builtins.float]"
reveal_type(u(2.2, False)) # N: Revealed type is "Union[builtins.float, builtins.bool]"
[builtins fixtures/primitives.pyi]
[case testSimplifyingUnionWithTypeTypes1]
from typing import TypeVar, Union, Type, Any
T = TypeVar('T')
S = TypeVar('S')
def u(x: T, y: S) -> Union[S, T]: pass
t_o: Type[object]
t_s: Type[str]
t_a: Type[Any]
# Two identical items
reveal_type(u(t_o, t_o)) # N: Revealed type is "Type[builtins.object]"
reveal_type(u(t_s, t_s)) # N: Revealed type is "Type[builtins.str]"
reveal_type(u(t_a, t_a)) # N: Revealed type is "Type[Any]"
reveal_type(u(type, type)) # N: Revealed type is "def (x: builtins.object) -> builtins.type"
# One type, other non-type
reveal_type(u(t_s, 1)) # N: Revealed type is "Union[builtins.int, Type[builtins.str]]"
reveal_type(u(1, t_s)) # N: Revealed type is "Union[Type[builtins.str], builtins.int]"
reveal_type(u(type, 1)) # N: Revealed type is "Union[builtins.int, def (x: builtins.object) -> builtins.type]"
reveal_type(u(1, type)) # N: Revealed type is "Union[def (x: builtins.object) -> builtins.type, builtins.int]"
reveal_type(u(t_a, 1)) # N: Revealed type is "Union[builtins.int, Type[Any]]"
reveal_type(u(1, t_a)) # N: Revealed type is "Union[Type[Any], builtins.int]"
reveal_type(u(t_o, 1)) # N: Revealed type is "Union[builtins.int, Type[builtins.object]]"
reveal_type(u(1, t_o)) # N: Revealed type is "Union[Type[builtins.object], builtins.int]"
[case testSimplifyingUnionWithTypeTypes2]
from typing import TypeVar, Union, Type, Any
T = TypeVar('T')
S = TypeVar('S')
def u(x: T, y: S) -> Union[S, T]: pass
t_o: Type[object]
t_s: Type[str]
t_a: Type[Any]
t: type
# Union with object
reveal_type(u(t_o, object())) # N: Revealed type is "builtins.object"
reveal_type(u(object(), t_o)) # N: Revealed type is "builtins.object"
reveal_type(u(t_s, object())) # N: Revealed type is "builtins.object"
reveal_type(u(object(), t_s)) # N: Revealed type is "builtins.object"
reveal_type(u(t_a, object())) # N: Revealed type is "builtins.object"
reveal_type(u(object(), t_a)) # N: Revealed type is "builtins.object"
# Union between type objects
reveal_type(u(t_o, t_a)) # N: Revealed type is "Union[Type[Any], Type[builtins.object]]"
reveal_type(u(t_a, t_o)) # N: Revealed type is "Union[Type[builtins.object], Type[Any]]"
reveal_type(u(t_s, t_o)) # N: Revealed type is "Type[builtins.object]"
reveal_type(u(t_o, t_s)) # N: Revealed type is "Type[builtins.object]"
reveal_type(u(t_o, type)) # N: Revealed type is "Type[builtins.object]"
reveal_type(u(type, t_o)) # N: Revealed type is "Type[builtins.object]"
reveal_type(u(t_a, t)) # N: Revealed type is "builtins.type"
reveal_type(u(t, t_a)) # N: Revealed type is "builtins.type"
# The following should arguably not be simplified, but it's unclear how to fix then
# without causing regressions elsewhere.
reveal_type(u(t_o, t)) # N: Revealed type is "builtins.type"
reveal_type(u(t, t_o)) # N: Revealed type is "builtins.type"
[case testNotSimplifyingUnionWithMetaclass]
from typing import TypeVar, Union, Type, Any
class M(type): pass
class M2(M): pass
class A(metaclass=M): pass
T = TypeVar('T')
S = TypeVar('S')
def u(x: T, y: S) -> Union[S, T]: pass
a: Any
t_a: Type[A]
reveal_type(u(M(*a), t_a)) # N: Revealed type is "__main__.M"
reveal_type(u(t_a, M(*a))) # N: Revealed type is "__main__.M"
reveal_type(u(M2(*a), t_a)) # N: Revealed type is "Union[Type[__main__.A], __main__.M2]"
reveal_type(u(t_a, M2(*a))) # N: Revealed type is "Union[__main__.M2, Type[__main__.A]]"
[case testSimplifyUnionWithCallable]
from typing import TypeVar, Union, Any, Callable
T = TypeVar('T')
S = TypeVar('S')
def u(x: T, y: S) -> Union[S, T]: pass
class C: pass
class D(C): pass
D_C: Callable[[D], C]
A_C: Callable[[Any], C]
D_A: Callable[[D], Any]
C_C: Callable[[C], C]
D_D: Callable[[D], D]
i_C: Callable[[int], C]
# TODO: Test argument names and kinds once we have flexible callable types.
reveal_type(u(D_C, D_C)) # N: Revealed type is "def (__main__.D) -> __main__.C"
reveal_type(u(A_C, D_C)) # N: Revealed type is "Union[def (__main__.D) -> __main__.C, def (Any) -> __main__.C]"
reveal_type(u(D_C, A_C)) # N: Revealed type is "Union[def (Any) -> __main__.C, def (__main__.D) -> __main__.C]"
reveal_type(u(D_A, D_C)) # N: Revealed type is "Union[def (__main__.D) -> __main__.C, def (__main__.D) -> Any]"
reveal_type(u(D_C, D_A)) # N: Revealed type is "Union[def (__main__.D) -> Any, def (__main__.D) -> __main__.C]"
reveal_type(u(D_C, C_C)) # N: Revealed type is "def (__main__.D) -> __main__.C"
reveal_type(u(C_C, D_C)) # N: Revealed type is "def (__main__.D) -> __main__.C"
reveal_type(u(D_C, D_D)) # N: Revealed type is "def (__main__.D) -> __main__.C"
reveal_type(u(D_D, D_C)) # N: Revealed type is "def (__main__.D) -> __main__.C"
reveal_type(u(D_C, i_C)) # N: Revealed type is "Union[def (builtins.int) -> __main__.C, def (__main__.D) -> __main__.C]"
[case testUnionOperatorMethodSpecialCase]
from typing import Union
class C:
def __le__(self, x: 'C') -> int: ...
class D:
def __le__(self, other) -> int: ...
class E:
def __ge__(self, other: Union[C, D]) -> int: ...
[case testUnionSimplificationWithBoolIntAndFloat]
from typing import List, Union
l = reveal_type([]) # type: List[Union[bool, int, float]] \
# N: Revealed type is "builtins.list[Union[builtins.int, builtins.float]]"
reveal_type(l) \
# N: Revealed type is "builtins.list[Union[builtins.bool, builtins.int, builtins.float]]"
[builtins fixtures/list.pyi]
[case testUnionSimplificationWithBoolIntAndFloat2]
from typing import List, Union
l = reveal_type([]) # type: List[Union[bool, int, float, str]] \
# N: Revealed type is "builtins.list[Union[builtins.int, builtins.float, builtins.str]]"
reveal_type(l) \
# N: Revealed type is "builtins.list[Union[builtins.bool, builtins.int, builtins.float, builtins.str]]"
[builtins fixtures/list.pyi]
[case testNestedUnionsProcessedCorrectly]
from typing import Union
class A: pass
class B: pass
class C: pass
def foo(bar: Union[Union[A, B], C]) -> None:
if isinstance(bar, A):
reveal_type(bar) # N: Revealed type is "__main__.A"
else:
reveal_type(bar) # N: Revealed type is "Union[__main__.B, __main__.C]"
[builtins fixtures/isinstance.pyi]
[out]
[case testAssignAnyToUnion]
from typing import Union, Any
x: Union[int, str]
a: Any
if bool():
x = a
# TODO: Maybe we should infer Any as the type instead.
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
[builtins fixtures/bool.pyi]
[case testAssignAnyToUnionWithAny]
from typing import Union, Any
x: Union[int, Any]
a: Any
if bool():
x = a
reveal_type(x) # N: Revealed type is "Any"
reveal_type(x) # N: Revealed type is "Union[builtins.int, Any]"
[builtins fixtures/bool.pyi]
[case testUnionMultiassignSingle]
from typing import Union, Tuple, Any
a: Union[Tuple[int], Tuple[float]]
(a1,) = a
reveal_type(a1) # N: Revealed type is "Union[builtins.int, builtins.float]"
b: Union[Tuple[int], Tuple[str]]
(b1,) = b
reveal_type(b1) # N: Revealed type is "Union[builtins.int, builtins.str]"
[builtins fixtures/tuple.pyi]
[case testUnionMultiassignDouble]
from typing import Union, Tuple
c: Union[Tuple[int, int], Tuple[int, float]]
(c1, c2) = c
reveal_type(c1) # N: Revealed type is "builtins.int"
reveal_type(c2) # N: Revealed type is "Union[builtins.int, builtins.float]"
[builtins fixtures/tuple.pyi]
[case testUnionMultiassignGeneric]
from typing import Union, Tuple, TypeVar
T = TypeVar('T')
S = TypeVar('S')
def pack_two(x: T, y: S) -> Union[Tuple[T, T], Tuple[S, S]]:
pass
(x, y) = pack_two(1, 'a')
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(y) # N: Revealed type is "Union[builtins.int, builtins.str]"
[builtins fixtures/tuple.pyi]
[case testUnionMultiassignAny]
from typing import Union, Tuple, Any
d: Union[Any, Tuple[float, float]]
(d1, d2) = d
reveal_type(d1) # N: Revealed type is "Union[Any, builtins.float]"
reveal_type(d2) # N: Revealed type is "Union[Any, builtins.float]"
e: Union[Any, Tuple[float, float], int]
(e1, e2) = e # E: "int" object is not iterable
[builtins fixtures/tuple.pyi]
[case testUnionMultiassignNotJoin]
from typing import Union, List
class A: pass
class B(A): pass
class C(A): pass
a: Union[List[B], List[C]]
x, y = a
reveal_type(x) # N: Revealed type is "Union[__main__.B, __main__.C]"
[builtins fixtures/list.pyi]
[case testUnionMultiassignRebind]
from typing import Union, List
class A: pass
class B(A): pass
class C(A): pass
obj: object
a: Union[List[B], List[C]]
obj, new = a
reveal_type(obj) # N: Revealed type is "Union[__main__.B, __main__.C]"
reveal_type(new) # N: Revealed type is "Union[__main__.B, __main__.C]"
obj = 1
reveal_type(obj) # N: Revealed type is "builtins.int"
[builtins fixtures/list.pyi]
[case testUnionMultiassignAlreadyDeclared]
from typing import Union, Tuple
a: Union[Tuple[int, int], Tuple[int, float]]
a1: object
a2: int
(a1, a2) = a # E: Incompatible types in assignment (expression has type "float", variable has type "int")
b: Union[Tuple[float, int], Tuple[int, int]]
b1: object
b2: int
(b1, b2) = b
reveal_type(b1) # N: Revealed type is "Union[builtins.float, builtins.int]"
reveal_type(b2) # N: Revealed type is "builtins.int"
c: Union[Tuple[int, int], Tuple[int, int]]
c1: object
c2: int
(c1, c2) = c
reveal_type(c1) # N: Revealed type is "builtins.int"
reveal_type(c2) # N: Revealed type is "builtins.int"
d: Union[Tuple[int, int], Tuple[int, float]]
d1: object
(d1, d2) = d
reveal_type(d1) # N: Revealed type is "builtins.int"
reveal_type(d2) # N: Revealed type is "Union[builtins.int, builtins.float]"
[builtins fixtures/tuple.pyi]
[case testUnionMultiassignIndexed]
from typing import Union, Tuple, List
class B:
x: object
x: List[int]
b: B
a: Union[Tuple[int, int], Tuple[int, object]]
(x[0], b.x) = a
reveal_type(x[0]) # N: Revealed type is "builtins.int"
reveal_type(b.x) # N: Revealed type is "builtins.object"
[builtins fixtures/list.pyi]
[case testUnionMultiassignIndexedWithError]
from typing import Union, Tuple, List
class A: pass
class B:
x: int
x: List[A]
b: B
a: Union[Tuple[int, int], Tuple[int, object]]
(x[0], b.x) = a # E: Incompatible types in assignment (expression has type "int", target has type "A") \
# E: Incompatible types in assignment (expression has type "object", variable has type "int")
reveal_type(x[0]) # N: Revealed type is "__main__.A"
reveal_type(b.x) # N: Revealed type is "builtins.int"
[builtins fixtures/list.pyi]
[case testUnionMultiassignPacked]
from typing import Union, Tuple, List
a: Union[Tuple[int, int, int], Tuple[int, int, str]]
a1: int
a2: object
(a1, *xs, a2) = a
reveal_type(a1) # N: Revealed type is "builtins.int"
reveal_type(xs) # N: Revealed type is "builtins.list[builtins.int]"
reveal_type(a2) # N: Revealed type is "Union[builtins.int, builtins.str]"
[builtins fixtures/list.pyi]
[case testUnpackingUnionOfListsInFunction]
from typing import Union, List
def f(x: bool) -> Union[List[int], List[str]]:
if x:
return [1, 1]
else:
return ['a', 'a']
def g(x: bool) -> None:
a, b = f(x)
reveal_type(a) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(b) # N: Revealed type is "Union[builtins.int, builtins.str]"
[builtins fixtures/list.pyi]
[case testUnionOfVariableLengthTupleUnpacking]
from typing import Tuple, Union
VarTuple = Union[Tuple[int, int], Tuple[int, int, int]]
def make_tuple() -> VarTuple:
pass
x = make_tuple()
a, b = x # E: Too many values to unpack (2 expected, 3 provided)
a, b, c = x # E: Need more than 2 values to unpack (3 expected)
c, *d = x
reveal_type(c) # N: Revealed type is "builtins.int"
reveal_type(d) # N: Revealed type is "builtins.list[builtins.int]"
[builtins fixtures/tuple.pyi]
[case testUnionOfNonIterableUnpacking]
from typing import Union
bad: Union[int, str]
x, y = bad # E: "int" object is not iterable \
# E: Unpacking a string is disallowed
reveal_type(x) # N: Revealed type is "Any"
reveal_type(y) # N: Revealed type is "Any"
[out]
[case testStringDisallowedUnpacking]
from typing import Dict
d: Dict[str, str]
for a, b in d: # E: Unpacking a string is disallowed
pass
s = "foo"
a, b = s # E: Unpacking a string is disallowed
[builtins fixtures/dict.pyi]
[out]
[case testUnionAlwaysTooMany]
from typing import Union, Tuple
bad: Union[Tuple[int, int, int], Tuple[str, str, str]]
x, y = bad # E: Too many values to unpack (2 expected, 3 provided)
reveal_type(x) # N: Revealed type is "Any"
reveal_type(y) # N: Revealed type is "Any"
[builtins fixtures/tuple.pyi]
[out]
[case testUnionAlwaysTooFew]
from typing import Union, Tuple
bad: Union[Tuple[int, int, int], Tuple[str, str, str]]
x, y, z, w = bad # E: Need more than 3 values to unpack (4 expected)
reveal_type(x) # N: Revealed type is "Any"
reveal_type(y) # N: Revealed type is "Any"
reveal_type(z) # N: Revealed type is "Any"
reveal_type(w) # N: Revealed type is "Any"
[builtins fixtures/tuple.pyi]
[out]
[case testUnionUnpackingChainedTuple]
from typing import Union, Tuple
good: Union[Tuple[int, int], Tuple[str, str]]
x, y = t = good
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(y) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(t) # N: Revealed type is "Union[Tuple[builtins.int, builtins.int], Tuple[builtins.str, builtins.str]]"
[builtins fixtures/tuple.pyi]
[out]
[case testUnionUnpackingChainedTuple2]
from typing import Union, Tuple
good: Union[Tuple[int, int], Tuple[str, str]]
t = x, y = good
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(y) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(t) # N: Revealed type is "Union[Tuple[builtins.int, builtins.int], Tuple[builtins.str, builtins.str]]"
[builtins fixtures/tuple.pyi]
[out]
[case testUnionUnpackingChainedTuple3]
from typing import Union, Tuple
good: Union[Tuple[int, int], Tuple[str, str]]
x, y = a, b = good
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(y) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(a) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(b) # N: Revealed type is "Union[builtins.int, builtins.str]"
[builtins fixtures/tuple.pyi]
[out]
[case testUnionUnpackingChainedList]
from typing import Union, List
good: Union[List[int], List[str]]
lst = x, y = good
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(y) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(lst) # N: Revealed type is "Union[builtins.list[builtins.int], builtins.list[builtins.str]]"
[builtins fixtures/list.pyi]
[out]
[case testUnionUnpackingChainedList2]
from typing import Union, List
good: Union[List[int], List[str]]
x, *y, z = lst = good
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(y) # N: Revealed type is "Union[builtins.list[builtins.int], builtins.list[builtins.str]]"
reveal_type(z) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(lst) # N: Revealed type is "Union[builtins.list[builtins.int], builtins.list[builtins.str]]"
[builtins fixtures/list.pyi]
[out]
[case testUnionUnpackingInForTuple]
from typing import Union, Tuple, NamedTuple
class NTInt(NamedTuple):
x: int
y: int
class NTStr(NamedTuple):
x: str
y: str
t1: NTInt
reveal_type(t1.__iter__) # N: Revealed type is "def () -> typing.Iterator[builtins.int]"
nt: Union[NTInt, NTStr]
reveal_type(nt.__iter__) # N: Revealed type is "Union[def () -> typing.Iterator[builtins.int], def () -> typing.Iterator[builtins.str]]"
for nx in nt:
reveal_type(nx) # N: Revealed type is "Union[builtins.int, builtins.str]"
t: Union[Tuple[int, int], Tuple[str, str]]
for x in t:
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
[builtins fixtures/for.pyi]
[out]
[case testUnionUnpackingInForList]
from typing import Union, List, Tuple
t: Union[List[Tuple[int, int]], List[Tuple[str, str]]]
for x, y in t:
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(y) # N: Revealed type is "Union[builtins.int, builtins.str]"
t2: List[Union[Tuple[int, int], Tuple[str, str]]]
for x2, y2 in t2:
reveal_type(x2) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(y2) # N: Revealed type is "Union[builtins.int, builtins.str]"
[builtins fixtures/for.pyi]
[out]
[case testUnionUnpackingDoubleBinder]
from typing import Union, Tuple
x: object
y: object
class A: pass
class B: pass
t1: Union[Tuple[A, A], Tuple[B, B]]
t2: Union[Tuple[int, int], Tuple[str, str]]
x, y = t1
reveal_type(x) # N: Revealed type is "Union[__main__.A, __main__.B]"
reveal_type(y) # N: Revealed type is "Union[__main__.A, __main__.B]"
x, y = t2
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(y) # N: Revealed type is "Union[builtins.int, builtins.str]"
x, y = object(), object()
reveal_type(x) # N: Revealed type is "builtins.object"
reveal_type(y) # N: Revealed type is "builtins.object"
[builtins fixtures/tuple.pyi]
[out]
[case testUnionUnpackingFromNestedTuples]
from typing import Union, Tuple
t: Union[Tuple[int, Tuple[int, int]], Tuple[str, Tuple[str, str]]]
x, (y, z) = t
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(y) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(z) # N: Revealed type is "Union[builtins.int, builtins.str]"
[builtins fixtures/tuple.pyi]
[out]
[case testNestedUnionUnpackingFromNestedTuples]
from typing import Union, Tuple
class A: pass
class B: pass
t: Union[Tuple[int, Union[Tuple[int, int], Tuple[A, A]]], Tuple[str, Union[Tuple[str, str], Tuple[B, B]]]]
x, (y, z) = t
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(y) # N: Revealed type is "Union[builtins.int, __main__.A, builtins.str, __main__.B]"
reveal_type(z) # N: Revealed type is "Union[builtins.int, __main__.A, builtins.str, __main__.B]"
[builtins fixtures/tuple.pyi]
[out]
[case testNestedUnionUnpackingFromNestedTuplesBinder]
from typing import Union, Tuple
class A: pass
class B: pass
x: object
y: object
z: object
t: Union[Tuple[int, Union[Tuple[int, int], Tuple[A, A]]], Tuple[str, Union[Tuple[str, str], Tuple[B, B]]]]
x, (y, z) = t
reveal_type(x) # N: Revealed type is "Union[builtins.int, builtins.str]"
reveal_type(y) # N: Revealed type is "Union[builtins.int, __main__.A, builtins.str, __main__.B]"
reveal_type(z) # N: Revealed type is "Union[builtins.int, __main__.A, builtins.str, __main__.B]"
[builtins fixtures/tuple.pyi]
[out]
[case testUnpackUnionNoCrashOnPartialNone]
from typing import Dict, Tuple, List, Any
a: Any
d: Dict[str, Tuple[List[Tuple[str, str]], str]]
x, _ = d.get(a, (None, None))
for y in x: pass # E: Item "None" of "Optional[List[Tuple[str, str]]]" has no attribute "__iter__" (not iterable)
if x:
for s, t in x:
reveal_type(s) # N: Revealed type is "builtins.str"
[builtins fixtures/dict.pyi]
[out]
[case testUnpackUnionNoCrashOnPartialNone2]
from typing import Dict, Tuple, List, Any
a: Any
x = None
d: Dict[str, Tuple[List[Tuple[str, str]], str]]
x, _ = d.get(a, (None, None))
for y in x: pass # E: Item "None" of "Optional[List[Tuple[str, str]]]" has no attribute "__iter__" (not iterable)
if x:
for s, t in x:
reveal_type(s) # N: Revealed type is "builtins.str"
[builtins fixtures/dict.pyi]
[out]
[case testUnpackUnionNoCrashOnPartialNoneBinder]
from typing import Dict, Tuple, List, Any
x: object
a: Any
d: Dict[str, Tuple[List[Tuple[str, str]], str]]
x, _ = d.get(a, (None, None))
reveal_type(x) # N: Revealed type is "Union[builtins.list[Tuple[builtins.str, builtins.str]], None]"
if x:
for y in x: pass
[builtins fixtures/dict.pyi]
[out]
[case testUnpackUnionNoCrashOnPartialList]
from typing import Dict, Tuple, List, Any
a: Any
d: Dict[str, Tuple[List[Tuple[str, str]], str]]
x, _ = d.get(a, ([], ""))
reveal_type(x) # N: Revealed type is "builtins.list[Tuple[builtins.str, builtins.str]]"
for y in x: pass
[builtins fixtures/dict.pyi]
[out]
[case testLongUnionFormatting]
from typing import Any, Generic, TypeVar, Union
T = TypeVar('T')
class ExtremelyLongTypeNameWhichIsGenericSoWeCanUseItMultipleTimes(Generic[T]):
pass
x: Union[ExtremelyLongTypeNameWhichIsGenericSoWeCanUseItMultipleTimes[int],
ExtremelyLongTypeNameWhichIsGenericSoWeCanUseItMultipleTimes[object],
ExtremelyLongTypeNameWhichIsGenericSoWeCanUseItMultipleTimes[float],
ExtremelyLongTypeNameWhichIsGenericSoWeCanUseItMultipleTimes[str],
ExtremelyLongTypeNameWhichIsGenericSoWeCanUseItMultipleTimes[Any],
ExtremelyLongTypeNameWhichIsGenericSoWeCanUseItMultipleTimes[bytes]]
def takes_int(arg: int) -> None: pass
takes_int(x) # E: Argument 1 to "takes_int" has incompatible type "Union[ExtremelyLongTypeNameWhichIsGenericSoWeCanUseItMultipleTimes[int], ExtremelyLongTypeNameWhichIsGenericSoWeCanUseItMultipleTimes[object], ExtremelyLongTypeNameWhichIsGenericSoWeCanUseItMultipleTimes[float], ExtremelyLongTypeNameWhichIsGenericSoWeCanUseItMultipleTimes[str], ExtremelyLongTypeNameWhichIsGenericSoWeCanUseItMultipleTimes[Any], ExtremelyLongTypeNameWhichIsGenericSoWeCanUseItMultipleTimes[bytes]]"; expected "int"
[case testRecursiveForwardReferenceInUnion]
# flags: --disable-recursive-aliases
from typing import List, Union
MYTYPE = List[Union[str, "MYTYPE"]] # E: Cannot resolve name "MYTYPE" (possible cyclic definition)
[builtins fixtures/list.pyi]
[case testNonStrictOptional]
# flags: --no-strict-optional
from typing import Optional, List
def union_test1(x):
# type: (Optional[List[int]]) -> Optional[int]
if x is None:
return x
else:
return x[0]
def union_test2(x):
# type: (Optional[List[int]]) -> Optional[int]
if isinstance(x, type(None)):
return x
else:
return x[0]
def f(): return 0
def union_test3():
# type: () -> int
x = f()
assert x is None
x = f()
return x + 1
[builtins fixtures/isinstancelist.pyi]
[case testInvariance]
from typing import List, Union
from enum import Enum
class Boop(Enum):
FOO = 1
def do_thing_with_enums(enums: Union[List[Enum], Enum]) -> None: ...
boop: List[Boop] = []
do_thing_with_enums(boop) # E: Argument 1 to "do_thing_with_enums" has incompatible type "List[Boop]"; expected "Union[List[Enum], Enum]" \
# N: "List" is invariant -- see https://mypy.readthedocs.io/en/stable/common_issues.html#variance \
# N: Consider using "Sequence" instead, which is covariant
[builtins fixtures/isinstancelist.pyi]
[case testAssignUnionWithTenaryExprWithEmptyCollection]
from typing import Dict, List, Union
x: Union[int, List[int]] = 1 if bool() else []
y: Union[int, Dict[int, int]] = 1 if bool() else {}
u: Union[int, List[int]] = [] if bool() else 1
v: Union[int, Dict[int, int]] = {} if bool() else 1
[builtins fixtures/isinstancelist.pyi]
[case testFlattenTypeAliasWhenAliasedAsUnion]
from typing import Union
T1 = int
T2 = Union[T1, float]
T3 = Union[T2, complex]
T4 = Union[T3, int]
def foo(a: T2, b: T2) -> T2:
return a + b
def bar(a: T4, b: T4) -> T4: # test multi-level alias
return a + b
[builtins fixtures/ops.pyi]
[case testJoinUnionWithUnionAndAny]
from typing import TypeVar, Union, Any
T = TypeVar("T")
def f(x: T, y: T) -> T:
return x
x: Union[None, Any]
y: Union[int, None]
reveal_type(f(x, y)) # N: Revealed type is "Union[None, Any, builtins.int]"
reveal_type(f(y, x)) # N: Revealed type is "Union[builtins.int, None, Any]"
[case testNestedProtocolUnions]
from typing import Union, Iterator, Iterable
def foo(
values: Union[
Iterator[Union[
Iterator[Union[Iterator[int], Iterable[int]]],
Iterable[Union[Iterator[int], Iterable[int]]],
]],
Iterable[Union[
Iterator[Union[Iterator[int], Iterable[int]]],
Iterable[Union[Iterator[int], Iterable[int]]],
]],
]
) -> Iterator[int]:
for i in values:
for j in i:
for k in j:
yield k
foo([[[1]]])
[builtins fixtures/list.pyi]
[case testNestedProtocolGenericUnions]
from typing import Union, Iterator, List
def foo(
values: Union[
Iterator[Union[
Iterator[Union[Iterator[int], List[int]]],
List[Union[Iterator[int], List[int]]],
]],
List[Union[
Iterator[Union[Iterator[int], List[int]]],
List[Union[Iterator[int], List[int]]],
]],
]
) -> Iterator[int]:
for i in values:
for j in i:
for k in j:
yield k
foo([[[1]]])
[builtins fixtures/list.pyi]
[case testNestedProtocolGenericUnionsDeep]
from typing import TypeVar, Union, Iterator, List
T = TypeVar("T")
Iter = Union[Iterator[T], List[T]]
def foo(
values: Iter[Iter[Iter[Iter[Iter[int]]]]],
) -> Iterator[int]:
for i in values:
for j in i:
for k in j:
for l in k:
for m in l:
yield m
foo([[[[[1]]]]])
[builtins fixtures/list.pyi]
[case testNestedInstanceUnsimplifiedUnion]
from typing import TypeVar, Union, Iterator, List, Any
T = TypeVar("T")
Iter = Union[Iterator[T], List[T]]
def foo(
values: Iter[Union[Any, Any]],
) -> Iterator[Any]:
for i in values:
yield i
foo([1])
[builtins fixtures/list.pyi]
[case testNestedInstanceTypeAlias]
from typing import TypeVar, Union, Iterator, List, Any
T = TypeVar("T")
Iter = Union[Iterator[T], List[T]]
def foo(
values: Iter["Any"],
) -> Iterator[Any]:
for i in values:
yield i
foo([1])
[builtins fixtures/list.pyi]
[case testGenericUnionMemberWithTypeVarConstraints]
from typing import Generic, TypeVar, Union
T = TypeVar('T', str, int)
class C(Generic[T]): ...
def f(s: Union[T, C[T]]) -> T: ...
ci: C[int]
cs: C[str]
reveal_type(f(1)) # N: Revealed type is "builtins.int"
reveal_type(f('')) # N: Revealed type is "builtins.str"
reveal_type(f(ci)) # N: Revealed type is "builtins.int"
reveal_type(f(cs)) # N: Revealed type is "builtins.str"
[case testNestedInstanceTypeAliasUnsimplifiedUnion]
from typing import TypeVar, Union, Iterator, List, Any
T = TypeVar("T")
Iter = Union[Iterator[T], List[T]]
def foo(
values: Iter["Union[Any, Any]"],
) -> Iterator[Any]:
for i in values:
yield i
foo([1])
[builtins fixtures/list.pyi]
[case testUnionIterableContainer]
from typing import Iterable, Container, Union
i: Iterable[str]
c: Container[str]
u: Union[Iterable[str], Container[str]]
ni: Union[Iterable[str], int]
nc: Union[Container[str], int]
'x' in i
'x' in c
'x' in u
'x' in ni # E: Unsupported right operand type for in ("Union[Iterable[str], int]")
'x' in nc # E: Unsupported right operand type for in ("Union[Container[str], int]")
[builtins fixtures/tuple.pyi]
[typing fixtures/typing-full.pyi]