Create a metaclass for each supplemental data type #972
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.
This allows many metaclass customizations without incurring the performance cost of allowing arbitrary metaclasses. As a side benefit, we get nontrivial construction and destruction of supplement types, and can check whether a particular nanobind type uses a particular supplement type. There are no additional per-instance performance or storage costs, no additional per-type storage costs, and negligible per-type performance costs.
The information about a particular supplement type is stored in a new
nb::detail::supplement_data
structure. An inline variable template is used to automatically create one of these in static data for each supplement type used in a particular extension module. Instances ofnb_meta
(i.e., metaclass types) gain a pointer to theirsupplement_data
, which is null for the default metaclassnb_type_0
. The non-default metaclass typesnb_type_xyz
are now stored in anb_type_map_slow
rather than a Python dictionary, and (except on free-threaded builds where everything is immortal) they are properly reference-counted so that they will be destroyed once all their instances are. This avoids leak warnings when assigning nanobind functions as their attributes.Size cost:
nb::detail::supplement_data
structure (five pointers) stored in static data per supplement type used in an extension module.I originally added some caching in static data to limit lookups by supplement type to one per supplement type per extension module. I removed this because it was a bit complex and I don't think it's necessary (we already do two type_map_slow lookups per nb_type_new, avoiding a third doesn't save all that much) but it would be easy to re-add. See commit 34739e3. The additional cost from that caching would be 104 bytes of code and two more pointers in
supplement_data
.