bevy_reflect: Type data registration callbacks#24518
Open
MrGVSV wants to merge 7 commits into
Open
Conversation
1 task
5f584ef to
e04239a
Compare
e04239a to
7174bbc
Compare
andriyDev
approved these changes
Jun 4, 2026
Contributor
andriyDev
left a comment
There was a problem hiding this comment.
Nice! Looks great, just a couple of nits.
Co-authored-by: andriyDev <andriydzikh@gmail.com> Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
3720a0d to
6820649
Compare
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.
Objective
This is a rework of #9777.
I'll give the TL;DR of the objective from that PR here.
Many times we'll define type data that relies on other types and type data being registered.
An example in our codebase might be
ReflectAsset. This type data wants to work with other types and type data. So to ensure these are available in the registry, we define an extension method onAppspecifically for their registration:bevy/crates/bevy_asset/src/lib.rs
Lines 673 to 691 in 7517c61
This method registers other types like
Handle<A>and type data likeReflectHandle. But users need to know to use it. Not only that, but it means that other libraries with similar needs will likely want to follow in the same footsteps, meaning more work for library authors and more mental burden for library users.Registering such a type should be as simple as this:
Done. No special app extension methods. Just a simple registration like every other type.
Solution
Callbacks
To achieve this, this PR adds a more comprehensive set of registration callbacks. The following callbacks have been added:
TypeData::on_insertTypeData::on_registerCreateTypeData::on_insert(CreateTypeData::insert_dependencieshas been deprecated)CreateTypeData::on_registerThe
on_insertcallbacks are invoked when the type data is inserted into aTypeRegistration. Theon_registercallbacks are invoked when thatTypeRegistrationis registered into aTypeRegistration(or immediately if already registered—more on how we do that later).I chose to allow callbacks on both traits for maximum flexibility. Here is a list of their pros/cons:
TypeDatacallbacksCreateTypeDatais also implementedTypeRegistration/TypeRegistryis used&selffor runtime-defined callbacksCreateTypeDatacallbacksTypeRegistrationandTypeRegistry&self(though, we certainly could add that if we think it would be beneficial)Below is how we might redefine
ReflectAssetto make use of these callbacks:Removed Clone
Additionally, I removed the restriction that
TypeRegistration: Clone. It's really not needed for any of our internal machinery and it doesn't appear to be useful for users in most cases.This also means that type data no longer needs to be
Clone. So now the only real requirements areSelf: Send + Sync + 'static, allowing for much more flexibility in defining type data.Derive Macro
We also introduce a derive macro to quickly derive
TypeDatawithout any callbacks. This macro was kept very barebones for this PR. We can explore improvements and helper attributes for it in a followup PR (such as a way to easily define callbacks or dependencies).Restricted Type Data Insertions
To ensure that callbacks are almost always properly invoked, we had to change how type data is inserted into a
TypeRegistration. The main change is that type data can no longer be inserted directly onto a&mut TypeRegistration. Instead, type data must be inserted onto an owned instance ofTypeRegistration.Additionally, the
on_insertcallbacks are provided aTypeRegistrationMut<'_>in order to mutably insert type data onto an existing registration. This type is also used by the newTypeRegistry::registration_scopemethod to provide users with a way of inserting multiple type data without incurring the cost of multiple registration lookups).By adding these restrictions, we can ensure that
on_registercallbacks are always invoked.Documentation Improvements
I also went ahead and added a new set of docs for the
type_datamodule (which is now public). I figured since things were getting somewhat complicated, it made sense to have a central place explaining how everything works together.I also updated the
type_dataexample to account for the new changes.Testing
I added extensive unit tests to
bevy_reflectand also updated thetype_dataexample.Followup Work
After working on this PR, I think I've determined the following work as good for followup:
registrydirectory moduleComponentderives)ReflectAsset, that could benefit from these changesinputandparamsfor talking aboutCreateTypeDatainput)Additionally, we could consider adding the ability to queue additionalDrafted a PR: MrGVSV#2on_registercallbacks onto aTypeRegistrationapart from type data (potentially removing the need forGetTypeRegistration::register_type_dependencies). This is actually trivial to implement with this PR, but I was worried there was already too much happening in a single diff. Of course, if we'd definitely like to do that, I can do that!AI Usage Disclaimer
As per the AI usage policy, I did not have LLMs generate any code, assets, examples, or documentation—including this PR's description. Nor did I use LLMs to make design decisions for me.
My AI usage was limited to using ChatGPT for rubberducking, evaluating solutions, and suggesting type names.
Showcase
Type data can now be defined with a comprehensive set of registration callbacks, including
on_insertandon_register.Additionally, type data no longer needs to be
Cloneand instead only needs to implement or deriveTypeData.Below is a snippet from our newly updated type data example:
Click to view showcase
Output: