Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/derive/src/lib.rs
6599 views
1
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
2
3
//! This crate contains macros used by Bevy's `Reflect` API.
4
//!
5
//! The main export of this crate is the derive macro for [`Reflect`]. This allows
6
//! types to easily implement `Reflect` along with other `bevy_reflect` traits,
7
//! such as `Struct`, `GetTypeRegistration`, and more— all with a single derive!
8
//!
9
//! Some other noteworthy exports include the derive macros for [`FromReflect`] and
10
//! [`TypePath`], as well as the [`reflect_trait`] attribute macro.
11
//!
12
//! [`Reflect`]: crate::derive_reflect
13
//! [`FromReflect`]: crate::derive_from_reflect
14
//! [`TypePath`]: crate::derive_type_path
15
//! [`reflect_trait`]: macro@reflect_trait
16
17
extern crate proc_macro;
18
19
mod attribute_parser;
20
mod container_attributes;
21
mod custom_attributes;
22
mod derive_data;
23
#[cfg(feature = "documentation")]
24
mod documentation;
25
mod enum_utility;
26
mod field_attributes;
27
mod from_reflect;
28
mod generics;
29
mod ident;
30
mod impls;
31
mod meta;
32
mod reflect_opaque;
33
mod registration;
34
mod remote;
35
mod result_sifter;
36
mod serialization;
37
mod string_expr;
38
mod struct_utility;
39
mod trait_reflection;
40
mod type_path;
41
mod where_clause_options;
42
43
use std::{fs, io::Read, path::PathBuf};
44
45
use crate::derive_data::{ReflectDerive, ReflectMeta, ReflectStruct};
46
use container_attributes::ContainerAttributes;
47
use derive_data::{ReflectImplSource, ReflectProvenance, ReflectTraitToImpl, ReflectTypePath};
48
use proc_macro::TokenStream;
49
use quote::quote;
50
use reflect_opaque::ReflectOpaqueDef;
51
use syn::{parse_macro_input, DeriveInput};
52
use type_path::NamedTypePathDef;
53
54
pub(crate) static REFLECT_ATTRIBUTE_NAME: &str = "reflect";
55
pub(crate) static TYPE_PATH_ATTRIBUTE_NAME: &str = "type_path";
56
pub(crate) static TYPE_NAME_ATTRIBUTE_NAME: &str = "type_name";
57
58
/// Used both for [`impl_reflect`] and [`derive_reflect`].
59
///
60
/// [`impl_reflect`]: macro@impl_reflect
61
/// [`derive_reflect`]: derive_reflect()
62
fn match_reflect_impls(ast: DeriveInput, source: ReflectImplSource) -> TokenStream {
63
let derive_data = match ReflectDerive::from_input(
64
&ast,
65
ReflectProvenance {
66
source,
67
trait_: ReflectTraitToImpl::Reflect,
68
},
69
) {
70
Ok(data) => data,
71
Err(err) => return err.into_compile_error().into(),
72
};
73
74
let assertions = impls::impl_assertions(&derive_data);
75
76
let (reflect_impls, from_reflect_impl) = match derive_data {
77
ReflectDerive::Struct(struct_data) | ReflectDerive::UnitStruct(struct_data) => (
78
impls::impl_struct(&struct_data),
79
if struct_data.meta().from_reflect().should_auto_derive() {
80
Some(from_reflect::impl_struct(&struct_data))
81
} else {
82
None
83
},
84
),
85
ReflectDerive::TupleStruct(struct_data) => (
86
impls::impl_tuple_struct(&struct_data),
87
if struct_data.meta().from_reflect().should_auto_derive() {
88
Some(from_reflect::impl_tuple_struct(&struct_data))
89
} else {
90
None
91
},
92
),
93
ReflectDerive::Enum(enum_data) => (
94
impls::impl_enum(&enum_data),
95
if enum_data.meta().from_reflect().should_auto_derive() {
96
Some(from_reflect::impl_enum(&enum_data))
97
} else {
98
None
99
},
100
),
101
ReflectDerive::Opaque(meta) => (
102
impls::impl_opaque(&meta),
103
if meta.from_reflect().should_auto_derive() {
104
Some(from_reflect::impl_opaque(&meta))
105
} else {
106
None
107
},
108
),
109
};
110
111
TokenStream::from(quote! {
112
const _: () = {
113
#reflect_impls
114
115
#from_reflect_impl
116
117
#assertions
118
};
119
})
120
}
121
122
/// The main derive macro used by `bevy_reflect` for deriving its `Reflect` trait.
123
///
124
/// This macro can be used on all structs and enums (unions are not supported).
125
/// It will automatically generate implementations for `Reflect`, `Typed`, `GetTypeRegistration`, and `FromReflect`.
126
/// And, depending on the item's structure, will either implement `Struct`, `TupleStruct`, or `Enum`.
127
///
128
/// See the [`FromReflect`] derive macro for more information on how to customize the `FromReflect` implementation.
129
///
130
/// # Container Attributes
131
///
132
/// This macro comes with some helper attributes that can be added to the container item
133
/// in order to provide additional functionality or alter the generated implementations.
134
///
135
/// In addition to those listed, this macro can also use the attributes for [`TypePath`] derives.
136
///
137
/// ## `#[reflect(Ident)]`
138
///
139
/// The `#[reflect(Ident)]` attribute is used to add type data registrations to the `GetTypeRegistration`
140
/// implementation corresponding to the given identifier, prepended by `Reflect`.
141
///
142
/// For example, `#[reflect(Foo, Bar)]` would add two registrations:
143
/// one for `ReflectFoo` and another for `ReflectBar`.
144
/// This assumes these types are indeed in-scope wherever this macro is called.
145
///
146
/// This is often used with traits that have been marked by the [`#[reflect_trait]`](macro@reflect_trait)
147
/// macro in order to register the type's implementation of that trait.
148
///
149
/// ### Default Registrations
150
///
151
/// The following types are automatically registered when deriving `Reflect`:
152
///
153
/// * `ReflectFromReflect` (unless opting out of `FromReflect`)
154
/// * `SerializationData`
155
/// * `ReflectFromPtr`
156
///
157
/// ### Special Identifiers
158
///
159
/// There are a few "special" identifiers that work a bit differently:
160
///
161
/// * `#[reflect(Clone)]` will force the implementation of `Reflect::reflect_clone` to rely on
162
/// the type's [`Clone`] implementation.
163
/// A custom implementation may be provided using `#[reflect(Clone(my_clone_func))]` where
164
/// `my_clone_func` is the path to a function matching the signature:
165
/// `(&Self) -> Self`.
166
/// * `#[reflect(Debug)]` will force the implementation of `Reflect::reflect_debug` to rely on
167
/// the type's [`Debug`] implementation.
168
/// A custom implementation may be provided using `#[reflect(Debug(my_debug_func))]` where
169
/// `my_debug_func` is the path to a function matching the signature:
170
/// `(&Self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result`.
171
/// * `#[reflect(PartialEq)]` will force the implementation of `Reflect::reflect_partial_eq` to rely on
172
/// the type's [`PartialEq`] implementation.
173
/// A custom implementation may be provided using `#[reflect(PartialEq(my_partial_eq_func))]` where
174
/// `my_partial_eq_func` is the path to a function matching the signature:
175
/// `(&Self, value: &dyn #bevy_reflect_path::Reflect) -> bool`.
176
/// * `#[reflect(Hash)]` will force the implementation of `Reflect::reflect_hash` to rely on
177
/// the type's [`Hash`] implementation.
178
/// A custom implementation may be provided using `#[reflect(Hash(my_hash_func))]` where
179
/// `my_hash_func` is the path to a function matching the signature: `(&Self) -> u64`.
180
/// * `#[reflect(Default)]` will register the `ReflectDefault` type data as normal.
181
/// However, it will also affect how certain other operations are performed in order
182
/// to improve performance and/or robustness.
183
/// An example of where this is used is in the [`FromReflect`] derive macro,
184
/// where adding this attribute will cause the `FromReflect` implementation to create
185
/// a base value using its [`Default`] implementation avoiding issues with ignored fields
186
/// (for structs and tuple structs only).
187
///
188
/// ## `#[reflect(opaque)]`
189
///
190
/// The `#[reflect(opaque)]` attribute denotes that the item should implement `Reflect` as an opaque type,
191
/// hiding its structure and fields from the reflection API.
192
/// This means that it will forgo implementing `Struct`, `TupleStruct`, or `Enum`.
193
///
194
/// Furthermore, it requires that the type implements [`Clone`].
195
/// If planning to serialize this type using the reflection serializers,
196
/// then the `Serialize` and `Deserialize` traits will need to be implemented and registered as well.
197
///
198
/// ## `#[reflect(from_reflect = false)]`
199
///
200
/// This attribute will opt-out of the default `FromReflect` implementation.
201
///
202
/// This is useful for when a type can't or shouldn't implement `FromReflect`,
203
/// or if a manual implementation is desired.
204
///
205
/// Note that in the latter case, `ReflectFromReflect` will no longer be automatically registered.
206
///
207
/// ## `#[reflect(type_path = false)]`
208
///
209
/// This attribute will opt-out of the default `TypePath` implementation.
210
///
211
/// This is useful for when a type can't or shouldn't implement `TypePath`,
212
/// or if a manual implementation is desired.
213
///
214
/// ## `#[reflect(no_field_bounds)]`
215
///
216
/// This attribute will opt-out of the default trait bounds added to all field types
217
/// for the generated reflection trait impls.
218
///
219
/// Normally, all fields will have the bounds `TypePath`, and either `FromReflect` or `Reflect`
220
/// depending on if `#[reflect(from_reflect = false)]` is used.
221
/// However, this might not always be desirable, and so this attribute may be used to remove those bounds.
222
///
223
/// ### Example
224
///
225
/// If a type is recursive the default bounds will cause an overflow error when building:
226
///
227
/// ```ignore (bevy_reflect is not accessible from this crate)
228
/// #[derive(Reflect)] // ERROR: overflow evaluating the requirement `Foo: FromReflect`
229
/// struct Foo {
230
/// foo: Vec<Foo>,
231
/// }
232
///
233
/// // Generates a where clause like:
234
/// // impl bevy_reflect::Reflect for Foo
235
/// // where
236
/// // Foo: Any + Send + Sync,
237
/// // Vec<Foo>: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
238
/// ```
239
///
240
/// In this case, `Foo` is given the bounds `Vec<Foo>: FromReflect + ...`,
241
/// which requires that `Foo` implements `FromReflect`,
242
/// which requires that `Vec<Foo>` implements `FromReflect`,
243
/// and so on, resulting in the error.
244
///
245
/// To fix this, we can add `#[reflect(no_field_bounds)]` to `Foo` to remove the bounds on `Vec<Foo>`:
246
///
247
/// ```ignore (bevy_reflect is not accessible from this crate)
248
/// #[derive(Reflect)]
249
/// #[reflect(no_field_bounds)]
250
/// struct Foo {
251
/// foo: Vec<Foo>,
252
/// }
253
///
254
/// // Generates a where clause like:
255
/// // impl bevy_reflect::Reflect for Foo
256
/// // where
257
/// // Self: Any + Send + Sync,
258
/// ```
259
///
260
/// ## `#[reflect(where T: Trait, U::Assoc: Trait, ...)]`
261
///
262
/// This attribute can be used to add additional bounds to the generated reflection trait impls.
263
///
264
/// This is useful for when a type needs certain bounds only applied to the reflection impls
265
/// that are not otherwise automatically added by the derive macro.
266
///
267
/// ### Example
268
///
269
/// In the example below, we want to enforce that `T::Assoc: List` is required in order for
270
/// `Foo<T>` to be reflectable, but we don't want it to prevent `Foo<T>` from being used
271
/// in places where `T::Assoc: List` is not required.
272
///
273
/// ```ignore
274
/// trait Trait {
275
/// type Assoc;
276
/// }
277
///
278
/// #[derive(Reflect)]
279
/// #[reflect(where T::Assoc: List)]
280
/// struct Foo<T: Trait> where T::Assoc: Default {
281
/// value: T::Assoc,
282
/// }
283
///
284
/// // Generates a where clause like:
285
/// //
286
/// // impl<T: Trait> bevy_reflect::Reflect for Foo<T>
287
/// // where
288
/// // Foo<T>: Any + Send + Sync,
289
/// // T::Assoc: Default,
290
/// // T: TypePath,
291
/// // T::Assoc: FromReflect + TypePath + MaybeTyped + RegisterForReflection,
292
/// // T::Assoc: List,
293
/// // {/* ... */}
294
/// ```
295
///
296
/// ## `#[reflect(@...)]`
297
///
298
/// This attribute can be used to register custom attributes to the type's `TypeInfo`.
299
///
300
/// It accepts any expression after the `@` symbol that resolves to a value which implements `Reflect`.
301
///
302
/// Any number of custom attributes may be registered, however, each the type of each attribute must be unique.
303
/// If two attributes of the same type are registered, the last one will overwrite the first.
304
///
305
/// ### Example
306
///
307
/// ```ignore
308
/// #[derive(Reflect)]
309
/// struct Required;
310
///
311
/// #[derive(Reflect)]
312
/// struct EditorTooltip(String);
313
///
314
/// impl EditorTooltip {
315
/// fn new(text: &str) -> Self {
316
/// Self(text.to_string())
317
/// }
318
/// }
319
///
320
/// #[derive(Reflect)]
321
/// // Specify a "required" status and tooltip:
322
/// #[reflect(@Required, @EditorTooltip::new("An ID is required!"))]
323
/// struct Id(u8);
324
/// ```
325
/// ## `#[reflect(no_auto_register)]`
326
///
327
/// This attribute will opt-out of the automatic reflect type registration.
328
///
329
/// All non-generic types annotated with `#[derive(Reflect)]` are usually automatically registered on app startup.
330
/// If this behavior is not desired, this attribute may be used to disable it for the annotated type.
331
///
332
/// # Field Attributes
333
///
334
/// Along with the container attributes, this macro comes with some attributes that may be applied
335
/// to the contained fields themselves.
336
///
337
/// ## `#[reflect(ignore)]`
338
///
339
/// This attribute simply marks a field to be ignored by the reflection API.
340
///
341
/// This allows fields to completely opt-out of reflection,
342
/// which may be useful for maintaining invariants, keeping certain data private,
343
/// or allowing the use of types that do not implement `Reflect` within the container.
344
///
345
/// ## `#[reflect(skip_serializing)]`
346
///
347
/// This works similar to `#[reflect(ignore)]`, but rather than opting out of _all_ of reflection,
348
/// it simply opts the field out of both serialization and deserialization.
349
/// This can be useful when a field should be accessible via reflection, but may not make
350
/// sense in a serialized form, such as computed data.
351
///
352
/// What this does is register the `SerializationData` type within the `GetTypeRegistration` implementation,
353
/// which will be used by the reflection serializers to determine whether or not the field is serializable.
354
///
355
/// ## `#[reflect(clone)]`
356
///
357
/// This attribute affects the `Reflect::reflect_clone` implementation.
358
///
359
/// Without this attribute, the implementation will rely on the field's own `Reflect::reflect_clone` implementation.
360
/// When this attribute is present, the implementation will instead use the field's `Clone` implementation directly.
361
///
362
/// The attribute may also take the path to a custom function like `#[reflect(clone = "path::to::my_clone_func")]`,
363
/// where `my_clone_func` matches the signature `(&Self) -> Self`.
364
///
365
/// This attribute does nothing if the containing struct/enum has the `#[reflect(Clone)]` attribute.
366
///
367
/// ## `#[reflect(@...)]`
368
///
369
/// This attribute can be used to register custom attributes to the field's `TypeInfo`.
370
///
371
/// It accepts any expression after the `@` symbol that resolves to a value which implements `Reflect`.
372
///
373
/// Any number of custom attributes may be registered, however, each the type of each attribute must be unique.
374
/// If two attributes of the same type are registered, the last one will overwrite the first.
375
///
376
/// ### Example
377
///
378
/// ```ignore
379
/// #[derive(Reflect)]
380
/// struct EditorTooltip(String);
381
///
382
/// impl EditorTooltip {
383
/// fn new(text: &str) -> Self {
384
/// Self(text.to_string())
385
/// }
386
/// }
387
///
388
/// #[derive(Reflect)]
389
/// struct Slider {
390
/// // Specify a custom range and tooltip:
391
/// #[reflect(@0.0..=1.0, @EditorTooltip::new("Must be between 0 and 1"))]
392
/// value: f32,
393
/// }
394
/// ```
395
///
396
/// [`reflect_trait`]: macro@reflect_trait
397
#[proc_macro_derive(Reflect, attributes(reflect, type_path, type_name))]
398
pub fn derive_reflect(input: TokenStream) -> TokenStream {
399
let ast = parse_macro_input!(input as DeriveInput);
400
match_reflect_impls(ast, ReflectImplSource::DeriveLocalType)
401
}
402
403
/// Derives the `FromReflect` trait.
404
///
405
/// # Field Attributes
406
///
407
/// ## `#[reflect(ignore)]`
408
///
409
/// The `#[reflect(ignore)]` attribute is shared with the [`#[derive(Reflect)]`](Reflect) macro and has much of the same
410
/// functionality in that it denotes that a field will be ignored by the reflection API.
411
///
412
/// The only major difference is that using it with this derive requires that the field implements [`Default`].
413
/// Without this requirement, there would be no way for `FromReflect` to automatically construct missing fields
414
/// that have been ignored.
415
///
416
/// ## `#[reflect(default)]`
417
///
418
/// If a field cannot be read, this attribute specifies a default value to be used in its place.
419
///
420
/// By default, this attribute denotes that the field's type implements [`Default`].
421
/// However, it can also take in a path string to a user-defined function that will return the default value.
422
/// This takes the form: `#[reflect(default = "path::to::my_function")]` where `my_function` is a parameterless
423
/// function that must return some default value for the type.
424
///
425
/// Specifying a custom default can be used to give different fields their own specialized defaults,
426
/// or to remove the `Default` requirement on fields marked with `#[reflect(ignore)]`.
427
/// Additionally, either form of this attribute can be used to fill in fields that are simply missing,
428
/// such as when converting a partially-constructed dynamic type to a concrete one.
429
#[proc_macro_derive(FromReflect, attributes(reflect))]
430
pub fn derive_from_reflect(input: TokenStream) -> TokenStream {
431
let ast = parse_macro_input!(input as DeriveInput);
432
433
let derive_data = match ReflectDerive::from_input(
434
&ast,
435
ReflectProvenance {
436
source: ReflectImplSource::DeriveLocalType,
437
trait_: ReflectTraitToImpl::FromReflect,
438
},
439
) {
440
Ok(data) => data,
441
Err(err) => return err.into_compile_error().into(),
442
};
443
444
let from_reflect_impl = match derive_data {
445
ReflectDerive::Struct(struct_data) | ReflectDerive::UnitStruct(struct_data) => {
446
from_reflect::impl_struct(&struct_data)
447
}
448
ReflectDerive::TupleStruct(struct_data) => from_reflect::impl_tuple_struct(&struct_data),
449
ReflectDerive::Enum(meta) => from_reflect::impl_enum(&meta),
450
ReflectDerive::Opaque(meta) => from_reflect::impl_opaque(&meta),
451
};
452
453
TokenStream::from(quote! {
454
const _: () = {
455
#from_reflect_impl
456
};
457
})
458
}
459
460
/// Derives the `TypePath` trait, providing a stable alternative to [`std::any::type_name`].
461
///
462
/// # Container Attributes
463
///
464
/// ## `#[type_path = "my_crate::foo"]`
465
///
466
/// Optionally specifies a custom module path to use instead of [`module_path`].
467
///
468
/// This path does not include the final identifier.
469
///
470
/// ## `#[type_name = "RenamedType"]`
471
///
472
/// Optionally specifies a new terminating identifier for `TypePath`.
473
///
474
/// To use this attribute, `#[type_path = "..."]` must also be specified.
475
#[proc_macro_derive(TypePath, attributes(type_path, type_name))]
476
pub fn derive_type_path(input: TokenStream) -> TokenStream {
477
let ast = parse_macro_input!(input as DeriveInput);
478
let derive_data = match ReflectDerive::from_input(
479
&ast,
480
ReflectProvenance {
481
source: ReflectImplSource::DeriveLocalType,
482
trait_: ReflectTraitToImpl::TypePath,
483
},
484
) {
485
Ok(data) => data,
486
Err(err) => return err.into_compile_error().into(),
487
};
488
489
let type_path_impl = impls::impl_type_path(derive_data.meta());
490
491
TokenStream::from(quote! {
492
const _: () = {
493
#type_path_impl
494
};
495
})
496
}
497
498
/// A macro that automatically generates type data for traits, which their implementors can then register.
499
///
500
/// The output of this macro is a struct that takes reflected instances of the implementor's type
501
/// and returns the value as a trait object.
502
/// Because of this, **it can only be used on [object-safe] traits.**
503
///
504
/// For a trait named `MyTrait`, this will generate the struct `ReflectMyTrait`.
505
/// The generated struct can be created using `FromType` with any type that implements the trait.
506
/// The creation and registration of this generated struct as type data can be automatically handled
507
/// by [`#[derive(Reflect)]`](Reflect).
508
///
509
/// # Example
510
///
511
/// ```ignore (bevy_reflect is not accessible from this crate)
512
/// # use std::any::TypeId;
513
/// # use bevy_reflect_derive::{Reflect, reflect_trait};
514
/// #[reflect_trait] // Generates `ReflectMyTrait`
515
/// trait MyTrait {
516
/// fn print(&self) -> &str;
517
/// }
518
///
519
/// #[derive(Reflect)]
520
/// #[reflect(MyTrait)] // Automatically registers `ReflectMyTrait`
521
/// struct SomeStruct;
522
///
523
/// impl MyTrait for SomeStruct {
524
/// fn print(&self) -> &str {
525
/// "Hello, World!"
526
/// }
527
/// }
528
///
529
/// // We can create the type data manually if we wanted:
530
/// let my_trait: ReflectMyTrait = FromType::<SomeStruct>::from_type();
531
///
532
/// // Or we can simply get it from the registry:
533
/// let mut registry = TypeRegistry::default();
534
/// registry.register::<SomeStruct>();
535
/// let my_trait = registry
536
/// .get_type_data::<ReflectMyTrait>(TypeId::of::<SomeStruct>())
537
/// .unwrap();
538
///
539
/// // Then use it on reflected data
540
/// let reflected: Box<dyn Reflect> = Box::new(SomeStruct);
541
/// let reflected_my_trait: &dyn MyTrait = my_trait.get(&*reflected).unwrap();
542
/// assert_eq!("Hello, World!", reflected_my_trait.print());
543
/// ```
544
///
545
/// [object-safe]: https://doc.rust-lang.org/reference/items/traits.html#object-safety
546
#[proc_macro_attribute]
547
pub fn reflect_trait(args: TokenStream, input: TokenStream) -> TokenStream {
548
trait_reflection::reflect_trait(&args, input)
549
}
550
551
/// Generates a wrapper type that can be used to "derive `Reflect`" for remote types.
552
///
553
/// This works by wrapping the remote type in a generated wrapper that has the `#[repr(transparent)]` attribute.
554
/// This allows the two types to be safely [transmuted] back-and-forth.
555
///
556
/// # Defining the Wrapper
557
///
558
/// Before defining the wrapper type, please note that it is _required_ that all fields of the remote type are public.
559
/// The generated code will, at times, need to access or mutate them,
560
/// and we do not currently have a way to assign getters/setters to each field
561
/// (but this may change in the future).
562
///
563
/// The wrapper definition should match the remote type 1-to-1.
564
/// This includes the naming and ordering of the fields and variants.
565
///
566
/// Generics and lifetimes do _not_ need to have the same names, however, they _do_ need to follow the same order.
567
/// Additionally, whether generics are inlined or placed in a where clause should not matter.
568
///
569
/// Lastly, all macros and doc-comments should be placed __below__ this attribute.
570
/// If they are placed above, they will not be properly passed to the generated wrapper type.
571
///
572
/// # Example
573
///
574
/// Given a remote type, `RemoteType`:
575
///
576
/// ```
577
/// #[derive(Default)]
578
/// struct RemoteType<T>
579
/// where
580
/// T: Default + Clone,
581
/// {
582
/// pub foo: T,
583
/// pub bar: usize
584
/// }
585
/// ```
586
///
587
/// We would define our wrapper type as such:
588
///
589
/// ```ignore
590
/// use external_crate::RemoteType;
591
///
592
/// #[reflect_remote(RemoteType<T>)]
593
/// #[derive(Default)]
594
/// pub struct WrapperType<T: Default + Clone> {
595
/// pub foo: T,
596
/// pub bar: usize
597
/// }
598
/// ```
599
///
600
/// Apart from all the reflection trait implementations, this generates something like the following:
601
///
602
/// ```ignore
603
/// use external_crate::RemoteType;
604
///
605
/// #[derive(Default)]
606
/// #[repr(transparent)]
607
/// pub struct Wrapper<T: Default + Clone>(RemoteType<T>);
608
/// ```
609
///
610
/// # Usage as a Field
611
///
612
/// You can tell `Reflect` to use a remote type's wrapper internally on fields of a struct or enum.
613
/// This allows the real type to be used as usual while `Reflect` handles everything internally.
614
/// To do this, add the `#[reflect(remote = path::to::MyType)]` attribute to your field:
615
///
616
/// ```ignore
617
/// #[derive(Reflect)]
618
/// struct SomeStruct {
619
/// #[reflect(remote = RemoteTypeWrapper)]
620
/// data: RemoteType
621
/// }
622
/// ```
623
///
624
/// ## Safety
625
///
626
/// When using the `#[reflect(remote = path::to::MyType)]` field attribute, be sure you are defining the correct wrapper type.
627
/// Internally, this field will be unsafely [transmuted], and is only sound if using a wrapper generated for the remote type.
628
/// This also means keeping your wrapper definitions up-to-date with the remote types.
629
///
630
/// [transmuted]: std::mem::transmute
631
#[proc_macro_attribute]
632
pub fn reflect_remote(args: TokenStream, input: TokenStream) -> TokenStream {
633
remote::reflect_remote(args, input)
634
}
635
636
/// A macro used to generate reflection trait implementations for the given type.
637
///
638
/// This is functionally the same as [deriving `Reflect`] using the `#[reflect(opaque)]` container attribute.
639
///
640
/// The only reason for this macro's existence is so that `bevy_reflect` can easily implement the reflection traits
641
/// on primitives and other opaque types internally.
642
///
643
/// Since this macro also implements `TypePath`, the type path must be explicit.
644
/// See [`impl_type_path!`] for the exact syntax.
645
///
646
/// # Examples
647
///
648
/// Types can be passed with or without registering type data:
649
///
650
/// ```ignore (bevy_reflect is not accessible from this crate)
651
/// impl_reflect_opaque!(my_crate::Foo);
652
/// impl_reflect_opaque!(my_crate::Bar(Debug, Default, Serialize, Deserialize));
653
/// ```
654
///
655
/// Generic types can also specify their parameters and bounds:
656
///
657
/// ```ignore (bevy_reflect is not accessible from this crate)
658
/// impl_reflect_opaque!(my_crate::Foo<T1, T2: Baz> where T1: Bar (Default, Serialize, Deserialize));
659
/// ```
660
///
661
/// Custom type paths can be specified:
662
///
663
/// ```ignore (bevy_reflect is not accessible from this crate)
664
/// impl_reflect_opaque!((in not_my_crate as NotFoo) Foo(Debug, Default));
665
/// ```
666
///
667
/// [deriving `Reflect`]: Reflect
668
#[proc_macro]
669
pub fn impl_reflect_opaque(input: TokenStream) -> TokenStream {
670
let def = parse_macro_input!(input with ReflectOpaqueDef::parse_reflect);
671
672
let default_name = &def.type_path.segments.last().unwrap().ident;
673
let type_path = if def.type_path.leading_colon.is_none() && def.custom_path.is_none() {
674
ReflectTypePath::Primitive(default_name)
675
} else {
676
ReflectTypePath::External {
677
path: &def.type_path,
678
custom_path: def.custom_path.map(|path| path.into_path(default_name)),
679
generics: &def.generics,
680
}
681
};
682
683
let meta = ReflectMeta::new(type_path, def.traits.unwrap_or_default());
684
685
#[cfg(feature = "documentation")]
686
let meta = meta.with_docs(documentation::Documentation::from_attributes(&def.attrs));
687
688
let reflect_impls = impls::impl_opaque(&meta);
689
let from_reflect_impl = from_reflect::impl_opaque(&meta);
690
691
TokenStream::from(quote! {
692
const _: () = {
693
#reflect_impls
694
#from_reflect_impl
695
};
696
})
697
}
698
699
/// A replacement for `#[derive(Reflect)]` to be used with foreign types which
700
/// the definitions of cannot be altered.
701
///
702
/// This macro is an alternative to [`impl_reflect_opaque!`] and [`impl_from_reflect_opaque!`]
703
/// which implement foreign types as Opaque types. Note that there is no `impl_from_reflect`,
704
/// as this macro will do the job of both. This macro implements them using one of the reflect
705
/// variant traits (`bevy_reflect::{Struct, TupleStruct, Enum}`, etc.),
706
/// which have greater functionality. The type being reflected must be in scope, as you cannot
707
/// qualify it in the macro as e.g. `bevy::prelude::Vec3`.
708
///
709
/// It is necessary to add a `#[type_path = "my_crate::foo"]` attribute to all types.
710
///
711
/// It may be necessary to add `#[reflect(Default)]` for some types, specifically non-constructible
712
/// foreign types. Without `Default` reflected for such types, you will usually get an arcane
713
/// error message and fail to compile. If the type does not implement `Default`, it may not
714
/// be possible to reflect without extending the macro.
715
///
716
///
717
/// # Example
718
/// Implementing `Reflect` for `bevy::prelude::Vec3` as a struct type:
719
/// ```ignore (bevy_reflect is not accessible from this crate)
720
/// use bevy::prelude::Vec3;
721
///
722
/// impl_reflect!(
723
/// #[reflect(PartialEq, Serialize, Deserialize, Default)]
724
/// #[type_path = "bevy::prelude"]
725
/// struct Vec3 {
726
/// x: f32,
727
/// y: f32,
728
/// z: f32
729
/// }
730
/// );
731
/// ```
732
#[proc_macro]
733
pub fn impl_reflect(input: TokenStream) -> TokenStream {
734
let ast = parse_macro_input!(input as DeriveInput);
735
match_reflect_impls(ast, ReflectImplSource::ImplRemoteType)
736
}
737
738
/// A macro used to generate a `FromReflect` trait implementation for the given type.
739
///
740
/// This is functionally the same as [deriving `FromReflect`] on a type that [derives `Reflect`] using
741
/// the `#[reflect(opaque)]` container attribute.
742
///
743
/// The only reason this macro exists is so that `bevy_reflect` can easily implement `FromReflect` on
744
/// primitives and other opaque types internally.
745
///
746
/// Please note that this macro will not work with any type that [derives `Reflect`] normally
747
/// or makes use of the [`impl_reflect_opaque!`] macro, as those macros also implement `FromReflect`
748
/// by default.
749
///
750
/// # Examples
751
///
752
/// ```ignore (bevy_reflect is not accessible from this crate)
753
/// impl_from_reflect_opaque!(foo<T1, T2: Baz> where T1: Bar);
754
/// ```
755
///
756
/// [deriving `FromReflect`]: FromReflect
757
/// [derives `Reflect`]: Reflect
758
#[proc_macro]
759
pub fn impl_from_reflect_opaque(input: TokenStream) -> TokenStream {
760
let def = parse_macro_input!(input with ReflectOpaqueDef::parse_from_reflect);
761
762
let default_name = &def.type_path.segments.last().unwrap().ident;
763
let type_path = if def.type_path.leading_colon.is_none()
764
&& def.custom_path.is_none()
765
&& def.generics.params.is_empty()
766
{
767
ReflectTypePath::Primitive(default_name)
768
} else {
769
ReflectTypePath::External {
770
path: &def.type_path,
771
custom_path: def.custom_path.map(|alias| alias.into_path(default_name)),
772
generics: &def.generics,
773
}
774
};
775
776
let from_reflect_impl =
777
from_reflect::impl_opaque(&ReflectMeta::new(type_path, def.traits.unwrap_or_default()));
778
779
TokenStream::from(quote! {
780
const _: () = {
781
#from_reflect_impl
782
};
783
})
784
}
785
786
/// A replacement for [deriving `TypePath`] for use on foreign types.
787
///
788
/// Since (unlike the derive) this macro may be invoked in a different module to where the type is defined,
789
/// it requires an 'absolute' path definition.
790
///
791
/// Specifically, a leading `::` denoting a global path must be specified
792
/// or a preceding `(in my_crate::foo)` to specify the custom path must be used.
793
///
794
/// # Examples
795
///
796
/// Implementing `TypePath` on a foreign type:
797
/// ```ignore (bevy_reflect is not accessible from this crate)
798
/// impl_type_path!(::foreign_crate::foo::bar::Baz);
799
/// ```
800
///
801
/// On a generic type (this can also accept trait bounds):
802
/// ```ignore (bevy_reflect is not accessible from this crate)
803
/// impl_type_path!(::foreign_crate::Foo<T>);
804
/// impl_type_path!(::foreign_crate::Goo<T: ?Sized>);
805
/// ```
806
///
807
/// On a primitive (note this will not compile for a non-primitive type):
808
/// ```ignore (bevy_reflect is not accessible from this crate)
809
/// impl_type_path!(bool);
810
/// ```
811
///
812
/// With a custom type path:
813
/// ```ignore (bevy_reflect is not accessible from this crate)
814
/// impl_type_path!((in other_crate::foo::bar) Baz);
815
/// ```
816
///
817
/// With a custom type path and a custom type name:
818
/// ```ignore (bevy_reflect is not accessible from this crate)
819
/// impl_type_path!((in other_crate::foo as Baz) Bar);
820
/// ```
821
///
822
/// [deriving `TypePath`]: TypePath
823
#[proc_macro]
824
pub fn impl_type_path(input: TokenStream) -> TokenStream {
825
let def = parse_macro_input!(input as NamedTypePathDef);
826
827
let type_path = match def {
828
NamedTypePathDef::External {
829
ref path,
830
custom_path,
831
ref generics,
832
} => {
833
let default_name = &path.segments.last().unwrap().ident;
834
835
ReflectTypePath::External {
836
path,
837
custom_path: custom_path.map(|path| path.into_path(default_name)),
838
generics,
839
}
840
}
841
NamedTypePathDef::Primitive(ref ident) => ReflectTypePath::Primitive(ident),
842
};
843
844
let meta = ReflectMeta::new(type_path, ContainerAttributes::default());
845
846
let type_path_impl = impls::impl_type_path(&meta);
847
848
TokenStream::from(quote! {
849
const _: () = {
850
#type_path_impl
851
};
852
})
853
}
854
855
/// Collects and loads type registrations when using `auto_register_static` feature.
856
///
857
/// Correctly using this macro requires following:
858
/// 1. This macro must be called **last** during compilation. This can be achieved by putting your main function
859
/// in a separate crate or restructuring your project to be separated into `bin` and `lib`, and putting this macro in `bin`.
860
/// Any automatic type registrations using `#[derive(Reflect)]` within the same crate as this macro are not guaranteed to run.
861
/// 2. Your project must be compiled with `auto_register_static` feature **and** `BEVY_REFLECT_AUTO_REGISTER_STATIC=1` env variable.
862
/// Enabling the feature generates registration functions while setting the variable enables export and
863
/// caching of registration function names.
864
/// 3. Must be called before creating `App` or using `TypeRegistry::register_derived_types`.
865
///
866
/// If you're experiencing linking issues try running `cargo clean` before rebuilding.
867
#[proc_macro]
868
pub fn load_type_registrations(_input: TokenStream) -> TokenStream {
869
if !cfg!(feature = "auto_register_static") {
870
return TokenStream::new();
871
}
872
873
let Ok(dir) = fs::read_dir(PathBuf::from("target").join("bevy_reflect_type_registrations"))
874
else {
875
return TokenStream::new();
876
};
877
let mut str_buf = String::new();
878
let mut registration_fns = Vec::new();
879
for file_path in dir {
880
let mut file = fs::OpenOptions::new()
881
.read(true)
882
.open(file_path.unwrap().path())
883
.unwrap();
884
file.read_to_string(&mut str_buf).unwrap();
885
registration_fns.extend(str_buf.lines().filter(|s| !s.is_empty()).map(|s| {
886
s.parse::<proc_macro2::TokenStream>()
887
.expect("Unexpected function name")
888
}));
889
str_buf.clear();
890
}
891
let bevy_reflect_path = meta::get_bevy_reflect_path();
892
TokenStream::from(quote! {
893
{
894
fn _register_types(){
895
unsafe extern "Rust" {
896
#( safe fn #registration_fns(registry_ptr: &mut #bevy_reflect_path::TypeRegistry); )*
897
};
898
#( #bevy_reflect_path::__macro_exports::auto_register::push_registration_fn(#registration_fns); )*
899
}
900
_register_types();
901
}
902
})
903
}
904
905