Repository navigation
Conversation
A `ClassVar` annotation can't remove a field inherited from a struct
base: the inherited field is baked into the slot layout and the field
list, while attribute access resolves to the class variable. The result
was an inconsistent struct -- the field stayed in `__struct_fields__`
and was still encoded, but the stored value was unreachable, and typed
decoders failed with `Type 'typing.ClassVar[...]' is not supported`.
Raise a `TypeError` when the struct is defined instead:
Cannot override inherited field 'x' with a `ClassVar` annotation in struct 'Child'
Fixes msgspec#1086
Siyet
left a comment
There was a problem hiding this comment.
Thanks for turning this around so quickly.
Failing at class definition time is the right call. On main the definition is accepted and the result is inconsistent: Child("x").name returns the class variable, the encoded output of that same instance carries the value stored in the slot, and building a decoder raises TypeError: Type 'typing.ClassVar[str]' is not supported. The check is in the right place and the error path is correct.
One request before this lands: the "Class Variables" section of docs/structs.rst still states that struct types exclude any annotation wrapped in typing.ClassVar from their fields, with no exception. A sentence there about the new restriction would help whoever runs into the error.
@provinzkraut, this follows your #1088 review asking for a loud failure at struct definition time. On #1086 you wanted other committers to weigh in first, and nobody has since. Since this turns a definition that is accepted today into a hard error, does landing it this way look right to you?
Fixes #1086 , following #1088 (review)
The implement reuses variable that will be later used, so no performance impact in normal scenario.
Example:
Output: