Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-39320: Fix changes in the evaluation logic of unpacking operations. #18264

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 39 additions & 0 deletions Lib/test/test_unpack_ex.py
Expand Up @@ -335,6 +335,45 @@
...
SyntaxError: can't use starred expression here

Check for correct execution order (all fail):

>>> x = None
>>> try:
... [*x, *print("This should be printed!")]
... except TypeError:
... pass
This should be printed!

>>> try:
... (*x, *print("This should be printed!"))
... except TypeError:
... pass
This should be printed!

>>> try:
... {*x, *print("This should be printed!")}
... except TypeError:
... pass
This should be printed!

>>> try:
... f(*x, *print("This should be printed!"))
... except TypeError:
... pass
This should be printed!

>>> try:
... {**x, **print("This should be printed!")}
... except TypeError:
... pass
This should be printed!

>>> try:
... f(**x, **print("This should be printed!"))
... except TypeError:
... pass
This should be printed!

Some size constraints (all fail.)

>>> s = ", ".join("a%d" % i for i in range(1<<8)) + ", *rest = range(1<<8 + 1)"
Expand Down
@@ -0,0 +1 @@
Fix a regression in the evaluation order of :pep:`448` unpacking syntax.
98 changes: 45 additions & 53 deletions Python/compile.c
Expand Up @@ -3710,43 +3710,34 @@ starunpack_helper(struct compiler *c, asdl_seq *elts, int pushed,
for (i = 0; i < n; i++) {
expr_ty elt = asdl_seq_GET(elts, i);
if (elt->kind == Starred_kind) {
ADDOP_I(c, build, pushed);
seen_star = 1;
break;
}
}
for (i = 0; i < n; i++) {
expr_ty elt = asdl_seq_GET(elts, i);
if (elt->kind == Starred_kind) {
VISIT(c, expr, elt->v.Starred.value);
}
else {
VISIT(c, expr, elt);
}
}
if (seen_star) {
seen_star = 0;
/* Reverse the stack: */
ADDOP_I(c, BUILD_TUPLE, n);
ADDOP_I(c, UNPACK_SEQUENCE, n);
for (i = 0; i < n; i++) {
expr_ty elt = asdl_seq_GET(elts, i);
if (elt->kind == Starred_kind) {
if (seen_star == 0) {
ADDOP_I(c, build, i+pushed);
seen_star = 1;
}
VISIT(c, expr, elt->v.Starred.value);
ADDOP_I(c, extend, 1);
}
else {
VISIT(c, expr, elt);
if (seen_star) {
ADDOP_I(c, add, 1);
}
}
ADDOP_I(c, elt->kind == Starred_kind ? extend : add, n-i);
}
assert(seen_star);
if (tuple) {
ADDOP(c, LIST_TO_TUPLE);
}
}
else {
for (i = 0; i < n; i++) {
expr_ty elt = asdl_seq_GET(elts, i);
VISIT(c, expr, elt);
}
if (tuple) {
ADDOP_I(c, BUILD_TUPLE, n+pushed);
} else {
ADDOP_I(c, build, n+pushed);
}
ADDOP_I(c, tuple ? BUILD_TUPLE : build, n+pushed);
}
return 1;
}
Expand Down Expand Up @@ -3867,40 +3858,33 @@ static int
compiler_dict(struct compiler *c, expr_ty e)
{
Py_ssize_t i, n, elements;
int have_dict;
int is_unpacking = 0;
n = asdl_seq_LEN(e->v.Dict.values);
have_dict = 0;
elements = 0;
int to_merge = 0;
for (i = 0; i < n; i++) {
is_unpacking = (expr_ty)asdl_seq_GET(e->v.Dict.keys, i) == NULL;
if (is_unpacking) {
if (elements) {
if (!compiler_subdict(c, e, i - elements, i)) {
return 0;
}
if (have_dict) {
ADDOP_I(c, DICT_UPDATE, 1);
}
have_dict = 1;
to_merge++;
elements = 0;
}
if (have_dict == 0) {
if (to_merge == 0) {
ADDOP_I(c, BUILD_MAP, 0);
have_dict = 1;
to_merge++;
}
VISIT(c, expr, (expr_ty)asdl_seq_GET(e->v.Dict.values, i));
ADDOP_I(c, DICT_UPDATE, 1);
to_merge++;
}
else {
if (elements == 0xFFFF) {
if (!compiler_subdict(c, e, i - elements, i)) {
return 0;
}
if (have_dict) {
ADDOP_I(c, DICT_UPDATE, 1);
}
have_dict = 1;
to_merge++;
elements = 0;
}
else {
Expand All @@ -3912,13 +3896,17 @@ compiler_dict(struct compiler *c, expr_ty e)
if (!compiler_subdict(c, e, n - elements, n)) {
return 0;
}
if (have_dict) {
ADDOP_I(c, DICT_UPDATE, 1);
}
have_dict = 1;
to_merge++;
}
if (!have_dict) {
if (!to_merge) {
ADDOP_I(c, BUILD_MAP, 0);
} else if (--to_merge) {
/* Reverse the stack. */
ADDOP_I(c, BUILD_TUPLE, to_merge)
ADDOP_I(c, UNPACK_SEQUENCE, to_merge)
while (to_merge) {
ADDOP_I(c, DICT_UPDATE, to_merge--);
}
}
return 1;
}
Expand Down Expand Up @@ -4283,8 +4271,7 @@ compiler_call_helper(struct compiler *c,
}
/* Then keyword arguments */
if (nkwelts) {
/* Has a new dict been pushed */
int have_dict = 0;
int to_merge = 0;

nseen = 0; /* the number of keyword arguments on the stack following */
for (i = 0; i < nkwelts; i++) {
Expand All @@ -4295,15 +4282,15 @@ compiler_call_helper(struct compiler *c,
if (!compiler_subkwargs(c, keywords, i - nseen, i)) {
return 0;
}
have_dict = 1;
to_merge++;
nseen = 0;
}
if (!have_dict) {
if (!to_merge) {
ADDOP_I(c, BUILD_MAP, 0);
have_dict = 1;
to_merge++;
}
VISIT(c, expr, kw->value);
ADDOP_I(c, DICT_MERGE, 1);
to_merge++;
}
else {
nseen++;
Expand All @@ -4314,12 +4301,17 @@ compiler_call_helper(struct compiler *c,
if (!compiler_subkwargs(c, keywords, nkwelts - nseen, nkwelts)) {
return 0;
}
if (have_dict) {
ADDOP_I(c, DICT_MERGE, 1);
to_merge++;
}
assert(to_merge);
if (--to_merge) {
/* Reverse the stack: */
ADDOP_I(c, BUILD_TUPLE, to_merge)
ADDOP_I(c, UNPACK_SEQUENCE, to_merge)
while (to_merge) {
ADDOP_I(c, DICT_MERGE, to_merge--);
}
have_dict = 1;
}
assert(have_dict);
}
ADDOP_I(c, CALL_FUNCTION_EX, nkwelts > 0);
return 1;
Expand Down