Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4d508ad

Browse files
committed
Fix for SF [ 734869 ] Lambda functions in list comprehensions
The compiler was reseting the list comprehension tmpname counter for each function, but the symtable was using the same counter for the entire module. Repair by move tmpname into the symtable entry. Bugfix candidate.
1 parent 6624e68 commit 4d508ad

5 files changed

Lines changed: 27 additions & 15 deletions

File tree

Include/symtable.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ struct symtable {
2828
int st_nscopes; /* number of scopes */
2929
int st_errors; /* number of errors */
3030
char *st_private; /* name of current class or NULL */
31-
int st_tmpname; /* temporary name counter */
3231
PyFutureFeatures *st_future; /* module's future features */
3332
};
3433

@@ -47,6 +46,7 @@ typedef struct _symtable_entry {
4746
including free refs to globals */
4847
int ste_generator; /* true if namespace is a generator */
4948
int ste_opt_lineno; /* lineno of last exec or import * */
49+
int ste_tmpname; /* temporary name counter */
5050
struct symtable *ste_table;
5151
} PySymtableEntryObject;
5252

Lib/test/output/test_grammar

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ classdef
6060
[3, 4, 5]
6161
[(1, 'Apple'), (1, 'Banana'), (1, 'Coconut'), (2, 'Apple'), (2, 'Banana'), (2, 'Coconut'), (3, 'Apple'), (3, 'Banana'), (3, 'Coconut'), (4, 'Apple'), (4, 'Banana'), (4, 'Coconut'), (5, 'Apple'), (5, 'Banana'), (5, 'Coconut')]
6262
[(1, 'Banana'), (1, 'Coconut'), (2, 'Banana'), (2, 'Coconut'), (3, 'Banana'), (3, 'Coconut'), (4, 'Banana'), (4, 'Coconut'), (5, 'Banana'), (5, 'Coconut')]
63+
[[1], [1, 1], [1, 2, 4], [1, 3, 9, 27], [1, 4, 16, 64, 256]]
6364
[False, False, False]
6465
[[1, 2], [3, 4], [5, 6]]
6566
[('Boeing', 'Airliner'), ('Boeing', 'Engine'), ('Ford', 'Engine'), ('Macdonalds', 'Cheeseburger')]

Lib/test/test_grammar.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,7 @@ def meth3(self, a1, a2): pass
701701
print [x for x in nums if x > 2]
702702
print [(i, s) for i in nums for s in strs]
703703
print [(i, s) for i in nums for s in [f for f in strs if "n" in f]]
704+
print [(lambda a:[a**i for i in range(a+1)])(j) for j in range(5)]
704705

705706
def test_in_func(l):
706707
return [None < x < 3 for x in l if x > 2]

Python/compile.c

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,7 @@ static void symtable_global(struct symtable *, node *);
731731
static void symtable_import(struct symtable *, node *);
732732
static void symtable_assign(struct symtable *, node *, int);
733733
static void symtable_list_comprehension(struct symtable *, node *);
734+
static void symtable_list_for(struct symtable *, node *);
734735

735736
static int symtable_update_free_vars(struct symtable *);
736737
static int symtable_undo_free(struct symtable *, PyObject *, PyObject *);
@@ -1602,6 +1603,8 @@ com_list_comprehension(struct compiling *c, node *n)
16021603
{
16031604
/* listmaker: test list_for */
16041605
char tmpname[30];
1606+
1607+
REQ(n, listmaker);
16051608
PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", ++c->c_tmpname);
16061609
com_addoparg(c, BUILD_LIST, 0);
16071610
com_addbyte(c, DUP_TOP); /* leave the result on the stack */
@@ -4921,7 +4924,6 @@ symtable_init()
49214924
st->st_cur = NULL;
49224925
st->st_nscopes = 0;
49234926
st->st_errors = 0;
4924-
st->st_tmpname = 0;
49254927
st->st_private = NULL;
49264928
return st;
49274929
fail:
@@ -5123,9 +5125,6 @@ symtable_enter_scope(struct symtable *st, char *name, int type,
51235125
if (st->st_cur) {
51245126
prev = st->st_cur;
51255127
if (PyList_Append(st->st_stack, (PyObject *)st->st_cur) < 0) {
5126-
/* Py_DECREF(st->st_cur); */
5127-
/* I believe the previous line would lead to a
5128-
double-DECREF when st is disposed - JRH */
51295128
st->st_errors++;
51305129
return;
51315130
}
@@ -5395,12 +5394,12 @@ symtable_node(struct symtable *st, node *n)
53955394
}
53965395
goto loop;
53975396
case list_iter:
5397+
/* only occurs when there are multiple for loops
5398+
in a list comprehension */
53985399
n = CHILD(n, 0);
5399-
if (TYPE(n) == list_for) {
5400-
st->st_tmpname++;
5401-
symtable_list_comprehension(st, n);
5402-
st->st_tmpname--;
5403-
} else {
5400+
if (TYPE(n) == list_for)
5401+
symtable_list_for(st, n);
5402+
else {
54045403
REQ(n, list_if);
54055404
symtable_node(st, CHILD(n, 1));
54065405
if (NCH(n) == 3) {
@@ -5428,10 +5427,7 @@ symtable_node(struct symtable *st, node *n)
54285427
/* fall through */
54295428
case listmaker:
54305429
if (NCH(n) > 1 && TYPE(CHILD(n, 1)) == list_for) {
5431-
st->st_tmpname++;
5432-
symtable_list_comprehension(st, CHILD(n, 1));
5433-
symtable_node(st, CHILD(n, 0));
5434-
st->st_tmpname--;
5430+
symtable_list_comprehension(st, n);
54355431
break;
54365432
}
54375433
/* fall through */
@@ -5629,10 +5625,23 @@ symtable_global(struct symtable *st, node *n)
56295625
static void
56305626
symtable_list_comprehension(struct symtable *st, node *n)
56315627
{
5628+
/* listmaker: test list_for */
56325629
char tmpname[30];
56335630

5634-
PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", st->st_tmpname);
5631+
REQ(n, listmaker);
5632+
PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]",
5633+
++st->st_cur->ste_tmpname);
56355634
symtable_add_def(st, tmpname, DEF_LOCAL);
5635+
symtable_list_for(st, CHILD(n, 1));
5636+
symtable_node(st, CHILD(n, 0));
5637+
--st->st_cur->ste_tmpname;
5638+
}
5639+
5640+
static void
5641+
symtable_list_for(struct symtable *st, node *n)
5642+
{
5643+
REQ(n, list_for);
5644+
/* list_for: for v in expr [list_iter] */
56365645
symtable_assign(st, CHILD(n, 1), 0);
56375646
symtable_node(st, CHILD(n, 3));
56385647
if (NCH(n) == 5)

Python/symtable.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ PySymtableEntry_New(struct symtable *st, char *name, int type, int lineno)
6161

6262
ste->ste_optimized = 0;
6363
ste->ste_opt_lineno = 0;
64+
ste->ste_tmpname = 0;
6465
ste->ste_lineno = lineno;
6566
switch (type) {
6667
case funcdef:

0 commit comments

Comments
 (0)