Skip to content

Commit 2f21f98

Browse files
authored
[mypyc] Make multiple assignment from list memory-safe with free threading (#21684)
Work on mypyc/mypyc#1202.
1 parent cd747e5 commit 2f21f98

3 files changed

Lines changed: 50 additions & 4 deletions

File tree

mypyc/irbuild/builder.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
BITMAP_BITS,
6363
EXT_SUFFIX,
6464
GENERATOR_ATTRIBUTE_PREFIX,
65+
IS_FREE_THREADED,
6566
MODULE_PREFIX,
6667
SELF_NAME,
6768
TEMP_ATTR_NAME,
@@ -146,7 +147,12 @@
146147
from mypyc.options import CompilerOptions
147148
from mypyc.primitives.dict_ops import dict_get_item_op, dict_set_item_op
148149
from mypyc.primitives.generic_ops import iter_op, next_op, py_setattr_op
149-
from mypyc.primitives.list_ops import list_get_item_unsafe_op, list_pop_last, to_list
150+
from mypyc.primitives.list_ops import (
151+
list_get_item_int64_op,
152+
list_get_item_unsafe_op,
153+
list_pop_last,
154+
to_list,
155+
)
150156
from mypyc.primitives.misc_ops import (
151157
check_unpack_count_op,
152158
get_module_dict_op,
@@ -893,7 +899,10 @@ def process_sequence_assignment(
893899
index: Value
894900
if is_list_rprimitive(rvalue.type):
895901
index = Integer(i, c_pyssize_t_rprimitive)
896-
item_value = self.primitive_op(list_get_item_unsafe_op, [rvalue, index], line)
902+
if not IS_FREE_THREADED:
903+
item_value = self.primitive_op(list_get_item_unsafe_op, [rvalue, index], line)
904+
else:
905+
item_value = self.primitive_op(list_get_item_int64_op, [rvalue, index], line)
897906
elif is_tuple_rprimitive(rvalue.type):
898907
index = Integer(i, c_pyssize_t_rprimitive)
899908
item_value = self.call_c(tuple_get_item_unsafe_op, [rvalue, index], line)

mypyc/primitives/list_ops.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@
110110
)
111111

112112
# Version with native int index
113-
method_op(
113+
list_get_item_int64_op = method_op(
114114
name="__getitem__",
115115
arg_types=[list_rprimitive, int64_rprimitive],
116116
return_type=object_rprimitive,

mypyc/test-data/irbuild-statements.test

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ L0:
575575
z = r6
576576
return 1
577577

578-
[case testMultipleAssignmentUnpackFromSequence]
578+
[case testMultipleAssignmentUnpackFromSequence_withgil]
579579
from typing import List, Tuple
580580

581581
def f(l: List[int], t: Tuple[int, ...]) -> None:
@@ -612,6 +612,43 @@ L0:
612612
y = r9
613613
return 1
614614

615+
[case testMultipleAssignmentUnpackFromSequence_nogil]
616+
from typing import List, Tuple
617+
618+
def f(l: List[int], t: Tuple[int, ...]) -> None:
619+
x: object
620+
y: int
621+
x, y = l
622+
x, y = t
623+
[out]
624+
def f(l, t):
625+
l :: list
626+
t :: tuple
627+
r0 :: i32
628+
r1 :: bit
629+
r2, r3, x :: object
630+
r4, y :: int
631+
r5 :: i32
632+
r6 :: bit
633+
r7, r8 :: object
634+
r9 :: int
635+
L0:
636+
r0 = CPySequence_CheckUnpackCount(l, 2)
637+
r1 = r0 >= 0 :: signed
638+
r2 = CPyList_GetItemInt64(l, 0)
639+
r3 = CPyList_GetItemInt64(l, 1)
640+
x = r2
641+
r4 = unbox(int, r3)
642+
y = r4
643+
r5 = CPySequence_CheckUnpackCount(t, 2)
644+
r6 = r5 >= 0 :: signed
645+
r7 = CPySequenceTuple_GetItemUnsafe(t, 0)
646+
r8 = CPySequenceTuple_GetItemUnsafe(t, 1)
647+
x = r7
648+
r9 = unbox(int, r8)
649+
y = r9
650+
return 1
651+
615652
[case testAssert]
616653
from typing import Optional
617654

0 commit comments

Comments
 (0)