[mypyc] Fix lambda inside comprehension (#21009)
Fixes https://github.com/mypyc/mypyc/issues/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>