mirror of
https://github.com/python/cpython.git
synced 2025-07-24 19:54:21 +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
|
@ -1001,7 +1001,7 @@ static int
|
|||
compiler_addop_name(struct compiler_unit *u, location loc,
|
||||
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) {
|
||||
return ERROR;
|
||||
}
|
||||
|
@ -1873,7 +1873,7 @@ compiler_visit_kwonlydefaults(struct compiler *c, location loc,
|
|||
arg_ty arg = asdl_seq_GET(kwonlyargs, i);
|
||||
expr_ty default_ = asdl_seq_GET(kw_defaults, i);
|
||||
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) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -1930,7 +1930,7 @@ compiler_visit_argannotation(struct compiler *c, identifier id,
|
|||
if (!annotation) {
|
||||
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) {
|
||||
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;
|
||||
int is_generic = asdl_seq_LEN(type_params) > 0;
|
||||
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>",
|
||||
s->v.ClassDef.name);
|
||||
if (!type_params_name) {
|
||||
|
@ -2637,6 +2636,7 @@ compiler_class(struct compiler *c, stmt_ty s)
|
|||
return ERROR;
|
||||
}
|
||||
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));
|
||||
_Py_DECLARE_STR(type_params, ".type_params");
|
||||
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;
|
||||
}
|
||||
|
||||
mangled = _Py_Mangle(c->u->u_private, name);
|
||||
mangled = _Py_MaybeMangle(c->u->u_private, c->u->u_ste, name);
|
||||
if (!mangled) {
|
||||
return ERROR;
|
||||
}
|
||||
|
@ -6512,7 +6512,7 @@ compiler_annassign(struct compiler *c, stmt_ty s)
|
|||
VISIT(c, expr, s->v.AnnAssign.annotation);
|
||||
}
|
||||
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(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_directives = NULL;
|
||||
ste->ste_mangled_names = NULL;
|
||||
|
||||
ste->ste_type = block;
|
||||
ste->ste_nested = 0;
|
||||
|
@ -166,6 +167,7 @@ ste_dealloc(PySTEntryObject *ste)
|
|||
Py_XDECREF(ste->ste_varnames);
|
||||
Py_XDECREF(ste->ste_children);
|
||||
Py_XDECREF(ste->ste_directives);
|
||||
Py_XDECREF(ste->ste_mangled_names);
|
||||
PyObject_Free(ste);
|
||||
}
|
||||
|
||||
|
@ -1338,6 +1340,11 @@ symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block,
|
|||
if (prev) {
|
||||
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. */
|
||||
Py_DECREF(ste);
|
||||
st->st_cur = ste;
|
||||
|
@ -1363,7 +1370,7 @@ symtable_enter_block(struct symtable *st, identifier name, _Py_block_ty block,
|
|||
static long
|
||||
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)
|
||||
return 0;
|
||||
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 *dict;
|
||||
long val;
|
||||
PyObject *mangled = _Py_Mangle(st->st_private, name);
|
||||
|
||||
PyObject *mangled = _Py_MaybeMangle(st->st_private, st->st_cur, name);
|
||||
|
||||
if (!mangled)
|
||||
return 0;
|
||||
|
@ -1474,6 +1480,11 @@ static int
|
|||
symtable_add_def(struct symtable *st, PyObject *name, int flag,
|
||||
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,
|
||||
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)) {
|
||||
return 0;
|
||||
}
|
||||
st->st_private = name;
|
||||
// This is used for setting the generic base
|
||||
_Py_DECLARE_STR(generic_base, ".generic_base");
|
||||
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)
|
||||
return 0;
|
||||
}
|
||||
mangled = _Py_Mangle(st->st_private, name);
|
||||
mangled = _Py_MaybeMangle(st->st_private, st->st_cur, name);
|
||||
if (!mangled)
|
||||
return 0;
|
||||
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);
|
||||
if (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 (!symtable_enter_type_param_block(st, s->v.ClassDef.name,
|
||||
(void *)s->v.ClassDef.type_params,
|
||||
|
@ -1680,6 +1691,11 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
|||
LOCATION(s))) {
|
||||
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, 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,
|
||||
s->end_lineno, s->end_col_offset))
|
||||
VISIT_QUIT(st, 0);
|
||||
tmp = st->st_private;
|
||||
st->st_private = s->v.ClassDef.name;
|
||||
if (asdl_seq_LEN(s->v.ClassDef.type_params) > 0) {
|
||||
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);
|
||||
st->st_private = tmp;
|
||||
if (!symtable_exit_block(st))
|
||||
VISIT_QUIT(st, 0);
|
||||
if (asdl_seq_LEN(s->v.ClassDef.type_params) > 0) {
|
||||
if (!symtable_exit_block(st))
|
||||
VISIT_QUIT(st, 0);
|
||||
}
|
||||
st->st_private = tmp;
|
||||
break;
|
||||
}
|
||||
case TypeAlias_kind: {
|
||||
|
@ -2776,6 +2791,26 @@ _Py_SymtableStringObjectFlags(const char *str, PyObject *filename,
|
|||
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 *
|
||||
_Py_Mangle(PyObject *privateobj, PyObject *ident)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue