diff --git a/Include/internal/pycore_symtable.h b/Include/internal/pycore_symtable.h index f109a7229c35df..b3eb2e12ddd2c9 100644 --- a/Include/internal/pycore_symtable.h +++ b/Include/internal/pycore_symtable.h @@ -72,6 +72,7 @@ struct symtable { the symbol table */ int recursion_depth; /* current recursion depth */ int recursion_limit; /* recursion limit */ + int st_kind; /* kind of module */ }; typedef struct _symtable_entry { diff --git a/Python/compile.c b/Python/compile.c index 381f3eb4b2a486..f888aba177e7d8 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1653,7 +1653,7 @@ compiler_setup_annotations_scope(struct compiler *c, location loc, static int compiler_leave_annotations_scope(struct compiler *c, location loc, - int annotations_len, jump_target_label label) + Py_ssize_t annotations_len, jump_target_label label) { ADDOP_I(c, loc, BUILD_MAP, annotations_len); ADDOP_IN_SCOPE(c, loc, RETURN_VALUE); @@ -6595,6 +6595,23 @@ check_ann_expr(struct compiler *c, expr_ty e) return SUCCESS; } +static int +check_annotation(struct compiler *c, stmt_ty s) +{ + /* Annotations of complex targets does not produce anything + under annotations future */ + if (c->c_future.ff_features & CO_FUTURE_ANNOTATIONS) { + return SUCCESS; + } + + /* Annotations are only evaluated in a module or class. */ + if (c->u->u_scope_type == COMPILER_SCOPE_MODULE || + c->u->u_scope_type == COMPILER_SCOPE_CLASS) { + return check_ann_expr(c, s->v.AnnAssign.annotation); + } + return SUCCESS; +} + static int check_ann_subscr(struct compiler *c, expr_ty e) { @@ -6630,7 +6647,11 @@ compiler_annassign(struct compiler *c, stmt_ty s) { location loc = LOC(s); expr_ty targ = s->v.AnnAssign.target; - PyObject* mangled; + bool is_interactive = ( + c->c_st->st_kind == Interactive_kind && c->u->u_scope_type == COMPILER_SCOPE_MODULE + ); + bool future_annotations = c->c_future.ff_features & CO_FUTURE_ANNOTATIONS; + PyObject *mangled; assert(s->kind == AnnAssign_kind); @@ -6645,11 +6666,16 @@ compiler_annassign(struct compiler *c, stmt_ty s) return ERROR; } /* If we have a simple name in a module or class, store annotation. */ - if ((c->c_future.ff_features & CO_FUTURE_ANNOTATIONS) && + if ((future_annotations || is_interactive) && s->v.AnnAssign.simple && (c->u->u_scope_type == COMPILER_SCOPE_MODULE || c->u->u_scope_type == COMPILER_SCOPE_CLASS)) { - VISIT(c, annexpr, s->v.AnnAssign.annotation); + if (future_annotations) { + VISIT(c, annexpr, s->v.AnnAssign.annotation); + } + else { + 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); ADDOP_LOAD_CONST_NEW(c, loc, mangled); @@ -6678,7 +6704,10 @@ compiler_annassign(struct compiler *c, stmt_ty s) targ->kind); return ERROR; } - /* For non-simple AnnAssign, the annotation is not evaluated. */ + /* Annotation is evaluated last. */ + if ((future_annotations || is_interactive) && !s->v.AnnAssign.simple && check_annotation(c, s) < 0) { + return ERROR; + } return SUCCESS; } diff --git a/Python/symtable.c b/Python/symtable.c index 9b7b09dfe68ade..a10e77e5738a9b 100644 --- a/Python/symtable.c +++ b/Python/symtable.c @@ -427,6 +427,7 @@ _PySymtable_Build(mod_ty mod, PyObject *filename, _PyFutureFeatures *future) } st->st_top = st->st_cur; + st->st_kind = mod->kind; switch (mod->kind) { case Module_kind: seq = mod->v.Module.body; @@ -2471,13 +2472,16 @@ symtable_visit_annotation(struct symtable *st, expr_ty annotation, struct _symtable_entry *parent_ste, void *key) { int future_annotations = st->st_future->ff_features & CO_FUTURE_ANNOTATIONS; + int is_top_level_interactive = ( + st->st_kind == Interactive_kind && st->st_cur->ste_type == ModuleBlock + ); if (future_annotations) { if(!symtable_enter_block(st, &_Py_ID(_annotation), AnnotationBlock, key, LOCATION(annotation))) { VISIT_QUIT(st, 0); } } - else { + else if (!is_top_level_interactive) { if (st->st_cur->ste_annotation_block == NULL) { PyObject *annotations_name = PyUnicode_FromFormat( "", parent_ste->ste_name); @@ -2518,7 +2522,7 @@ symtable_visit_annotation(struct symtable *st, expr_ty annotation, } } VISIT(st, expr, annotation); - if (!symtable_exit_block(st)) { + if ((future_annotations || !is_top_level_interactive) && !symtable_exit_block(st)) { VISIT_QUIT(st, 0); } return 1;