Skip to content

Add TypeRegistration::on_register#2

Draft
MrGVSV wants to merge 1 commit into
mrgvsv/type-data-callbacksfrom
mrgvsv/type-registration-callbacks
Draft

Add TypeRegistration::on_register#2
MrGVSV wants to merge 1 commit into
mrgvsv/type-data-callbacksfrom
mrgvsv/type-registration-callbacks

Conversation

@MrGVSV
Copy link
Copy Markdown
Owner

@MrGVSV MrGVSV commented Jun 5, 2026

Objective

Followup to bevyengine#24518.

bevyengine#24518 makes it so that type data can be given on_insert and on_register callbacks. This enables users to add dependencies and other registry/registration operations in a much more flexible way.

My goal with this PR is to unify that experience for GetTypeRegistration. This would also allow us to run these callbacks even for a dynamically generated TypeRegistration (since we normally only run GetTypeRegistration::register_type_dependencies via TypeRegistry::register where the type of T is known at compile time).

Solution

This PR deprecates GetTypeRegistration::register_type_dependencies in favor of a new TypeRegistration::on_register callback system.

impl GetTypeRegistration for MyType {
  fn get_type_registration() -> TypeRegistration {
    TypeRegistration::of::<Self>()
      .on_register(|registry| {
        registry.register::<Option<Self>>();
      })
  }
}

TypeRegistration::on_register accepts a FnOnce(&mut TypeRegistry) + Send + Sync + 'static and runs when a type is registered into a TypeRegistry.

I chose to make it so that by default TypeRegistration::on_register will wrap any existing callback, running the old run first then the new one on registration. This was done to prevent footguns where a user attempts to add a callback for a TypeRegistration created via GetTypeRegistration::get_type_registration, since they'd inadvertently lose any registration callback set by the implementation (including the registration of any type dependencies).

Instead, if users want to completely replace the callback, I added TypeRegistration::replace_on_register.

Both methods take self and return Self, thus adding some amount of assurance that they will not be overwritten by downstream consumers and so that they can be used in the builder pattern for creating a TypeRegistration.

This does come at the cost of a Box (~8 bytes) per registration, but I think the more consistent API is worth it. Though I'm open to closing this out if we feel this is an unnecessary increase in memory consumption.

Testing

I added new unit and doc tests in bevy_reflect.


Showcase

A TypeRegistration can now be given a custom on-registration callback directly:

let registration = TypeRegistration::of::<MyType>()
  .on_register(|registry| {
    registry.register::<Option<MyType>>();
  });

registry.add_registration(registration);
assert!(registry.contains(TypeId::of::<MyType>()));
assert!(registry.contains(TypeId::of::<Option<MyType>>()));

Deprecates `GetTypeRegistration::register_type_dependencies`
@MrGVSV MrGVSV force-pushed the mrgvsv/type-registration-callbacks branch from 816a867 to 7474c6a Compare June 6, 2026 17:48
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.

1 participant