gh-138349: Fix crash when combining module-level annotation and listcomp (#138363)

This commit is contained in:
Jelle Zijlstra 2025-09-10 06:18:39 -07:00 committed by GitHub
parent f5fa336579
commit 7a6fd4a45d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 48 additions and 5 deletions

View file

@ -279,11 +279,13 @@ Known values:
Python 3.14b1 3624 (Don't optimize LOAD_FAST when local is killed by DELETE_FAST) Python 3.14b1 3624 (Don't optimize LOAD_FAST when local is killed by DELETE_FAST)
Python 3.14b3 3625 (Fix handling of opcodes that may leave operands on the stack when optimizing LOAD_FAST) Python 3.14b3 3625 (Fix handling of opcodes that may leave operands on the stack when optimizing LOAD_FAST)
Python 3.14rc2 3626 (Fix missing exception handlers in logical expression) Python 3.14rc2 3626 (Fix missing exception handlers in logical expression)
Python 3.14rc3 3627 (Fix miscompilation of some module-level annotations)
Python 3.15a0 3650 (Initial version) Python 3.15a0 3650 (Initial version)
Python 3.15a1 3651 (Simplify LOAD_CONST) Python 3.15a1 3651 (Simplify LOAD_CONST)
Python 3.15a1 3652 (Virtual iterators) Python 3.15a1 3652 (Virtual iterators)
Python 3.15a1 3653 (Fix handling of opcodes that may leave operands on the stack when optimizing LOAD_FAST) Python 3.15a1 3653 (Fix handling of opcodes that may leave operands on the stack when optimizing LOAD_FAST)
Python 3.15a1 3654 (Fix missing exception handlers in logical expression) Python 3.15a1 3654 (Fix missing exception handlers in logical expression)
Python 3.15a1 3655 (Fix miscompilation of some module-level annotations)
Python 3.16 will start with 3700 Python 3.16 will start with 3700
@ -297,7 +299,7 @@ PC/launcher.c must also be updated.
*/ */
#define PYC_MAGIC_NUMBER 3654 #define PYC_MAGIC_NUMBER 3655
/* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes /* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes
(little-endian) and then appending b'\r\n'. */ (little-endian) and then appending b'\r\n'. */
#define PYC_MAGIC_NUMBER_TOKEN \ #define PYC_MAGIC_NUMBER_TOKEN \

View file

@ -835,3 +835,40 @@ def test_complex_comprehension_inlining_exec(self):
genexp = annos["unique_name_2"][0] genexp = annos["unique_name_2"][0]
lamb = list(genexp)[0] lamb = list(genexp)[0]
self.assertEqual(lamb(), 42) self.assertEqual(lamb(), 42)
# gh-138349
def test_module_level_annotation_plus_listcomp(self):
cases = [
"""
def report_error():
pass
try:
[0 for name_2 in unique_name_0 if (lambda: name_2)]
except:
pass
annotated_name: 0
""",
"""
class Generic:
pass
try:
[0 for name_2 in unique_name_0 if (0 for unique_name_1 in unique_name_2 for unique_name_3 in name_2)]
except:
pass
annotated_name: 0
""",
"""
class Generic:
pass
annotated_name: 0
try:
[0 for name_2 in [[0]] for unique_name_1 in unique_name_2 if (lambda: name_2)]
except:
pass
""",
]
for code in cases:
with self.subTest(code=code):
mod = build_module(code)
annos = mod.__annotations__
self.assertEqual(annos, {"annotated_name": 0})

View file

@ -0,0 +1,2 @@
Fix crash in certain cases where a module contains both a module-level
annotation and a comprehension.

View file

@ -5477,10 +5477,12 @@ codegen_annassign(compiler *c, stmt_ty s)
RETURN_IF_ERROR(_PyCompile_AddDeferredAnnotation( RETURN_IF_ERROR(_PyCompile_AddDeferredAnnotation(
c, s, &conditional_annotation_index)); c, s, &conditional_annotation_index));
if (conditional_annotation_index != NULL) { if (conditional_annotation_index != NULL) {
ADDOP_NAME( if (SCOPE_TYPE(c) == COMPILE_SCOPE_CLASS) {
c, loc, ADDOP_NAME(c, loc, LOAD_DEREF, &_Py_ID(__conditional_annotations__), cellvars);
SCOPE_TYPE(c) == COMPILE_SCOPE_CLASS ? LOAD_DEREF : LOAD_NAME, }
&_Py_ID(__conditional_annotations__), cellvars); else {
ADDOP_NAME(c, loc, LOAD_NAME, &_Py_ID(__conditional_annotations__), names);
}
ADDOP_LOAD_CONST_NEW(c, loc, conditional_annotation_index); ADDOP_LOAD_CONST_NEW(c, loc, conditional_annotation_index);
ADDOP_I(c, loc, SET_ADD, 1); ADDOP_I(c, loc, SET_ADD, 1);
ADDOP(c, loc, POP_TOP); ADDOP(c, loc, POP_TOP);