| [case testGetAttribute] |
| class A: |
| x: int |
| |
| def f(a: A) -> int: |
| return a.x |
| [out] |
| def f(a): |
| a :: __main__.A |
| r0 :: int |
| L0: |
| r0 = a.x |
| return r0 |
| |
| [case testSetAttribute] |
| class A: |
| x: int |
| |
| def f(a: A) -> None: |
| a.x = 1 |
| [out] |
| def f(a): |
| a :: __main__.A |
| r0 :: bool |
| L0: |
| a.x = 2; r0 = is_error |
| return 1 |
| |
| [case testUserClassInList] |
| class C: |
| x: int |
| |
| def f() -> int: |
| c = C() |
| c.x = 5 |
| a = [c] |
| d = a[0] |
| return d.x + 1 |
| [out] |
| def f(): |
| r0, c :: __main__.C |
| r1 :: bool |
| r2 :: list |
| r3, r4 :: ptr |
| a :: list |
| r5 :: object |
| r6, d :: __main__.C |
| r7, r8 :: int |
| L0: |
| r0 = C() |
| c = r0 |
| c.x = 10; r1 = is_error |
| r2 = PyList_New(1) |
| r3 = get_element_ptr r2 ob_item :: PyListObject |
| r4 = load_mem r3 :: ptr* |
| set_mem r4, c :: builtins.object* |
| keep_alive r2 |
| a = r2 |
| r5 = CPyList_GetItemShort(a, 0) |
| r6 = cast(__main__.C, r5) |
| d = r6 |
| r7 = borrow d.x |
| r8 = CPyTagged_Add(r7, 2) |
| keep_alive d |
| return r8 |
| |
| [case testMethodCall] |
| class A: |
| def f(self, x: int, y: str) -> int: |
| return x + 10 |
| |
| def g(a: A) -> None: |
| a.f(1, 'hi') |
| [out] |
| def A.f(self, x, y): |
| self :: __main__.A |
| x :: int |
| y :: str |
| r0 :: int |
| L0: |
| r0 = CPyTagged_Add(x, 20) |
| return r0 |
| def g(a): |
| a :: __main__.A |
| r0 :: str |
| r1 :: int |
| L0: |
| r0 = 'hi' |
| r1 = a.f(2, r0) |
| return 1 |
| |
| [case testForwardUse] |
| def g(a: A) -> int: |
| return a.n |
| |
| class A: |
| n : int |
| |
| [out] |
| def g(a): |
| a :: __main__.A |
| r0 :: int |
| L0: |
| r0 = a.n |
| return r0 |
| |
| [case testOptionalMember] |
| from typing import Optional |
| class Node: |
| next: Optional[Node] |
| def length(self) -> int: |
| if self.next is not None: |
| return 1 + self.next.length() |
| return 1 |
| [out] |
| def Node.length(self): |
| self :: __main__.Node |
| r0 :: union[__main__.Node, None] |
| r1 :: object |
| r2 :: bit |
| r3 :: union[__main__.Node, None] |
| r4 :: __main__.Node |
| r5, r6 :: int |
| L0: |
| r0 = borrow self.next |
| r1 = load_address _Py_NoneStruct |
| r2 = r0 != r1 |
| keep_alive self |
| if r2 goto L1 else goto L2 :: bool |
| L1: |
| r3 = self.next |
| r4 = cast(__main__.Node, r3) |
| r5 = r4.length() |
| r6 = CPyTagged_Add(2, r5) |
| return r6 |
| L2: |
| return 2 |
| |
| [case testSubclass] |
| class A: |
| def __init__(self) -> None: |
| self.x = 10 |
| class B(A): |
| def __init__(self) -> None: |
| self.x = 20 |
| self.y = 30 |
| [out] |
| def A.__init__(self): |
| self :: __main__.A |
| L0: |
| self.x = 20 |
| return 1 |
| def B.__init__(self): |
| self :: __main__.B |
| L0: |
| self.x = 40 |
| self.y = 60 |
| return 1 |
| |
| [case testAttrLvalue] |
| class O(object): |
| def __init__(self) -> None: |
| self.x = 1 |
| |
| def increment(o: O) -> O: |
| o.x += 1 |
| return o |
| [out] |
| def O.__init__(self): |
| self :: __main__.O |
| L0: |
| self.x = 2 |
| return 1 |
| def increment(o): |
| o :: __main__.O |
| r0, r1 :: int |
| r2 :: bool |
| L0: |
| r0 = borrow o.x |
| r1 = CPyTagged_Add(r0, 2) |
| o.x = r1; r2 = is_error |
| return o |
| |
| [case testSubclass_toplevel] |
| from typing import TypeVar, Generic |
| from mypy_extensions import trait |
| T = TypeVar('T') |
| class C: |
| pass |
| |
| @trait |
| class S: |
| pass |
| |
| class D(C, S, Generic[T]): |
| pass |
| |
| [out] |
| def __top_level__(): |
| r0, r1 :: object |
| r2 :: bit |
| r3 :: str |
| r4, r5 :: object |
| r6 :: str |
| r7 :: dict |
| r8, r9 :: object |
| r10 :: str |
| r11 :: dict |
| r12 :: object |
| r13 :: str |
| r14 :: dict |
| r15 :: str |
| r16, r17 :: object |
| r18 :: dict |
| r19 :: str |
| r20 :: i32 |
| r21 :: bit |
| r22 :: object |
| r23 :: str |
| r24, r25 :: object |
| r26 :: bool |
| r27 :: str |
| r28 :: tuple |
| r29 :: i32 |
| r30 :: bit |
| r31 :: dict |
| r32 :: str |
| r33 :: i32 |
| r34 :: bit |
| r35 :: object |
| r36 :: str |
| r37, r38 :: object |
| r39 :: str |
| r40 :: tuple |
| r41 :: i32 |
| r42 :: bit |
| r43 :: dict |
| r44 :: str |
| r45 :: i32 |
| r46 :: bit |
| r47, r48 :: object |
| r49 :: dict |
| r50 :: str |
| r51 :: object |
| r52 :: dict |
| r53 :: str |
| r54, r55 :: object |
| r56 :: tuple |
| r57 :: str |
| r58, r59 :: object |
| r60 :: bool |
| r61, r62 :: str |
| r63 :: tuple |
| r64 :: i32 |
| r65 :: bit |
| r66 :: dict |
| r67 :: str |
| r68 :: i32 |
| r69 :: bit |
| L0: |
| r0 = builtins :: module |
| r1 = load_address _Py_NoneStruct |
| r2 = r0 != r1 |
| if r2 goto L2 else goto L1 :: bool |
| L1: |
| r3 = 'builtins' |
| r4 = PyImport_Import(r3) |
| builtins = r4 :: module |
| L2: |
| r5 = ('TypeVar', 'Generic') |
| r6 = 'typing' |
| r7 = __main__.globals :: static |
| r8 = CPyImport_ImportFromMany(r6, r5, r5, r7) |
| typing = r8 :: module |
| r9 = ('trait',) |
| r10 = 'mypy_extensions' |
| r11 = __main__.globals :: static |
| r12 = CPyImport_ImportFromMany(r10, r9, r9, r11) |
| mypy_extensions = r12 :: module |
| r13 = 'T' |
| r14 = __main__.globals :: static |
| r15 = 'TypeVar' |
| r16 = CPyDict_GetItem(r14, r15) |
| r17 = PyObject_CallFunctionObjArgs(r16, r13, 0) |
| r18 = __main__.globals :: static |
| r19 = 'T' |
| r20 = CPyDict_SetItem(r18, r19, r17) |
| r21 = r20 >= 0 :: signed |
| r22 = <error> :: object |
| r23 = '__main__' |
| r24 = __main__.C_template :: type |
| r25 = CPyType_FromTemplate(r24, r22, r23) |
| r26 = C_trait_vtable_setup() |
| r27 = '__mypyc_attrs__' |
| r28 = PyTuple_Pack(0) |
| r29 = PyObject_SetAttr(r25, r27, r28) |
| r30 = r29 >= 0 :: signed |
| __main__.C = r25 :: type |
| r31 = __main__.globals :: static |
| r32 = 'C' |
| r33 = CPyDict_SetItem(r31, r32, r25) |
| r34 = r33 >= 0 :: signed |
| r35 = <error> :: object |
| r36 = '__main__' |
| r37 = __main__.S_template :: type |
| r38 = CPyType_FromTemplate(r37, r35, r36) |
| r39 = '__mypyc_attrs__' |
| r40 = PyTuple_Pack(0) |
| r41 = PyObject_SetAttr(r38, r39, r40) |
| r42 = r41 >= 0 :: signed |
| __main__.S = r38 :: type |
| r43 = __main__.globals :: static |
| r44 = 'S' |
| r45 = CPyDict_SetItem(r43, r44, r38) |
| r46 = r45 >= 0 :: signed |
| r47 = __main__.C :: type |
| r48 = __main__.S :: type |
| r49 = __main__.globals :: static |
| r50 = 'Generic' |
| r51 = CPyDict_GetItem(r49, r50) |
| r52 = __main__.globals :: static |
| r53 = 'T' |
| r54 = CPyDict_GetItem(r52, r53) |
| r55 = PyObject_GetItem(r51, r54) |
| r56 = PyTuple_Pack(3, r47, r48, r55) |
| r57 = '__main__' |
| r58 = __main__.D_template :: type |
| r59 = CPyType_FromTemplate(r58, r56, r57) |
| r60 = D_trait_vtable_setup() |
| r61 = '__mypyc_attrs__' |
| r62 = '__dict__' |
| r63 = PyTuple_Pack(1, r62) |
| r64 = PyObject_SetAttr(r59, r61, r63) |
| r65 = r64 >= 0 :: signed |
| __main__.D = r59 :: type |
| r66 = __main__.globals :: static |
| r67 = 'D' |
| r68 = CPyDict_SetItem(r66, r67, r59) |
| r69 = r68 >= 0 :: signed |
| return 1 |
| |
| [case testIsInstance] |
| class A: pass |
| class B(A): pass |
| |
| def f(x: A) -> B: |
| if isinstance(x, B): |
| return x |
| return B() |
| [out] |
| def f(x): |
| x :: __main__.A |
| r0 :: object |
| r1 :: ptr |
| r2 :: object |
| r3 :: bit |
| r4, r5 :: __main__.B |
| L0: |
| r0 = __main__.B :: type |
| r1 = get_element_ptr x ob_type :: PyObject |
| r2 = load_mem r1 :: builtins.object* |
| keep_alive x |
| r3 = r2 == r0 |
| if r3 goto L1 else goto L2 :: bool |
| L1: |
| r4 = cast(__main__.B, x) |
| return r4 |
| L2: |
| r5 = B() |
| return r5 |
| |
| [case testIsInstanceTuple] |
| from typing import Union |
| class R: pass |
| class A(R): pass |
| class B(R): pass |
| class C(R): pass |
| |
| def f(x: R) -> Union[A, B]: |
| if isinstance(x, (A, B)): |
| return x |
| return A() |
| [out] |
| def f(x): |
| x :: __main__.R |
| r0 :: object |
| r1 :: ptr |
| r2 :: object |
| r3 :: bit |
| r4 :: bool |
| r5 :: object |
| r6 :: ptr |
| r7 :: object |
| r8 :: bit |
| r9 :: union[__main__.A, __main__.B] |
| r10 :: __main__.A |
| L0: |
| r0 = __main__.A :: type |
| r1 = get_element_ptr x ob_type :: PyObject |
| r2 = load_mem r1 :: builtins.object* |
| keep_alive x |
| r3 = r2 == r0 |
| if r3 goto L1 else goto L2 :: bool |
| L1: |
| r4 = r3 |
| goto L3 |
| L2: |
| r5 = __main__.B :: type |
| r6 = get_element_ptr x ob_type :: PyObject |
| r7 = load_mem r6 :: builtins.object* |
| keep_alive x |
| r8 = r7 == r5 |
| r4 = r8 |
| L3: |
| if r4 goto L4 else goto L5 :: bool |
| L4: |
| r9 = cast(union[__main__.A, __main__.B], x) |
| return r9 |
| L5: |
| r10 = A() |
| return r10 |
| |
| [case testIsInstanceFewSubclasses] |
| class R: pass |
| class A(R): pass |
| |
| def f(x: object) -> R: |
| if isinstance(x, R): |
| return x |
| return A() |
| [out] |
| def f(x): |
| x, r0 :: object |
| r1 :: ptr |
| r2 :: object |
| r3 :: bit |
| r4 :: bool |
| r5 :: object |
| r6 :: ptr |
| r7 :: object |
| r8 :: bit |
| r9 :: __main__.R |
| r10 :: __main__.A |
| L0: |
| r0 = __main__.A :: type |
| r1 = get_element_ptr x ob_type :: PyObject |
| r2 = load_mem r1 :: builtins.object* |
| keep_alive x |
| r3 = r2 == r0 |
| if r3 goto L1 else goto L2 :: bool |
| L1: |
| r4 = r3 |
| goto L3 |
| L2: |
| r5 = __main__.R :: type |
| r6 = get_element_ptr x ob_type :: PyObject |
| r7 = load_mem r6 :: builtins.object* |
| keep_alive x |
| r8 = r7 == r5 |
| r4 = r8 |
| L3: |
| if r4 goto L4 else goto L5 :: bool |
| L4: |
| r9 = cast(__main__.R, x) |
| return r9 |
| L5: |
| r10 = A() |
| return r10 |
| |
| [case testIsInstanceFewSubclassesTrait] |
| from mypy_extensions import trait |
| class B: pass |
| @trait |
| class R: pass |
| class A(B, R): pass |
| class C(B, R): pass |
| |
| def f(x: object) -> R: |
| if isinstance(x, R): |
| return x |
| return A() |
| [out] |
| def f(x): |
| x, r0 :: object |
| r1 :: ptr |
| r2 :: object |
| r3 :: bit |
| r4 :: bool |
| r5 :: object |
| r6 :: ptr |
| r7 :: object |
| r8 :: bit |
| r9 :: __main__.R |
| r10 :: __main__.A |
| L0: |
| r0 = __main__.A :: type |
| r1 = get_element_ptr x ob_type :: PyObject |
| r2 = load_mem r1 :: builtins.object* |
| keep_alive x |
| r3 = r2 == r0 |
| if r3 goto L1 else goto L2 :: bool |
| L1: |
| r4 = r3 |
| goto L3 |
| L2: |
| r5 = __main__.C :: type |
| r6 = get_element_ptr x ob_type :: PyObject |
| r7 = load_mem r6 :: builtins.object* |
| keep_alive x |
| r8 = r7 == r5 |
| r4 = r8 |
| L3: |
| if r4 goto L4 else goto L5 :: bool |
| L4: |
| r9 = cast(__main__.R, x) |
| return r9 |
| L5: |
| r10 = A() |
| return r10 |
| |
| [case testIsInstanceManySubclasses] |
| class R: pass |
| class A(R): pass |
| class B(R): pass |
| class C(R): pass |
| |
| def f(x: object) -> R: |
| if isinstance(x, R): |
| return x |
| return B() |
| [out] |
| def f(x): |
| x, r0 :: object |
| r1 :: bool |
| r2 :: __main__.R |
| r3 :: __main__.B |
| L0: |
| r0 = __main__.R :: type |
| r1 = CPy_TypeCheck(x, r0) |
| if r1 goto L1 else goto L2 :: bool |
| L1: |
| r2 = cast(__main__.R, x) |
| return r2 |
| L2: |
| r3 = B() |
| return r3 |
| |
| [case testFakeSuper] |
| class A: |
| def __init__(self, x: int) -> None: |
| self.x = x |
| class B(A): |
| def __init__(self, x: int, y: int) -> None: |
| A.__init__(self, x) |
| self.y = y |
| [out] |
| def A.__init__(self, x): |
| self :: __main__.A |
| x :: int |
| L0: |
| self.x = x |
| return 1 |
| def B.__init__(self, x, y): |
| self :: __main__.B |
| x, y :: int |
| r0 :: None |
| L0: |
| r0 = A.__init__(self, x) |
| self.y = y |
| return 1 |
| |
| [case testClassMethod] |
| class C: |
| @staticmethod |
| def foo(x: int) -> int: return 10 + x |
| @classmethod |
| def bar(cls, x: int) -> int: return 10 + x |
| |
| def lol() -> int: |
| return C.foo(1) + C.bar(2) |
| [out] |
| def C.foo(x): |
| x, r0 :: int |
| L0: |
| r0 = CPyTagged_Add(20, x) |
| return r0 |
| def C.bar(cls, x): |
| cls :: object |
| x, r0 :: int |
| L0: |
| r0 = CPyTagged_Add(20, x) |
| return r0 |
| def lol(): |
| r0 :: int |
| r1 :: object |
| r2, r3 :: int |
| L0: |
| r0 = C.foo(2) |
| r1 = __main__.C :: type |
| r2 = C.bar(r1, 4) |
| r3 = CPyTagged_Add(r0, r2) |
| return r3 |
| |
| [case testCallClassMethodViaCls] |
| class C: |
| @classmethod |
| def f(cls, x: int) -> int: |
| return cls.g(x) |
| |
| @classmethod |
| def g(cls, x: int) -> int: |
| return x |
| |
| class D: |
| @classmethod |
| def f(cls, x: int) -> int: |
| # TODO: This could aso be optimized, since g is not ever overridden |
| return cls.g(x) |
| |
| @classmethod |
| def g(cls, x: int) -> int: |
| return x |
| |
| class DD(D): |
| pass |
| [out] |
| def C.f(cls, x): |
| cls :: object |
| x :: int |
| r0 :: object |
| r1 :: int |
| L0: |
| r0 = __main__.C :: type |
| r1 = C.g(r0, x) |
| return r1 |
| def C.g(cls, x): |
| cls :: object |
| x :: int |
| L0: |
| return x |
| def D.f(cls, x): |
| cls :: object |
| x :: int |
| r0 :: str |
| r1, r2 :: object |
| r3 :: int |
| L0: |
| r0 = 'g' |
| r1 = box(int, x) |
| r2 = CPyObject_CallMethodObjArgs(cls, r0, r1, 0) |
| r3 = unbox(int, r2) |
| return r3 |
| def D.g(cls, x): |
| cls :: object |
| x :: int |
| L0: |
| return x |
| |
| [case testCannotAssignToClsArgument] |
| from typing import Any, cast |
| |
| class C: |
| @classmethod |
| def m(cls) -> None: |
| cls = cast(Any, D) # E: Cannot assign to the first argument of classmethod |
| cls, x = cast(Any, D), 1 # E: Cannot assign to the first argument of classmethod |
| cls, x = cast(Any, [1, 2]) # E: Cannot assign to the first argument of classmethod |
| cls.m() |
| |
| class D: |
| pass |
| |
| [case testSuper1] |
| class A: |
| def __init__(self, x: int) -> None: |
| self.x = x |
| class B(A): |
| def __init__(self, x: int, y: int) -> None: |
| super().__init__(x) |
| self.y = y |
| [out] |
| def A.__init__(self, x): |
| self :: __main__.A |
| x :: int |
| L0: |
| self.x = x |
| return 1 |
| def B.__init__(self, x, y): |
| self :: __main__.B |
| x, y :: int |
| r0 :: None |
| L0: |
| r0 = A.__init__(self, x) |
| self.y = y |
| return 1 |
| |
| [case testSuper2] |
| from mypy_extensions import trait |
| @trait |
| class T: |
| def foo(self) -> None: pass |
| |
| class X(T): |
| def foo(self) -> None: |
| super().foo() |
| [out] |
| def T.foo(self): |
| self :: __main__.T |
| L0: |
| return 1 |
| def X.foo(self): |
| self :: __main__.X |
| r0 :: None |
| L0: |
| r0 = T.foo(self) |
| return 1 |
| |
| [case testSuperCallToObjectInitIsOmitted] |
| class C: |
| def __init__(self) -> None: |
| super().__init__() |
| class D: pass |
| class E(D): |
| def __init__(self) -> None: |
| super().__init__() |
| class F(C): |
| def __init__(self) -> None: |
| super().__init__() |
| class DictSubclass(dict): |
| def __init__(self) -> None: |
| super().__init__() |
| [out] |
| def C.__init__(self): |
| self :: __main__.C |
| L0: |
| return 1 |
| def E.__init__(self): |
| self :: __main__.E |
| L0: |
| return 1 |
| def F.__init__(self): |
| self :: __main__.F |
| r0 :: None |
| L0: |
| r0 = C.__init__(self) |
| return 1 |
| def DictSubclass.__init__(self): |
| self :: dict |
| r0 :: object |
| r1 :: str |
| r2, r3, r4 :: object |
| r5 :: str |
| r6, r7 :: object |
| L0: |
| r0 = builtins :: module |
| r1 = 'super' |
| r2 = CPyObject_GetAttr(r0, r1) |
| r3 = __main__.DictSubclass :: type |
| r4 = PyObject_CallFunctionObjArgs(r2, r3, self, 0) |
| r5 = '__init__' |
| r6 = CPyObject_GetAttr(r4, r5) |
| r7 = PyObject_CallFunctionObjArgs(r6, 0) |
| return 1 |
| |
| [case testClassVariable] |
| from typing import ClassVar |
| class A: |
| x = 10 # type: ClassVar[int] |
| |
| def f() -> int: |
| return A.x |
| [out] |
| def f(): |
| r0 :: object |
| r1 :: str |
| r2 :: object |
| r3 :: int |
| L0: |
| r0 = __main__.A :: type |
| r1 = 'x' |
| r2 = CPyObject_GetAttr(r0, r1) |
| r3 = unbox(int, r2) |
| return r3 |
| |
| [case testNoEqDefined] |
| class A: |
| pass |
| |
| def f(a: A, b: A) -> bool: |
| return a == b |
| |
| def f2(a: A, b: A) -> bool: |
| return a != b |
| |
| [out] |
| def f(a, b): |
| a, b :: __main__.A |
| r0 :: bit |
| L0: |
| r0 = a == b |
| return r0 |
| def f2(a, b): |
| a, b :: __main__.A |
| r0 :: bit |
| L0: |
| r0 = a != b |
| return r0 |
| |
| [case testEqDefined] |
| class Base: |
| def __eq__(self, other: object) -> bool: |
| return False |
| class Derived(Base): |
| def __eq__(self, other: object) -> bool: |
| return True |
| |
| def f(a: Base, b: Base) -> bool: |
| return a == b |
| |
| def f2(a: Base, b: Base) -> bool: |
| return a != b |
| |
| def fOpt(a: Derived, b: Derived) -> bool: |
| return a == b |
| |
| def fOpt2(a: Derived, b: Derived) -> bool: |
| return a != b |
| |
| [out] |
| def Base.__eq__(self, other): |
| self :: __main__.Base |
| other, r0 :: object |
| L0: |
| r0 = box(bool, 0) |
| return r0 |
| def Base.__ne__(__mypyc_self__, rhs): |
| __mypyc_self__ :: __main__.Base |
| rhs, r0, r1 :: object |
| r2 :: bit |
| r3 :: i32 |
| r4 :: bit |
| r5 :: bool |
| r6 :: object |
| L0: |
| r0 = __mypyc_self__.__eq__(rhs) |
| r1 = load_address _Py_NotImplementedStruct |
| r2 = r0 == r1 |
| if r2 goto L2 else goto L1 :: bool |
| L1: |
| r3 = PyObject_Not(r0) |
| r4 = r3 >= 0 :: signed |
| r5 = truncate r3: i32 to builtins.bool |
| r6 = box(bool, r5) |
| return r6 |
| L2: |
| return r1 |
| def Derived.__eq__(self, other): |
| self :: __main__.Derived |
| other, r0 :: object |
| L0: |
| r0 = box(bool, 1) |
| return r0 |
| def f(a, b): |
| a, b :: __main__.Base |
| r0 :: object |
| r1 :: bool |
| L0: |
| r0 = PyObject_RichCompare(a, b, 2) |
| r1 = unbox(bool, r0) |
| return r1 |
| def f2(a, b): |
| a, b :: __main__.Base |
| r0 :: object |
| r1 :: bool |
| L0: |
| r0 = PyObject_RichCompare(a, b, 3) |
| r1 = unbox(bool, r0) |
| return r1 |
| def fOpt(a, b): |
| a, b :: __main__.Derived |
| r0 :: object |
| r1 :: bool |
| L0: |
| r0 = a.__eq__(b) |
| r1 = unbox(bool, r0) |
| return r1 |
| def fOpt2(a, b): |
| a, b :: __main__.Derived |
| r0 :: object |
| r1 :: bool |
| L0: |
| r0 = a.__ne__(b) |
| r1 = unbox(bool, r0) |
| return r1 |
| |
| [case testEqDefinedLater] |
| def f(a: 'Base', b: 'Base') -> bool: |
| return a == b |
| |
| def f2(a: 'Base', b: 'Base') -> bool: |
| return a != b |
| |
| def fOpt(a: 'Derived', b: 'Derived') -> bool: |
| return a == b |
| |
| def fOpt2(a: 'Derived', b: 'Derived') -> bool: |
| return a != b |
| |
| class Base: |
| pass |
| class Derived(Base): |
| def __eq__(self, other: object) -> bool: |
| return True |
| |
| [out] |
| def f(a, b): |
| a, b :: __main__.Base |
| r0 :: object |
| r1 :: bool |
| L0: |
| r0 = PyObject_RichCompare(a, b, 2) |
| r1 = unbox(bool, r0) |
| return r1 |
| def f2(a, b): |
| a, b :: __main__.Base |
| r0 :: object |
| r1 :: bool |
| L0: |
| r0 = PyObject_RichCompare(a, b, 3) |
| r1 = unbox(bool, r0) |
| return r1 |
| def fOpt(a, b): |
| a, b :: __main__.Derived |
| r0 :: object |
| r1 :: bool |
| L0: |
| r0 = a.__eq__(b) |
| r1 = unbox(bool, r0) |
| return r1 |
| def fOpt2(a, b): |
| a, b :: __main__.Derived |
| r0 :: str |
| r1 :: object |
| r2 :: bool |
| L0: |
| r0 = '__ne__' |
| r1 = CPyObject_CallMethodObjArgs(a, r0, b, 0) |
| r2 = unbox(bool, r1) |
| return r2 |
| def Derived.__eq__(self, other): |
| self :: __main__.Derived |
| other, r0 :: object |
| L0: |
| r0 = box(bool, 1) |
| return r0 |
| def Derived.__ne__(__mypyc_self__, rhs): |
| __mypyc_self__ :: __main__.Derived |
| rhs, r0, r1 :: object |
| r2 :: bit |
| r3 :: i32 |
| r4 :: bit |
| r5 :: bool |
| r6 :: object |
| L0: |
| r0 = __mypyc_self__.__eq__(rhs) |
| r1 = load_address _Py_NotImplementedStruct |
| r2 = r0 == r1 |
| if r2 goto L2 else goto L1 :: bool |
| L1: |
| r3 = PyObject_Not(r0) |
| r4 = r3 >= 0 :: signed |
| r5 = truncate r3: i32 to builtins.bool |
| r6 = box(bool, r5) |
| return r6 |
| L2: |
| return r1 |
| |
| [case testDefaultVars] |
| from typing import ClassVar, Optional |
| class A: |
| x = 10 |
| def lol(self) -> None: |
| self.x = 100 |
| |
| LOL = 'lol' |
| class B(A): |
| y = LOL |
| z: Optional[str] = None |
| b = True |
| bogus = None # type: int |
| [out] |
| def A.lol(self): |
| self :: __main__.A |
| r0 :: bool |
| L0: |
| self.x = 200; r0 = is_error |
| return 1 |
| def A.__mypyc_defaults_setup(__mypyc_self__): |
| __mypyc_self__ :: __main__.A |
| L0: |
| __mypyc_self__.x = 20 |
| return 1 |
| def B.__mypyc_defaults_setup(__mypyc_self__): |
| __mypyc_self__ :: __main__.B |
| r0 :: dict |
| r1 :: str |
| r2 :: object |
| r3 :: str |
| r4 :: object |
| L0: |
| __mypyc_self__.x = 20 |
| r0 = __main__.globals :: static |
| r1 = 'LOL' |
| r2 = CPyDict_GetItem(r0, r1) |
| r3 = cast(str, r2) |
| __mypyc_self__.y = r3 |
| r4 = box(None, 1) |
| __mypyc_self__.z = r4 |
| __mypyc_self__.b = 1 |
| return 1 |
| |
| [case testSubclassDictSpecalized] |
| from typing import Dict |
| class WelpDict(Dict[str, int]): |
| pass |
| def foo(x: WelpDict) -> None: |
| # we care that the specalized op gets used |
| x.update(x) |
| [out] |
| def foo(x): |
| x :: dict |
| r0 :: i32 |
| r1 :: bit |
| L0: |
| r0 = CPyDict_Update(x, x) |
| r1 = r0 >= 0 :: signed |
| return 1 |
| |
| [case testNoSpuriousLinearity] |
| # Make sure that the non-trait MRO linearity check isn't affected by processing order |
| class A(B): pass |
| class B(C): pass |
| class C: pass |
| [out] |
| |
| [case testDeletableSemanticAnalysis] |
| class Err1: |
| __deletable__ = 'x' # E: "__deletable__" must be initialized with a list or tuple expression |
| class Err2: |
| __deletable__ = [ |
| 1 # E: Invalid "__deletable__" item; string literal expected |
| ] |
| class Err3: |
| __deletable__ = ['x', ['y'], 'z'] # E: Invalid "__deletable__" item; string literal expected |
| class Err4: |
| __deletable__ = (1,) # E: Invalid "__deletable__" item; string literal expected |
| a = ['x'] |
| class Err5: |
| __deletable__ = a # E: "__deletable__" must be initialized with a list or tuple expression |
| |
| class Ok1: |
| __deletable__ = ('x',) |
| x: int |
| class Ok2: |
| __deletable__ = ['x'] |
| x: int |
| |
| [case testInvalidDeletableAttribute] |
| class NotDeletable: |
| __deletable__ = ['x'] |
| x: int |
| y: int |
| |
| def g(o: NotDeletable) -> None: |
| del o.x |
| del o.y # E: "y" cannot be deleted \ |
| # N: Using "__deletable__ = ['<attr>']" in the class body enables "del obj.<attr>" |
| |
| class Base: |
| x: int |
| |
| class Deriv(Base): |
| __deletable__ = ['x'] # E: Attribute "x" not defined in "Deriv" (defined in "Base") |
| |
| class UndefinedDeletable: |
| __deletable__ = ['x'] # E: Attribute "x" not defined |
| |
| class DeletableProperty: |
| __deletable__ = ['prop'] # E: Cannot make property "prop" deletable |
| |
| @property |
| def prop(self) -> int: |
| return 5 |
| |
| [case testFinalDeletable] |
| from typing import Final |
| |
| class DeletableFinal1: |
| x: Final[int] # E: Deletable attribute cannot be final |
| |
| __deletable__ = ['x'] |
| |
| def __init__(self, x: int) -> None: |
| self.x = x |
| |
| class DeletableFinal2: |
| X: Final = 0 # E: Deletable attribute cannot be final |
| |
| __deletable__ = ['X'] |
| |
| [case testNeedAnnotateClassVar] |
| from typing import Final, ClassVar, Type |
| |
| class C: |
| a = 'A' |
| b: str = 'B' |
| f: Final = 'F' |
| c: ClassVar = 'C' |
| |
| class D(C): |
| pass |
| |
| def f() -> None: |
| C.a # E: Cannot access instance attribute "a" through class object \ |
| # N: (Hint: Use "x: Final = ..." or "x: ClassVar = ..." to define a class attribute) |
| C.b # E: Cannot access instance attribute "b" through class object \ |
| # N: (Hint: Use "x: Final = ..." or "x: ClassVar = ..." to define a class attribute) |
| C.f |
| C.c |
| |
| D.a # E: Cannot access instance attribute "a" through class object \ |
| # N: (Hint: Use "x: Final = ..." or "x: ClassVar = ..." to define a class attribute) |
| D.b # E: Cannot access instance attribute "b" through class object \ |
| # N: (Hint: Use "x: Final = ..." or "x: ClassVar = ..." to define a class attribute) |
| D.f |
| D.c |
| |
| def g(c: Type[C], d: Type[D]) -> None: |
| c.a # E: Cannot access instance attribute "a" through class object \ |
| # N: (Hint: Use "x: Final = ..." or "x: ClassVar = ..." to define a class attribute) |
| c.f |
| c.c |
| |
| d.a # E: Cannot access instance attribute "a" through class object \ |
| # N: (Hint: Use "x: Final = ..." or "x: ClassVar = ..." to define a class attribute) |
| d.f |
| d.c |
| |
| [case testSetAttributeWithDefaultInInit] |
| class C: |
| s = '' |
| |
| def __init__(self, s: str) -> None: |
| self.s = s |
| [out] |
| def C.__init__(self, s): |
| self :: __main__.C |
| s :: str |
| r0 :: bool |
| L0: |
| self.s = s; r0 = is_error |
| return 1 |
| def C.__mypyc_defaults_setup(__mypyc_self__): |
| __mypyc_self__ :: __main__.C |
| r0 :: str |
| L0: |
| r0 = '' |
| __mypyc_self__.s = r0 |
| return 1 |
| |
| [case testBorrowAttribute] |
| def f(d: D) -> int: |
| return d.c.x |
| |
| class C: |
| x: int |
| class D: |
| c: C |
| [out] |
| def f(d): |
| d :: __main__.D |
| r0 :: __main__.C |
| r1 :: int |
| L0: |
| r0 = borrow d.c |
| r1 = r0.x |
| keep_alive d |
| return r1 |
| |
| [case testNoBorrowOverPropertyAccess] |
| class C: |
| d: D |
| class D: |
| @property |
| def e(self) -> E: |
| return E() |
| class E: |
| x: int |
| def f(c: C) -> int: |
| return c.d.e.x |
| [out] |
| def D.e(self): |
| self :: __main__.D |
| r0 :: __main__.E |
| L0: |
| r0 = E() |
| return r0 |
| def f(c): |
| c :: __main__.C |
| r0 :: __main__.D |
| r1 :: __main__.E |
| r2 :: int |
| L0: |
| r0 = c.d |
| r1 = r0.e |
| r2 = r1.x |
| return r2 |
| |
| [case testBorrowResultOfCustomGetItemInIfStatement] |
| from typing import List |
| |
| class C: |
| def __getitem__(self, x: int) -> List[int]: |
| return [] |
| |
| def f(x: C) -> None: |
| # In this case the keep_alive must come before the branch, as otherwise |
| # reference count transform will get confused. |
| if x[1][0] == 2: |
| y = 1 |
| else: |
| y = 2 |
| [out] |
| def C.__getitem__(self, x): |
| self :: __main__.C |
| x :: int |
| r0 :: list |
| L0: |
| r0 = PyList_New(0) |
| return r0 |
| def f(x): |
| x :: __main__.C |
| r0 :: list |
| r1 :: object |
| r2 :: int |
| r3 :: bit |
| y :: int |
| L0: |
| r0 = x.__getitem__(2) |
| r1 = CPyList_GetItemShortBorrow(r0, 0) |
| r2 = unbox(int, r1) |
| r3 = r2 == 4 |
| keep_alive r0 |
| if r3 goto L1 else goto L2 :: bool |
| L1: |
| y = 2 |
| goto L3 |
| L2: |
| y = 4 |
| L3: |
| return 1 |
| |
| [case testIncompatibleDefinitionOfAttributeInSubclass] |
| from mypy_extensions import trait |
| |
| class Base: |
| x: int |
| |
| class Bad1(Base): |
| x: bool # E: Type of "x" is incompatible with definition in class "Base" |
| |
| class Good1(Base): |
| x: int |
| |
| class Good2(Base): |
| x: int = 0 |
| |
| class Good3(Base): |
| x = 0 |
| |
| class Good4(Base): |
| def __init__(self) -> None: |
| self.x = 0 |
| |
| class Good5(Base): |
| def __init__(self) -> None: |
| self.x: int = 0 |
| |
| class Base2(Base): |
| pass |
| |
| class Bad2(Base2): |
| x: bool = False # E: Type of "x" is incompatible with definition in class "Base" |
| |
| class Bad3(Base): |
| x = False # E: Type of "x" is incompatible with definition in class "Base" |
| |
| @trait |
| class T: |
| y: object |
| |
| class E(T): |
| y: str # E: Type of "y" is incompatible with definition in trait "T" |