mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
gh-132479: Fix crash with multiple comprehensions in annotations (#132778)
This commit is contained in:
parent
08e331d05e
commit
01317bb449
3 changed files with 72 additions and 6 deletions
|
@ -723,3 +723,66 @@ class ConditionalAnnotationTests(unittest.TestCase):
|
|||
"""
|
||||
expected = {"before": "before", "after": "after"}
|
||||
self.check_scopes(code, expected, expected)
|
||||
|
||||
|
||||
class RegressionTests(unittest.TestCase):
|
||||
# gh-132479
|
||||
def test_complex_comprehension_inlining(self):
|
||||
# Test that the various repro cases from the issue don't crash
|
||||
cases = [
|
||||
"""
|
||||
(unique_name_0): 0
|
||||
unique_name_1: (
|
||||
0
|
||||
for (
|
||||
0
|
||||
for unique_name_2 in 0
|
||||
for () in (0 for unique_name_3 in unique_name_4 for unique_name_5 in name_1)
|
||||
).name_3 in {0: 0 for name_1 in unique_name_8}
|
||||
if name_1
|
||||
)
|
||||
""",
|
||||
"""
|
||||
unique_name_0: 0
|
||||
unique_name_1: {
|
||||
0: 0
|
||||
for unique_name_2 in [0 for name_0 in unique_name_4]
|
||||
if {
|
||||
0: 0
|
||||
for unique_name_5 in 0
|
||||
if name_0
|
||||
if ((name_0 for unique_name_8 in unique_name_9) for [] in 0)
|
||||
}
|
||||
}
|
||||
""",
|
||||
"""
|
||||
0[0]: {0 for name_0 in unique_name_1}
|
||||
unique_name_2: {
|
||||
0: (lambda: name_0 for unique_name_4 in unique_name_5)
|
||||
for unique_name_6 in ()
|
||||
if name_0
|
||||
}
|
||||
""",
|
||||
]
|
||||
for case in cases:
|
||||
case = textwrap.dedent(case)
|
||||
compile(case, "<test>", "exec")
|
||||
|
||||
def test_complex_comprehension_inlining_exec(self):
|
||||
code = """
|
||||
unique_name_1 = unique_name_5 = [1]
|
||||
name_0 = 42
|
||||
unique_name_7: {name_0 for name_0 in unique_name_1}
|
||||
unique_name_2: {
|
||||
0: (lambda: name_0 for unique_name_4 in unique_name_5)
|
||||
for unique_name_6 in [1]
|
||||
if name_0
|
||||
}
|
||||
"""
|
||||
mod = build_module(code)
|
||||
annos = mod.__annotations__
|
||||
self.assertEqual(annos.keys(), {"unique_name_7", "unique_name_2"})
|
||||
self.assertEqual(annos["unique_name_7"], {True})
|
||||
genexp = annos["unique_name_2"][0]
|
||||
lamb = list(genexp)[0]
|
||||
self.assertEqual(lamb(), 42)
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Fix compiler crash in certain circumstances where multiple module-level
|
||||
annotations include comprehensions and other nested scopes.
|
|
@ -1394,7 +1394,7 @@ symtable_exit_block(struct symtable *st)
|
|||
}
|
||||
|
||||
static int
|
||||
symtable_enter_existing_block(struct symtable *st, PySTEntryObject* ste)
|
||||
symtable_enter_existing_block(struct symtable *st, PySTEntryObject* ste, bool add_to_children)
|
||||
{
|
||||
if (PyList_Append(st->st_stack, (PyObject *)ste) < 0) {
|
||||
return 0;
|
||||
|
@ -1425,7 +1425,7 @@ symtable_enter_existing_block(struct symtable *st, PySTEntryObject* ste)
|
|||
if (ste->ste_type == ModuleBlock)
|
||||
st->st_global = st->st_cur->ste_symbols;
|
||||
|
||||
if (prev) {
|
||||
if (add_to_children && prev) {
|
||||
if (PyList_Append(prev->ste_children, (PyObject *)ste) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -1440,7 +1440,7 @@ symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block,
|
|||
PySTEntryObject *ste = ste_new(st, name, block, ast, loc);
|
||||
if (ste == NULL)
|
||||
return 0;
|
||||
int result = symtable_enter_existing_block(st, ste);
|
||||
int result = symtable_enter_existing_block(st, ste, /* add_to_children */true);
|
||||
Py_DECREF(ste);
|
||||
if (block == AnnotationBlock || block == TypeVariableBlock || block == TypeAliasBlock) {
|
||||
_Py_DECLARE_STR(format, ".format");
|
||||
|
@ -1866,7 +1866,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
|||
Py_DECREF(new_ste);
|
||||
return 0;
|
||||
}
|
||||
if (!symtable_enter_existing_block(st, new_ste)) {
|
||||
if (!symtable_enter_existing_block(st, new_ste, /* add_to_children */true)) {
|
||||
Py_DECREF(new_ste);
|
||||
return 0;
|
||||
}
|
||||
|
@ -2223,7 +2223,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
|||
Py_DECREF(new_ste);
|
||||
return 0;
|
||||
}
|
||||
if (!symtable_enter_existing_block(st, new_ste)) {
|
||||
if (!symtable_enter_existing_block(st, new_ste, /* add_to_children */true)) {
|
||||
Py_DECREF(new_ste);
|
||||
return 0;
|
||||
}
|
||||
|
@ -2776,7 +2776,8 @@ symtable_visit_annotation(struct symtable *st, expr_ty annotation, void *key)
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (!symtable_enter_existing_block(st, parent_ste->ste_annotation_block)) {
|
||||
if (!symtable_enter_existing_block(st, parent_ste->ste_annotation_block,
|
||||
/* add_to_children */false)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue