From cce7fd996b0556023d0f6a6017d56e604ee3b260 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 9 Jun 2025 10:16:59 +0300 Subject: [PATCH] gh-121914: Change the names of the symbol tables for lambda and genexpr Change the names of the symbol tables for lambda expressions and generator expressions to "" and "" respectively to avoid conflicts with user-defined names. --- .../pycore_global_objects_fini_generated.h | 5 -- Include/internal/pycore_global_strings.h | 5 -- .../internal/pycore_runtime_init_generated.h | 5 -- .../internal/pycore_unicodeobject_generated.h | 20 ------- Lib/symtable.py | 12 ----- Lib/test/test_symtable.py | 52 +++++++++++++++++++ ...-06-09-10-16-55.gh-issue-121914.G6Avkq.rst | 3 ++ Python/symtable.c | 10 ++-- 8 files changed, 60 insertions(+), 52 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-06-09-10-16-55.gh-issue-121914.G6Avkq.rst diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h index e118b86db50754..4387eddec98512 100644 --- a/Include/internal/pycore_global_objects_fini_generated.h +++ b/Include/internal/pycore_global_objects_fini_generated.h @@ -904,7 +904,6 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(deterministic)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(device)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(dict)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(dictcomp)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(difference_update)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(digest)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(digest_size)); @@ -979,7 +978,6 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(func)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(future)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(generation)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(genexpr)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(get)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(get_debug)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(get_event_loop)); @@ -1055,7 +1053,6 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(kw2)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(kwdefaults)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(label)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(lambda)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(last)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(last_exc)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(last_node)); @@ -1071,7 +1068,6 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(line)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(line_buffering)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(lineno)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(listcomp)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(little)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(lo)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(locale)); @@ -1217,7 +1213,6 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) { _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(server_hostname)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(server_side)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(session)); - _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(setcomp)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(setpgroup)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(setsid)); _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(setsigdef)); diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h index 36f3d23d095d59..d917b574afa77d 100644 --- a/Include/internal/pycore_global_strings.h +++ b/Include/internal/pycore_global_strings.h @@ -395,7 +395,6 @@ struct _Py_global_strings { STRUCT_FOR_ID(deterministic) STRUCT_FOR_ID(device) STRUCT_FOR_ID(dict) - STRUCT_FOR_ID(dictcomp) STRUCT_FOR_ID(difference_update) STRUCT_FOR_ID(digest) STRUCT_FOR_ID(digest_size) @@ -470,7 +469,6 @@ struct _Py_global_strings { STRUCT_FOR_ID(func) STRUCT_FOR_ID(future) STRUCT_FOR_ID(generation) - STRUCT_FOR_ID(genexpr) STRUCT_FOR_ID(get) STRUCT_FOR_ID(get_debug) STRUCT_FOR_ID(get_event_loop) @@ -546,7 +544,6 @@ struct _Py_global_strings { STRUCT_FOR_ID(kw2) STRUCT_FOR_ID(kwdefaults) STRUCT_FOR_ID(label) - STRUCT_FOR_ID(lambda) STRUCT_FOR_ID(last) STRUCT_FOR_ID(last_exc) STRUCT_FOR_ID(last_node) @@ -562,7 +559,6 @@ struct _Py_global_strings { STRUCT_FOR_ID(line) STRUCT_FOR_ID(line_buffering) STRUCT_FOR_ID(lineno) - STRUCT_FOR_ID(listcomp) STRUCT_FOR_ID(little) STRUCT_FOR_ID(lo) STRUCT_FOR_ID(locale) @@ -708,7 +704,6 @@ struct _Py_global_strings { STRUCT_FOR_ID(server_hostname) STRUCT_FOR_ID(server_side) STRUCT_FOR_ID(session) - STRUCT_FOR_ID(setcomp) STRUCT_FOR_ID(setpgroup) STRUCT_FOR_ID(setsid) STRUCT_FOR_ID(setsigdef) diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h index d172cc1485d426..e3963dde56c8af 100644 --- a/Include/internal/pycore_runtime_init_generated.h +++ b/Include/internal/pycore_runtime_init_generated.h @@ -902,7 +902,6 @@ extern "C" { INIT_ID(deterministic), \ INIT_ID(device), \ INIT_ID(dict), \ - INIT_ID(dictcomp), \ INIT_ID(difference_update), \ INIT_ID(digest), \ INIT_ID(digest_size), \ @@ -977,7 +976,6 @@ extern "C" { INIT_ID(func), \ INIT_ID(future), \ INIT_ID(generation), \ - INIT_ID(genexpr), \ INIT_ID(get), \ INIT_ID(get_debug), \ INIT_ID(get_event_loop), \ @@ -1053,7 +1051,6 @@ extern "C" { INIT_ID(kw2), \ INIT_ID(kwdefaults), \ INIT_ID(label), \ - INIT_ID(lambda), \ INIT_ID(last), \ INIT_ID(last_exc), \ INIT_ID(last_node), \ @@ -1069,7 +1066,6 @@ extern "C" { INIT_ID(line), \ INIT_ID(line_buffering), \ INIT_ID(lineno), \ - INIT_ID(listcomp), \ INIT_ID(little), \ INIT_ID(lo), \ INIT_ID(locale), \ @@ -1215,7 +1211,6 @@ extern "C" { INIT_ID(server_hostname), \ INIT_ID(server_side), \ INIT_ID(session), \ - INIT_ID(setcomp), \ INIT_ID(setpgroup), \ INIT_ID(setsid), \ INIT_ID(setsigdef), \ diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h index 0a9be4e41ace89..191e54925ff3bd 100644 --- a/Include/internal/pycore_unicodeobject_generated.h +++ b/Include/internal/pycore_unicodeobject_generated.h @@ -1368,10 +1368,6 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); - string = &_Py_ID(dictcomp); - _PyUnicode_InternStatic(interp, &string); - assert(_PyUnicode_CheckConsistency(string, 1)); - assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(difference_update); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -1668,10 +1664,6 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); - string = &_Py_ID(genexpr); - _PyUnicode_InternStatic(interp, &string); - assert(_PyUnicode_CheckConsistency(string, 1)); - assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(get); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -1972,10 +1964,6 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); - string = &_Py_ID(lambda); - _PyUnicode_InternStatic(interp, &string); - assert(_PyUnicode_CheckConsistency(string, 1)); - assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(last); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2036,10 +2024,6 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); - string = &_Py_ID(listcomp); - _PyUnicode_InternStatic(interp, &string); - assert(_PyUnicode_CheckConsistency(string, 1)); - assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(little); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); @@ -2620,10 +2604,6 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) { _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); assert(PyUnicode_GET_LENGTH(string) != 1); - string = &_Py_ID(setcomp); - _PyUnicode_InternStatic(interp, &string); - assert(_PyUnicode_CheckConsistency(string, 1)); - assert(PyUnicode_GET_LENGTH(string) != 1); string = &_Py_ID(setpgroup); _PyUnicode_InternStatic(interp, &string); assert(_PyUnicode_CheckConsistency(string, 1)); diff --git a/Lib/symtable.py b/Lib/symtable.py index 7a30e1ac4ca378..77475c3ffd9224 100644 --- a/Lib/symtable.py +++ b/Lib/symtable.py @@ -255,11 +255,6 @@ def is_local_symbol(ident): if is_local_symbol(st.name): match st.type: case _symtable.TYPE_FUNCTION: - # generators are of type TYPE_FUNCTION with a ".0" - # parameter as a first parameter (which makes them - # distinguishable from a function named 'genexpr') - if st.name == 'genexpr' and '.0' in st.varnames: - continue d[st.name] = 1 case _symtable.TYPE_TYPE_PARAMETERS: # Get the function-def block in the annotation @@ -267,13 +262,6 @@ def is_local_symbol(ident): scope_name = st.name for c in st.children: if c.name == scope_name and c.type == _symtable.TYPE_FUNCTION: - # A generic generator of type TYPE_FUNCTION - # cannot be a direct child of 'st' (but it - # can be a descendant), e.g.: - # - # class A: - # type genexpr[genexpr] = (x for x in []) - assert scope_name != 'genexpr' or '.0' not in c.varnames d[scope_name] = 1 break self.__methods = tuple(d) diff --git a/Lib/test/test_symtable.py b/Lib/test/test_symtable.py index 24d89b09d946ad..26c75fcbc2bd7f 100644 --- a/Lib/test/test_symtable.py +++ b/Lib/test/test_symtable.py @@ -527,6 +527,58 @@ def test_symtable_entry_repr(self): expected = f"" self.assertEqual(repr(self.top._table), expected) + def test_lambda(self): + st = symtable.symtable("lambda x: x", "?", "exec") + self.assertEqual(len(st.get_children()), 1) + st = st.get_children()[0] + self.assertIs(st.get_type(), symtable.SymbolTableType.FUNCTION) + self.assertEqual(st.get_name(), "") + self.assertFalse(st.is_nested()) + self.assertEqual(sorted(st.get_identifiers()), ["x"]) + self.assertEqual(st.get_children(), []) + + def test_nested_lambda(self): + st = symtable.symtable("lambda x: lambda y=x: y", "?", "exec") + self.assertEqual(len(st.get_children()), 1) + st = st.get_children()[0] + self.assertIs(st.get_type(), symtable.SymbolTableType.FUNCTION) + self.assertEqual(st.get_name(), "") + self.assertFalse(st.is_nested()) + self.assertEqual(sorted(st.get_identifiers()), ["x"]) + self.assertEqual(len(st.get_children()), 1) + st = st.get_children()[0] + self.assertIs(st.get_type(), symtable.SymbolTableType.FUNCTION) + self.assertEqual(st.get_name(), "") + self.assertTrue(st.is_nested()) + self.assertEqual(sorted(st.get_identifiers()), ["y"]) + self.assertEqual(st.get_children(), []) + + def test_genexpr(self): + st = symtable.symtable("(x for x in a)", "?", "exec") + self.assertEqual(len(st.get_children()), 1) + st = st.get_children()[0] + self.assertIs(st.get_type(), symtable.SymbolTableType.FUNCTION) + self.assertEqual(st.get_name(), "") + self.assertFalse(st.is_nested()) + self.assertEqual(sorted(st.get_identifiers()), [".0", "x"]) + self.assertEqual(st.get_children(), []) + + def test_nested_genexpr(self): + st = symtable.symtable("((y for y in x) for x in a)", "?", "exec") + self.assertEqual(len(st.get_children()), 1) + st = st.get_children()[0] + self.assertIs(st.get_type(), symtable.SymbolTableType.FUNCTION) + self.assertEqual(st.get_name(), "") + self.assertFalse(st.is_nested()) + self.assertEqual(sorted(st.get_identifiers()), [".0", "x"]) + self.assertEqual(len(st.get_children()), 1) + st = st.get_children()[0] + self.assertIs(st.get_type(), symtable.SymbolTableType.FUNCTION) + self.assertEqual(st.get_name(), "") + self.assertTrue(st.is_nested()) + self.assertEqual(sorted(st.get_identifiers()), [".0", "y"]) + self.assertEqual(st.get_children(), []) + class ComprehensionTests(unittest.TestCase): def get_identifiers_recursive(self, st, res): diff --git a/Misc/NEWS.d/next/Library/2025-06-09-10-16-55.gh-issue-121914.G6Avkq.rst b/Misc/NEWS.d/next/Library/2025-06-09-10-16-55.gh-issue-121914.G6Avkq.rst new file mode 100644 index 00000000000000..a1314a9cb7f943 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-06-09-10-16-55.gh-issue-121914.G6Avkq.rst @@ -0,0 +1,3 @@ +Changed the names of the symbol tables for lambda expressions and generator +expressions to "" and "" respectively to avoid conflicts +with user-defined names. diff --git a/Python/symtable.c b/Python/symtable.c index a3d0fff80d24a1..bcd7365f8e1f14 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -2413,7 +2413,7 @@ symtable_visit_expr(struct symtable *st, expr_ty e) VISIT_SEQ(st, expr, e->v.Lambda.args->defaults); if (e->v.Lambda.args->kw_defaults) VISIT_SEQ_WITH_NULL(st, expr, e->v.Lambda.args->kw_defaults); - if (!symtable_enter_block(st, &_Py_ID(lambda), + if (!symtable_enter_block(st, &_Py_STR(anon_lambda), FunctionBlock, (void *)e, LOCATION(e))) { return 0; } @@ -3055,7 +3055,7 @@ symtable_handle_comprehension(struct symtable *st, expr_ty e, static int symtable_visit_genexp(struct symtable *st, expr_ty e) { - return symtable_handle_comprehension(st, e, &_Py_ID(genexpr), + return symtable_handle_comprehension(st, e, &_Py_STR(anon_genexpr), e->v.GeneratorExp.generators, e->v.GeneratorExp.elt, NULL); } @@ -3063,7 +3063,7 @@ symtable_visit_genexp(struct symtable *st, expr_ty e) static int symtable_visit_listcomp(struct symtable *st, expr_ty e) { - return symtable_handle_comprehension(st, e, &_Py_ID(listcomp), + return symtable_handle_comprehension(st, e, &_Py_STR(anon_listcomp), e->v.ListComp.generators, e->v.ListComp.elt, NULL); } @@ -3071,7 +3071,7 @@ symtable_visit_listcomp(struct symtable *st, expr_ty e) static int symtable_visit_setcomp(struct symtable *st, expr_ty e) { - return symtable_handle_comprehension(st, e, &_Py_ID(setcomp), + return symtable_handle_comprehension(st, e, &_Py_STR(anon_setcomp), e->v.SetComp.generators, e->v.SetComp.elt, NULL); } @@ -3079,7 +3079,7 @@ symtable_visit_setcomp(struct symtable *st, expr_ty e) static int symtable_visit_dictcomp(struct symtable *st, expr_ty e) { - return symtable_handle_comprehension(st, e, &_Py_ID(dictcomp), + return symtable_handle_comprehension(st, e, &_Py_STR(anon_dictcomp), e->v.DictComp.generators, e->v.DictComp.key, e->v.DictComp.value);