diff --git a/mypyc/lib-rt/CPy.h b/mypyc/lib-rt/CPy.h index 1f0cf4dd63d6..b8c39772dfae 100644 --- a/mypyc/lib-rt/CPy.h +++ b/mypyc/lib-rt/CPy.h @@ -667,6 +667,7 @@ PyObject *CPySequence_Multiply(PyObject *seq, CPyTagged t_size); PyObject *CPySequence_RMultiply(CPyTagged t_size, PyObject *seq); PyObject *CPySequence_InPlaceMultiply(PyObject *seq, CPyTagged t_size); PyObject *CPyList_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end); +char CPyList_Clear(PyObject *list); PyObject *CPyList_Copy(PyObject *list); int CPySequence_Check(PyObject *obj); diff --git a/mypyc/lib-rt/list_ops.c b/mypyc/lib-rt/list_ops.c index 4dddb2249f06..03af8a769c0e 100644 --- a/mypyc/lib-rt/list_ops.c +++ b/mypyc/lib-rt/list_ops.c @@ -29,6 +29,23 @@ PyObject *CPyList_Build(Py_ssize_t len, ...) { return res; } +char CPyList_Clear(PyObject *list) { + if (PyList_CheckExact(list)) { + PyList_Clear(list); + } else { + _Py_IDENTIFIER(clear); + PyObject *name = _PyUnicode_FromId(&PyId_clear); + if (name == NULL) { + return 0; + } + PyObject *res = PyObject_CallMethodNoArgs(list, name); + if (res == NULL) { + return 0; + } + } + return 1; +} + PyObject *CPyList_Copy(PyObject *list) { if(PyList_CheckExact(list)) { return PyList_GetSlice(list, 0, PyList_GET_SIZE(list)); diff --git a/mypyc/primitives/list_ops.py b/mypyc/primitives/list_ops.py index 99df6fe0dc9c..d0e0af9f987f 100644 --- a/mypyc/primitives/list_ops.py +++ b/mypyc/primitives/list_ops.py @@ -271,6 +271,15 @@ error_kind=ERR_MAGIC, ) +# list.clear() +method_op( + name="clear", + arg_types=[list_rprimitive], + return_type=bit_rprimitive, + c_function_name="CPyList_Clear", + error_kind=ERR_FALSE, +) + # list.copy() method_op( name="copy", diff --git a/mypyc/test-data/fixtures/ir.py b/mypyc/test-data/fixtures/ir.py index 1b92590a5fd4..532cbbc06177 100644 --- a/mypyc/test-data/fixtures/ir.py +++ b/mypyc/test-data/fixtures/ir.py @@ -245,6 +245,7 @@ def sort(self) -> None: pass def reverse(self) -> None: pass def remove(self, o: _T) -> None: pass def index(self, o: _T) -> int: pass + def clear(self) -> None: pass def copy(self) -> List[_T]: pass class dict(Mapping[_K, _V]): diff --git a/mypyc/test-data/irbuild-lists.test b/mypyc/test-data/irbuild-lists.test index 2435b5aee350..72caa5fad8d8 100644 --- a/mypyc/test-data/irbuild-lists.test +++ b/mypyc/test-data/irbuild-lists.test @@ -220,6 +220,18 @@ L0: r1 = r0 << 1 return r1 +[case testListClear] +from typing import List +def f(l: List[int]) -> None: + return l.clear() +[out] +def f(l): + l :: list + r0 :: bit +L0: + r0 = CPyList_Clear(l) + return 1 + [case testListCopy] from typing import List from typing import Any diff --git a/mypyc/test-data/run-lists.test b/mypyc/test-data/run-lists.test index 07c6d7735f10..85e0926027c5 100644 --- a/mypyc/test-data/run-lists.test +++ b/mypyc/test-data/run-lists.test @@ -51,6 +51,32 @@ print(2, a) 1 [-1, 5] 2 [340282366920938463463374607431768211461, -170141183460469231731687303715884105736] +[case testListClear] +from typing import List, Any +from copysubclass import subc + +def test_list_clear() -> None: + l1 = [1, 2, 3, -4, 5] + l1.clear() + assert l1 == [] + l1.clear() + assert l1 == [] + l2: List[Any] = [] + l2.clear() + assert l2 == [] + l3 = [1, 2, 3, "abcdef"] + l3.clear() + assert l3 == [] + # subclass testing + l4: subc = subc([1, 2, 3]) + l4.clear() + assert l4 == [] + +[file copysubclass.py] +from typing import Any +class subc(list[Any]): + pass + [case testListCopy] from typing import List from copysubclass import subc