Skip to content

Commit ad24c19

Browse files
committed
Fix the optimization for starred comprehensions.
1 parent 5d9ccf3 commit ad24c19

2 files changed

Lines changed: 63 additions & 16 deletions

File tree

Lib/test/test_listcomps.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,33 @@ def exhaust(coro):
835835
exhaust(gen2(numbers()))
836836
self.assertEqual(count, 5)
837837

838+
def test_optimization_with_starred_unpack(self):
839+
with self.assertRaises(TypeError):
840+
[*i for i in [1, 2, 3]]
841+
842+
async def coro():
843+
async def gen():
844+
yield 1
845+
846+
with self.assertRaises(TypeError):
847+
[*i async for i in gen()]
848+
849+
c = coro()
850+
while True:
851+
try:
852+
c.send(None)
853+
except StopIteration:
854+
break
855+
856+
count = 0
857+
def weird():
858+
nonlocal count
859+
count += 1
860+
yield 0
861+
862+
[*weird() for _ in range(5)]
863+
self.assertEqual(count, 5)
864+
838865
__test__ = {'doctests' : doctests}
839866

840867
def load_tests(loader, tests, pattern):

Python/codegen.c

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4560,6 +4560,28 @@ codegen_comprehension_generator(compiler *c, location loc,
45604560
}
45614561
}
45624562

4563+
static int
4564+
codegen_starred_comprehension(compiler *c, location loc, expr_ty value, bool discard)
4565+
{
4566+
NEW_JUMP_TARGET_LABEL(c, unpack_start);
4567+
NEW_JUMP_TARGET_LABEL(c, unpack_end);
4568+
VISIT(c, expr, value);
4569+
ADDOP_I(c, loc, GET_ITER, 0);
4570+
USE_LABEL(c, unpack_start);
4571+
ADDOP_JUMP(c, loc, FOR_ITER, unpack_end);
4572+
if (discard) {
4573+
ADDOP(c, loc, POP_TOP);
4574+
} else {
4575+
ADDOP_YIELD(c, loc);
4576+
ADDOP(c, loc, POP_TOP);
4577+
}
4578+
ADDOP_JUMP(c, NO_LOCATION, JUMP, unpack_start);
4579+
USE_LABEL(c, unpack_end);
4580+
ADDOP(c, NO_LOCATION, END_FOR);
4581+
ADDOP(c, NO_LOCATION, POP_ITER);
4582+
return SUCCESS;
4583+
}
4584+
45634585
static int
45644586
codegen_sync_comprehension_generator(compiler *c, location loc,
45654587
asdl_comprehension_seq *generators,
@@ -4645,18 +4667,7 @@ codegen_sync_comprehension_generator(compiler *c, location loc,
46454667
case COMP_GENEXP:
46464668
assert(!avoid_creation);
46474669
if (elt->kind == Starred_kind) {
4648-
NEW_JUMP_TARGET_LABEL(c, unpack_start);
4649-
NEW_JUMP_TARGET_LABEL(c, unpack_end);
4650-
VISIT(c, expr, elt->v.Starred.value);
4651-
ADDOP_I(c, elt_loc, GET_ITER, 0);
4652-
USE_LABEL(c, unpack_start);
4653-
ADDOP_JUMP(c, elt_loc, FOR_ITER, unpack_end);
4654-
ADDOP_YIELD(c, elt_loc);
4655-
ADDOP(c, elt_loc, POP_TOP);
4656-
ADDOP_JUMP(c, NO_LOCATION, JUMP, unpack_start);
4657-
USE_LABEL(c, unpack_end);
4658-
ADDOP(c, NO_LOCATION, END_FOR);
4659-
ADDOP(c, NO_LOCATION, POP_ITER);
4670+
RETURN_IF_ERROR(codegen_starred_comprehension(c, elt_loc, elt->v.Starred.value, /*discard=*/false));
46604671
}
46614672
else {
46624673
VISIT(c, expr, elt);
@@ -4666,8 +4677,12 @@ codegen_sync_comprehension_generator(compiler *c, location loc,
46664677
break;
46674678
case COMP_LISTCOMP:
46684679
if (avoid_creation) {
4669-
VISIT(c, expr, elt);
4670-
ADDOP(c, elt_loc, POP_TOP);
4680+
if (elt->kind == Starred_kind) {
4681+
RETURN_IF_ERROR(codegen_starred_comprehension(c, elt_loc, elt->v.Starred.value, /*discard=*/true));
4682+
} else {
4683+
VISIT(c, expr, elt);
4684+
ADDOP(c, elt_loc, POP_TOP);
4685+
}
46714686
break;
46724687
}
46734688
if (elt->kind == Starred_kind) {
@@ -4815,10 +4830,15 @@ codegen_async_comprehension_generator(compiler *c, location loc,
48154830
break;
48164831
case COMP_LISTCOMP:
48174832
if (avoid_creation) {
4818-
VISIT(c, expr, elt);
4819-
ADDOP(c, elt_loc, POP_TOP);
4833+
if (elt->kind == Starred_kind) {
4834+
RETURN_IF_ERROR(codegen_starred_comprehension(c, elt_loc, elt->v.Starred.value, /*discard=*/false));
4835+
} else {
4836+
VISIT(c, expr, elt);
4837+
ADDOP(c, elt_loc, POP_TOP);
4838+
}
48204839
break;
48214840
}
4841+
48224842
if (elt->kind == Starred_kind) {
48234843
VISIT(c, expr, elt->v.Starred.value);
48244844
ADDOP_I(c, elt_loc, LIST_EXTEND, depth + 1);

0 commit comments

Comments
 (0)