[Python-Dev] bug in grammar

Guido van Rossum guido@digicool.com
Thu, 18 Jan 2001 11:55:39 -0500


> As part of the implementation of PEP 227 (and in an attempt to reach
> some low-hanging fruit Guido mentioned on the types-sig long ago), I
> have been working on a compiler pass that generates a module-level
> symbol table.  I recently discovered a bug in the handling of list
> comprehensions that was giving me headaches.
> 
> I realize now that the problem is with the current grammar and/or
> compiler.  Here's a simple demonstration; try it in your friendly
> python 2.0 interpreter.
> 
> >>> [i for i in range(10)] = (1, 2, 3)
> Traceback (most recent call last):
>   File "<stdin>", line 1, in ?
> ValueError: unpack list of wrong size
> 
> The generated bytecode is:
> 
>           0 SET_LINENO               0
> 
>           3 SET_LINENO               1
>           6 LOAD_CONST               0 (1)
>           9 LOAD_CONST               1 (2)
>          12 LOAD_CONST               2 (3)
>          15 BUILD_TUPLE              3
>          18 UNPACK_SEQUENCE          1
>          21 STORE_NAME               0 (i)
>          24 LOAD_CONST               3 (None)
>          27 RETURN_VALUE        
> 
> I assume this isn't intended :-).  The compiler is ignoring everything
> after the initial atom in the list comprehension.  It's basically
> compiling the code as if it were:
> 
> [i] = (1, 2, 3)
> 
> I'm not sure how to try and fix this.  Should the grammar allow one to
> construct the example statement above?  If not, I'm not sure how to
> fix the grammar.  If not, I suppose the compiler should detect that
> the list comp is misplaced.  This seems fairly messy, since there are
> about 10 nodes between the expr_stmt and the list_for.
> 
> Or is this a cool way to use list comprehensions to generate
> ValueErrors?

Good catch!  Not everything cool deserves to be preserved.

It looks like this happens because the code that traverses lists on
the left-hand side of an assignment was never told about list
comprehensions.  You're right that the grammar can't be fixed; it's
for the same reason that it can't be fixed to disallow "f() = 1".

The solution is to add a test for this to the compiler that flags this
as an error.

--Guido van Rossum (home page: http://www.python.org/~guido/)