gh-121404: pass metadata to compiler_enter_scope (optionally) so that codegen functions don't need to set it on the code unit (#123078)

This commit is contained in:
Irit Katriel 2024-08-19 11:49:42 +01:00 committed by GitHub
parent b9e10d1a0f
commit e077b201f4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1057,7 +1057,8 @@ codegen_addop_j(instr_sequence *seq, location loc,
static int
compiler_enter_scope(struct compiler *c, identifier name, int scope_type,
void *key, int lineno, PyObject *private)
void *key, int lineno, PyObject *private,
_PyCompile_CodeUnitMetadata *umd)
{
location loc = LOCATION(lineno, lineno, 0, 0);
@ -1069,9 +1070,14 @@ compiler_enter_scope(struct compiler *c, identifier name, int scope_type,
return ERROR;
}
u->u_scope_type = scope_type;
u->u_metadata.u_argcount = 0;
u->u_metadata.u_posonlyargcount = 0;
u->u_metadata.u_kwonlyargcount = 0;
if (umd != NULL) {
u->u_metadata = *umd;
}
else {
u->u_metadata.u_argcount = 0;
u->u_metadata.u_posonlyargcount = 0;
u->u_metadata.u_kwonlyargcount = 0;
}
u->u_ste = _PySymtable_Lookup(c->c_st, key);
if (!u->u_ste) {
compiler_unit_free(u);
@ -1441,14 +1447,19 @@ compiler_unwind_fblock_stack(struct compiler *c, location *ploc,
}
static int
compiler_setup_annotations_scope(struct compiler *c, location loc,
void *key, PyObject *name)
codegen_setup_annotations_scope(struct compiler *c, location loc,
void *key, PyObject *name)
{
if (compiler_enter_scope(c, name, COMPILER_SCOPE_ANNOTATIONS,
key, loc.lineno, NULL) == -1) {
return ERROR;
}
c->u->u_metadata.u_posonlyargcount = 1;
_PyCompile_CodeUnitMetadata umd = {
.u_posonlyargcount = 1,
};
RETURN_IF_ERROR(
compiler_enter_scope(c, name, COMPILER_SCOPE_ANNOTATIONS,
key, loc.lineno, NULL, &umd));
assert(c->u->u_metadata.u_posonlyargcount == 1);
assert(c->u->u_metadata.u_argcount == 0);
assert(c->u->u_metadata.u_kwonlyargcount == 0);
// if .format != 1: raise NotImplementedError
_Py_DECLARE_STR(format, ".format");
ADDOP_I(c, loc, LOAD_FAST, 0);
@ -1463,8 +1474,8 @@ compiler_setup_annotations_scope(struct compiler *c, location loc,
}
static int
compiler_leave_annotations_scope(struct compiler *c, location loc,
Py_ssize_t annotations_len)
codegen_leave_annotations_scope(struct compiler *c, location loc,
Py_ssize_t annotations_len)
{
ADDOP_I(c, loc, BUILD_MAP, annotations_len);
ADDOP_IN_SCOPE(c, loc, RETURN_VALUE);
@ -1534,8 +1545,8 @@ compiler_body(struct compiler *c, location loc, asdl_stmt_seq *stmts)
assert(ste->ste_annotation_block != NULL);
PyObject *deferred_anno = Py_NewRef(c->u->u_deferred_annotations);
void *key = (void *)((uintptr_t)ste->ste_id + 1);
if (compiler_setup_annotations_scope(c, loc, key,
ste->ste_annotation_block->ste_name) == -1) {
if (codegen_setup_annotations_scope(c, loc, key,
ste->ste_annotation_block->ste_name) == -1) {
Py_DECREF(deferred_anno);
return ERROR;
}
@ -1555,7 +1566,7 @@ compiler_body(struct compiler *c, location loc, asdl_stmt_seq *stmts)
Py_DECREF(deferred_anno);
RETURN_IF_ERROR(
compiler_leave_annotations_scope(c, loc, annotations_len)
codegen_leave_annotations_scope(c, loc, annotations_len)
);
RETURN_IF_ERROR(
compiler_nameop(c, loc, &_Py_ID(__annotate__), Store)
@ -1618,7 +1629,7 @@ compiler_enter_anonymous_scope(struct compiler* c, mod_ty mod)
_Py_DECLARE_STR(anon_module, "<module>");
RETURN_IF_ERROR(
compiler_enter_scope(c, &_Py_STR(anon_module), COMPILER_SCOPE_MODULE,
mod, 1, NULL));
mod, 1, NULL, NULL));
return SUCCESS;
}
@ -1828,7 +1839,7 @@ compiler_visit_annexpr(struct compiler *c, expr_ty annotation)
}
static int
compiler_argannotation(struct compiler *c, identifier id,
codegen_argannotation(struct compiler *c, identifier id,
expr_ty annotation, Py_ssize_t *annotations_len, location loc)
{
if (!annotation) {
@ -1862,14 +1873,14 @@ compiler_argannotation(struct compiler *c, identifier id,
}
static int
compiler_argannotations(struct compiler *c, asdl_arg_seq* args,
Py_ssize_t *annotations_len, location loc)
codegen_argannotations(struct compiler *c, asdl_arg_seq* args,
Py_ssize_t *annotations_len, location loc)
{
int i;
for (i = 0; i < asdl_seq_LEN(args); i++) {
arg_ty arg = (arg_ty)asdl_seq_GET(args, i);
RETURN_IF_ERROR(
compiler_argannotation(
codegen_argannotation(
c,
arg->arg,
arg->annotation,
@ -1880,40 +1891,40 @@ compiler_argannotations(struct compiler *c, asdl_arg_seq* args,
}
static int
compiler_annotations_in_scope(struct compiler *c, location loc,
arguments_ty args, expr_ty returns,
Py_ssize_t *annotations_len)
codegen_annotations_in_scope(struct compiler *c, location loc,
arguments_ty args, expr_ty returns,
Py_ssize_t *annotations_len)
{
RETURN_IF_ERROR(
compiler_argannotations(c, args->args, annotations_len, loc));
codegen_argannotations(c, args->args, annotations_len, loc));
RETURN_IF_ERROR(
compiler_argannotations(c, args->posonlyargs, annotations_len, loc));
codegen_argannotations(c, args->posonlyargs, annotations_len, loc));
if (args->vararg && args->vararg->annotation) {
RETURN_IF_ERROR(
compiler_argannotation(c, args->vararg->arg,
args->vararg->annotation, annotations_len, loc));
codegen_argannotation(c, args->vararg->arg,
args->vararg->annotation, annotations_len, loc));
}
RETURN_IF_ERROR(
compiler_argannotations(c, args->kwonlyargs, annotations_len, loc));
codegen_argannotations(c, args->kwonlyargs, annotations_len, loc));
if (args->kwarg && args->kwarg->annotation) {
RETURN_IF_ERROR(
compiler_argannotation(c, args->kwarg->arg,
args->kwarg->annotation, annotations_len, loc));
codegen_argannotation(c, args->kwarg->arg,
args->kwarg->annotation, annotations_len, loc));
}
RETURN_IF_ERROR(
compiler_argannotation(c, &_Py_ID(return), returns, annotations_len, loc));
codegen_argannotation(c, &_Py_ID(return), returns, annotations_len, loc));
return 0;
}
static int
compiler_annotations(struct compiler *c, location loc,
arguments_ty args, expr_ty returns)
codegen_annotations(struct compiler *c, location loc,
arguments_ty args, expr_ty returns)
{
/* Push arg annotation names and values.
The expressions are evaluated separately from the rest of the source code.
@ -1930,15 +1941,15 @@ compiler_annotations(struct compiler *c, location loc,
bool annotations_used = ste->ste_annotations_used;
if (annotations_used) {
if (compiler_setup_annotations_scope(c, loc, (void *)args,
ste->ste_name) < 0) {
if (codegen_setup_annotations_scope(c, loc, (void *)args,
ste->ste_name) < 0) {
Py_DECREF(ste);
return ERROR;
}
}
Py_DECREF(ste);
if (compiler_annotations_in_scope(c, loc, args, returns, &annotations_len) < 0) {
if (codegen_annotations_in_scope(c, loc, args, returns, &annotations_len) < 0) {
if (annotations_used) {
compiler_exit_scope(c);
}
@ -1947,7 +1958,7 @@ compiler_annotations(struct compiler *c, location loc,
if (annotations_used) {
RETURN_IF_ERROR(
compiler_leave_annotations_scope(c, loc, annotations_len)
codegen_leave_annotations_scope(c, loc, annotations_len)
);
return MAKE_FUNCTION_ANNOTATE;
}
@ -2011,7 +2022,7 @@ compiler_type_param_bound_or_default(struct compiler *c, expr_ty e,
{
PyObject *defaults = PyTuple_Pack(1, _PyLong_GetOne());
ADDOP_LOAD_CONST_NEW(c, LOC(e), defaults);
if (compiler_setup_annotations_scope(c, LOC(e), key, name) == -1) {
if (codegen_setup_annotations_scope(c, LOC(e), key, name) == -1) {
return ERROR;
}
if (allow_starred && e->kind == Starred_kind) {
@ -2155,8 +2166,13 @@ compiler_function_body(struct compiler *c, stmt_ty s, int is_async, Py_ssize_t f
scope_type = COMPILER_SCOPE_FUNCTION;
}
_PyCompile_CodeUnitMetadata umd = {
.u_argcount = asdl_seq_LEN(args->args),
.u_posonlyargcount = asdl_seq_LEN(args->posonlyargs),
.u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs),
};
RETURN_IF_ERROR(
compiler_enter_scope(c, name, scope_type, (void *)s, firstlineno, NULL));
compiler_enter_scope(c, name, scope_type, (void *)s, firstlineno, NULL, &umd));
Py_ssize_t first_instr = 0;
PyObject *docstring = _PyAST_GetDocString(body);
@ -2181,9 +2197,9 @@ compiler_function_body(struct compiler *c, stmt_ty s, int is_async, Py_ssize_t f
}
Py_CLEAR(docstring);
c->u->u_metadata.u_argcount = asdl_seq_LEN(args->args);
c->u->u_metadata.u_posonlyargcount = asdl_seq_LEN(args->posonlyargs);
c->u->u_metadata.u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs);
assert(c->u->u_metadata.u_argcount == asdl_seq_LEN(args->args));
assert(c->u->u_metadata.u_posonlyargcount == asdl_seq_LEN(args->posonlyargs));
assert(c->u->u_metadata.u_kwonlyargcount == asdl_seq_LEN(args->kwonlyargs));
NEW_JUMP_TARGET_LABEL(c, start);
USE_LABEL(c, start);
@ -2222,7 +2238,7 @@ compiler_function_body(struct compiler *c, stmt_ty s, int is_async, Py_ssize_t f
}
static int
compiler_function(struct compiler *c, stmt_ty s, int is_async)
codegen_function(struct compiler *c, stmt_ty s, int is_async)
{
arguments_ty args;
expr_ty returns;
@ -2282,8 +2298,11 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
if (!type_params_name) {
return ERROR;
}
_PyCompile_CodeUnitMetadata umd = {
.u_argcount = num_typeparam_args,
};
if (compiler_enter_scope(c, type_params_name, COMPILER_SCOPE_ANNOTATIONS,
(void *)type_params, firstlineno, NULL) == -1) {
(void *)type_params, firstlineno, NULL, &umd) == -1) {
Py_DECREF(type_params_name);
return ERROR;
}
@ -2294,7 +2313,7 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
}
}
int annotations_flag = compiler_annotations(c, loc, args, returns);
int annotations_flag = codegen_annotations(c, loc, args, returns);
if (annotations_flag < 0) {
if (is_generic) {
compiler_exit_scope(c);
@ -2314,7 +2333,7 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
ADDOP_I_IN_SCOPE(c, loc, SWAP, 2);
ADDOP_I_IN_SCOPE(c, loc, CALL_INTRINSIC_2, INTRINSIC_SET_FUNCTION_TYPE_PARAMS);
c->u->u_metadata.u_argcount = num_typeparam_args;
assert(c->u->u_metadata.u_argcount == num_typeparam_args);
PyCodeObject *co = optimize_and_assemble(c, 0);
compiler_exit_scope(c);
if (co == NULL) {
@ -2365,7 +2384,7 @@ compiler_class_body(struct compiler *c, stmt_ty s, int firstlineno)
/* 1. compile the class body into a code object */
RETURN_IF_ERROR(
compiler_enter_scope(c, s->v.ClassDef.name, COMPILER_SCOPE_CLASS,
(void *)s, firstlineno, s->v.ClassDef.name));
(void *)s, firstlineno, s->v.ClassDef.name, NULL));
location loc = LOCATION(firstlineno, firstlineno, 0, 0);
/* load (global) __name__ ... */
@ -2508,7 +2527,7 @@ compiler_class(struct compiler *c, stmt_ty s)
return ERROR;
}
if (compiler_enter_scope(c, type_params_name, COMPILER_SCOPE_ANNOTATIONS,
(void *)type_params, firstlineno, s->v.ClassDef.name) == -1) {
(void *)type_params, firstlineno, s->v.ClassDef.name, NULL) == -1) {
Py_DECREF(type_params_name);
return ERROR;
}
@ -2592,7 +2611,7 @@ compiler_typealias_body(struct compiler *c, stmt_ty s)
PyObject *defaults = PyTuple_Pack(1, _PyLong_GetOne());
ADDOP_LOAD_CONST_NEW(c, loc, defaults);
RETURN_IF_ERROR(
compiler_setup_annotations_scope(c, LOC(s), s, name));
codegen_setup_annotations_scope(c, LOC(s), s, name));
/* Make None the first constant, so the evaluate function can't have a
docstring. */
RETURN_IF_ERROR(compiler_add_const(c, Py_None));
@ -2627,7 +2646,7 @@ compiler_typealias(struct compiler *c, stmt_ty s)
return ERROR;
}
if (compiler_enter_scope(c, type_params_name, COMPILER_SCOPE_ANNOTATIONS,
(void *)type_params, loc.lineno, NULL) == -1) {
(void *)type_params, loc.lineno, NULL, NULL) == -1) {
Py_DECREF(type_params_name);
return ERROR;
}
@ -2889,18 +2908,23 @@ compiler_lambda(struct compiler *c, expr_ty e)
return ERROR;
}
_PyCompile_CodeUnitMetadata umd = {
.u_argcount = asdl_seq_LEN(args->args),
.u_posonlyargcount = asdl_seq_LEN(args->posonlyargs),
.u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs),
};
_Py_DECLARE_STR(anon_lambda, "<lambda>");
RETURN_IF_ERROR(
compiler_enter_scope(c, &_Py_STR(anon_lambda), COMPILER_SCOPE_LAMBDA,
(void *)e, e->lineno, NULL));
(void *)e, e->lineno, NULL, &umd));
/* Make None the first constant, so the lambda can't have a
docstring. */
RETURN_IF_ERROR(compiler_add_const(c, Py_None));
c->u->u_metadata.u_argcount = asdl_seq_LEN(args->args);
c->u->u_metadata.u_posonlyargcount = asdl_seq_LEN(args->posonlyargs);
c->u->u_metadata.u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs);
assert(c->u->u_metadata.u_argcount == asdl_seq_LEN(args->args));
assert(c->u->u_metadata.u_posonlyargcount == asdl_seq_LEN(args->posonlyargs));
assert(c->u->u_metadata.u_kwonlyargcount == asdl_seq_LEN(args->kwonlyargs));
VISIT_IN_SCOPE(c, expr, e->v.Lambda.body);
if (SYMTABLE_ENTRY(c)->ste_generator) {
co = optimize_and_assemble(c, 0);
@ -3867,7 +3891,7 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)
switch (s->kind) {
case FunctionDef_kind:
return compiler_function(c, s, 0);
return codegen_function(c, s, 0);
case ClassDef_kind:
return compiler_class(c, s);
case TypeAlias_kind:
@ -3949,7 +3973,7 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)
case With_kind:
return compiler_with(c, s, 0);
case AsyncFunctionDef_kind:
return compiler_function(c, s, 1);
return codegen_function(c, s, 1);
case AsyncWith_kind:
return compiler_async_with(c, s, 0);
case AsyncFor_kind:
@ -5674,7 +5698,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type,
}
else {
if (compiler_enter_scope(c, name, COMPILER_SCOPE_COMPREHENSION,
(void *)e, e->lineno, NULL) < 0) {
(void *)e, e->lineno, NULL, NULL) < 0) {
goto error;
}
}