Skip to content

Commit 78c9c54

Browse files
committed
[mypyc] feat: __mypyc_empty_tuple__ constant
1 parent 116b92b commit 78c9c54

File tree

5 files changed

+33
-2
lines changed

5 files changed

+33
-2
lines changed

mypyc/irbuild/ll_builder.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@
188188
)
189189
from mypyc.primitives.tuple_ops import (
190190
list_tuple_op,
191+
load_empty_tuple_constant_op,
191192
new_tuple_op,
192193
new_tuple_with_length_op,
193194
sequence_tuple_op,
@@ -2359,8 +2360,11 @@ def builtin_len(self, val: Value, line: int, use_pyssize_t: bool = False) -> Val
23592360
return self.call_c(generic_len_op, [val], line)
23602361

23612362
def new_tuple(self, items: list[Value], line: int) -> Value:
2362-
size: Value = Integer(len(items), c_pyssize_t_rprimitive)
2363-
return self.call_c(new_tuple_op, [size] + items, line)
2363+
if items:
2364+
size: Value = Integer(len(items), c_pyssize_t_rprimitive)
2365+
return self.call_c(new_tuple_op, [size] + items, line)
2366+
else:
2367+
return self.call_c(load_empty_tuple_constant_op, [], line)
23642368

23652369
def new_tuple_with_length(self, length: Value, line: int) -> Value:
23662370
"""This function returns an uninitialized tuple.

mypyc/lib-rt/CPy.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ typedef struct tuple_T4CIOO {
6464
} tuple_T4CIOO;
6565
#endif
6666

67+
// System-wide empty tuple constant
68+
extern PyObject * __mypyc_empty_tuple__;
69+
70+
static inline PyObject *_CPyTuple_LoadEmptyTupleConstant() {
71+
Py_INCREF(__mypyc_empty_tuple__);
72+
return __mypyc_empty_tuple__;
73+
}
6774

6875
// Native object operations
6976

mypyc/lib-rt/init.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,14 @@ PyObject *_CPy_ExcDummy = (PyObject *)&_CPy_ExcDummyStruct;
1010
// things at load time.
1111
void CPy_Init(void) {
1212
_CPy_ExcDummyStruct.ob_base.ob_type = &PyBaseObject_Type;
13+
14+
// Initialize system-wide empty tuple constant
15+
if (__mypyc_empty_tuple__ == NULL) {
16+
__mypyc_empty_tuple__ = PyTuple_New(0);
17+
if (!__mypyc_empty_tuple__) {
18+
PyErr_SetString(PyExc_RuntimeError, "Failed to initialize __mypyc_empty_tuple__");
19+
return;
20+
}
21+
Py_INCREF(__mypyc_empty_tuple__);
22+
}
1323
}

mypyc/lib-rt/tuple_ops.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
#include <Python.h>
66
#include "CPy.h"
77

8+
// System-wide empty tuple constant
9+
PyObject * __mypyc_empty_tuple__ = NULL;
10+
811
PyObject *CPySequenceTuple_GetItem(PyObject *tuple, CPyTagged index) {
912
if (CPyTagged_CheckShort(index)) {
1013
Py_ssize_t n = CPyTagged_ShortAsSsize_t(index);

mypyc/primitives/tuple_ops.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@
5555
error_kind=ERR_MAGIC,
5656
)
5757

58+
load_empty_tuple_constant_op = custom_op(
59+
arg_types=[],
60+
return_type=tuple_rprimitive,
61+
c_function_name="_CPyTuple_LoadEmptyTupleConstant",
62+
error_kind=ERR_NEVER,
63+
)
64+
5865
# PyTuple_SET_ITEM does no error checking,
5966
# and should only be used to fill in brand new tuples.
6067
new_tuple_set_item_op = custom_op(

0 commit comments

Comments
 (0)