-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Evaluation of iterables in generator expressions uses wrong scope #1159
Comments
scoder changed description from In Python, this works:
In current Cython, this raises an error at runtime as the iterable inside of the generator expression refers to the loop target variable, not the name in the outer scope. (So the iterable happens to be None.) The name of the iterable must be looked up before creating the entry of the target variable in the inner scope. to In Python, this works:
In current Cython, this raises an error at runtime as the iterable inside of the generator expression refers to the loop target variable, not the name in the outer scope. (So the iterable happens to be None.) The name of the iterable (or rather the entire iterable expression) must be evaluated in the outer scope. |
scoder changed cc to In Python, this works:
In current Cython, this raises an error at runtime as the iterable inside of the generator expression refers to the loop target variable, not the name in the outer scope. (So the iterable happens to be None.) The name of the iterable (or rather the entire iterable expression) must be evaluated in the outer scope. to In Python, this works:
In current Cython, this raises an error at runtime as the iterable inside of the generator expression refers to the loop target variable, not the name in the outer scope. (So the iterable happens to be None.) The name of the iterable (or rather the entire iterable expression) must be evaluated in the outer scope. Actually, it's even different - CPython simply pre-evaluates the outermost iterable when creating the generator. Example (Py3.2):
So, basically, the outermost iterable should be evaluated into a closure variable of the generator, instead of letting the generator evaluate it itself. This:
should be transformed into
|
scoder commented Another test that currently works differently in Python than in Cython:
|
scoder changed priority from |
scoder changed milestone from Fixed here: |
scoder changed priority from |
scoder changed milestone from |
@scoder thanks for the cleanup--I see now how the bug described in this ticket is still a problem too. I'll see if I can do something about it... |
Apparently the original attempt to fix this was also reverted in a3d4461, which is part of my confusion as well. |
I'd be happy to have more people look into this, but be "warned", it's not entirely trivial. Cython looks at the iterable in several places in order to optimise loops. Moving the iterable out of the generator too early will prevent these optimisations. Moving it out too late will lead to incorrect declarations inside and/or outside of the generator. This is one of the bugs that have been languishing for a bit of a reason. |
Thanks for the admonition. That will help me understand better what the problem is. |
Nominating this as a release blocker for Cython 3.0 to keep it in sight, although it's not really a breaking change. |
Fixes #1159. This should be a simpler way of dealing with the long-standing generator and comprehension scoping issues. Unlike the previous PR it is fairly non-intrusive (i.e. doesn't wrap everything in `ResultRefNodes`) and therefore the changes should be more reasonable. Instead it: * Gives `IteratorNode` a scope (pointed at the outer scope rather than the scope of the generator/comprehension) * Tags each `ExprNode` inside the generator iterator sequence with a number, and uses those tags later to work out what needs to be converted to an argument for the generator. If an `ExprNode` is optimized out then that's fine - one of its children will have been tagged.
In Python, this works:
In current Cython, this raises an error at runtime as the iterable inside of the generator expression refers to the loop target variable, not the name in the outer scope. (So the iterable happens to be None.)
The name of the iterable (or rather the entire iterable expression) must be evaluated in the outer scope.
Actually, it's even different - CPython simply pre-evaluates the outermost iterable when creating the generator. Example (Py3.2):
So, basically, the outermost iterable should be evaluated into a closure variable of the generator, instead of letting the generator evaluate it itself. This:
should be transformed into
Note that this also applies to list comprehensions with
language_level=3
.Migrated from http://trac.cython.org/ticket/600
The text was updated successfully, but these errors were encountered: