You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fixesmypyc/mypyc#1190
There's a subtle difference between mypyc and CPython when it comes to
evaluating comprehensions:
- CPython creates an implicit function scope for every comprehension
(visible as `MAKE_FUNCTION` etc)
- Mypyc inlines comprehensions directly into the enclosing/outer scope
This leads to the following bug: When a lambda inside a comprehension
tries to capture the loop variable, the closure/env-class machinery
fails because there's no scope boundary to chain through.
Consider this example with a module level comprehension which currently
fails with `UnboundLocalError`:
```Python3
# bug.py
d = {name: (lambda: name) for name in ("a", "b")}
d["a"]()
```
<br />
Schematically:
```Bash
Before (broken):
module scope (no env class)
└── lambda (needs env class to find 'name') → crash
After (fixed):
module scope
└── comprehension scope (has env class with 'name' attribute)
└── lambda (loads 'name' from comprehensions env class) → works
```
<br />
Three failure modes depending on where the comprehension lives:
- Module level: UnboundLocalError at runtime -> the lambda can't find
the variable
- Class level: KeyError compiler crash -> env class setup fails entirely
- Function level: Already worked, because the enclosing function
provides the env class
The fix creates a _lightweight_ synthetic scope (new `FuncInfo` + `env`
class) only when a comprehension body contains a lambda, while still
inlining the comprehension into the same basic blocks otherwise.
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
0 commit comments