mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 07:31:38 +00:00 
			
		
		
		
	gh-119311: Fix name mangling with PEP 695 generic classes (#119464)
Fixes #119311. Fixes #119395.
This commit is contained in:
		
							parent
							
								
									3e8b60905e
								
							
						
					
					
						commit
						a9a74da4a0
					
				
					 7 changed files with 150 additions and 14 deletions
				
			
		| 
						 | 
					@ -81,6 +81,7 @@ typedef struct _symtable_entry {
 | 
				
			||||||
    PyObject *ste_varnames;  /* list of function parameters */
 | 
					    PyObject *ste_varnames;  /* list of function parameters */
 | 
				
			||||||
    PyObject *ste_children;  /* list of child blocks */
 | 
					    PyObject *ste_children;  /* list of child blocks */
 | 
				
			||||||
    PyObject *ste_directives;/* locations of global and nonlocal statements */
 | 
					    PyObject *ste_directives;/* locations of global and nonlocal statements */
 | 
				
			||||||
 | 
					    PyObject *ste_mangled_names; /* set of names for which mangling should be applied */
 | 
				
			||||||
    _Py_block_ty ste_type;
 | 
					    _Py_block_ty ste_type;
 | 
				
			||||||
    int ste_nested;      /* true if block is nested */
 | 
					    int ste_nested;      /* true if block is nested */
 | 
				
			||||||
    unsigned ste_free : 1;        /* true if block has free variables */
 | 
					    unsigned ste_free : 1;        /* true if block has free variables */
 | 
				
			||||||
| 
						 | 
					@ -128,6 +129,7 @@ extern PySTEntryObject* _PySymtable_Lookup(struct symtable *, void *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern void _PySymtable_Free(struct symtable *);
 | 
					extern void _PySymtable_Free(struct symtable *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern PyObject *_Py_MaybeMangle(PyObject *privateobj, PySTEntryObject *ste, PyObject *name);
 | 
				
			||||||
extern PyObject* _Py_Mangle(PyObject *p, PyObject *name);
 | 
					extern PyObject* _Py_Mangle(PyObject *p, PyObject *name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Flags for def-use information */
 | 
					/* Flags for def-use information */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -473,6 +473,7 @@ def _write_atomic(path, data, mode=0o666):
 | 
				
			||||||
#     Python 3.13a5 3569 (Specialize CONTAINS_OP)
 | 
					#     Python 3.13a5 3569 (Specialize CONTAINS_OP)
 | 
				
			||||||
#     Python 3.13a6 3570 (Add __firstlineno__ class attribute)
 | 
					#     Python 3.13a6 3570 (Add __firstlineno__ class attribute)
 | 
				
			||||||
#     Python 3.14a1 3600 (Add LOAD_COMMON_CONSTANT)
 | 
					#     Python 3.14a1 3600 (Add LOAD_COMMON_CONSTANT)
 | 
				
			||||||
 | 
					#     Python 3.14a1 3601 (Fix miscompilation of private names in generic classes)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#     Python 3.15 will start with 3700
 | 
					#     Python 3.15 will start with 3700
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -489,7 +490,7 @@ def _write_atomic(path, data, mode=0o666):
 | 
				
			||||||
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
 | 
					# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
 | 
				
			||||||
# in PC/launcher.c must also be updated.
 | 
					# in PC/launcher.c must also be updated.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MAGIC_NUMBER = (3600).to_bytes(2, 'little') + b'\r\n'
 | 
					MAGIC_NUMBER = (3601).to_bytes(2, 'little') + b'\r\n'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little')  # For import.c
 | 
					_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little')  # For import.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -823,6 +823,100 @@ def meth[__U](self, arg: __T, arg2: __U):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.assertEqual(Foo.Alias.__value__, (T, V))
 | 
					        self.assertEqual(Foo.Alias.__value__, (T, V))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_no_leaky_mangling_in_module(self):
 | 
				
			||||||
 | 
					        ns = run_code("""
 | 
				
			||||||
 | 
					            __before = "before"
 | 
				
			||||||
 | 
					            class X[T]: pass
 | 
				
			||||||
 | 
					            __after = "after"
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					        self.assertEqual(ns["__before"], "before")
 | 
				
			||||||
 | 
					        self.assertEqual(ns["__after"], "after")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_no_leaky_mangling_in_function(self):
 | 
				
			||||||
 | 
					        ns = run_code("""
 | 
				
			||||||
 | 
					            def f():
 | 
				
			||||||
 | 
					                class X[T]: pass
 | 
				
			||||||
 | 
					                _X_foo = 2
 | 
				
			||||||
 | 
					                __foo = 1
 | 
				
			||||||
 | 
					                assert locals()['__foo'] == 1
 | 
				
			||||||
 | 
					                return __foo
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					        self.assertEqual(ns["f"](), 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_no_leaky_mangling_in_class(self):
 | 
				
			||||||
 | 
					        ns = run_code("""
 | 
				
			||||||
 | 
					            class Outer:
 | 
				
			||||||
 | 
					                __before = "before"
 | 
				
			||||||
 | 
					                class Inner[T]:
 | 
				
			||||||
 | 
					                    __x = "inner"
 | 
				
			||||||
 | 
					                __after = "after"
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					        Outer = ns["Outer"]
 | 
				
			||||||
 | 
					        self.assertEqual(Outer._Outer__before, "before")
 | 
				
			||||||
 | 
					        self.assertEqual(Outer.Inner._Inner__x, "inner")
 | 
				
			||||||
 | 
					        self.assertEqual(Outer._Outer__after, "after")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_no_mangling_in_bases(self):
 | 
				
			||||||
 | 
					        ns = run_code("""
 | 
				
			||||||
 | 
					            class __Base:
 | 
				
			||||||
 | 
					                def __init_subclass__(self, **kwargs):
 | 
				
			||||||
 | 
					                    self.kwargs = kwargs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            class Derived[T](__Base, __kwarg=1):
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					        Derived = ns["Derived"]
 | 
				
			||||||
 | 
					        self.assertEqual(Derived.__bases__, (ns["__Base"], Generic))
 | 
				
			||||||
 | 
					        self.assertEqual(Derived.kwargs, {"__kwarg": 1})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_no_mangling_in_nested_scopes(self):
 | 
				
			||||||
 | 
					        ns = run_code("""
 | 
				
			||||||
 | 
					            from test.test_type_params import make_base
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            class __X:
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            class Y[T: __X](
 | 
				
			||||||
 | 
					                make_base(lambda: __X),
 | 
				
			||||||
 | 
					                # doubly nested scope
 | 
				
			||||||
 | 
					                make_base(lambda: (lambda: __X)),
 | 
				
			||||||
 | 
					                # list comprehension
 | 
				
			||||||
 | 
					                make_base([__X for _ in (1,)]),
 | 
				
			||||||
 | 
					                # genexp
 | 
				
			||||||
 | 
					                make_base(__X for _ in (1,)),
 | 
				
			||||||
 | 
					            ):
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					        Y = ns["Y"]
 | 
				
			||||||
 | 
					        T, = Y.__type_params__
 | 
				
			||||||
 | 
					        self.assertIs(T.__bound__, ns["__X"])
 | 
				
			||||||
 | 
					        base0 = Y.__bases__[0]
 | 
				
			||||||
 | 
					        self.assertIs(base0.__arg__(), ns["__X"])
 | 
				
			||||||
 | 
					        base1 = Y.__bases__[1]
 | 
				
			||||||
 | 
					        self.assertIs(base1.__arg__()(), ns["__X"])
 | 
				
			||||||
 | 
					        base2 = Y.__bases__[2]
 | 
				
			||||||
 | 
					        self.assertEqual(base2.__arg__, [ns["__X"]])
 | 
				
			||||||
 | 
					        base3 = Y.__bases__[3]
 | 
				
			||||||
 | 
					        self.assertEqual(list(base3.__arg__), [ns["__X"]])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_type_params_are_mangled(self):
 | 
				
			||||||
 | 
					        ns = run_code("""
 | 
				
			||||||
 | 
					            from test.test_type_params import make_base
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            class Foo[__T, __U: __T](make_base(__T), make_base(lambda: __T)):
 | 
				
			||||||
 | 
					                param = __T
 | 
				
			||||||
 | 
					        """)
 | 
				
			||||||
 | 
					        Foo = ns["Foo"]
 | 
				
			||||||
 | 
					        T, U = Foo.__type_params__
 | 
				
			||||||
 | 
					        self.assertEqual(T.__name__, "__T")
 | 
				
			||||||
 | 
					        self.assertEqual(U.__name__, "__U")
 | 
				
			||||||
 | 
					        self.assertIs(U.__bound__, T)
 | 
				
			||||||
 | 
					        self.assertIs(Foo.param, T)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        base1, base2, *_ = Foo.__bases__
 | 
				
			||||||
 | 
					        self.assertIs(base1.__arg__, T)
 | 
				
			||||||
 | 
					        self.assertIs(base2.__arg__(), T)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TypeParamsComplexCallsTest(unittest.TestCase):
 | 
					class TypeParamsComplexCallsTest(unittest.TestCase):
 | 
				
			||||||
    def test_defaults(self):
 | 
					    def test_defaults(self):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					Fix bug where names appearing after a generic class are mangled as if they
 | 
				
			||||||
 | 
					are in the generic class.
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					Fix bug where names are unexpectedly mangled in the bases of generic
 | 
				
			||||||
 | 
					classes.
 | 
				
			||||||
| 
						 | 
					@ -1001,7 +1001,7 @@ static int
 | 
				
			||||||
compiler_addop_name(struct compiler_unit *u, location loc,
 | 
					compiler_addop_name(struct compiler_unit *u, location loc,
 | 
				
			||||||
                    int opcode, PyObject *dict, PyObject *o)
 | 
					                    int opcode, PyObject *dict, PyObject *o)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    PyObject *mangled = _Py_Mangle(u->u_private, o);
 | 
					    PyObject *mangled = _Py_MaybeMangle(u->u_private, u->u_ste, o);
 | 
				
			||||||
    if (!mangled) {
 | 
					    if (!mangled) {
 | 
				
			||||||
        return ERROR;
 | 
					        return ERROR;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -1873,7 +1873,7 @@ compiler_visit_kwonlydefaults(struct compiler *c, location loc,
 | 
				
			||||||
        arg_ty arg = asdl_seq_GET(kwonlyargs, i);
 | 
					        arg_ty arg = asdl_seq_GET(kwonlyargs, i);
 | 
				
			||||||
        expr_ty default_ = asdl_seq_GET(kw_defaults, i);
 | 
					        expr_ty default_ = asdl_seq_GET(kw_defaults, i);
 | 
				
			||||||
        if (default_) {
 | 
					        if (default_) {
 | 
				
			||||||
            PyObject *mangled = _Py_Mangle(c->u->u_private, arg->arg);
 | 
					            PyObject *mangled = _Py_MaybeMangle(c->u->u_private, c->u->u_ste, arg->arg);
 | 
				
			||||||
            if (!mangled) {
 | 
					            if (!mangled) {
 | 
				
			||||||
                goto error;
 | 
					                goto error;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -1930,7 +1930,7 @@ compiler_visit_argannotation(struct compiler *c, identifier id,
 | 
				
			||||||
    if (!annotation) {
 | 
					    if (!annotation) {
 | 
				
			||||||
        return SUCCESS;
 | 
					        return SUCCESS;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    PyObject *mangled = _Py_Mangle(c->u->u_private, id);
 | 
					    PyObject *mangled = _Py_MaybeMangle(c->u->u_private, c->u->u_ste, id);
 | 
				
			||||||
    if (!mangled) {
 | 
					    if (!mangled) {
 | 
				
			||||||
        return ERROR;
 | 
					        return ERROR;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -2625,7 +2625,6 @@ compiler_class(struct compiler *c, stmt_ty s)
 | 
				
			||||||
    asdl_type_param_seq *type_params = s->v.ClassDef.type_params;
 | 
					    asdl_type_param_seq *type_params = s->v.ClassDef.type_params;
 | 
				
			||||||
    int is_generic = asdl_seq_LEN(type_params) > 0;
 | 
					    int is_generic = asdl_seq_LEN(type_params) > 0;
 | 
				
			||||||
    if (is_generic) {
 | 
					    if (is_generic) {
 | 
				
			||||||
        Py_XSETREF(c->u->u_private, Py_NewRef(s->v.ClassDef.name));
 | 
					 | 
				
			||||||
        PyObject *type_params_name = PyUnicode_FromFormat("<generic parameters of %U>",
 | 
					        PyObject *type_params_name = PyUnicode_FromFormat("<generic parameters of %U>",
 | 
				
			||||||
                                                         s->v.ClassDef.name);
 | 
					                                                         s->v.ClassDef.name);
 | 
				
			||||||
        if (!type_params_name) {
 | 
					        if (!type_params_name) {
 | 
				
			||||||
| 
						 | 
					@ -2637,6 +2636,7 @@ compiler_class(struct compiler *c, stmt_ty s)
 | 
				
			||||||
            return ERROR;
 | 
					            return ERROR;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Py_DECREF(type_params_name);
 | 
					        Py_DECREF(type_params_name);
 | 
				
			||||||
 | 
					        Py_XSETREF(c->u->u_private, Py_NewRef(s->v.ClassDef.name));
 | 
				
			||||||
        RETURN_IF_ERROR_IN_SCOPE(c, compiler_type_params(c, type_params));
 | 
					        RETURN_IF_ERROR_IN_SCOPE(c, compiler_type_params(c, type_params));
 | 
				
			||||||
        _Py_DECLARE_STR(type_params, ".type_params");
 | 
					        _Py_DECLARE_STR(type_params, ".type_params");
 | 
				
			||||||
        RETURN_IF_ERROR_IN_SCOPE(c, compiler_nameop(c, loc, &_Py_STR(type_params), Store));
 | 
					        RETURN_IF_ERROR_IN_SCOPE(c, compiler_nameop(c, loc, &_Py_STR(type_params), Store));
 | 
				
			||||||
| 
						 | 
					@ -4203,7 +4203,7 @@ compiler_nameop(struct compiler *c, location loc,
 | 
				
			||||||
        return ERROR;
 | 
					        return ERROR;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mangled = _Py_Mangle(c->u->u_private, name);
 | 
					    mangled = _Py_MaybeMangle(c->u->u_private, c->u->u_ste, name);
 | 
				
			||||||
    if (!mangled) {
 | 
					    if (!mangled) {
 | 
				
			||||||
        return ERROR;
 | 
					        return ERROR;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -6512,7 +6512,7 @@ compiler_annassign(struct compiler *c, stmt_ty s)
 | 
				
			||||||
                VISIT(c, expr, s->v.AnnAssign.annotation);
 | 
					                VISIT(c, expr, s->v.AnnAssign.annotation);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            ADDOP_NAME(c, loc, LOAD_NAME, &_Py_ID(__annotations__), names);
 | 
					            ADDOP_NAME(c, loc, LOAD_NAME, &_Py_ID(__annotations__), names);
 | 
				
			||||||
            mangled = _Py_Mangle(c->u->u_private, targ->v.Name.id);
 | 
					            mangled = _Py_MaybeMangle(c->u->u_private, c->u->u_ste, targ->v.Name.id);
 | 
				
			||||||
            ADDOP_LOAD_CONST_NEW(c, loc, mangled);
 | 
					            ADDOP_LOAD_CONST_NEW(c, loc, mangled);
 | 
				
			||||||
            ADDOP(c, loc, STORE_SUBSCR);
 | 
					            ADDOP(c, loc, STORE_SUBSCR);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -103,6 +103,7 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block,
 | 
				
			||||||
    ste->ste_children = NULL;
 | 
					    ste->ste_children = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ste->ste_directives = NULL;
 | 
					    ste->ste_directives = NULL;
 | 
				
			||||||
 | 
					    ste->ste_mangled_names = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ste->ste_type = block;
 | 
					    ste->ste_type = block;
 | 
				
			||||||
    ste->ste_nested = 0;
 | 
					    ste->ste_nested = 0;
 | 
				
			||||||
| 
						 | 
					@ -166,6 +167,7 @@ ste_dealloc(PySTEntryObject *ste)
 | 
				
			||||||
    Py_XDECREF(ste->ste_varnames);
 | 
					    Py_XDECREF(ste->ste_varnames);
 | 
				
			||||||
    Py_XDECREF(ste->ste_children);
 | 
					    Py_XDECREF(ste->ste_children);
 | 
				
			||||||
    Py_XDECREF(ste->ste_directives);
 | 
					    Py_XDECREF(ste->ste_directives);
 | 
				
			||||||
 | 
					    Py_XDECREF(ste->ste_mangled_names);
 | 
				
			||||||
    PyObject_Free(ste);
 | 
					    PyObject_Free(ste);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1338,6 +1340,11 @@ symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block,
 | 
				
			||||||
    if (prev) {
 | 
					    if (prev) {
 | 
				
			||||||
        ste->ste_comp_iter_expr = prev->ste_comp_iter_expr;
 | 
					        ste->ste_comp_iter_expr = prev->ste_comp_iter_expr;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    /* No need to inherit ste_mangled_names in classes, where all names
 | 
				
			||||||
 | 
					     * are mangled. */
 | 
				
			||||||
 | 
					    if (prev && prev->ste_mangled_names != NULL && block != ClassBlock) {
 | 
				
			||||||
 | 
					        ste->ste_mangled_names = Py_NewRef(prev->ste_mangled_names);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    /* The entry is owned by the stack. Borrow it for st_cur. */
 | 
					    /* The entry is owned by the stack. Borrow it for st_cur. */
 | 
				
			||||||
    Py_DECREF(ste);
 | 
					    Py_DECREF(ste);
 | 
				
			||||||
    st->st_cur = ste;
 | 
					    st->st_cur = ste;
 | 
				
			||||||
| 
						 | 
					@ -1363,7 +1370,7 @@ symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block,
 | 
				
			||||||
static long
 | 
					static long
 | 
				
			||||||
symtable_lookup_entry(struct symtable *st, PySTEntryObject *ste, PyObject *name)
 | 
					symtable_lookup_entry(struct symtable *st, PySTEntryObject *ste, PyObject *name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    PyObject *mangled = _Py_Mangle(st->st_private, name);
 | 
					    PyObject *mangled = _Py_MaybeMangle(st->st_private, ste, name);
 | 
				
			||||||
    if (!mangled)
 | 
					    if (!mangled)
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    long ret = _PyST_GetSymbol(ste, mangled);
 | 
					    long ret = _PyST_GetSymbol(ste, mangled);
 | 
				
			||||||
| 
						 | 
					@ -1384,8 +1391,7 @@ symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _s
 | 
				
			||||||
    PyObject *o;
 | 
					    PyObject *o;
 | 
				
			||||||
    PyObject *dict;
 | 
					    PyObject *dict;
 | 
				
			||||||
    long val;
 | 
					    long val;
 | 
				
			||||||
    PyObject *mangled = _Py_Mangle(st->st_private, name);
 | 
					    PyObject *mangled = _Py_MaybeMangle(st->st_private, st->st_cur, name);
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!mangled)
 | 
					    if (!mangled)
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
| 
						 | 
					@ -1474,6 +1480,11 @@ static int
 | 
				
			||||||
symtable_add_def(struct symtable *st, PyObject *name, int flag,
 | 
					symtable_add_def(struct symtable *st, PyObject *name, int flag,
 | 
				
			||||||
                 int lineno, int col_offset, int end_lineno, int end_col_offset)
 | 
					                 int lineno, int col_offset, int end_lineno, int end_col_offset)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    if ((flag & DEF_TYPE_PARAM) && st->st_cur->ste_mangled_names != NULL) {
 | 
				
			||||||
 | 
					        if(PySet_Add(st->st_cur->ste_mangled_names, name) < 0) {
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return symtable_add_def_helper(st, name, flag, st->st_cur,
 | 
					    return symtable_add_def_helper(st, name, flag, st->st_cur,
 | 
				
			||||||
                        lineno, col_offset, end_lineno, end_col_offset);
 | 
					                        lineno, col_offset, end_lineno, end_col_offset);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1508,7 +1519,6 @@ symtable_enter_type_param_block(struct symtable *st, identifier name,
 | 
				
			||||||
                              lineno, col_offset, end_lineno, end_col_offset)) {
 | 
					                              lineno, col_offset, end_lineno, end_col_offset)) {
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        st->st_private = name;
 | 
					 | 
				
			||||||
        // This is used for setting the generic base
 | 
					        // This is used for setting the generic base
 | 
				
			||||||
        _Py_DECLARE_STR(generic_base, ".generic_base");
 | 
					        _Py_DECLARE_STR(generic_base, ".generic_base");
 | 
				
			||||||
        if (!symtable_add_def(st, &_Py_STR(generic_base), DEF_LOCAL,
 | 
					        if (!symtable_add_def(st, &_Py_STR(generic_base), DEF_LOCAL,
 | 
				
			||||||
| 
						 | 
					@ -1597,7 +1607,7 @@ symtable_record_directive(struct symtable *st, identifier name, int lineno,
 | 
				
			||||||
        if (!st->st_cur->ste_directives)
 | 
					        if (!st->st_cur->ste_directives)
 | 
				
			||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    mangled = _Py_Mangle(st->st_private, name);
 | 
					    mangled = _Py_MaybeMangle(st->st_private, st->st_cur, name);
 | 
				
			||||||
    if (!mangled)
 | 
					    if (!mangled)
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    data = Py_BuildValue("(Niiii)", mangled, lineno, col_offset, end_lineno, end_col_offset);
 | 
					    data = Py_BuildValue("(Niiii)", mangled, lineno, col_offset, end_lineno, end_col_offset);
 | 
				
			||||||
| 
						 | 
					@ -1673,6 +1683,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
 | 
				
			||||||
            VISIT_QUIT(st, 0);
 | 
					            VISIT_QUIT(st, 0);
 | 
				
			||||||
        if (s->v.ClassDef.decorator_list)
 | 
					        if (s->v.ClassDef.decorator_list)
 | 
				
			||||||
            VISIT_SEQ(st, expr, s->v.ClassDef.decorator_list);
 | 
					            VISIT_SEQ(st, expr, s->v.ClassDef.decorator_list);
 | 
				
			||||||
 | 
					        tmp = st->st_private;
 | 
				
			||||||
        if (asdl_seq_LEN(s->v.ClassDef.type_params) > 0) {
 | 
					        if (asdl_seq_LEN(s->v.ClassDef.type_params) > 0) {
 | 
				
			||||||
            if (!symtable_enter_type_param_block(st, s->v.ClassDef.name,
 | 
					            if (!symtable_enter_type_param_block(st, s->v.ClassDef.name,
 | 
				
			||||||
                                                (void *)s->v.ClassDef.type_params,
 | 
					                                                (void *)s->v.ClassDef.type_params,
 | 
				
			||||||
| 
						 | 
					@ -1680,6 +1691,11 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
 | 
				
			||||||
                                                LOCATION(s))) {
 | 
					                                                LOCATION(s))) {
 | 
				
			||||||
                VISIT_QUIT(st, 0);
 | 
					                VISIT_QUIT(st, 0);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            st->st_private = s->v.ClassDef.name;
 | 
				
			||||||
 | 
					            st->st_cur->ste_mangled_names = PySet_New(NULL);
 | 
				
			||||||
 | 
					            if (!st->st_cur->ste_mangled_names) {
 | 
				
			||||||
 | 
					                VISIT_QUIT(st, 0);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            VISIT_SEQ(st, type_param, s->v.ClassDef.type_params);
 | 
					            VISIT_SEQ(st, type_param, s->v.ClassDef.type_params);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        VISIT_SEQ(st, expr, s->v.ClassDef.bases);
 | 
					        VISIT_SEQ(st, expr, s->v.ClassDef.bases);
 | 
				
			||||||
| 
						 | 
					@ -1688,7 +1704,6 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
 | 
				
			||||||
                                  (void *)s, s->lineno, s->col_offset,
 | 
					                                  (void *)s, s->lineno, s->col_offset,
 | 
				
			||||||
                                  s->end_lineno, s->end_col_offset))
 | 
					                                  s->end_lineno, s->end_col_offset))
 | 
				
			||||||
            VISIT_QUIT(st, 0);
 | 
					            VISIT_QUIT(st, 0);
 | 
				
			||||||
        tmp = st->st_private;
 | 
					 | 
				
			||||||
        st->st_private = s->v.ClassDef.name;
 | 
					        st->st_private = s->v.ClassDef.name;
 | 
				
			||||||
        if (asdl_seq_LEN(s->v.ClassDef.type_params) > 0) {
 | 
					        if (asdl_seq_LEN(s->v.ClassDef.type_params) > 0) {
 | 
				
			||||||
            if (!symtable_add_def(st, &_Py_ID(__type_params__),
 | 
					            if (!symtable_add_def(st, &_Py_ID(__type_params__),
 | 
				
			||||||
| 
						 | 
					@ -1702,13 +1717,13 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        VISIT_SEQ(st, stmt, s->v.ClassDef.body);
 | 
					        VISIT_SEQ(st, stmt, s->v.ClassDef.body);
 | 
				
			||||||
        st->st_private = tmp;
 | 
					 | 
				
			||||||
        if (!symtable_exit_block(st))
 | 
					        if (!symtable_exit_block(st))
 | 
				
			||||||
            VISIT_QUIT(st, 0);
 | 
					            VISIT_QUIT(st, 0);
 | 
				
			||||||
        if (asdl_seq_LEN(s->v.ClassDef.type_params) > 0) {
 | 
					        if (asdl_seq_LEN(s->v.ClassDef.type_params) > 0) {
 | 
				
			||||||
            if (!symtable_exit_block(st))
 | 
					            if (!symtable_exit_block(st))
 | 
				
			||||||
                VISIT_QUIT(st, 0);
 | 
					                VISIT_QUIT(st, 0);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        st->st_private = tmp;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case TypeAlias_kind: {
 | 
					    case TypeAlias_kind: {
 | 
				
			||||||
| 
						 | 
					@ -2776,6 +2791,26 @@ _Py_SymtableStringObjectFlags(const char *str, PyObject *filename,
 | 
				
			||||||
    return st;
 | 
					    return st;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PyObject *
 | 
				
			||||||
 | 
					_Py_MaybeMangle(PyObject *privateobj, PySTEntryObject *ste, PyObject *name)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /* Special case for type parameter blocks around generic classes:
 | 
				
			||||||
 | 
					     * we want to mangle type parameter names (so a type param with a private
 | 
				
			||||||
 | 
					     * name can be used inside the class body), but we don't want to mangle
 | 
				
			||||||
 | 
					     * any other names that appear within the type parameter scope.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    if (ste->ste_mangled_names != NULL) {
 | 
				
			||||||
 | 
					        int result = PySet_Contains(ste->ste_mangled_names, name);
 | 
				
			||||||
 | 
					        if (result < 0) {
 | 
				
			||||||
 | 
					            return NULL;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (result == 0) {
 | 
				
			||||||
 | 
					            return Py_NewRef(name);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return _Py_Mangle(privateobj, name);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PyObject *
 | 
					PyObject *
 | 
				
			||||||
_Py_Mangle(PyObject *privateobj, PyObject *ident)
 | 
					_Py_Mangle(PyObject *privateobj, PyObject *ident)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue