Skip to content

gh-161849: Fix crash compiling a class that binds __classdict__ - #161933

Open
0z5a wants to merge 1 commit into
python:mainfrom
0z5a:gh-161849-classdict-binding
Open

0z5a wants to merge 1 commit into
python:mainfrom
0z5a:gh-161849-classdict-binding

Conversation

@0z5a

@0z5a 0z5a commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

When a class body binds __classdict__ (assignment, for target, del or global), analyze_name() in Python/symtable.c applied the rule for names bound in the enclosing class to __classdict__ as well. Annotation and type parameter scopes inside the class then treated it as a global instead of a free variable, so they lost the __classdict__ cell the class creates for them. Compiling a generic class in such a class body hit the assemble.c assertion (segfault in a release build); an annotated method, a generic function or a type alias raised SystemError.

The change skips that rule for __classdict__ only, so these scopes always use the cell. Other names bound in the class keep the current behaviour.

Tests: new DeferredEvaluationTests.test_class_binds_dunder_classdict in test_type_annotations covers assignment, annotated assignment, for and global, and checks that annotations, type parameter bounds and the alias value still resolve against the class namespace. Debug build of current main (ab48ba8edf) on macOS arm64: without the symtable.c change the new test fails with SystemError and the reproducer from the issue aborts on the assertion; with it both pass. test_type_annotations, test_type_params, test_symtable, test_compile, test_annotationlib, test_grammar, test_syntax, test_scope, test_typing, test_dis, test_ast, test_inspect, test_builtin, test_funcattrs, test_descr, test_super and test_class pass, and test_type_annotations -R 3:3 reports no leaks.

This change was drafted with Claude Code (claude-opus-5-5); the test results above are from the runs described.

When a class body binds __classdict__ (assignment, for target, global,
del), analyze_name() treated the name as global in the annotation and
type parameter scopes that can see the class, so they no longer got the
__classdict__ cell the class creates for them. Compiling such a class
with a generic class inside crashed, and with an annotated method or a
type alias raised SystemError.

Skip that rule for __classdict__ itself.
@python-cla-bot

Copy link
Copy Markdown

The following commit authors need to sign the Contributor License Agreement:

CLA not signed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant