| [case testIsNone] | |
| from typing import Optional | |
| class A: pass | |
| def f(x: Optional[A]) -> int: | |
| if x is None: | |
| return 1 | |
| return 2 | |
| [out] | |
| def f(x): | |
| x :: union[__main__.A, None] | |
| r0 :: object | |
| r1 :: bit | |
| L0: | |
| r0 = load_address _Py_NoneStruct | |
| r1 = x == r0 | |
| if r1 goto L1 else goto L2 :: bool | |
| L1: | |
| return 2 | |
| L2: | |
| return 4 | |
| [case testIsNotNone] | |
| from typing import Optional | |
| class A: pass | |
| def f(x: Optional[A]) -> int: | |
| if x is not None: | |
| return 1 | |
| return 2 | |
| [out] | |
| def f(x): | |
| x :: union[__main__.A, None] | |
| r0 :: object | |
| r1 :: bit | |
| L0: | |
| r0 = load_address _Py_NoneStruct | |
| r1 = x != r0 | |
| if r1 goto L1 else goto L2 :: bool | |
| L1: | |
| return 2 | |
| L2: | |
| return 4 | |
| [case testIsTruthy] | |
| from typing import Optional | |
| class A: pass | |
| def f(x: Optional[A]) -> int: | |
| if x: | |
| return 1 | |
| return 2 | |
| [out] | |
| def f(x): | |
| x :: union[__main__.A, None] | |
| r0 :: object | |
| r1 :: bit | |
| L0: | |
| r0 = load_address _Py_NoneStruct | |
| r1 = x != r0 | |
| if r1 goto L1 else goto L2 :: bool | |
| L1: | |
| return 2 | |
| L2: | |
| return 4 | |
| [case testIsTruthyOverride] | |
| from typing import Optional | |
| class A: pass | |
| class B(A): | |
| def __bool__(self) -> bool: | |
| return False | |
| def f(x: Optional[A]) -> int: | |
| if x: | |
| return 1 | |
| return 2 | |
| [out] | |
| def B.__bool__(self): | |
| self :: __main__.B | |
| L0: | |
| return 0 | |
| def f(x): | |
| x :: union[__main__.A, None] | |
| r0 :: object | |
| r1 :: bit | |
| r2 :: __main__.A | |
| r3 :: i32 | |
| r4 :: bit | |
| r5 :: bool | |
| L0: | |
| r0 = load_address _Py_NoneStruct | |
| r1 = x != r0 | |
| if r1 goto L1 else goto L3 :: bool | |
| L1: | |
| r2 = cast(__main__.A, x) | |
| r3 = PyObject_IsTrue(r2) | |
| r4 = r3 >= 0 :: signed | |
| r5 = truncate r3: i32 to builtins.bool | |
| if r5 goto L2 else goto L3 :: bool | |
| L2: | |
| return 2 | |
| L3: | |
| return 4 | |
| [case testAssignToOptional] | |
| from typing import Optional | |
| class A: | |
| a: Optional[int] | |
| def f(x: Optional[A], y: Optional[A], z: Optional[int]) -> None: | |
| x = None | |
| x = A() | |
| x = y | |
| z = 1 | |
| a = A() | |
| a.a = 1 | |
| a.a = None | |
| [out] | |
| def f(x, y, z): | |
| x, y :: union[__main__.A, None] | |
| z :: union[int, None] | |
| r0 :: object | |
| r1 :: __main__.A | |
| r2 :: object | |
| r3, a :: __main__.A | |
| r4 :: object | |
| r5 :: bool | |
| r6 :: object | |
| r7 :: bool | |
| L0: | |
| r0 = box(None, 1) | |
| x = r0 | |
| r1 = A() | |
| x = r1 | |
| x = y | |
| r2 = object 1 | |
| z = r2 | |
| r3 = A() | |
| a = r3 | |
| r4 = object 1 | |
| a.a = r4; r5 = is_error | |
| r6 = box(None, 1) | |
| a.a = r6; r7 = is_error | |
| return 1 | |
| [case testBoxOptionalListItem] | |
| from typing import List, Optional | |
| def f(x: List[Optional[int]]) -> None: | |
| x[0] = 0 | |
| x[1] = None | |
| [out] | |
| def f(x): | |
| x :: list | |
| r0 :: object | |
| r1 :: bit | |
| r2 :: object | |
| r3 :: bit | |
| L0: | |
| r0 = object 0 | |
| r1 = CPyList_SetItem(x, 0, r0) | |
| r2 = box(None, 1) | |
| r3 = CPyList_SetItem(x, 2, r2) | |
| return 1 | |
| [case testNarrowDownFromOptional] | |
| from typing import Optional | |
| class A: pass | |
| def f(x: Optional[A]) -> A: | |
| y = A() | |
| if x is not None: | |
| y = x | |
| return x | |
| return y | |
| [out] | |
| def f(x): | |
| x :: union[__main__.A, None] | |
| r0, y :: __main__.A | |
| r1 :: object | |
| r2 :: bit | |
| r3, r4 :: __main__.A | |
| L0: | |
| r0 = A() | |
| y = r0 | |
| r1 = load_address _Py_NoneStruct | |
| r2 = x != r1 | |
| if r2 goto L1 else goto L2 :: bool | |
| L1: | |
| r3 = cast(__main__.A, x) | |
| y = r3 | |
| r4 = cast(__main__.A, x) | |
| return r4 | |
| L2: | |
| return y | |
| [case testPartialOptionalType] | |
| def f(y: int) -> None: | |
| x = None | |
| if y == 1: | |
| x = y | |
| if x is not None: | |
| y = x | |
| [out] | |
| def f(y): | |
| y :: int | |
| r0 :: object | |
| x :: union[int, None] | |
| r1 :: bit | |
| r2, r3 :: object | |
| r4 :: bit | |
| r5 :: int | |
| L0: | |
| r0 = box(None, 1) | |
| x = r0 | |
| r1 = int_eq y, 2 | |
| if r1 goto L1 else goto L2 :: bool | |
| L1: | |
| r2 = box(int, y) | |
| x = r2 | |
| L2: | |
| r3 = load_address _Py_NoneStruct | |
| r4 = x != r3 | |
| if r4 goto L3 else goto L4 :: bool | |
| L3: | |
| r5 = unbox(int, x) | |
| y = r5 | |
| L4: | |
| return 1 | |
| [case testUnionType_withgil] | |
| from typing import Union | |
| class A: | |
| a: int | |
| def f(x: Union[int, A]) -> int: | |
| if isinstance(x, int): | |
| return x + 1 | |
| else: | |
| return x.a | |
| [out] | |
| def f(x): | |
| x :: union[int, __main__.A] | |
| r0 :: bit | |
| r1, r2 :: int | |
| r3 :: __main__.A | |
| r4 :: int | |
| L0: | |
| r0 = PyLong_Check(x) | |
| if r0 goto L1 else goto L2 :: bool | |
| L1: | |
| r1 = unbox(int, x) | |
| r2 = CPyTagged_Add(r1, 2) | |
| return r2 | |
| L2: | |
| r3 = borrow cast(__main__.A, x) | |
| r4 = r3.a | |
| keep_alive x | |
| return r4 | |
| L3: | |
| unreachable | |
| [case testUnionTypeInList] | |
| from typing import List, Union | |
| def f(x: List[Union[int, str]]) -> object: | |
| return x[0] | |
| [out] | |
| def f(x): | |
| x :: list | |
| r0 :: object | |
| r1 :: union[int, str] | |
| L0: | |
| r0 = CPyList_GetItemShort(x, 0) | |
| r1 = cast(union[int, str], r0) | |
| return r1 | |
| [case testUnionAttributeAccess] | |
| from typing import Union | |
| class A: | |
| a: int | |
| class B: | |
| a: object | |
| def get(o: Union[A, B]) -> None: | |
| z = o.a | |
| def set(o: Union[A, B], s: str) -> None: | |
| o.a = s | |
| [out] | |
| def get(o): | |
| o :: union[__main__.A, __main__.B] | |
| r0 :: object | |
| r1 :: ptr | |
| r2 :: object | |
| r3 :: bit | |
| r4 :: __main__.A | |
| r5 :: int | |
| r6, r7 :: object | |
| r8 :: __main__.B | |
| r9, z :: object | |
| L0: | |
| r0 = __main__.A :: type | |
| r1 = get_element_ptr o ob_type :: PyObject | |
| r2 = borrow load_mem r1 :: builtins.object* | |
| keep_alive o | |
| r3 = r2 == r0 | |
| if r3 goto L1 else goto L2 :: bool | |
| L1: | |
| r4 = cast(__main__.A, o) | |
| r5 = r4.a | |
| r6 = box(int, r5) | |
| r7 = r6 | |
| goto L3 | |
| L2: | |
| r8 = cast(__main__.B, o) | |
| r9 = r8.a | |
| r7 = r9 | |
| L3: | |
| z = r7 | |
| return 1 | |
| def set(o, s): | |
| o :: union[__main__.A, __main__.B] | |
| s, r0 :: str | |
| r1 :: i32 | |
| r2 :: bit | |
| L0: | |
| r0 = 'a' | |
| r1 = PyObject_SetAttr(o, r0, s) | |
| r2 = r1 >= 0 :: signed | |
| return 1 | |
| [case testUnionMethodCall] | |
| from typing import Union | |
| class A: | |
| def f(self, x: int) -> int: | |
| return x | |
| class B: | |
| def f(self, x: object) -> object: | |
| return x | |
| class C: | |
| def f(self, x: object) -> int: | |
| return 0 | |
| def g(o: Union[A, B, C]) -> None: | |
| z = o.f(1) | |
| [out] | |
| def A.f(self, x): | |
| self :: __main__.A | |
| x :: int | |
| L0: | |
| return x | |
| def B.f(self, x): | |
| self :: __main__.B | |
| x :: object | |
| L0: | |
| return x | |
| def C.f(self, x): | |
| self :: __main__.C | |
| x :: object | |
| L0: | |
| return 0 | |
| def g(o): | |
| o :: union[__main__.A, __main__.B, __main__.C] | |
| r0 :: object | |
| r1 :: ptr | |
| r2 :: object | |
| r3 :: bit | |
| r4 :: __main__.A | |
| r5 :: int | |
| r6, r7, r8 :: object | |
| r9 :: ptr | |
| r10 :: object | |
| r11 :: bit | |
| r12 :: __main__.B | |
| r13, r14 :: object | |
| r15 :: __main__.C | |
| r16 :: object | |
| r17 :: int | |
| r18, z :: object | |
| L0: | |
| r0 = __main__.A :: type | |
| r1 = get_element_ptr o ob_type :: PyObject | |
| r2 = borrow load_mem r1 :: builtins.object* | |
| keep_alive o | |
| r3 = r2 == r0 | |
| if r3 goto L1 else goto L2 :: bool | |
| L1: | |
| r4 = cast(__main__.A, o) | |
| r5 = r4.f(2) | |
| r6 = box(int, r5) | |
| r7 = r6 | |
| goto L5 | |
| L2: | |
| r8 = __main__.B :: type | |
| r9 = get_element_ptr o ob_type :: PyObject | |
| r10 = borrow load_mem r9 :: builtins.object* | |
| keep_alive o | |
| r11 = r10 == r8 | |
| if r11 goto L3 else goto L4 :: bool | |
| L3: | |
| r12 = cast(__main__.B, o) | |
| r13 = object 1 | |
| r14 = r12.f(r13) | |
| r7 = r14 | |
| goto L5 | |
| L4: | |
| r15 = cast(__main__.C, o) | |
| r16 = object 1 | |
| r17 = r15.f(r16) | |
| r18 = box(int, r17) | |
| r7 = r18 | |
| L5: | |
| z = r7 | |
| return 1 | |
| [case testUnionWithNonNativeItem] | |
| from typing import Union | |
| from m import B | |
| class A: | |
| x: int | |
| def f(o: Union[A, B]) -> None: | |
| o.x | |
| def g(o: Union[B, A]) -> None: | |
| o.x | |
| [file m.py] | |
| class B: | |
| x: int | |
| [out] | |
| def f(o): | |
| o :: union[__main__.A, object] | |
| r0 :: object | |
| r1 :: ptr | |
| r2 :: object | |
| r3 :: bit | |
| r4 :: __main__.A | |
| r5, r6 :: int | |
| r7 :: object | |
| r8 :: str | |
| r9 :: object | |
| r10 :: int | |
| L0: | |
| r0 = __main__.A :: type | |
| r1 = get_element_ptr o ob_type :: PyObject | |
| r2 = borrow load_mem r1 :: builtins.object* | |
| keep_alive o | |
| r3 = r2 == r0 | |
| if r3 goto L1 else goto L2 :: bool | |
| L1: | |
| r4 = cast(__main__.A, o) | |
| r5 = r4.x | |
| r6 = r5 | |
| goto L3 | |
| L2: | |
| r7 = o | |
| r8 = 'x' | |
| r9 = CPyObject_GetAttr(r7, r8) | |
| r10 = unbox(int, r9) | |
| r6 = r10 | |
| L3: | |
| return 1 | |
| def g(o): | |
| o :: union[object, __main__.A] | |
| r0 :: object | |
| r1 :: ptr | |
| r2 :: object | |
| r3 :: bit | |
| r4 :: __main__.A | |
| r5, r6 :: int | |
| r7 :: object | |
| r8 :: str | |
| r9 :: object | |
| r10 :: int | |
| L0: | |
| r0 = __main__.A :: type | |
| r1 = get_element_ptr o ob_type :: PyObject | |
| r2 = borrow load_mem r1 :: builtins.object* | |
| keep_alive o | |
| r3 = r2 == r0 | |
| if r3 goto L1 else goto L2 :: bool | |
| L1: | |
| r4 = cast(__main__.A, o) | |
| r5 = r4.x | |
| r6 = r5 | |
| goto L3 | |
| L2: | |
| r7 = o | |
| r8 = 'x' | |
| r9 = CPyObject_GetAttr(r7, r8) | |
| r10 = unbox(int, r9) | |
| r6 = r10 | |
| L3: | |
| return 1 | |
| [case testUnionWithNoNativeItems] | |
| from typing import Union | |
| from m import A, B | |
| def f(o: Union[A, B]) -> None: | |
| o.x | |
| [file m.py] | |
| class A: | |
| x: object | |
| class B: | |
| x: int | |
| [out] | |
| def f(o): | |
| o :: object | |
| r0 :: str | |
| r1 :: object | |
| L0: | |
| r0 = 'x' | |
| r1 = CPyObject_GetAttr(o, r0) | |
| return 1 |