-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bevy_reflect: Add
Reflectable
trait (#5772)
# Objective When deriving `Reflect`, users will notice that their generic arguments also need to implement `Reflect`: ```rust #[derive(Reflect)] struct Foo<T: Reflect> { value: T } ``` This works well for now. However, as we want to do more with `Reflect`, these bounds might need to change. For example, to get #4154 working, we likely need to enforce the `GetTypeRegistration` trait. So now we have: ```rust #[derive(Reflect)] struct Foo<T: Reflect + GetTypeRegistration> { value: T } ``` Not great, but not horrible. However, we might then want to do something as suggested in [this](#5745 (comment)) comment and add a `ReflectTypeName` trait for stable type name support. Well now we have: ```rust #[derive(Reflect)] struct Foo<T: Reflect + GetTypeRegistration + ReflectTypeName> { value: T } ``` Now imagine that for even two or three generic types. Yikes! As the API changes it would be nice if users didn't need to manually migrate their generic type bounds like this. A lot of these traits are (or will/might be) core to the entire reflection API. And although `Reflect` can't add them as supertraits for object-safety reasons, they are still indirectly required for things to function properly (manual implementors will know how easy it is to forget to implement `GetTypeRegistration`). And they should all be automatically implemented for user types anyways as long they're using `#[derive(Reflect)]`. ## Solution Add a "catch-all" trait called `Reflectable` whose supertraits are a select handful of core reflection traits. This allows us to consolidate all the examples above into this: ```rust #[derive(Reflect)] struct Foo<T: Reflectable> { value: T } ``` And as we experiment with the API, users can rest easy knowing they don't need to migrate dozens upon dozens of types. It should all be automatic! ## Discussion 1. Thoughts on the name `Reflectable`? Is it too easily confused with `Reflect`? Or does it at least accurately describe that this contains the core traits? If not, maybe `BaseReflect`? --- ## Changelog - Added the `Reflectable` trait --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
- Loading branch information
1 parent
8d78c37
commit 6954146
Showing
5 changed files
with
50 additions
and
3 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
use crate::{GetTypeRegistration, Reflect, TypePath, Typed}; | ||
|
||
/// A catch-all trait that is bound by the core reflection traits, | ||
/// useful to simplify reflection-based generic type bounds. | ||
/// | ||
/// You do _not_ need to implement this trait manually. | ||
/// It is automatically implemented for all types that implement its supertraits. | ||
/// And these supertraits are all automatically derived with the [`Reflect` derive macro]. | ||
/// | ||
/// This should namely be used to bound generic arguments to the necessary traits for reflection. | ||
/// Doing this has the added benefit of reducing migration costs, as a change to the required traits | ||
/// is automatically handled by this trait. | ||
/// | ||
/// For now, the supertraits of this trait includes: | ||
/// * [`Reflect`] | ||
/// * [`GetTypeRegistration`] | ||
/// * [`Typed`] | ||
/// * [`TypePath`] | ||
/// | ||
/// ## Example | ||
/// | ||
/// ``` | ||
/// # use bevy_reflect::{Reflect, Reflectable}; | ||
/// #[derive(Reflect)] | ||
/// struct MyStruct<T: Reflectable> { | ||
/// value: T | ||
/// } | ||
/// ``` | ||
/// | ||
/// [`Reflect` derive macro]: bevy_reflect_derive::Reflect | ||
pub trait Reflectable: Reflect + GetTypeRegistration + Typed + TypePath {} | ||
|
||
impl<T: Reflect + GetTypeRegistration + Typed + TypePath> Reflectable for T {} |
This file contains 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
This file contains 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