Skip to content

Commit b85d9a3

Browse files
committed
Auto-register ReflectFromReflect
1 parent f64192c commit b85d9a3

File tree

17 files changed

+209
-94
lines changed

17 files changed

+209
-94
lines changed

crates/bevy_asset/src/handle.rs

+2
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@ where
103103
marker: PhantomData<fn() -> T>,
104104
}
105105

106+
#[derive(Default)]
106107
enum HandleType {
108+
#[default]
107109
Weak,
108110
Strong(Sender<RefChange>),
109111
}

crates/bevy_input/src/touchpad.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use bevy_ecs::event::Event;
2-
use bevy_reflect::{Reflect, ReflectFromReflect};
2+
use bevy_reflect::Reflect;
33

44
#[cfg(feature = "serialize")]
55
use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
@@ -13,7 +13,7 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
1313
///
1414
/// - Only available on **`macOS`**.
1515
#[derive(Event, Debug, Clone, Copy, PartialEq, Reflect)]
16-
#[reflect(Debug, PartialEq, FromReflect)]
16+
#[reflect(Debug, PartialEq)]
1717
#[cfg_attr(
1818
feature = "serialize",
1919
derive(serde::Serialize, serde::Deserialize),
@@ -30,7 +30,7 @@ pub struct TouchpadMagnify(pub f32);
3030
///
3131
/// - Only available on **`macOS`**.
3232
#[derive(Event, Debug, Clone, Copy, PartialEq, Reflect)]
33-
#[reflect(Debug, PartialEq, FromReflect)]
33+
#[reflect(Debug, PartialEq)]
3434
#[cfg_attr(
3535
feature = "serialize",
3636
derive(serde::Serialize, serde::Deserialize),

crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs

+6-17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use crate::container_attributes::{FromReflectAttrs, ReflectTraits};
22
use crate::field_attributes::{parse_field_attrs, ReflectFieldAttr};
3-
use crate::fq_std::{FQAny, FQDefault, FQSend, FQSync};
43
use crate::type_path::parse_path_no_leading_colon;
54
use crate::utility::{members_to_serialization_denylist, StringExpr, WhereClauseOptions};
65
use bit_set::BitSet;
@@ -89,6 +88,7 @@ pub(crate) struct ReflectEnum<'a> {
8988
}
9089

9190
/// Represents a field on a struct or tuple struct.
91+
#[derive(Clone)]
9292
pub(crate) struct StructField<'a> {
9393
/// The raw field.
9494
pub data: &'a Field,
@@ -450,6 +450,7 @@ impl<'a> ReflectStruct<'a> {
450450
}
451451

452452
/// Get a collection of types which are ignored by the reflection API
453+
#[allow(dead_code)]
453454
pub fn ignored_types(&self) -> Vec<syn::Type> {
454455
self.ignored_fields()
455456
.map(|field| field.data.ty.clone())
@@ -470,14 +471,7 @@ impl<'a> ReflectStruct<'a> {
470471
}
471472

472473
pub fn where_clause_options(&self) -> WhereClauseOptions {
473-
let bevy_reflect_path = &self.meta().bevy_reflect_path;
474-
WhereClauseOptions {
475-
active_types: self.active_types().into(),
476-
active_trait_bounds: quote! { #bevy_reflect_path::Reflect },
477-
ignored_types: self.ignored_types().into(),
478-
ignored_trait_bounds: quote! { #FQAny + #FQSend + #FQSync },
479-
..WhereClauseOptions::type_path_bounds(self.meta())
480-
}
474+
WhereClauseOptions::new(self.meta(), self.active_fields(), self.ignored_fields())
481475
}
482476
}
483477

@@ -508,6 +502,7 @@ impl<'a> ReflectEnum<'a> {
508502
}
509503

510504
/// Get a collection of types which are exposed to the reflection API
505+
#[allow(dead_code)]
511506
pub fn active_types(&self) -> Vec<syn::Type> {
512507
self.active_fields()
513508
.map(|field| field.data.ty.clone())
@@ -522,21 +517,15 @@ impl<'a> ReflectEnum<'a> {
522517
}
523518

524519
/// Get a collection of types which are ignored to the reflection API
520+
#[allow(dead_code)]
525521
pub fn ignored_types(&self) -> Vec<syn::Type> {
526522
self.ignored_fields()
527523
.map(|field| field.data.ty.clone())
528524
.collect()
529525
}
530526

531527
pub fn where_clause_options(&self) -> WhereClauseOptions {
532-
let bevy_reflect_path = &self.meta().bevy_reflect_path;
533-
WhereClauseOptions {
534-
active_types: self.active_types().into(),
535-
active_trait_bounds: quote! { #bevy_reflect_path::FromReflect },
536-
ignored_types: self.ignored_types().into(),
537-
ignored_trait_bounds: quote! { #FQAny + #FQSend + #FQSync + #FQDefault },
538-
..WhereClauseOptions::type_path_bounds(self.meta())
539-
}
528+
WhereClauseOptions::new(self.meta(), self.active_fields(), self.ignored_fields())
540529
}
541530
}
542531

crates/bevy_reflect/bevy_reflect_derive/src/documentation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use syn::{Attribute, Expr, ExprLit, Lit, Meta};
99
///
1010
/// When converted to a [`TokenStream`], this will output an `Option<String>`
1111
/// containing the collection of doc comments.
12-
#[derive(Default)]
12+
#[derive(Default, Clone)]
1313
pub(crate) struct Documentation {
1414
docs: Vec<String>,
1515
}

crates/bevy_reflect/bevy_reflect_derive/src/field_attributes.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ impl ReflectIgnoreBehavior {
4646
}
4747

4848
/// A container for attributes defined on a reflected type's field.
49-
#[derive(Default)]
49+
#[derive(Default, Clone)]
5050
pub(crate) struct ReflectFieldAttr {
5151
/// Determines how this field should be ignored if at all.
5252
pub ignore: ReflectIgnoreBehavior,
@@ -55,7 +55,7 @@ pub(crate) struct ReflectFieldAttr {
5555
}
5656

5757
/// Controls how the default value is determined for a field.
58-
#[derive(Default)]
58+
#[derive(Default, Clone)]
5959
pub(crate) enum DefaultBehavior {
6060
/// Field is required.
6161
#[default]

crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs

+33-19
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::container_attributes::REFLECT_DEFAULT;
22
use crate::derive_data::ReflectEnum;
33
use crate::enum_utility::{get_variant_constructors, EnumVariantConstructors};
44
use crate::field_attributes::DefaultBehavior;
5-
use crate::fq_std::{FQAny, FQClone, FQDefault, FQOption, FQSend, FQSync};
5+
use crate::fq_std::{FQAny, FQClone, FQDefault, FQOption};
66
use crate::utility::{extend_where_clause, ident_or_index, WhereClauseOptions};
77
use crate::{ReflectMeta, ReflectStruct};
88
use proc_macro2::Span;
@@ -24,7 +24,7 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream {
2424
let bevy_reflect_path = meta.bevy_reflect_path();
2525
let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl();
2626
let where_from_reflect_clause =
27-
extend_where_clause(where_clause, &WhereClauseOptions::type_path_bounds(meta));
27+
extend_where_clause(where_clause, &WhereClauseOptions::new_value(meta));
2828
quote! {
2929
impl #impl_generics #bevy_reflect_path::FromReflect for #type_path #ty_generics #where_from_reflect_clause {
3030
fn from_reflect(reflect: &dyn #bevy_reflect_path::Reflect) -> #FQOption<Self> {
@@ -52,13 +52,19 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream
5252
// Add FromReflect bound for each active field
5353
let where_from_reflect_clause = extend_where_clause(
5454
where_clause,
55-
&WhereClauseOptions {
56-
active_types: reflect_enum.active_types().into_boxed_slice(),
57-
ignored_types: reflect_enum.ignored_types().into_boxed_slice(),
58-
active_trait_bounds: quote!(#bevy_reflect_path::FromReflect),
59-
ignored_trait_bounds: quote!(#FQDefault + #FQAny + #FQSend + #FQSync),
60-
..WhereClauseOptions::type_path_bounds(reflect_enum.meta())
61-
},
55+
&WhereClauseOptions::new_with_bounds(
56+
reflect_enum.meta(),
57+
reflect_enum.active_fields(),
58+
reflect_enum.ignored_fields(),
59+
|field| match &field.attrs.default {
60+
DefaultBehavior::Default => Some(quote!(#FQDefault)),
61+
_ => None,
62+
},
63+
|field| match &field.attrs.default {
64+
DefaultBehavior::Func(_) => None,
65+
_ => Some(quote!(#FQDefault)),
66+
},
67+
),
6268
);
6369

6470
quote! {
@@ -140,17 +146,25 @@ fn impl_struct_internal(
140146
// Add FromReflect bound for each active field
141147
let where_from_reflect_clause = extend_where_clause(
142148
where_clause,
143-
&WhereClauseOptions {
144-
active_types: reflect_struct.active_types().into_boxed_slice(),
145-
ignored_types: reflect_struct.ignored_types().into_boxed_slice(),
146-
active_trait_bounds: quote!(#bevy_reflect_path::FromReflect),
147-
ignored_trait_bounds: if is_defaultable {
148-
quote!(#FQAny + #FQSend + #FQSync)
149-
} else {
150-
quote!(#FQDefault + #FQAny + #FQSend + #FQSync)
149+
&WhereClauseOptions::new_with_bounds(
150+
reflect_struct.meta(),
151+
reflect_struct.active_fields(),
152+
reflect_struct.ignored_fields(),
153+
|field| match &field.attrs.default {
154+
DefaultBehavior::Default => Some(quote!(#FQDefault)),
155+
_ => None,
156+
},
157+
|field| {
158+
if is_defaultable {
159+
None
160+
} else {
161+
match &field.attrs.default {
162+
DefaultBehavior::Func(_) => None,
163+
_ => Some(quote!(#FQDefault)),
164+
}
165+
}
151166
},
152-
..WhereClauseOptions::type_path_bounds(reflect_struct.meta())
153-
},
167+
),
154168
);
155169

156170
quote! {

crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream {
2121
#[cfg(not(feature = "documentation"))]
2222
let with_docs: Option<proc_macro2::TokenStream> = None;
2323

24-
let where_clause_options = WhereClauseOptions::type_path_bounds(meta);
24+
let where_clause_options = WhereClauseOptions::new_value(meta);
2525
let typed_impl = impl_typed(
2626
meta,
2727
&where_clause_options,

crates/bevy_reflect/bevy_reflect_derive/src/lib.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ pub(crate) static TYPE_NAME_ATTRIBUTE_NAME: &str = "type_name";
7575
/// This is often used with traits that have been marked by the [`#[reflect_trait]`](macro@reflect_trait)
7676
/// macro in order to register the type's implementation of that trait.
7777
///
78+
/// ### Default Registrations
79+
///
80+
/// The following types are automatically registered when deriving `Reflect`:
81+
///
82+
/// * `ReflectFromReflect` (unless opting out of `FromReflect`)
83+
/// * `SerializationData`
84+
/// * `ReflectFromPtr`
85+
///
7886
/// ### Special Identifiers
7987
///
8088
/// There are a few "special" identifiers that work a bit differently:
@@ -118,6 +126,8 @@ pub(crate) static TYPE_NAME_ATTRIBUTE_NAME: &str = "type_name";
118126
/// This is useful for when a type can't or shouldn't implement `FromReflect`,
119127
/// or if a manual implementation is desired.
120128
///
129+
/// Note that in the latter case, `ReflectFromReflect` will no longer be automatically registered.
130+
///
121131
/// # Field Attributes
122132
///
123133
/// Along with the container attributes, this macro comes with some attributes that may be applied
@@ -263,7 +273,8 @@ pub fn derive_type_path(input: TokenStream) -> TokenStream {
263273

264274
impls::impl_type_path(
265275
derive_data.meta(),
266-
&WhereClauseOptions::type_path_bounds(derive_data.meta()),
276+
// Use `WhereClauseOptions::new_value` here so we don't enforce reflection bounds
277+
&WhereClauseOptions::new_value(derive_data.meta()),
267278
)
268279
.into()
269280
}
@@ -565,7 +576,7 @@ pub fn impl_type_path(input: TokenStream) -> TokenStream {
565576

566577
let meta = ReflectMeta::new(type_path, ReflectTraits::default());
567578

568-
impls::impl_type_path(&meta, &WhereClauseOptions::type_path_bounds(&meta)).into()
579+
impls::impl_type_path(&meta, &WhereClauseOptions::new_value(&meta)).into()
569580
}
570581

571582
/// Derives `TypeUuid` for the given type. This is used internally to implement `TypeUuid` on foreign types, such as those in the std. This macro should be used in the format of `<[Generic Params]> [Type (Path)], [Uuid (String Literal)]`.

crates/bevy_reflect/bevy_reflect_derive/src/registration.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
//! Contains code related specifically to Bevy's type registration.
22
3+
use crate::derive_data::ReflectMeta;
34
use crate::utility::{extend_where_clause, WhereClauseOptions};
45
use bit_set::BitSet;
56
use quote::quote;
67

7-
use crate::derive_data::ReflectMeta;
8-
98
/// Creates the `GetTypeRegistration` impl for the given type data.
109
#[allow(clippy::too_many_arguments)]
1110
pub(crate) fn impl_get_type_registration(
@@ -17,6 +16,16 @@ pub(crate) fn impl_get_type_registration(
1716
let bevy_reflect_path = meta.bevy_reflect_path();
1817
let registration_data = meta.traits().idents();
1918
let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl();
19+
let where_reflect_clause = extend_where_clause(where_clause, where_clause_options);
20+
21+
let from_reflect_data = if meta.from_reflect().should_auto_derive() {
22+
Some(quote! {
23+
registration.insert::<#bevy_reflect_path::ReflectFromReflect>(#bevy_reflect_path::FromType::<Self>::from_type());
24+
})
25+
} else {
26+
None
27+
};
28+
2029
let serialization_data = serialization_denylist.map(|denylist| {
2130
let denylist = denylist.into_iter();
2231
quote! {
@@ -25,14 +34,13 @@ pub(crate) fn impl_get_type_registration(
2534
}
2635
});
2736

28-
let where_reflect_clause = extend_where_clause(where_clause, where_clause_options);
29-
3037
quote! {
3138
#[allow(unused_mut)]
3239
impl #impl_generics #bevy_reflect_path::GetTypeRegistration for #type_path #ty_generics #where_reflect_clause {
3340
fn get_type_registration() -> #bevy_reflect_path::TypeRegistration {
3441
let mut registration = #bevy_reflect_path::TypeRegistration::of::<Self>();
3542
registration.insert::<#bevy_reflect_path::ReflectFromPtr>(#bevy_reflect_path::FromType::<Self>::from_type());
43+
#from_reflect_data
3644
#serialization_data
3745
#(registration.insert::<#registration_data>(#bevy_reflect_path::FromType::<Self>::from_type());)*
3846
registration

0 commit comments

Comments
 (0)