summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorCarl Meyer <carl@oddbird.net>2023-05-11 23:48:21 (GMT)
committerGitHub <noreply@github.com>2023-05-11 23:48:21 (GMT)
commitac66cc17f21653b66321b50d0a1f792982fca21f (patch)
tree7a9b4ac1d0b55e685748ed65597a4acaef0c03c9 /Python
parent37a5d256b97bc9d2a0ff445997fec851e328ebad (diff)
downloadcpython-ac66cc17f21653b66321b50d0a1f792982fca21f.zip
cpython-ac66cc17f21653b66321b50d0a1f792982fca21f.tar.gz
cpython-ac66cc17f21653b66321b50d0a1f792982fca21f.tar.bz2
gh-104377: fix cell in comprehension that is free in outer scope (#104394)
Diffstat (limited to 'Python')
-rw-r--r--Python/compile.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/Python/compile.c b/Python/compile.c
index 941c6e9..f8d0197 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -5028,14 +5028,19 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
long scope = (symbol >> SCOPE_OFFSET) & SCOPE_MASK;
PyObject *outv = PyDict_GetItemWithError(c->u->u_ste->ste_symbols, k);
if (outv == NULL) {
+ assert(PyErr_Occurred());
return ERROR;
}
assert(PyLong_Check(outv));
long outsc = (PyLong_AS_LONG(outv) >> SCOPE_OFFSET) & SCOPE_MASK;
- if (scope != outsc) {
+ if (scope != outsc && !(scope == CELL && outsc == FREE)) {
// If a name has different scope inside than outside the
// comprehension, we need to temporarily handle it with the
- // right scope while compiling the comprehension.
+ // right scope while compiling the comprehension. (If it's free
+ // in outer scope and cell in inner scope, we can't treat it as
+ // both cell and free in the same function, but treating it as
+ // free throughout is fine; it's *_DEREF either way.)
+
if (state->temp_symbols == NULL) {
state->temp_symbols = PyDict_New();
if (state->temp_symbols == NULL) {
@@ -5071,7 +5076,11 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
// comprehension and restore the original one after
ADDOP_NAME(c, loc, LOAD_FAST_AND_CLEAR, k, varnames);
if (scope == CELL) {
- ADDOP_NAME(c, loc, MAKE_CELL, k, cellvars);
+ if (outsc == FREE) {
+ ADDOP_NAME(c, loc, MAKE_CELL, k, freevars);
+ } else {
+ ADDOP_NAME(c, loc, MAKE_CELL, k, cellvars);
+ }
}
if (PyList_Append(state->pushed_locals, k) < 0) {
return ERROR;