Skip to content

Commit 6cff874

Browse files
author
Guido van Rossum
committed
Issue python#27999: Make "global after use" a SyntaxError, and ditto for nonlocal.
Patch by Ivan Levkivskyi.
1 parent 95e502e commit 6cff874

4 files changed

Lines changed: 59 additions & 71 deletions

File tree

Doc/reference/simple_stmts.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -903,11 +903,12 @@ block textually preceding that :keyword:`global` statement.
903903

904904
Names listed in a :keyword:`global` statement must not be defined as formal
905905
parameters or in a :keyword:`for` loop control target, :keyword:`class`
906-
definition, function definition, or :keyword:`import` statement.
906+
definition, function definition, :keyword:`import` statement, or variable
907+
annotation.
907908

908909
.. impl-detail::
909910

910-
The current implementation does not enforce the two restrictions, but
911+
The current implementation does not enforce some of these restriction, but
911912
programs should not abuse this freedom, as future implementations may enforce
912913
them or silently change the meaning of the program.
913914

Lib/test/test_syntax.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,23 @@
366366
...
367367
SyntaxError: too many statically nested blocks
368368
369-
Misuse of the nonlocal statement can lead to a few unique syntax errors.
369+
Misuse of the nonlocal and global statement can lead to a few unique syntax errors.
370+
371+
>>> def f():
372+
... x = 1
373+
... global x
374+
Traceback (most recent call last):
375+
...
376+
SyntaxError: name 'x' is assigned to before global declaration
377+
378+
>>> def f():
379+
... x = 1
380+
... def g():
381+
... print(x)
382+
... nonlocal x
383+
Traceback (most recent call last):
384+
...
385+
SyntaxError: name 'x' is used prior to nonlocal declaration
370386
371387
>>> def f(x):
372388
... nonlocal x

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ What's New in Python 3.6.0 beta 1
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #27999: Make "global after use" a SyntaxError, and ditto for nonlocal.
14+
Patch by Ivan Levkivskyi.
15+
1316
- Issue #28003: Implement PEP 525 -- Asynchronous Generators.
1417

1518
- Issue #27985: Implement PEP 526 -- Syntax for Variable Annotations.

Python/symtable.c

Lines changed: 36 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,22 @@
66

77
/* error strings used for warnings */
88
#define GLOBAL_AFTER_ASSIGN \
9-
"name '%.400s' is assigned to before global declaration"
9+
"name '%U' is assigned to before global declaration"
1010

1111
#define NONLOCAL_AFTER_ASSIGN \
12-
"name '%.400s' is assigned to before nonlocal declaration"
12+
"name '%U' is assigned to before nonlocal declaration"
1313

1414
#define GLOBAL_AFTER_USE \
15-
"name '%.400s' is used prior to global declaration"
15+
"name '%U' is used prior to global declaration"
1616

1717
#define NONLOCAL_AFTER_USE \
18-
"name '%.400s' is used prior to nonlocal declaration"
18+
"name '%U' is used prior to nonlocal declaration"
19+
20+
#define GLOBAL_ANNOT \
21+
"annotated name '%U' can't be global"
22+
23+
#define NONLOCAL_ANNOT \
24+
"annotated name '%U' can't be nonlocal"
1925

2026
#define IMPORT_STAR_WARNING "import * only allowed at module level"
2127

@@ -161,7 +167,6 @@ PyTypeObject PySTEntry_Type = {
161167
};
162168

163169
static int symtable_analyze(struct symtable *st);
164-
static int symtable_warn(struct symtable *st, const char *msg, int lineno);
165170
static int symtable_enter_block(struct symtable *st, identifier name,
166171
_Py_block_ty block, void *ast, int lineno,
167172
int col_offset);
@@ -907,27 +912,6 @@ symtable_analyze(struct symtable *st)
907912
return r;
908913
}
909914

910-
911-
static int
912-
symtable_warn(struct symtable *st, const char *msg, int lineno)
913-
{
914-
PyObject *message = PyUnicode_FromString(msg);
915-
if (message == NULL)
916-
return 0;
917-
if (PyErr_WarnExplicitObject(PyExc_SyntaxWarning, message, st->st_filename,
918-
lineno, NULL, NULL) < 0) {
919-
Py_DECREF(message);
920-
if (PyErr_ExceptionMatches(PyExc_SyntaxWarning)) {
921-
PyErr_SetString(PyExc_SyntaxError, msg);
922-
PyErr_SyntaxLocationObject(st->st_filename, st->st_cur->ste_lineno,
923-
st->st_cur->ste_col_offset);
924-
}
925-
return 0;
926-
}
927-
Py_DECREF(message);
928-
return 1;
929-
}
930-
931915
/* symtable_enter_block() gets a reference via ste_new.
932916
This reference is released when the block is exited, via the DECREF
933917
in symtable_exit_block().
@@ -1212,9 +1196,8 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
12121196
if ((cur & (DEF_GLOBAL | DEF_NONLOCAL))
12131197
&& s->v.AnnAssign.simple) {
12141198
PyErr_Format(PyExc_SyntaxError,
1215-
"annotated name '%U' can't be %s",
1216-
e_name->v.Name.id,
1217-
cur & DEF_GLOBAL ? "global" : "nonlocal");
1199+
cur & DEF_GLOBAL ? GLOBAL_ANNOT : NONLOCAL_ANNOT,
1200+
e_name->v.Name.id);
12181201
PyErr_SyntaxLocationObject(st->st_filename,
12191202
s->lineno,
12201203
s->col_offset);
@@ -1297,31 +1280,24 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
12971280
long cur = symtable_lookup(st, name);
12981281
if (cur < 0)
12991282
VISIT_QUIT(st, 0);
1300-
if (cur & DEF_ANNOT) {
1283+
if (cur & (DEF_LOCAL | USE | DEF_ANNOT)) {
1284+
char* msg;
1285+
if (cur & DEF_ANNOT) {
1286+
msg = GLOBAL_ANNOT;
1287+
}
1288+
if (cur & DEF_LOCAL) {
1289+
msg = GLOBAL_AFTER_ASSIGN;
1290+
}
1291+
else {
1292+
msg = GLOBAL_AFTER_USE;
1293+
}
13011294
PyErr_Format(PyExc_SyntaxError,
1302-
"annotated name '%U' can't be global",
1303-
name);
1295+
msg, name);
13041296
PyErr_SyntaxLocationObject(st->st_filename,
13051297
s->lineno,
13061298
s->col_offset);
13071299
VISIT_QUIT(st, 0);
13081300
}
1309-
if (cur & (DEF_LOCAL | USE)) {
1310-
char buf[256];
1311-
char *c_name = _PyUnicode_AsString(name);
1312-
if (!c_name)
1313-
return 0;
1314-
if (cur & DEF_LOCAL)
1315-
PyOS_snprintf(buf, sizeof(buf),
1316-
GLOBAL_AFTER_ASSIGN,
1317-
c_name);
1318-
else
1319-
PyOS_snprintf(buf, sizeof(buf),
1320-
GLOBAL_AFTER_USE,
1321-
c_name);
1322-
if (!symtable_warn(st, buf, s->lineno))
1323-
VISIT_QUIT(st, 0);
1324-
}
13251301
if (!symtable_add_def(st, name, DEF_GLOBAL))
13261302
VISIT_QUIT(st, 0);
13271303
if (!symtable_record_directive(st, name, s))
@@ -1337,31 +1313,23 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
13371313
long cur = symtable_lookup(st, name);
13381314
if (cur < 0)
13391315
VISIT_QUIT(st, 0);
1340-
if (cur & DEF_ANNOT) {
1341-
PyErr_Format(PyExc_SyntaxError,
1342-
"annotated name '%U' can't be nonlocal",
1343-
name);
1316+
if (cur & (DEF_LOCAL | USE | DEF_ANNOT)) {
1317+
char* msg;
1318+
if (cur & DEF_ANNOT) {
1319+
msg = NONLOCAL_ANNOT;
1320+
}
1321+
if (cur & DEF_LOCAL) {
1322+
msg = NONLOCAL_AFTER_ASSIGN;
1323+
}
1324+
else {
1325+
msg = NONLOCAL_AFTER_USE;
1326+
}
1327+
PyErr_Format(PyExc_SyntaxError, msg, name);
13441328
PyErr_SyntaxLocationObject(st->st_filename,
13451329
s->lineno,
13461330
s->col_offset);
13471331
VISIT_QUIT(st, 0);
13481332
}
1349-
if (cur & (DEF_LOCAL | USE)) {
1350-
char buf[256];
1351-
char *c_name = _PyUnicode_AsString(name);
1352-
if (!c_name)
1353-
return 0;
1354-
if (cur & DEF_LOCAL)
1355-
PyOS_snprintf(buf, sizeof(buf),
1356-
NONLOCAL_AFTER_ASSIGN,
1357-
c_name);
1358-
else
1359-
PyOS_snprintf(buf, sizeof(buf),
1360-
NONLOCAL_AFTER_USE,
1361-
c_name);
1362-
if (!symtable_warn(st, buf, s->lineno))
1363-
VISIT_QUIT(st, 0);
1364-
}
13651333
if (!symtable_add_def(st, name, DEF_NONLOCAL))
13661334
VISIT_QUIT(st, 0);
13671335
if (!symtable_record_directive(st, name, s))

0 commit comments

Comments
 (0)