@@ -5458,10 +5458,48 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
5458
5458
while (PyDict_Next (entry -> ste_symbols , & pos , & k , & v )) {
5459
5459
assert (PyLong_Check (v ));
5460
5460
long symbol = PyLong_AS_LONG (v );
5461
- // only values bound in the comprehension (DEF_LOCAL) need to be handled
5462
- // at all; DEF_LOCAL | DEF_NONLOCAL can occur in the case of an
5463
- // assignment expression to a nonlocal in the comprehension, these don't
5464
- // need handling here since they shouldn't be isolated
5461
+ long scope = (symbol >> SCOPE_OFFSET ) & SCOPE_MASK ;
5462
+ PyObject * outv = PyDict_GetItemWithError (c -> u -> u_ste -> ste_symbols , k );
5463
+ if (outv == NULL ) {
5464
+ if (PyErr_Occurred ()) {
5465
+ return ERROR ;
5466
+ }
5467
+ outv = _PyLong_GetZero ();
5468
+ }
5469
+ assert (PyLong_CheckExact (outv ));
5470
+ long outsc = (PyLong_AS_LONG (outv ) >> SCOPE_OFFSET ) & SCOPE_MASK ;
5471
+ // If a name has different scope inside than outside the comprehension,
5472
+ // we need to temporarily handle it with the right scope while
5473
+ // compiling the comprehension. If it's free in the comprehension
5474
+ // scope, no special handling; it should be handled the same as the
5475
+ // enclosing scope. (If it's free in outer scope and cell in inner
5476
+ // scope, we can't treat it as both cell and free in the same function,
5477
+ // but treating it as free throughout is fine; it's *_DEREF
5478
+ // either way.)
5479
+ if ((scope != outsc && scope != FREE && !(scope == CELL && outsc == FREE ))
5480
+ || in_class_block ) {
5481
+ if (state -> temp_symbols == NULL ) {
5482
+ state -> temp_symbols = PyDict_New ();
5483
+ if (state -> temp_symbols == NULL ) {
5484
+ return ERROR ;
5485
+ }
5486
+ }
5487
+ // update the symbol to the in-comprehension version and save
5488
+ // the outer version; we'll restore it after running the
5489
+ // comprehension
5490
+ Py_INCREF (outv );
5491
+ if (PyDict_SetItem (c -> u -> u_ste -> ste_symbols , k , v ) < 0 ) {
5492
+ Py_DECREF (outv );
5493
+ return ERROR ;
5494
+ }
5495
+ if (PyDict_SetItem (state -> temp_symbols , k , outv ) < 0 ) {
5496
+ Py_DECREF (outv );
5497
+ return ERROR ;
5498
+ }
5499
+ Py_DECREF (outv );
5500
+ }
5501
+ // locals handling for names bound in comprehension (DEF_LOCAL |
5502
+ // DEF_NONLOCAL occurs in assignment expression to nonlocal)
5465
5503
if ((symbol & DEF_LOCAL && !(symbol & DEF_NONLOCAL )) || in_class_block ) {
5466
5504
if (!_PyST_IsFunctionLike (c -> u -> u_ste )) {
5467
5505
// non-function scope: override this name to use fast locals
@@ -5481,41 +5519,6 @@ push_inlined_comprehension_state(struct compiler *c, location loc,
5481
5519
}
5482
5520
}
5483
5521
}
5484
- long scope = (symbol >> SCOPE_OFFSET ) & SCOPE_MASK ;
5485
- PyObject * outv = PyDict_GetItemWithError (c -> u -> u_ste -> ste_symbols , k );
5486
- if (outv == NULL ) {
5487
- outv = _PyLong_GetZero ();
5488
- }
5489
- assert (PyLong_Check (outv ));
5490
- long outsc = (PyLong_AS_LONG (outv ) >> SCOPE_OFFSET ) & SCOPE_MASK ;
5491
- if (scope != outsc && !(scope == CELL && outsc == FREE )) {
5492
- // If a name has different scope inside than outside the
5493
- // comprehension, we need to temporarily handle it with the
5494
- // right scope while compiling the comprehension. (If it's free
5495
- // in outer scope and cell in inner scope, we can't treat it as
5496
- // both cell and free in the same function, but treating it as
5497
- // free throughout is fine; it's *_DEREF either way.)
5498
-
5499
- if (state -> temp_symbols == NULL ) {
5500
- state -> temp_symbols = PyDict_New ();
5501
- if (state -> temp_symbols == NULL ) {
5502
- return ERROR ;
5503
- }
5504
- }
5505
- // update the symbol to the in-comprehension version and save
5506
- // the outer version; we'll restore it after running the
5507
- // comprehension
5508
- Py_INCREF (outv );
5509
- if (PyDict_SetItem (c -> u -> u_ste -> ste_symbols , k , v ) < 0 ) {
5510
- Py_DECREF (outv );
5511
- return ERROR ;
5512
- }
5513
- if (PyDict_SetItem (state -> temp_symbols , k , outv ) < 0 ) {
5514
- Py_DECREF (outv );
5515
- return ERROR ;
5516
- }
5517
- Py_DECREF (outv );
5518
- }
5519
5522
// local names bound in comprehension must be isolated from
5520
5523
// outer scope; push existing value (which may be NULL if
5521
5524
// not defined) on stack
0 commit comments