Repository navigation
Conversation
Fixes mypyc/mypyc#1102. Native classes support weak references if they opt in using `@mypyc_attr(weakrefs=True)`, which adds a weak reference list field to the object struct. The base class of a hierarchy must opt in, since the offset of the field must be the same in all subclasses. Native subclasses of non-native classes (other than dict/Exception subclasses) always support weak references, like interpreted subclasses. They already have `__dict__` storage, and the weak reference list goes next to it at no additional memory cost: in the managed pre-header on 3.12+ (Py_TPFLAGS_MANAGED_WEAKREF), and in a trailing slot after `__dict__` on older versions. This works the same way whether or not the base class supports weak references, so mypyc doesn't need to know anything about the base class. Previously some of these classes were weak-referenceable (on 3.11 and earlier, or if the base class supported them), but tp_dealloc never cleared the weak references, so they resurrected freed memory. Now tp_dealloc clears weak references for all classes that support them. On 3.11 and earlier, callable classes (used for nested functions, lambdas and singledispatch functions) and native dict/Exception subclasses used to accept weak references, but the result crashed or corrupted memory once the object died. They now reject weak references, as on 3.12+, and their instances are one pointer smaller.
p-sawicki
approved these changes
Nov 6, 2026
| or not self.is_generated | ||
| or self.has_dict | ||
| # For the __weakref__ getset | ||
| or (self.is_ext_class and not self.is_trait and self.supports_weakrefs()) |
Collaborator
There was a problem hiding this comment.
same condition as has_weakrefs in emitclass.py - could move it to a helper method.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes mypyc/mypyc#1102.
Native classes support weak references if they opt in using
@mypyc_attr(weakrefs=True), which adds a weak reference list field to the object struct. The base class of a hierarchy must opt in, since the offset of the field must be the same in all subclasses.Native subclasses of non-native classes (other than dict/Exception subclasses) always support weak references, like interpreted subclasses.
Previously some of these classes were weak-referenceable (on 3.11 and earlier, or if the base class supported them), but tp_dealloc never cleared the weak references, so they resurrected freed memory. Now tp_dealloc clears weak references for all classes that support them.
On 3.11 and earlier, callable classes (used for nested functions, lambdas and singledispatch functions) and native dict/Exception subclasses used to accept weak references, but the result crashed or corrupted memory once the object died. They now reject weak references, as on 3.12+, and their instances are one pointer smaller.