| [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 = box(None, 1) |
| 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, r2 :: bit |
| L0: |
| r0 = box(None, 1) |
| r1 = x == r0 |
| r2 = r1 ^ 1 |
| if r2 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 :: int32 |
| 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: int32 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 = box(short_int, 2) |
| z = r2 |
| r3 = A() |
| a = r3 |
| r4 = box(short_int, 2) |
| 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 = box(short_int, 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, r3 :: bit |
| r4, r5 :: __main__.A |
| L0: |
| r0 = A() |
| y = r0 |
| r1 = box(None, 1) |
| r2 = x == r1 |
| r3 = r2 ^ 1 |
| if r3 goto L1 else goto L2 :: bool |
| L1: |
| r4 = cast(__main__.A, x) |
| y = r4 |
| r5 = cast(__main__.A, x) |
| return r5 |
| 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, r5 :: bit |
| r6 :: int |
| L0: |
| r0 = box(None, 1) |
| x = r0 |
| r1 = y == 2 |
| if r1 goto L1 else goto L2 :: bool |
| L1: |
| r2 = box(int, y) |
| x = r2 |
| L2: |
| r3 = box(None, 1) |
| r4 = x == r3 |
| r5 = r4 ^ 1 |
| if r5 goto L3 else goto L4 :: bool |
| L3: |
| r6 = unbox(int, x) |
| y = r6 |
| L4: |
| return 1 |
| |
| [case testUnionType] |
| 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 :: object |
| r1 :: int32 |
| r2 :: bit |
| r3 :: bool |
| r4, r5 :: int |
| r6 :: __main__.A |
| r7 :: int |
| L0: |
| r0 = load_address PyLong_Type |
| r1 = PyObject_IsInstance(x, r0) |
| r2 = r1 >= 0 :: signed |
| r3 = truncate r1: int32 to builtins.bool |
| if r3 goto L1 else goto L2 :: bool |
| L1: |
| r4 = unbox(int, x) |
| r5 = CPyTagged_Add(r4, 2) |
| return r5 |
| L2: |
| r6 = cast(__main__.A, x) |
| r7 = r6.a |
| return r7 |
| 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 = 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 :: int32 |
| 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 = 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 = 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 = box(short_int, 2) |
| r14 = r12.f(r13) |
| r7 = r14 |
| goto L5 |
| L4: |
| r15 = cast(__main__.C, o) |
| r16 = box(short_int, 2) |
| 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 = 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 = 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 :: union[object, object] |
| r0 :: object |
| r1 :: str |
| r2, r3 :: object |
| L0: |
| r0 = o |
| r1 = 'x' |
| r2 = CPyObject_GetAttr(r0, r1) |
| r3 = r2 |
| L1: |
| return 1 |
| |