diff options
author | Tian Gao <gaogaotiantian@hotmail.com> | 2025-02-19 17:11:17 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-02-19 17:11:17 (GMT) |
commit | ccf17323c218a2fdcf7f4845d3eaa74ebddefa44 (patch) | |
tree | 7ac99611ee4ba2458137cdf659411bc3d42853bc | |
parent | 5f00501a940a0fb97870e70066fb301909320388 (diff) | |
download | cpython-ccf17323c218a2fdcf7f4845d3eaa74ebddefa44.zip cpython-ccf17323c218a2fdcf7f4845d3eaa74ebddefa44.tar.gz cpython-ccf17323c218a2fdcf7f4845d3eaa74ebddefa44.tar.bz2 |
gh-128396: Fix a crash when inline comprehension has the same local variable as the outside scope (#130235)
-rw-r--r-- | Lib/test/test_frame.py | 6 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Core_and_Builtins/2025-02-17-18-59-33.gh-issue-128396.iVtoYY.rst | 1 | ||||
-rw-r--r-- | Objects/frameobject.c | 11 |
3 files changed, 16 insertions, 2 deletions
diff --git a/Lib/test/test_frame.py b/Lib/test/test_frame.py index 4d08606..a6e11f1 100644 --- a/Lib/test/test_frame.py +++ b/Lib/test/test_frame.py @@ -346,6 +346,12 @@ class TestFrameLocals(unittest.TestCase): self.assertEqual(x, 2) self.assertEqual(y, 3) + def test_closure_with_inline_comprehension(self): + lambda: k + k = 1 + lst = [locals() for k in [0]] + self.assertEqual(lst[0]['k'], 0) + def test_as_dict(self): x = 1 y = 2 diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-17-18-59-33.gh-issue-128396.iVtoYY.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-17-18-59-33.gh-issue-128396.iVtoYY.rst new file mode 100644 index 0000000..4382b77 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-17-18-59-33.gh-issue-128396.iVtoYY.rst @@ -0,0 +1 @@ +Fix a crash that occurs when calling :func:`locals` inside an inline comprehension that uses the same local variable as the outer frame scope where the variable is a free or cell var. diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 8ebcc1a..dbeee50 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -45,8 +45,15 @@ framelocalsproxy_getval(_PyInterpreterFrame *frame, PyCodeObject *co, int i) if (kind == CO_FAST_FREE || kind & CO_FAST_CELL) { // The cell was set when the frame was created from // the function's closure. - assert(PyCell_Check(value)); - cell = value; + // GH-128396: With PEP 709, it's possible to have a fast variable in + // an inlined comprehension that has the same name as the cell variable + // in the frame, where the `kind` obtained from frame can not guarantee + // that the variable is a cell. + // If the variable is not a cell, we are okay with it and we can simply + // return the value. + if (PyCell_Check(value)) { + cell = value; + } } if (cell != NULL) { |