Skip to content

[mypyc] Fix ClassVar self-references in class bodies#21011

Open
VaggelisD wants to merge 2 commits intopython:masterfrom
VaggelisD:fix-classvar-self-reference
Open

[mypyc] Fix ClassVar self-references in class bodies#21011
VaggelisD wants to merge 2 commits intopython:masterfrom
VaggelisD:fix-classvar-self-reference

Conversation

@VaggelisD
Copy link
Contributor

@VaggelisD VaggelisD commented Mar 12, 2026

Fixes mypyc/mypyc#972.

In CPython, the class body executes as a function where earlier assignments are available to later ones e.g this is possible:

class Foo:
  A: t.ClassVar = {1, 2, 3}
  B: t.ClassVar = {4, 5, 6}
  C: t.ClassVar = A | B

mypyc previously resolved such names via load_global(), looking them up in the module globals dict where they don't exist causing a KeyError at runtime.

This PR fixes this by tracking ClassVar names as they're defined during class body processing, and redirecting lookups to the class being built: the type object (py_get_attr) for extension classes, or the class dict (dict_get_item_op) for non-extension classes.

VaggelisD and others added 2 commits March 12, 2026 15:37
In CPython, the class body executes as a function where earlier
assignments are available to later ones (e.g. C = A | B where A
is a ClassVar defined earlier in the same class). mypyc previously
resolved such names via load_global(), looking them up in the module
globals dict where they don't exist — causing a KeyError at runtime.

Fix by tracking ClassVar names as they're defined during class body
processing, and redirecting lookups to the class being built: the
type object (py_get_attr) for extension classes, or the class dict
(dict_get_item_op) for non-extension classes.

This enables patterns like:
    class Parser:
        TYPE_TOKENS: ClassVar = {"INT", "VARCHAR"}
        FUNC_TOKENS: ClassVar = TYPE_TOKENS | {"FUNCTION"}
@ilevkivskyi
Copy link
Member

IIUC this fixes mypyc/mypyc#972. If yes, could you please updated PR description to start with "Fixes mypyc/mypyc#972"?

@ilevkivskyi
Copy link
Member

Btw thanks for all the PRs! Please note that we will have a release soon, so if you want these PRs included in v1.20, please ping @JukkaL (who will be release manager).

@VaggelisD
Copy link
Contributor Author

Hey @ilevkivskyi, we actually ran into this in independently in SQLGlot, thus the dict-based repro instead of the much simpler b=a as was noted in the issue. Thanks for the heads up, updated the description.


Btw thanks for all the PRs

Thank you for the project! We were able to make SQLGlot faster by 4-5x on avg and we only just got started. Hopefully we will be contributing even more fixes and features.


Regarding pinging, is asking for a review in Github the preferred way? I'm sure the core contributors are oversubscribed so I've avoided pinging in general. I had also joined the Gitter to discuss these solutions but I'm not sure if it's active anymore?

@ilevkivskyi
Copy link
Member

Regarding pinging, is asking for a review in Github the preferred way?

Yeah, you can request review or @-mention. It is true that we are quite busy here, but I for example don't mind being pinged sometimes, since I sometimes simply forget about a PR.

I had also joined the Gitter to discuss these solutions but I'm not sure if it's active anymore?

Yeah, Gitter is not active. We want to create a new Discord server at some point soon, but didn't get to this yet.

@VaggelisD
Copy link
Contributor Author

Yeah, Gitter is not active. We want to create a new Discord server at some point soon, but didn't get to this yet.

Stating the obvious here but a Discord would be awesome; I can vouch that having to manage a community channel is not easy but it'd be of great help for external contributors, especially for more complex PRs in which upfront coordination & design can massively reduce PR friction later down the road. We'll jump in when it's ready!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Can't access ClassVars directly in the class body

2 participants