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
{{ message }}
Repository navigation
Class-scope comprehension with lambda raises SystemError #150700
changed the title [-]Class-scope inlined comprehensions can crash the compiler when a nested function captures class[/-][+]Class-scope comprehension with lambda raises SystemError[/+]on Jun 1, 2026
Out of curiosity, how was this found? I'm asking because it seems quite like our other OSS-Fuzz things (like the one you linked), and I'm wondering if we missed a finding?
As part of implementation of PEP 709 in GraalPy done by my colleague @msimacek, during review I asked Codex to look for corner cases and gaps around the code handling the name resolution and it came up with this (manifested by different internal error). Then we realized it is also not working on CPython.
Also don't forget __classdict__ and __conditional_annotations__ (which I suppose I technically broke some time ago), they can also be dropped.
I was just about to mention them, yes. class C: [lambda: __conditional_annotations__ for () in ()], class C: [lambda: __classdict__ for () in ()] reproduce too.
#149806 is unrelated because it fixes annotation visiting code and the issue here lies in inline_comprehension.
This is an edge case of #120295 (which is the likely cause of regression).
In inline_comprehension(), when __class__ / __classdict__ / __conditional_annotations__ appears as FREE in a comprehension's symbol table because a nested scope captured it (e.g. these lambdas), this name is still discarded from comp_free unconditionally. This prevents drop_class_free() from seeing it, so the appropriate ste_needs_(...) flag is never set on the enclosing class. That leads to codegen_make_closure() throwing SystemError when it couldn't find __class__ / __classdict__ / __conditional_annotations__ in the class's cellvars.
We could just only discard from comp_free when no child scope (e.g. a lambda) still needs the name as FREE. When a child scope does need it, keep it in comp_free so drop_class_free() can set the appropriate flag and the class creates the implicit cell.
Activity
[-]Class-scope inlined comprehensions can crash the compiler when a nested function captures class[/-][+]Class-scope comprehension with lambda raises SystemError[/+]terryjreedy commentedon Jun 1, 2026
Same on Windows back to 3.12. In 3.11, "NameError: cannot access free variable 'class' where it is not associated with a value in enclosing scope".
StanFromIreland commentedon Jun 1, 2026
Out of curiosity, how was this found? I'm asking because it seems quite like our other OSS-Fuzz things (like the one you linked), and I'm wondering if we missed a finding?
steve-s commentedon Jun 1, 2026
As part of implementation of PEP 709 in GraalPy done by my colleague @msimacek, during review I asked Codex to look for corner cases and gaps around the code handling the name resolution and it came up with this (manifested by different internal error). Then we realized it is also not working on CPython.
johnslavik commentedon Jun 1, 2026
MREs:
class C: [lambda: __class__ for () in ()],class C: [lambda: super() for () in ()]StanFromIreland commentedon Jun 1, 2026
Also don't forget
__classdict__and__conditional_annotations__(which I suppose I technically broke some time ago), they can also be dropped.johnslavik commentedon Jun 1, 2026
I was just about to mention them, yes.
class C: [lambda: __conditional_annotations__ for () in ()],class C: [lambda: __classdict__ for () in ()]reproduce too.johnslavik commentedon Jun 1, 2026
#149806 is unrelated because it fixes annotation visiting code and the issue here lies in
inline_comprehension.This is an edge case of #120295 (which is the likely cause of regression).
In
inline_comprehension(), when__class__/__classdict__/__conditional_annotations__appears asFREEin a comprehension's symbol table because a nested scope captured it (e.g. these lambdas), this name is still discarded fromcomp_freeunconditionally. This preventsdrop_class_free()from seeing it, so the appropriateste_needs_(...)flag is never set on the enclosing class. That leads tocodegen_make_closure()throwingSystemErrorwhen it couldn't find__class__/__classdict__/__conditional_annotations__in the class's cellvars.We could just only discard from
comp_freewhen no child scope (e.g. a lambda) still needs the name asFREE. When a child scope does need it, keep it incomp_freesodrop_class_free()can set the appropriate flag and the class creates the implicit cell.Merge branch 'main' into pythongh-150700-class-scope-comprehension-wi…
gh-150700: Fix class-scope inline comprehensions when nested scopes r…
[3.14] gh-150700: Fix class-scope inline comprehensions when nested s…
[3.15] gh-150700: Fix class-scope inline comprehensions when nested s…
Fix SystemError during REPL input compilation corrupting display
Fix SystemError during REPL input compilation corrupting display
Fix SystemError during REPL input compilation corrupting display
Fix SystemError during REPL input compilation corrupting display
Fix SystemError during REPL input compilation corrupting display
Fix SystemError during REPL input compilation corrupting display
Fix SystemError during REPL input compilation corrupting display
pythongh-150700: Fix class-scope inline comprehensions when nested sc…