Skip to content

Commit 723e0de

Browse files
authored
Merge pull request #45 from Eddy114514/listcomp_new
Add Py3k warning for list comprehension target rebinding and regression test
2 parents f029068 + fe9a868 commit 723e0de

2 files changed

Lines changed: 65 additions & 0 deletions

File tree

Lib/test/test_grammar.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,9 @@ def foo(): print([x for x in [1, 2, 2]])
10701070
with warnings.catch_warnings(record=True) as w:
10711071
warnings.filterwarnings('always', category=Py3xWarning)
10721072
def foo(): x = 0; [x for x in [1, 2, 2]]; print(x)
1073+
with check_py3k_warnings(
1074+
("list comprehension rebinds name 'x'", Py3xWarning)):
1075+
exec "x = 'outer'; ys = [x for x in range(3)]\n" in {}
10731076
def foo(): x = 0; print(x); [x for x in [1, 2, 2]]
10741077
def foo():
10751078
x = 0

Python/symtable.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ static int symtable_visit_alias(struct symtable *st, alias_ty);
179179
static int symtable_visit_comprehension(struct symtable *st, comprehension_ty);
180180
static int symtable_visit_keyword(struct symtable *st, keyword_ty);
181181
static int symtable_visit_slice(struct symtable *st, slice_ty);
182+
static int symtable_warn_listcomp_target(struct symtable *st, expr_ty target,
183+
int lineno);
184+
static int symtable_warn_listcomp_shadowing(struct symtable *st, expr_ty e);
182185
static int symtable_visit_params(struct symtable *st, asdl_seq *args, int top);
183186
static int symtable_visit_params_nested(struct symtable *st, asdl_seq *args);
184187
static int symtable_implicit_arg(struct symtable *st, int pos);
@@ -1483,6 +1486,61 @@ symtable_visit_slice(struct symtable *st, slice_ty s)
14831486
return 1;
14841487
}
14851488

1489+
static int
1490+
symtable_warn_listcomp_target(struct symtable *st, expr_ty target, int lineno)
1491+
{
1492+
switch (target->kind) {
1493+
case Name_kind: {
1494+
long flags = symtable_lookup(st, target->v.Name.id);
1495+
if (flags & (DEF_BOUND | DEF_GLOBAL)) {
1496+
char buf[256];
1497+
PyOS_snprintf(buf, sizeof(buf),
1498+
"list comprehension rebinds name '%.100s'; "
1499+
"in 3.x the name is not rebound",
1500+
PyString_AS_STRING(target->v.Name.id));
1501+
if (!symtable_warn(st, PyExc_Py3xWarning, buf, lineno))
1502+
return 0;
1503+
}
1504+
break;
1505+
}
1506+
case Tuple_kind: {
1507+
int i;
1508+
for (i = 0; i < asdl_seq_LEN(target->v.Tuple.elts); i++) {
1509+
expr_ty elt = (expr_ty)asdl_seq_GET(target->v.Tuple.elts, i);
1510+
if (!symtable_warn_listcomp_target(st, elt, lineno))
1511+
return 0;
1512+
}
1513+
break;
1514+
}
1515+
case List_kind: {
1516+
int i;
1517+
for (i = 0; i < asdl_seq_LEN(target->v.List.elts); i++) {
1518+
expr_ty elt = (expr_ty)asdl_seq_GET(target->v.List.elts, i);
1519+
if (!symtable_warn_listcomp_target(st, elt, lineno))
1520+
return 0;
1521+
}
1522+
break;
1523+
}
1524+
default:
1525+
break;
1526+
}
1527+
return 1;
1528+
}
1529+
1530+
static int
1531+
symtable_warn_listcomp_shadowing(struct symtable *st, expr_ty e)
1532+
{
1533+
int i;
1534+
asdl_seq *generators = e->v.ListComp.generators;
1535+
1536+
for (i = 0; i < asdl_seq_LEN(generators); i++) {
1537+
comprehension_ty lc = (comprehension_ty)asdl_seq_GET(generators, i);
1538+
if (!symtable_warn_listcomp_target(st, lc->target, e->lineno))
1539+
return 0;
1540+
}
1541+
return 1;
1542+
}
1543+
14861544
static int
14871545
symtable_new_tmpname(struct symtable *st)
14881546
{
@@ -1556,6 +1614,10 @@ symtable_visit_listcomp(struct symtable *st, expr_ty e)
15561614
{
15571615
asdl_seq *generators = e->v.ListComp.generators;
15581616
int i, is_generator;
1617+
1618+
if (Py_Py3kWarningFlag && !symtable_warn_listcomp_shadowing(st, e))
1619+
return 0;
1620+
15591621
/* In order to check for yield expressions under '-3', we clear
15601622
the generator flag, and restore it at the end */
15611623
is_generator = st->st_cur->ste_generator;

0 commit comments

Comments
 (0)