Repository navigation
gh-119395: Fix leaky mangling after generic classes #119399
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| Fix bug where any names appearing after a generic class were mangled as if | ||
| they were part of the generic class. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2624,6 +2624,7 @@ 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; | ||
| PyObject *old_u_private = Py_XNewRef(c->u->u_private); | ||
| if (is_generic) { | ||
| Py_XSETREF(c->u->u_private, Py_NewRef(s->v.ClassDef.name)); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The save-restore pattern is not needed or used in Setting it on the outer compiler unit works here, because If we move this line down to after |
||
| PyObject *type_params_name = PyUnicode_FromFormat("<generic parameters of %U>", | ||
|
|
@@ -2701,6 +2702,7 @@ compiler_class(struct compiler *c, stmt_ty s) | |
| s->v.ClassDef.bases, | ||
| s->v.ClassDef.keywords)); | ||
| } | ||
| Py_XSETREF(c->u->u_private, old_u_private); | ||
|
|
||
| /* 6. apply decorators */ | ||
| RETURN_IF_ERROR(compiler_apply_decorators(c, decos)); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1508,7 +1508,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, | ||
|
|
@@ -1673,13 +1672,15 @@ 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); | ||
| PyObject *old_st_private = st->st_private; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't care too much either way, but I think it would be equivalent and simpler to move the existing pair of lines up to right here. We want to unconditionally set it to the same thing either way. If it's a problem to have
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| 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, | ||
| false, false, s->kind, | ||
| LOCATION(s))) { | ||
| VISIT_QUIT(st, 0); | ||
| } | ||
| st->st_private = s->v.ClassDef.name; | ||
| VISIT_SEQ(st, type_param, s->v.ClassDef.type_params); | ||
| } | ||
| VISIT_SEQ(st, expr, s->v.ClassDef.bases); | ||
|
|
@@ -1709,6 +1710,7 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s) | |
| if (!symtable_exit_block(st)) | ||
| VISIT_QUIT(st, 0); | ||
| } | ||
| st->st_private = old_st_private; | ||
| break; | ||
| } | ||
| case TypeAlias_kind: { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it a good idea to test
__before = "class"; __after = "class"names in the class scope here? Or do we have them tested?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean in the inner class? That wouldn't really be relevant here since there is nothing else interesting going on in the inner class body.