Skip to content

Commit f5a5ba1

Browse files
committed
Document reflect_trait
1 parent 546f3b1 commit f5a5ba1

File tree

1 file changed

+54
-0
lines changed
  • crates/bevy_reflect/bevy_reflect_derive/src

1 file changed

+54
-0
lines changed

crates/bevy_reflect/bevy_reflect_derive/src/lib.rs

+54
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ pub(crate) static REFLECT_VALUE_ATTRIBUTE_NAME: &str = "reflect_value";
5959
/// one for `ReflectFoo` and another for `ReflectBar`.
6060
/// This assumes these types are indeed in-scope wherever this macro is called.
6161
///
62+
/// This is often used with traits that have been marked by the [`reflect_trait`] macro
63+
/// in order to register the type's implementation of that trait.
64+
///
6265
/// ### Special Identifiers
6366
///
6467
/// There are a few "special" identifiers that work a bit differently:
@@ -116,6 +119,8 @@ pub(crate) static REFLECT_VALUE_ATTRIBUTE_NAME: &str = "reflect_value";
116119
///
117120
/// What this does is register the `SerializationData` type within the `GetTypeRegistration` implementation,
118121
/// which will be used by the reflection serializers to determine whether or not the field is serializable.
122+
///
123+
/// [`reflect_trait`]: macro@reflect_trait
119124
#[proc_macro_derive(Reflect, attributes(reflect, reflect_value))]
120125
pub fn derive_reflect(input: TokenStream) -> TokenStream {
121126
let ast = parse_macro_input!(input as DeriveInput);
@@ -167,6 +172,55 @@ pub fn derive_type_uuid(input: TokenStream) -> TokenStream {
167172
type_uuid::type_uuid_derive(input)
168173
}
169174

175+
/// A macro that automatically generates type data for traits, which their implementors can then register.
176+
///
177+
/// The output of this macro is a struct that takes reflected instances of the implementor's type
178+
/// and returns the value as a trait object.
179+
/// Because of this, **it can only be used on [object-safe] traits.**
180+
///
181+
/// For a trait named `MyTrait`, this will generate the struct `ReflectMyTrait`.
182+
/// The generated struct can be created using `FromType` with any type that implements the trait.
183+
/// The creation and registration of this generated struct as type data can be automatically handled
184+
/// by the [`Reflect` derive macro].
185+
///
186+
/// # Example
187+
///
188+
/// ```ignore
189+
/// # use std::any::TypeId;
190+
/// # use bevy_reflect_derive::{Reflect, reflect_trait};
191+
/// #[reflect_trait] // Generates `ReflectMyTrait`
192+
/// trait MyTrait {
193+
/// fn print(&self) -> &str;
194+
/// }
195+
///
196+
/// #[derive(Reflect)]
197+
/// #[reflect(MyTrait)] // Automatically registers `ReflectMyTrait`
198+
/// struct SomeStruct;
199+
///
200+
/// impl MyTrait for SomeStruct {
201+
/// fn print(&self) -> &str {
202+
/// "Hello, World!"
203+
/// }
204+
/// }
205+
///
206+
/// // We can create the type data manually if we wanted:
207+
/// let my_trait: ReflectMyTrait = FromType::<SomeStruct>::from_type();
208+
///
209+
/// // Or we can simply get it from the registry:
210+
/// let mut registry = TypeRegistry::default();
211+
/// registry.register::<SomeStruct>();
212+
/// let my_trait = registry
213+
/// .get_type_data::<ReflectMyTrait>(TypeId::of::<SomeStruct>())
214+
/// .unwrap();
215+
///
216+
/// // Then use it on reflected data
217+
/// let reflected: Box<dyn Reflect> = Box::new(SomeStruct);
218+
/// let reflected_my_trait: &dyn MyTrait = my_trait.get(&*reflected).unwrap();
219+
/// assert_eq!("Hello, World!", reflected_my_trait.print());
220+
/// ```
221+
///
222+
/// [object-safe]: https://doc.rust-lang.org/reference/items/traits.html#object-safety
223+
/// [`Reflect` derive macro]: Reflect
170224
#[proc_macro_attribute]
171225
pub fn reflect_trait(args: TokenStream, input: TokenStream) -> TokenStream {
172226
trait_reflection::reflect_trait(&args, input)

0 commit comments

Comments
 (0)