From 0a7fde1d8bd361af0b0b702facdd1c635d0eedae Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 29 Sep 2024 10:58:13 -0700 Subject: [PATCH 01/17] Removed `PartialReflect` bound on `MaybeTyped` --- crates/bevy_reflect/src/type_info.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index 2add261aa2b68..db9b2c4fe7ccb 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -1,7 +1,7 @@ use crate::{ ArrayInfo, DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicStruct, DynamicTuple, - DynamicTupleStruct, EnumInfo, Generics, ListInfo, MapInfo, PartialReflect, Reflect, - ReflectKind, SetInfo, StructInfo, TupleInfo, TupleStructInfo, TypePath, TypePathTable, + DynamicTupleStruct, EnumInfo, Generics, ListInfo, MapInfo, Reflect, ReflectKind, SetInfo, + StructInfo, TupleInfo, TupleStructInfo, TypePath, TypePathTable, }; use core::{ any::{Any, TypeId}, @@ -112,7 +112,7 @@ pub trait Typed: Reflect + TypePath { message = "`{Self}` does not implement `Typed` so cannot provide static type information", note = "consider annotating `{Self}` with `#[derive(Reflect)]`" )] -pub trait MaybeTyped: PartialReflect { +pub trait MaybeTyped { /// Returns the compile-time [info] for the underlying type, if it exists. /// /// [info]: TypeInfo From 4c467f32849e9bb8a4adc29cbf3d619f05b1c8fe Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 29 Sep 2024 10:58:31 -0700 Subject: [PATCH 02/17] Removed `PartialReflect` bounds in field info constructors --- crates/bevy_reflect/src/fields.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bevy_reflect/src/fields.rs b/crates/bevy_reflect/src/fields.rs index 3a521c21ccbee..66cc2c0de9744 100644 --- a/crates/bevy_reflect/src/fields.rs +++ b/crates/bevy_reflect/src/fields.rs @@ -1,7 +1,7 @@ use crate::{ attributes::{impl_custom_attribute_methods, CustomAttributes}, type_info::impl_type_methods, - MaybeTyped, PartialReflect, Type, TypeInfo, TypePath, + MaybeTyped, Type, TypeInfo, TypePath, }; use bevy_platform_support::sync::Arc; @@ -18,7 +18,7 @@ pub struct NamedField { impl NamedField { /// Create a new [`NamedField`]. - pub fn new(name: &'static str) -> Self { + pub fn new(name: &'static str) -> Self { Self { name, type_info: T::maybe_type_info, @@ -80,7 +80,7 @@ pub struct UnnamedField { } impl UnnamedField { - pub fn new(index: usize) -> Self { + pub fn new(index: usize) -> Self { Self { index, type_info: T::maybe_type_info, From f58d2c402b87fe5fbe86a7c491848fe4cb8d5de9 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 29 Sep 2024 10:59:45 -0700 Subject: [PATCH 03/17] Added `CastPartialReflect` and `CastReflect` --- .../bevy_reflect/derive/src/struct_utility.rs | 8 +- .../derive/src/where_clause_options.rs | 4 +- crates/bevy_reflect/src/cast.rs | 185 ++++++++++++++++++ crates/bevy_reflect/src/lib.rs | 1 + 4 files changed, 194 insertions(+), 4 deletions(-) create mode 100644 crates/bevy_reflect/src/cast.rs diff --git a/crates/bevy_reflect/derive/src/struct_utility.rs b/crates/bevy_reflect/derive/src/struct_utility.rs index 09604419b6043..50bd063dbe2d8 100644 --- a/crates/bevy_reflect/derive/src/struct_utility.rs +++ b/crates/bevy_reflect/derive/src/struct_utility.rs @@ -28,7 +28,9 @@ impl FieldAccessors { <#wrapper_ty as #bevy_reflect_path::ReflectRemote>::as_wrapper(&#accessor) } } - None => quote!(& #accessor), + None => { + quote!(#bevy_reflect_path::cast::CastPartialReflect::as_partial_reflect(&#accessor)) + } } }); let fields_mut = Self::get_fields(reflect_struct, |field, accessor| { @@ -38,7 +40,9 @@ impl FieldAccessors { <#wrapper_ty as #bevy_reflect_path::ReflectRemote>::as_wrapper_mut(&mut #accessor) } } - None => quote!(&mut #accessor), + None => { + quote!(#bevy_reflect_path::cast::CastPartialReflect::as_partial_reflect_mut(&mut #accessor)) + } } }); diff --git a/crates/bevy_reflect/derive/src/where_clause_options.rs b/crates/bevy_reflect/derive/src/where_clause_options.rs index 1551e008d017c..7608716cc1ecb 100644 --- a/crates/bevy_reflect/derive/src/where_clause_options.rs +++ b/crates/bevy_reflect/derive/src/where_clause_options.rs @@ -170,14 +170,14 @@ impl<'a, 'b> WhereClauseOptions<'a, 'b> { } } - /// The `PartialReflect` or `FromReflect` bound to use based on `#[reflect(from_reflect = false)]`. + /// The `CastPartialReflect` or `FromReflect` bound to use based on `#[reflect(from_reflect = false)]`. fn reflect_bound(&self) -> TokenStream { let bevy_reflect_path = self.meta.bevy_reflect_path(); if self.meta.from_reflect().should_auto_derive() { quote!(#bevy_reflect_path::FromReflect) } else { - quote!(#bevy_reflect_path::PartialReflect) + quote!(#bevy_reflect_path::cast::CastPartialReflect) } } diff --git a/crates/bevy_reflect/src/cast.rs b/crates/bevy_reflect/src/cast.rs new file mode 100644 index 0000000000000..85f107802c078 --- /dev/null +++ b/crates/bevy_reflect/src/cast.rs @@ -0,0 +1,185 @@ +use crate as bevy_reflect; +use crate::__macro_exports::RegisterForReflection; +use crate::{MaybeTyped, PartialReflect, Reflect}; +use bevy_reflect_derive::impl_type_path; + +pub trait CastPartialReflect { + fn as_partial_reflect(&self) -> &dyn PartialReflect; + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect; + fn into_partial_reflect(self: Box) -> Box; +} + +impl CastPartialReflect for T { + fn as_partial_reflect(&self) -> &dyn PartialReflect { + self + } + + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { + self + } + + fn into_partial_reflect(self: Box) -> Box { + self + } +} + +impl CastPartialReflect for dyn PartialReflect { + fn as_partial_reflect(&self) -> &dyn PartialReflect { + self + } + + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { + self + } + + fn into_partial_reflect(self: Box) -> Box { + self + } +} + +impl CastPartialReflect for dyn Reflect { + fn as_partial_reflect(&self) -> &dyn PartialReflect { + self.as_partial_reflect() + } + + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { + self.as_partial_reflect_mut() + } + + fn into_partial_reflect(self: Box) -> Box { + self.into_partial_reflect() + } +} + +impl CastPartialReflect for Box { + fn as_partial_reflect(&self) -> &dyn PartialReflect { + self.as_ref() + } + + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { + self.as_mut() + } + + fn into_partial_reflect(self: Box) -> Box { + *self + } +} + +impl CastPartialReflect for Box { + fn as_partial_reflect(&self) -> &dyn PartialReflect { + self.as_ref().as_partial_reflect() + } + + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { + self.as_mut().as_partial_reflect_mut() + } + + fn into_partial_reflect(self: Box) -> Box { + self.into_reflect().into_partial_reflect() + } +} + +pub trait CastReflect: CastPartialReflect { + fn as_reflect(&self) -> &dyn Reflect; + fn as_reflect_mut(&mut self) -> &mut dyn Reflect; + fn into_reflect(self: Box) -> Box; +} + +impl CastReflect for T { + fn as_reflect(&self) -> &dyn Reflect { + self + } + + fn as_reflect_mut(&mut self) -> &mut dyn Reflect { + self + } + + fn into_reflect(self: Box) -> Box { + self + } +} + +impl CastReflect for dyn Reflect { + fn as_reflect(&self) -> &dyn Reflect { + self + } + + fn as_reflect_mut(&mut self) -> &mut dyn Reflect { + self + } + + fn into_reflect(self: Box) -> Box { + self + } +} + +impl CastReflect for Box { + fn as_reflect(&self) -> &dyn Reflect { + self.as_ref() + } + + fn as_reflect_mut(&mut self) -> &mut dyn Reflect { + self.as_mut() + } + + fn into_reflect(self: Box) -> Box { + *self + } +} + +impl_type_path!(::alloc::boxed::Box); + +impl MaybeTyped for Box {} +impl MaybeTyped for Box {} + +impl RegisterForReflection for Box {} +impl RegisterForReflection for Box {} + +#[cfg(test)] +mod tests { + use super::*; + use crate as bevy_reflect; + use crate::{Struct, TupleStruct}; + use static_assertions::assert_not_impl_all; + + #[test] + fn should_not_reflect_box() { + assert_not_impl_all!(Box: Reflect, PartialReflect); + assert_not_impl_all!(Box: Reflect, PartialReflect); + assert_not_impl_all!(Box: Reflect, PartialReflect); + } + + #[test] + fn should_reflect_boxed_struct_field() { + #[derive(Reflect)] + #[reflect(from_reflect = false)] + struct MyStruct { + value: Box, + } + + let my_struct: Box = Box::new(MyStruct { + value: Box::new(123_i32), + }); + + let field = my_struct.field("value").unwrap(); + assert_eq!(field.try_downcast_ref::(), Some(&123)); + + let field_info = field.get_represented_type_info().unwrap(); + assert!(field_info.ty().is::()); + } + + #[test] + fn should_reflect_boxed_tuple_struct_field() { + #[derive(Reflect)] + #[reflect(from_reflect = false)] + struct MyStruct(Box); + + let my_struct: Box = Box::new(MyStruct(Box::new(123_i32))); + + let field = my_struct.field(0).unwrap(); + assert_eq!(field.try_downcast_ref::(), Some(&123)); + + let field_info = field.get_represented_type_info().unwrap(); + assert!(field_info.ty().is::()); + } +} diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index cf38c1da5086f..03e0cd2fbcc4a 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -568,6 +568,7 @@ extern crate alloc; extern crate self as bevy_reflect; mod array; +pub mod cast; mod fields; mod from_reflect; #[cfg(feature = "functions")] From 5afbd0b29f7e64a22d0924dd2b40353928ed3369 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 29 Sep 2024 11:05:22 -0700 Subject: [PATCH 04/17] Removed `Reflect` bound on `FromReflect` Replaced with `Any + CastPartialReflect` to prepare for enum and general `FromReflect` support for `Box` --- crates/bevy_asset/src/reflect.rs | 2 +- crates/bevy_ecs/src/reflect/bundle.rs | 2 +- crates/bevy_ecs/src/reflect/component.rs | 2 +- crates/bevy_ecs/src/reflect/resource.rs | 4 +- crates/bevy_reflect/derive/src/impls/enums.rs | 13 +- crates/bevy_reflect/src/cast.rs | 3 +- crates/bevy_reflect/src/from_reflect.rs | 6 +- crates/bevy_reflect/src/impls/smallvec.rs | 14 +-- crates/bevy_reflect/src/impls/std.rs | 112 +++++++++--------- crates/bevy_reflect/src/tuple.rs | 6 +- crates/bevy_state/src/app.rs | 14 +-- 11 files changed, 93 insertions(+), 85 deletions(-) diff --git a/crates/bevy_asset/src/reflect.rs b/crates/bevy_asset/src/reflect.rs index 5c436c10610f0..2f62d353ea18f 100644 --- a/crates/bevy_asset/src/reflect.rs +++ b/crates/bevy_asset/src/reflect.rs @@ -132,7 +132,7 @@ impl ReflectAsset { } } -impl FromType for ReflectAsset { +impl FromType for ReflectAsset { fn from_type() -> Self { ReflectAsset { handle_type_id: TypeId::of::>(), diff --git a/crates/bevy_ecs/src/reflect/bundle.rs b/crates/bevy_ecs/src/reflect/bundle.rs index b7acf69d6aad9..b38103de22a84 100644 --- a/crates/bevy_ecs/src/reflect/bundle.rs +++ b/crates/bevy_ecs/src/reflect/bundle.rs @@ -50,7 +50,7 @@ impl ReflectBundleFns { /// /// This is useful if you want to start with the default implementation before overriding some /// of the functions to create a custom implementation. - pub fn new() -> Self { + pub fn new() -> Self { >::from_type().0 } } diff --git a/crates/bevy_ecs/src/reflect/component.rs b/crates/bevy_ecs/src/reflect/component.rs index bffd2e9c290b7..f42545e0a0d98 100644 --- a/crates/bevy_ecs/src/reflect/component.rs +++ b/crates/bevy_ecs/src/reflect/component.rs @@ -136,7 +136,7 @@ impl ReflectComponentFns { /// /// This is useful if you want to start with the default implementation before overriding some /// of the functions to create a custom implementation. - pub fn new() -> Self { + pub fn new() -> Self { >::from_type().0 } } diff --git a/crates/bevy_ecs/src/reflect/resource.rs b/crates/bevy_ecs/src/reflect/resource.rs index 34e593a6ef00e..64ab0b34f1c0d 100644 --- a/crates/bevy_ecs/src/reflect/resource.rs +++ b/crates/bevy_ecs/src/reflect/resource.rs @@ -72,7 +72,7 @@ impl ReflectResourceFns { /// /// This is useful if you want to start with the default implementation before overriding some /// of the functions to create a custom implementation. - pub fn new() -> Self { + pub fn new() -> Self { >::from_type().0 } } @@ -200,7 +200,7 @@ impl ReflectResource { } } -impl FromType for ReflectResource { +impl FromType for ReflectResource { fn from_type() -> Self { ReflectResource(ReflectResourceFns { insert: |world, reflected_resource, registry| { diff --git a/crates/bevy_reflect/derive/src/impls/enums.rs b/crates/bevy_reflect/derive/src/impls/enums.rs index 235a7cff1c0e0..5314bade5e1cf 100644 --- a/crates/bevy_reflect/derive/src/impls/enums.rs +++ b/crates/bevy_reflect/derive/src/impls/enums.rs @@ -341,18 +341,25 @@ fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Iden is_mutable: bool, bevy_reflect_path: &Path, ) -> proc_macro2::TokenStream { - let method = if is_mutable { + let remote_method = if is_mutable { quote!(as_wrapper_mut) } else { quote!(as_wrapper) }; + let cast_method = if is_mutable { + quote!(#bevy_reflect_path::cast::CastPartialReflect::as_partial_reflect_mut) + } else { + quote!(#bevy_reflect_path::cast::CastPartialReflect::as_partial_reflect) + }; field .attrs .remote .as_ref() - .map(|ty| quote!(<#ty as #bevy_reflect_path::ReflectRemote>::#method(#ident))) - .unwrap_or_else(|| quote!(#ident)) + .map( + |ty| quote!(<#ty as #bevy_reflect_path::ReflectRemote>::#remote_method(#ident)), + ) + .unwrap_or_else(|| quote!(#cast_method(#ident))) } match &variant.fields { diff --git a/crates/bevy_reflect/src/cast.rs b/crates/bevy_reflect/src/cast.rs index 85f107802c078..f46bd861e946d 100644 --- a/crates/bevy_reflect/src/cast.rs +++ b/crates/bevy_reflect/src/cast.rs @@ -1,7 +1,7 @@ -use crate as bevy_reflect; use crate::__macro_exports::RegisterForReflection; use crate::{MaybeTyped, PartialReflect, Reflect}; use bevy_reflect_derive::impl_type_path; +use alloc::boxed::Box; pub trait CastPartialReflect { fn as_partial_reflect(&self) -> &dyn PartialReflect; @@ -138,7 +138,6 @@ impl RegisterForReflection for Box {} #[cfg(test)] mod tests { use super::*; - use crate as bevy_reflect; use crate::{Struct, TupleStruct}; use static_assertions::assert_not_impl_all; diff --git a/crates/bevy_reflect/src/from_reflect.rs b/crates/bevy_reflect/src/from_reflect.rs index dc113d869f3c7..ca9a73a006c6a 100644 --- a/crates/bevy_reflect/src/from_reflect.rs +++ b/crates/bevy_reflect/src/from_reflect.rs @@ -1,5 +1,7 @@ +use crate::cast::CastPartialReflect; use crate::{FromType, PartialReflect, Reflect}; use alloc::boxed::Box; +use core::any::Any; /// A trait that enables types to be dynamically constructed from reflected data. /// @@ -26,7 +28,7 @@ use alloc::boxed::Box; message = "`{Self}` does not implement `FromReflect` so cannot be created through reflection", note = "consider annotating `{Self}` with `#[derive(Reflect)]`" )] -pub trait FromReflect: Reflect + Sized { +pub trait FromReflect: Any + CastPartialReflect + Sized { /// Constructs a concrete instance of `Self` from a reflected value. fn from_reflect(reflect: &dyn PartialReflect) -> Option; @@ -117,7 +119,7 @@ impl ReflectFromReflect { } } -impl FromType for ReflectFromReflect { +impl FromType for ReflectFromReflect { fn from_type() -> Self { Self { from_reflect: |reflect_value| { diff --git a/crates/bevy_reflect/src/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index afb75aff8d997..1142e5d49a8ba 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -12,7 +12,7 @@ use crate::{ impl List for SmallVec where - T::Item: FromReflect + MaybeTyped + TypePath, + T::Item: FromReflect + Reflect + MaybeTyped + TypePath, { fn get(&self, index: usize) -> Option<&dyn PartialReflect> { if index < SmallVec::len(self) { @@ -79,7 +79,7 @@ where } impl PartialReflect for SmallVec where - T::Item: FromReflect + MaybeTyped + TypePath, + T::Item: FromReflect + Reflect + MaybeTyped + TypePath, { fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) @@ -145,7 +145,7 @@ where impl Reflect for SmallVec where - T::Item: FromReflect + MaybeTyped + TypePath, + T::Item: FromReflect + Reflect + MaybeTyped + TypePath, { fn into_any(self: Box) -> Box { self @@ -179,7 +179,7 @@ where impl Typed for SmallVec where - T::Item: FromReflect + MaybeTyped + TypePath, + T::Item: FromReflect + Reflect + MaybeTyped + TypePath, { fn type_info() -> &'static TypeInfo { static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); @@ -196,7 +196,7 @@ impl_type_path!(::smallvec::SmallVec); impl FromReflect for SmallVec where - T::Item: FromReflect + MaybeTyped + TypePath, + T::Item: FromReflect + Reflect + MaybeTyped + TypePath, { fn from_reflect(reflect: &dyn PartialReflect) -> Option { let ref_list = reflect.reflect_ref().as_list().ok()?; @@ -213,7 +213,7 @@ where impl GetTypeRegistration for SmallVec where - T::Item: FromReflect + MaybeTyped + TypePath, + T::Item: FromReflect + Reflect + MaybeTyped + TypePath, { fn get_type_registration() -> TypeRegistration { let mut registration = TypeRegistration::of::>(); @@ -223,4 +223,4 @@ where } #[cfg(feature = "functions")] -crate::func::macros::impl_function_traits!(SmallVec; where T::Item: FromReflect + MaybeTyped + TypePath); +crate::func::macros::impl_function_traits!(SmallVec; where T::Item: FromReflect + Reflect + MaybeTyped + TypePath); diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 119b66e3ed6d0..39f7178f0efbd 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -409,7 +409,7 @@ impl_reflect_for_atomic!( macro_rules! impl_reflect_for_veclike { ($ty:ty, $insert:expr, $remove:expr, $push:expr, $pop:expr, $sub:ty) => { - impl List for $ty { + impl List for $ty { #[inline] fn get(&self, index: usize) -> Option<&dyn PartialReflect> { <$sub>::get(self, index).map(|value| value as &dyn PartialReflect) @@ -468,7 +468,7 @@ macro_rules! impl_reflect_for_veclike { } } - impl PartialReflect for $ty { + impl PartialReflect for $ty { #[inline] fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) @@ -539,9 +539,9 @@ macro_rules! impl_reflect_for_veclike { } } - impl_full_reflect!( for $ty where T: FromReflect + MaybeTyped + TypePath + GetTypeRegistration); + impl_full_reflect!( for $ty where T: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration); - impl Typed for $ty { + impl Typed for $ty { fn type_info() -> &'static TypeInfo { static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); CELL.get_or_insert::(|| { @@ -554,7 +554,7 @@ macro_rules! impl_reflect_for_veclike { } } - impl GetTypeRegistration + impl GetTypeRegistration for $ty { fn get_type_registration() -> TypeRegistration { @@ -569,7 +569,7 @@ macro_rules! impl_reflect_for_veclike { } } - impl FromReflect for $ty { + impl FromReflect for $ty { fn from_reflect(reflect: &dyn PartialReflect) -> Option { let ref_list = reflect.reflect_ref().as_list().ok()?; @@ -588,7 +588,7 @@ macro_rules! impl_reflect_for_veclike { impl_reflect_for_veclike!(Vec, Vec::insert, Vec::remove, Vec::push, Vec::pop, [T]); impl_type_path!(::alloc::vec::Vec); #[cfg(feature = "functions")] -crate::func::macros::impl_function_traits!(Vec; ); +crate::func::macros::impl_function_traits!(Vec; ); impl_reflect_for_veclike!( VecDeque, @@ -600,14 +600,14 @@ impl_reflect_for_veclike!( ); impl_type_path!(::alloc::collections::VecDeque); #[cfg(feature = "functions")] -crate::func::macros::impl_function_traits!(VecDeque; ); +crate::func::macros::impl_function_traits!(VecDeque; ); macro_rules! impl_reflect_for_hashmap { ($ty:path) => { impl Map for $ty where - K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Hash, - V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, + K: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Hash, + V: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration, S: TypePath + BuildHasher + Send + Sync, { fn get(&self, key: &dyn PartialReflect) -> Option<&dyn PartialReflect> { @@ -706,8 +706,8 @@ macro_rules! impl_reflect_for_hashmap { impl PartialReflect for $ty where - K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Hash, - V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, + K: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Hash, + V: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration, S: TypePath + BuildHasher + Send + Sync, { fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { @@ -777,15 +777,15 @@ macro_rules! impl_reflect_for_hashmap { impl_full_reflect!( for $ty where - K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Hash, - V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, + K: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Hash, + V: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration, S: TypePath + BuildHasher + Send + Sync, ); impl Typed for $ty where - K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Hash, - V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, + K: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Hash, + V: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration, S: TypePath + BuildHasher + Send + Sync, { fn type_info() -> &'static TypeInfo { @@ -803,8 +803,8 @@ macro_rules! impl_reflect_for_hashmap { impl GetTypeRegistration for $ty where - K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Hash, - V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, + K: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Hash, + V: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration, S: TypePath + BuildHasher + Send + Sync + Default, { fn get_type_registration() -> TypeRegistration { @@ -822,8 +822,8 @@ macro_rules! impl_reflect_for_hashmap { impl FromReflect for $ty where - K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Hash, - V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, + K: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Hash, + V: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration, S: TypePath + BuildHasher + Default + Send + Sync, { fn from_reflect(reflect: &dyn PartialReflect) -> Option { @@ -853,8 +853,8 @@ impl_type_path!(::std::collections::HashMap); #[cfg(all(feature = "functions", feature = "std"))] crate::func::macros::impl_function_traits!(::std::collections::HashMap; < - K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Hash, - V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, + K: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Hash, + V: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration, S: TypePath + BuildHasher + Default + Send + Sync > ); @@ -864,8 +864,8 @@ impl_type_path!(::bevy_platform_support::collections::HashMap); #[cfg(feature = "functions")] crate::func::macros::impl_function_traits!(::bevy_platform_support::collections::HashMap; < - K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Hash, - V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, + K: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Hash, + V: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration, S: TypePath + BuildHasher + Default + Send + Sync > ); @@ -874,7 +874,7 @@ macro_rules! impl_reflect_for_hashset { ($ty:path) => { impl Set for $ty where - V: FromReflect + TypePath + GetTypeRegistration + Eq + Hash, + V: FromReflect + Reflect + TypePath + GetTypeRegistration + Eq + Hash, S: TypePath + BuildHasher + Send + Sync, { fn get(&self, value: &dyn PartialReflect) -> Option<&dyn PartialReflect> { @@ -943,7 +943,7 @@ macro_rules! impl_reflect_for_hashset { impl PartialReflect for $ty where - V: FromReflect + TypePath + GetTypeRegistration + Eq + Hash, + V: FromReflect + Reflect + TypePath + GetTypeRegistration + Eq + Hash, S: TypePath + BuildHasher + Send + Sync, { fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { @@ -1013,7 +1013,7 @@ macro_rules! impl_reflect_for_hashset { impl Typed for $ty where - V: FromReflect + TypePath + GetTypeRegistration + Eq + Hash, + V: FromReflect + Reflect + TypePath + GetTypeRegistration + Eq + Hash, S: TypePath + BuildHasher + Send + Sync, { fn type_info() -> &'static TypeInfo { @@ -1030,7 +1030,7 @@ macro_rules! impl_reflect_for_hashset { impl GetTypeRegistration for $ty where - V: FromReflect + TypePath + GetTypeRegistration + Eq + Hash, + V: FromReflect + Reflect + TypePath + GetTypeRegistration + Eq + Hash, S: TypePath + BuildHasher + Send + Sync + Default, { fn get_type_registration() -> TypeRegistration { @@ -1048,13 +1048,13 @@ macro_rules! impl_reflect_for_hashset { impl_full_reflect!( for $ty where - V: FromReflect + TypePath + GetTypeRegistration + Eq + Hash, + V: FromReflect + Reflect + TypePath + GetTypeRegistration + Eq + Hash, S: TypePath + BuildHasher + Send + Sync, ); impl FromReflect for $ty where - V: FromReflect + TypePath + GetTypeRegistration + Eq + Hash, + V: FromReflect + Reflect + TypePath + GetTypeRegistration + Eq + Hash, S: TypePath + BuildHasher + Default + Send + Sync, { fn from_reflect(reflect: &dyn PartialReflect) -> Option { @@ -1083,7 +1083,7 @@ impl_type_path!(::std::collections::HashSet); #[cfg(all(feature = "functions", feature = "std"))] crate::func::macros::impl_function_traits!(::std::collections::HashSet; < - V: Hash + Eq + FromReflect + TypePath + GetTypeRegistration, + V: Hash + Eq + FromReflect + Reflect + TypePath + GetTypeRegistration, S: TypePath + BuildHasher + Default + Send + Sync > ); @@ -1093,15 +1093,15 @@ impl_type_path!(::bevy_platform_support::collections::HashSet); #[cfg(feature = "functions")] crate::func::macros::impl_function_traits!(::bevy_platform_support::collections::HashSet; < - V: Hash + Eq + FromReflect + TypePath + GetTypeRegistration, + V: Hash + Eq + FromReflect + Reflect + TypePath + GetTypeRegistration, S: TypePath + BuildHasher + Default + Send + Sync > ); impl Map for ::alloc::collections::BTreeMap where - K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Ord, - V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, + K: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Ord, + V: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration, { fn get(&self, key: &dyn PartialReflect) -> Option<&dyn PartialReflect> { key.try_downcast_ref::() @@ -1202,8 +1202,8 @@ where impl PartialReflect for ::alloc::collections::BTreeMap where - K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Ord, - V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, + K: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Ord, + V: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration, { fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) @@ -1268,14 +1268,14 @@ where impl_full_reflect!( for ::alloc::collections::BTreeMap where - K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Ord, - V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, + K: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Ord, + V: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration, ); impl Typed for ::alloc::collections::BTreeMap where - K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Ord, - V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, + K: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Ord, + V: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration, { fn type_info() -> &'static TypeInfo { static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); @@ -1292,8 +1292,8 @@ where impl GetTypeRegistration for ::alloc::collections::BTreeMap where - K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Ord, - V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, + K: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Ord, + V: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration, { fn get_type_registration() -> TypeRegistration { let mut registration = TypeRegistration::of::(); @@ -1305,8 +1305,8 @@ where impl FromReflect for ::alloc::collections::BTreeMap where - K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Ord, - V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, + K: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Ord, + V: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration, { fn from_reflect(reflect: &dyn PartialReflect) -> Option { let ref_map = reflect.reflect_ref().as_map().ok()?; @@ -1327,8 +1327,8 @@ impl_type_path!(::alloc::collections::BTreeMap); #[cfg(feature = "functions")] crate::func::macros::impl_function_traits!(::alloc::collections::BTreeMap; < - K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Ord, - V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + K: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Ord, + V: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration > ); @@ -1476,8 +1476,8 @@ impl R } } -impl FromReflect - for [T; N] +impl + FromReflect for [T; N] { fn from_reflect(reflect: &dyn PartialReflect) -> Option { let ref_array = reflect.reflect_ref().as_array().ok()?; @@ -1693,7 +1693,7 @@ where } } -impl List +impl List for Cow<'static, [T]> { fn get(&self, index: usize) -> Option<&dyn PartialReflect> { @@ -1752,7 +1752,7 @@ impl List } } -impl PartialReflect +impl PartialReflect for Cow<'static, [T]> { fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { @@ -1824,10 +1824,10 @@ impl Parti impl_full_reflect!( for Cow<'static, [T]> where - T: FromReflect + Clone + MaybeTyped + TypePath + GetTypeRegistration, + T: FromReflect + Reflect + Clone + MaybeTyped + TypePath + GetTypeRegistration, ); -impl Typed +impl Typed for Cow<'static, [T]> { fn type_info() -> &'static TypeInfo { @@ -1836,8 +1836,8 @@ impl Typed } } -impl GetTypeRegistration - for Cow<'static, [T]> +impl + GetTypeRegistration for Cow<'static, [T]> { fn get_type_registration() -> TypeRegistration { TypeRegistration::of::>() @@ -1848,7 +1848,7 @@ impl GetTy } } -impl FromReflect +impl FromReflect for Cow<'static, [T]> { fn from_reflect(reflect: &dyn PartialReflect) -> Option { @@ -1865,7 +1865,7 @@ impl FromR } #[cfg(feature = "functions")] -crate::func::macros::impl_function_traits!(Cow<'static, [T]>; ); +crate::func::macros::impl_function_traits!(Cow<'static, [T]>; ); impl PartialReflect for &'static str { fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index 28f95b6886cd8..d413fbbedca67 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -649,7 +649,7 @@ macro_rules! impl_reflect_tuple { } } - impl<$($name: FromReflect + MaybeTyped + TypePath + GetTypeRegistration),*> FromReflect for ($($name,)*) + impl<$($name: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> FromReflect for ($($name,)*) { fn from_reflect(reflect: &dyn PartialReflect) -> Option { let _ref_tuple = reflect.reflect_ref().as_tuple().ok()?; @@ -765,7 +765,7 @@ const _: () = { macro_rules! impl_from_arg_tuple { ($(#[$meta:meta])* $($name: ident),*) => { $(#[$meta])* - $crate::func::args::impl_from_arg!(($($name,)*); <$($name: FromReflect + MaybeTyped + TypePath + GetTypeRegistration),*>); + $crate::func::args::impl_from_arg!(($($name,)*); <$($name: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration),*>); }; } @@ -780,7 +780,7 @@ const _: () = { macro_rules! impl_into_return_tuple { ($(#[$meta:meta])* $($name: ident),+) => { $(#[$meta])* - $crate::func::impl_into_return!(($($name,)*); <$($name: FromReflect + MaybeTyped + TypePath + GetTypeRegistration),*>); + $crate::func::impl_into_return!(($($name,)*); <$($name: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration),*>); }; } diff --git a/crates/bevy_state/src/app.rs b/crates/bevy_state/src/app.rs index 2419efd4d8a99..99904e6176d4f 100644 --- a/crates/bevy_state/src/app.rs +++ b/crates/bevy_state/src/app.rs @@ -12,7 +12,7 @@ use crate::{ }; #[cfg(feature = "bevy_reflect")] -use bevy_reflect::{FromReflect, GetTypeRegistration, Typed}; +use bevy_reflect::{FromReflect, GetTypeRegistration, Reflect, Typed}; /// State installation methods for [`App`] and [`SubApp`]. pub trait AppExtStates { @@ -72,7 +72,7 @@ pub trait AppExtStates { /// This enables reflection code to access the state. For detailed information, see the docs on [`crate::reflect::ReflectState`] . fn register_type_state(&mut self) -> &mut Self where - S: States + FromReflect + GetTypeRegistration + Typed; + S: States + FromReflect + Reflect + GetTypeRegistration + Typed; #[cfg(feature = "bevy_reflect")] /// Registers the state type `T` using [`App::register_type`], @@ -82,7 +82,7 @@ pub trait AppExtStates { /// For detailed information, see the docs on [`crate::reflect::ReflectState`] and [`crate::reflect::ReflectFreelyMutableState`]. fn register_type_mutable_state(&mut self) -> &mut Self where - S: FreelyMutableState + FromReflect + GetTypeRegistration + Typed; + S: FreelyMutableState + FromReflect + Reflect + GetTypeRegistration + Typed; } /// Separate function to only warn once for all state installation methods. @@ -233,7 +233,7 @@ impl AppExtStates for SubApp { #[cfg(feature = "bevy_reflect")] fn register_type_state(&mut self) -> &mut Self where - S: States + FromReflect + GetTypeRegistration + Typed, + S: States + FromReflect + Reflect + GetTypeRegistration + Typed, { self.register_type::(); self.register_type::>(); @@ -244,7 +244,7 @@ impl AppExtStates for SubApp { #[cfg(feature = "bevy_reflect")] fn register_type_mutable_state(&mut self) -> &mut Self where - S: FreelyMutableState + FromReflect + GetTypeRegistration + Typed, + S: FreelyMutableState + FromReflect + Reflect + GetTypeRegistration + Typed, { self.register_type::(); self.register_type::>(); @@ -284,7 +284,7 @@ impl AppExtStates for App { #[cfg(feature = "bevy_reflect")] fn register_type_state(&mut self) -> &mut Self where - S: States + FromReflect + GetTypeRegistration + Typed, + S: States + FromReflect + Reflect + GetTypeRegistration + Typed, { self.main_mut().register_type_state::(); self @@ -293,7 +293,7 @@ impl AppExtStates for App { #[cfg(feature = "bevy_reflect")] fn register_type_mutable_state(&mut self) -> &mut Self where - S: FreelyMutableState + FromReflect + GetTypeRegistration + Typed, + S: FreelyMutableState + FromReflect + Reflect + GetTypeRegistration + Typed, { self.main_mut().register_type_mutable_state::(); self From adabe4c4e1cef28a63253645c8aa6b35de9ef90e Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 29 Sep 2024 12:31:40 -0700 Subject: [PATCH 05/17] Removed `Reflect` bound on `TypeRegistration::of` --- crates/bevy_reflect/src/type_registry.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_reflect/src/type_registry.rs b/crates/bevy_reflect/src/type_registry.rs index cf80749edebbb..78ba96eb579c2 100644 --- a/crates/bevy_reflect/src/type_registry.rs +++ b/crates/bevy_reflect/src/type_registry.rs @@ -520,7 +520,7 @@ impl Debug for TypeRegistration { impl TypeRegistration { /// Creates type registration information for `T`. - pub fn of() -> Self { + pub fn of() -> Self { Self { data: Default::default(), type_info: T::type_info(), From 648d568e9a83c5159ef4a5f89d7fe4f932568659 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 29 Sep 2024 12:33:18 -0700 Subject: [PATCH 06/17] Removed `Reflect` bound on `Typed` --- crates/bevy_reflect/src/type_info.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index db9b2c4fe7ccb..ee1cb8efd2b85 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -91,7 +91,7 @@ use thiserror::Error; message = "`{Self}` does not implement `Typed` so cannot provide static type information", note = "consider annotating `{Self}` with `#[derive(Reflect)]`" )] -pub trait Typed: Reflect + TypePath { +pub trait Typed: TypePath { /// Returns the compile-time [info] for the underlying type. /// /// [info]: TypeInfo From d6282ed17f86096459ed34a189b06fd96aee5d41 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 29 Sep 2024 12:33:36 -0700 Subject: [PATCH 07/17] Removed `Reflect` bound on `OpaqueInfo::new` --- crates/bevy_reflect/src/type_info.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index ee1cb8efd2b85..fd090ec3be310 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -1,6 +1,6 @@ use crate::{ ArrayInfo, DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicStruct, DynamicTuple, - DynamicTupleStruct, EnumInfo, Generics, ListInfo, MapInfo, Reflect, ReflectKind, SetInfo, + DynamicTupleStruct, EnumInfo, Generics, ListInfo, MapInfo, ReflectKind, SetInfo, StructInfo, TupleInfo, TupleStructInfo, TypePath, TypePathTable, }; use core::{ @@ -558,7 +558,7 @@ pub struct OpaqueInfo { } impl OpaqueInfo { - pub fn new() -> Self { + pub fn new() -> Self { Self { ty: Type::of::(), generics: Generics::new(), From 89a17f0638bb8cee712d553e7686e2a0ad72aa2b Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 29 Sep 2024 12:37:01 -0700 Subject: [PATCH 08/17] Implemented casting traits for all types Also adds support for tuples of boxed values --- crates/bevy_ecs/src/reflect/map_entities.rs | 4 +- crates/bevy_ecs/src/reflect/visit_entities.rs | 4 +- .../bevy_reflect/derive/src/impls/casting.rs | 45 +++++ .../bevy_reflect/derive/src/impls/common.rs | 5 + crates/bevy_reflect/derive/src/impls/mod.rs | 1 + crates/bevy_reflect/src/array.rs | 7 +- crates/bevy_reflect/src/cast.rs | 95 ++++++++-- crates/bevy_reflect/src/enums/dynamic_enum.rs | 7 +- .../bevy_reflect/src/func/dynamic_function.rs | 2 + crates/bevy_reflect/src/impls/smallvec.rs | 48 ++--- crates/bevy_reflect/src/impls/std.rs | 169 +++++------------- crates/bevy_reflect/src/list.rs | 2 + crates/bevy_reflect/src/map.rs | 7 +- crates/bevy_reflect/src/reflect.rs | 3 + crates/bevy_reflect/src/set.rs | 2 + crates/bevy_reflect/src/struct_trait.rs | 2 + crates/bevy_reflect/src/tuple.rs | 64 +++++-- crates/bevy_reflect/src/tuple_struct.rs | 2 + 18 files changed, 264 insertions(+), 205 deletions(-) create mode 100644 crates/bevy_reflect/derive/src/impls/casting.rs diff --git a/crates/bevy_ecs/src/reflect/map_entities.rs b/crates/bevy_ecs/src/reflect/map_entities.rs index 04fc25579906d..ee8cad82ef0cb 100644 --- a/crates/bevy_ecs/src/reflect/map_entities.rs +++ b/crates/bevy_ecs/src/reflect/map_entities.rs @@ -1,5 +1,5 @@ use crate::entity::{EntityMapper, MapEntities}; -use bevy_reflect::{FromReflect, FromType, PartialReflect}; +use bevy_reflect::{FromReflect, FromType, PartialReflect, Reflect}; /// For a specific type of value, this maps any fields with values of type [`Entity`] to a new world. /// @@ -25,7 +25,7 @@ impl ReflectMapEntities { } } -impl FromType for ReflectMapEntities { +impl FromType for ReflectMapEntities { fn from_type() -> Self { ReflectMapEntities { map_entities: |reflected, mut mapper| { diff --git a/crates/bevy_ecs/src/reflect/visit_entities.rs b/crates/bevy_ecs/src/reflect/visit_entities.rs index 11f02612ba1f9..35cc650fd69ce 100644 --- a/crates/bevy_ecs/src/reflect/visit_entities.rs +++ b/crates/bevy_ecs/src/reflect/visit_entities.rs @@ -1,5 +1,5 @@ use crate::entity::{Entity, VisitEntities, VisitEntitiesMut}; -use bevy_reflect::{FromReflect, FromType, PartialReflect}; +use bevy_reflect::{FromReflect, FromType, PartialReflect, Reflect}; /// For a reflected value, apply an operation to all contained entities. /// @@ -49,7 +49,7 @@ impl ReflectVisitEntitiesMut { } } -impl FromType for ReflectVisitEntitiesMut { +impl FromType for ReflectVisitEntitiesMut { fn from_type() -> Self { ReflectVisitEntitiesMut { visit_entities_mut: |component, f| { diff --git a/crates/bevy_reflect/derive/src/impls/casting.rs b/crates/bevy_reflect/derive/src/impls/casting.rs new file mode 100644 index 0000000000000..2d635c74af67a --- /dev/null +++ b/crates/bevy_reflect/derive/src/impls/casting.rs @@ -0,0 +1,45 @@ +use crate::derive_data::ReflectMeta; +use crate::where_clause_options::WhereClauseOptions; +use proc_macro2::TokenStream; +use quote::quote; + +/// Generates impls for the `CastPartialReflect` and `CastReflect` traits. +pub(crate) fn impl_casting_traits( + meta: &ReflectMeta, + where_clause_options: &WhereClauseOptions, +) -> TokenStream { + let bevy_reflect_path = meta.bevy_reflect_path(); + let type_path = meta.type_path(); + let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl(); + let where_reflect_clause = where_clause_options.extend_where_clause(where_clause); + + quote! { + impl #impl_generics #bevy_reflect_path::cast::CastPartialReflect for #type_path #ty_generics #where_reflect_clause { + fn as_partial_reflect(&self) -> &dyn #bevy_reflect_path::PartialReflect { + self + } + + fn as_partial_reflect_mut(&mut self) -> &mut dyn #bevy_reflect_path::PartialReflect { + self + } + + fn into_partial_reflect(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box { + self + } + } + + impl #impl_generics #bevy_reflect_path::cast::CastReflect for #type_path #ty_generics #where_reflect_clause { + fn as_reflect(&self) -> &dyn #bevy_reflect_path::Reflect { + self + } + + fn as_reflect_mut(&mut self) -> &mut dyn #bevy_reflect_path::Reflect { + self + } + + fn into_reflect(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box { + self + } + } + } +} diff --git a/crates/bevy_reflect/derive/src/impls/common.rs b/crates/bevy_reflect/derive/src/impls/common.rs index e8fdadb03e368..680dc972f1a6b 100644 --- a/crates/bevy_reflect/derive/src/impls/common.rs +++ b/crates/bevy_reflect/derive/src/impls/common.rs @@ -2,6 +2,7 @@ use bevy_macro_utils::fq_std::{FQAny, FQOption, FQResult}; use quote::quote; +use crate::impls::casting::impl_casting_traits; use crate::{derive_data::ReflectMeta, where_clause_options::WhereClauseOptions}; pub fn impl_full_reflect( @@ -50,6 +51,8 @@ pub fn impl_full_reflect( } }; + let casting_impls = impl_casting_traits(meta, where_clause_options); + quote! { impl #impl_generics #bevy_reflect_path::Reflect for #type_path #ty_generics #where_reflect_clause { #any_impls @@ -78,6 +81,8 @@ pub fn impl_full_reflect( #FQResult::Ok(()) } } + + #casting_impls } } diff --git a/crates/bevy_reflect/derive/src/impls/mod.rs b/crates/bevy_reflect/derive/src/impls/mod.rs index 6477c4041e3a3..aa9e0bfd7e69e 100644 --- a/crates/bevy_reflect/derive/src/impls/mod.rs +++ b/crates/bevy_reflect/derive/src/impls/mod.rs @@ -1,4 +1,5 @@ mod assertions; +mod casting; mod common; mod enums; #[cfg(feature = "functions")] diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index 300e69c2a71e9..b8cf70983921b 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -1,8 +1,8 @@ use crate::generics::impl_generic_info_methods; use crate::{ - type_info::impl_type_methods, utility::reflect_hasher, ApplyError, Generics, MaybeTyped, - PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Type, TypeInfo, - TypePath, + cast::impl_cast_partial_reflect, type_info::impl_type_methods, utility::reflect_hasher, + ApplyError, Generics, MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut, + ReflectOwned, ReflectRef, Type, TypeInfo, TypePath, }; use alloc::{boxed::Box, vec::Vec}; use bevy_reflect_derive::impl_type_path; @@ -358,6 +358,7 @@ impl<'a> IntoIterator for &'a DynamicArray { } impl_type_path!((in bevy_reflect) DynamicArray); +impl_cast_partial_reflect!(for DynamicArray); /// An iterator over an [`Array`]. pub struct ArrayIter<'a> { diff --git a/crates/bevy_reflect/src/cast.rs b/crates/bevy_reflect/src/cast.rs index f46bd861e946d..cfa5d7b61c96a 100644 --- a/crates/bevy_reflect/src/cast.rs +++ b/crates/bevy_reflect/src/cast.rs @@ -1,25 +1,29 @@ use crate::__macro_exports::RegisterForReflection; -use crate::{MaybeTyped, PartialReflect, Reflect}; -use bevy_reflect_derive::impl_type_path; +use crate::utility::GenericTypeInfoCell; +use crate::{ + GetTypeRegistration, MaybeTyped, OpaqueInfo, PartialReflect, Reflect, TypeInfo, TypePath, + TypeRegistration, Typed, +}; use alloc::boxed::Box; +use bevy_reflect_derive::impl_type_path; -pub trait CastPartialReflect { +pub trait CastPartialReflect: Send + Sync + 'static { fn as_partial_reflect(&self) -> &dyn PartialReflect; fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect; fn into_partial_reflect(self: Box) -> Box; } -impl CastPartialReflect for T { +impl CastPartialReflect for Box { fn as_partial_reflect(&self) -> &dyn PartialReflect { - self + T::as_partial_reflect(self) } fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self + T::as_partial_reflect_mut(self) } fn into_partial_reflect(self: Box) -> Box { - self + T::into_partial_reflect(*self) } } @@ -85,17 +89,17 @@ pub trait CastReflect: CastPartialReflect { fn into_reflect(self: Box) -> Box; } -impl CastReflect for T { +impl CastReflect for Box { fn as_reflect(&self) -> &dyn Reflect { - self + T::as_reflect(self) } fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self + T::as_reflect_mut(self) } fn into_reflect(self: Box) -> Box { - self + T::into_reflect(*self) } } @@ -132,13 +136,69 @@ impl_type_path!(::alloc::boxed::Box); impl MaybeTyped for Box {} impl MaybeTyped for Box {} +impl Typed for Box { + fn type_info() -> &'static TypeInfo { + static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); + CELL.get_or_insert::(|| TypeInfo::Opaque(OpaqueInfo::new::())) + } +} + impl RegisterForReflection for Box {} impl RegisterForReflection for Box {} +impl GetTypeRegistration for Box { + fn get_type_registration() -> TypeRegistration { + TypeRegistration::of::() + } +} + +macro_rules! impl_cast_partial_reflect { + ($(<$($id:ident),* $(,)?>)? for $ty:ty $(where $($tt:tt)*)?) => { + impl $(<$($id),*>)? $crate::cast::CastPartialReflect for $ty $(where $($tt)*)? { + fn as_partial_reflect(&self) -> &dyn $crate::PartialReflect { + self + } + + fn as_partial_reflect_mut(&mut self) -> &mut dyn $crate::PartialReflect { + self + } + + fn into_partial_reflect(self: Box) -> Box { + self + } + } + }; +} + +pub(crate) use impl_cast_partial_reflect; + +macro_rules! impl_casting_traits { + ($(<$($id:ident),* $(,)?>)? for $ty:ty $(where $($tt:tt)*)?) => { + + $crate::cast::impl_cast_partial_reflect!($(<$($id),*>)? for $ty $(where $($tt)*)?); + + impl $(<$($id),*>)? $crate::cast::CastReflect for $ty $(where $($tt)*)? { + fn as_reflect(&self) -> &dyn $crate::Reflect { + self + } + + fn as_reflect_mut(&mut self) -> &mut dyn $crate::Reflect { + self + } + + fn into_reflect(self: Box) -> Box { + self + } + } + }; +} + +pub(crate) use impl_casting_traits; + #[cfg(test)] mod tests { use super::*; - use crate::{Struct, TupleStruct}; + use crate::{Struct, Tuple, TupleStruct}; use static_assertions::assert_not_impl_all; #[test] @@ -181,4 +241,15 @@ mod tests { let field_info = field.get_represented_type_info().unwrap(); assert!(field_info.ty().is::()); } + + #[test] + fn should_reflect_boxed_tuple_field() { + let my_struct: Box = Box::new((Box::new(10_i32),)); + + let field = my_struct.field(0).unwrap(); + assert_eq!(field.try_downcast_ref::(), Some(&10)); + + let field_info = field.get_represented_type_info().unwrap(); + assert!(field_info.ty().is::()); + } } diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index d9e228c07eaae..aab1bd214c88f 100644 --- a/crates/bevy_reflect/src/enums/dynamic_enum.rs +++ b/crates/bevy_reflect/src/enums/dynamic_enum.rs @@ -1,9 +1,9 @@ use bevy_reflect_derive::impl_type_path; use crate::{ - enum_debug, enum_hash, enum_partial_eq, ApplyError, DynamicStruct, DynamicTuple, Enum, - PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Struct, Tuple, - TypeInfo, VariantFieldIter, VariantType, + cast::impl_cast_partial_reflect, enum_debug, enum_hash, enum_partial_eq, ApplyError, + DynamicStruct, DynamicTuple, Enum, PartialReflect, Reflect, ReflectKind, ReflectMut, + ReflectOwned, ReflectRef, Struct, Tuple, TypeInfo, VariantFieldIter, VariantType, }; use alloc::{boxed::Box, string::String}; @@ -406,3 +406,4 @@ impl PartialReflect for DynamicEnum { } impl_type_path!((in bevy_reflect) DynamicEnum); +impl_cast_partial_reflect!(for DynamicEnum); diff --git a/crates/bevy_reflect/src/func/dynamic_function.rs b/crates/bevy_reflect/src/func/dynamic_function.rs index 6d1c9776a9f7b..f7ff56d0ac79e 100644 --- a/crates/bevy_reflect/src/func/dynamic_function.rs +++ b/crates/bevy_reflect/src/func/dynamic_function.rs @@ -1,3 +1,4 @@ +use crate::cast::impl_cast_partial_reflect; use crate::{ __macro_exports::RegisterForReflection, func::{ @@ -446,6 +447,7 @@ impl MaybeTyped for DynamicFunction<'static> {} impl RegisterForReflection for DynamicFunction<'static> {} impl_type_path!((in bevy_reflect) DynamicFunction<'env>); +impl_cast_partial_reflect!(for DynamicFunction<'static>); /// Outputs the function's signature. /// diff --git a/crates/bevy_reflect/src/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index 1142e5d49a8ba..61d3486f73ce8 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -1,13 +1,12 @@ use alloc::{boxed::Box, vec::Vec}; use bevy_reflect_derive::impl_type_path; -use core::any::Any; use smallvec::{Array as SmallArray, SmallVec}; use crate::{ - utility::GenericTypeInfoCell, ApplyError, FromReflect, FromType, Generics, GetTypeRegistration, - List, ListInfo, ListIter, MaybeTyped, PartialReflect, Reflect, ReflectFromPtr, ReflectKind, - ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypeParamInfo, TypePath, TypeRegistration, - Typed, + reflect::impl_full_reflect, utility::GenericTypeInfoCell, ApplyError, FromReflect, FromType, + Generics, GetTypeRegistration, List, ListInfo, ListIter, MaybeTyped, PartialReflect, Reflect, + ReflectFromPtr, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypeParamInfo, + TypePath, TypeRegistration, Typed, }; impl List for SmallVec @@ -143,39 +142,12 @@ where } } -impl Reflect for SmallVec -where - T::Item: FromReflect + Reflect + MaybeTyped + TypePath, -{ - fn into_any(self: Box) -> Box { - self - } - - fn as_any(&self) -> &dyn Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn Any { - self - } - - fn into_reflect(self: Box) -> Box { - self - } - - fn as_reflect(&self) -> &dyn Reflect { - self - } - - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self - } - - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } -} +impl_full_reflect!( + for SmallVec + where + T: SmallArray + TypePath + Send + Sync, + T::Item: FromReflect + Reflect + MaybeTyped + TypePath +); impl Typed for SmallVec where diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 39f7178f0efbd..5ff1f97864594 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -3,6 +3,7 @@ reason = "Temporary workaround for impl_reflect!(Option/Result false-positive" )] +use crate::cast::{CastPartialReflect, CastReflect}; use crate::{ impl_type_path, map_apply, map_partial_eq, map_try_apply, prelude::ReflectDefault, @@ -1476,6 +1477,38 @@ impl R } } +impl CastPartialReflect + for [T; N] +{ + fn as_partial_reflect(&self) -> &dyn PartialReflect { + self + } + + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { + self + } + + fn into_partial_reflect(self: Box) -> Box { + self + } +} + +impl CastReflect + for [T; N] +{ + fn as_reflect(&self) -> &dyn Reflect { + self + } + + fn as_reflect_mut(&mut self) -> &mut dyn Reflect { + self + } + + fn into_reflect(self: Box) -> Box { + self + } +} + impl FromReflect for [T; N] { @@ -1945,37 +1978,6 @@ impl PartialReflect for &'static str { } } -impl Reflect for &'static str { - fn into_any(self: Box) -> Box { - self - } - - fn as_any(&self) -> &dyn Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn Any { - self - } - - fn into_reflect(self: Box) -> Box { - self - } - - fn as_reflect(&self) -> &dyn Reflect { - self - } - - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self - } - - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } -} - impl Typed for &'static str { fn type_info() -> &'static TypeInfo { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); @@ -1998,6 +2000,8 @@ impl FromReflect for &'static str { } } +impl_full_reflect!(for &'static str); + #[cfg(feature = "functions")] crate::func::macros::impl_function_traits!(&'static str); @@ -2080,38 +2084,6 @@ impl PartialReflect for &'static Path { } } -#[cfg(feature = "std")] -impl Reflect for &'static Path { - fn into_any(self: Box) -> Box { - self - } - - fn as_any(&self) -> &dyn Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn Any { - self - } - - fn into_reflect(self: Box) -> Box { - self - } - - fn as_reflect(&self) -> &dyn Reflect { - self - } - - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self - } - - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } -} - #[cfg(feature = "std")] impl Typed for &'static Path { fn type_info() -> &'static TypeInfo { @@ -2137,6 +2109,9 @@ impl FromReflect for &'static Path { } } +#[cfg(feature = "std")] +impl_full_reflect!(for &'static Path); + #[cfg(all(feature = "functions", feature = "std"))] crate::func::macros::impl_function_traits!(&'static Path); @@ -2223,38 +2198,6 @@ impl PartialReflect for Cow<'static, Path> { } } -#[cfg(feature = "std")] -impl Reflect for Cow<'static, Path> { - fn into_any(self: Box) -> Box { - self - } - - fn as_any(&self) -> &dyn Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn Any { - self - } - - fn into_reflect(self: Box) -> Box { - self - } - - fn as_reflect(&self) -> &dyn Reflect { - self - } - - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self - } - - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } -} - #[cfg(feature = "std")] impl Typed for Cow<'static, Path> { fn type_info() -> &'static TypeInfo { @@ -2286,6 +2229,9 @@ impl GetTypeRegistration for Cow<'static, Path> { } } +#[cfg(feature = "std")] +impl_full_reflect!(for Cow<'static, Path>); + #[cfg(all(feature = "functions", feature = "std"))] crate::func::macros::impl_function_traits!(Cow<'static, Path>); @@ -2377,37 +2323,6 @@ impl PartialReflect for &'static Location<'static> { } } -impl Reflect for &'static Location<'static> { - fn into_any(self: Box) -> Box { - self - } - - fn as_any(&self) -> &dyn Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn Any { - self - } - - fn into_reflect(self: Box) -> Box { - self - } - - fn as_reflect(&self) -> &dyn Reflect { - self - } - - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self - } - - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } -} - impl Typed for &'static Location<'static> { fn type_info() -> &'static TypeInfo { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); @@ -2430,6 +2345,8 @@ impl FromReflect for &'static Location<'static> { } } +impl_full_reflect!(for &'static Location<'static>); + #[cfg(all(feature = "functions", feature = "std"))] crate::func::macros::impl_function_traits!(&'static Location<'static>); diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index e0f019c4b26dc..fe9eee6944bcc 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -13,6 +13,7 @@ use crate::{ MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Type, TypeInfo, TypePath, }; +use crate::cast::impl_cast_partial_reflect; /// A trait used to power [list-like] operations via [reflection]. /// @@ -347,6 +348,7 @@ impl PartialReflect for DynamicList { } impl_type_path!((in bevy_reflect) DynamicList); +impl_cast_partial_reflect!(for DynamicList); impl Debug for DynamicList { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index 1ce685b127854..a7754cce9768f 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -4,9 +4,9 @@ use bevy_platform_support::collections::HashTable; use bevy_reflect_derive::impl_type_path; use crate::{ - generics::impl_generic_info_methods, type_info::impl_type_methods, ApplyError, Generics, - MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Type, - TypeInfo, TypePath, + cast::impl_cast_partial_reflect, generics::impl_generic_info_methods, + type_info::impl_type_methods, ApplyError, Generics, MaybeTyped, PartialReflect, Reflect, + ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Type, TypeInfo, TypePath, }; use alloc::{boxed::Box, format, vec::Vec}; @@ -452,6 +452,7 @@ impl PartialReflect for DynamicMap { } impl_type_path!((in bevy_reflect) DynamicMap); +impl_cast_partial_reflect!(for DynamicMap); impl Debug for DynamicMap { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index 0898ff3630fe9..c97764c29ce9d 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -507,6 +507,9 @@ impl TypePath for dyn Reflect { macro_rules! impl_full_reflect { ($(<$($id:ident),* $(,)?>)? for $ty:ty $(where $($tt:tt)*)?) => { + + $crate::cast::impl_casting_traits!($(<$($id),*>)? for $ty $(where $($tt)*)?); + impl $(<$($id),*>)? $crate::Reflect for $ty $(where $($tt)*)? { fn into_any(self: Box) -> Box { self diff --git a/crates/bevy_reflect/src/set.rs b/crates/bevy_reflect/src/set.rs index 799499a8adcd7..89fe503737b48 100644 --- a/crates/bevy_reflect/src/set.rs +++ b/crates/bevy_reflect/src/set.rs @@ -6,6 +6,7 @@ use bevy_platform_support::collections::{ }; use bevy_reflect_derive::impl_type_path; +use crate::cast::impl_cast_partial_reflect; use crate::{ generics::impl_generic_info_methods, hash_error, type_info::impl_type_methods, ApplyError, Generics, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Type, @@ -338,6 +339,7 @@ impl PartialReflect for DynamicSet { } impl_type_path!((in bevy_reflect) DynamicSet); +impl_cast_partial_reflect!(for DynamicSet); impl Debug for DynamicSet { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index dc7ed55cefef3..29f67d664842d 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -1,6 +1,7 @@ use crate::generics::impl_generic_info_methods; use crate::{ attributes::{impl_custom_attribute_methods, CustomAttributes}, + cast::impl_cast_partial_reflect, type_info::impl_type_methods, ApplyError, Generics, NamedField, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Type, TypeInfo, TypePath, @@ -471,6 +472,7 @@ impl PartialReflect for DynamicStruct { } impl_type_path!((in bevy_reflect) DynamicStruct); +impl_cast_partial_reflect!(for DynamicStruct); impl Debug for DynamicStruct { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index d413fbbedca67..8a4de93638444 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -3,10 +3,13 @@ use variadics_please::all_tuples; use crate::generics::impl_generic_info_methods; use crate::{ - type_info::impl_type_methods, utility::GenericTypePathCell, ApplyError, FromReflect, Generics, - GetTypeRegistration, MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut, - ReflectOwned, ReflectRef, Type, TypeInfo, TypePath, TypeRegistration, TypeRegistry, Typed, - UnnamedField, + cast::{impl_cast_partial_reflect, CastPartialReflect, CastReflect}, + type_info::impl_type_methods, + utility::GenericTypePathCell, + ApplyError, FromReflect, Generics, GetTypeRegistration, MaybeTyped, PartialReflect, Reflect, + ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Type, TypeInfo, TypePath, TypeRegistration, + TypeRegistry, Typed, UnnamedField, + __macro_exports::RegisterForReflection, }; use alloc::{boxed::Box, vec, vec::Vec}; use core::{ @@ -365,6 +368,7 @@ impl PartialReflect for DynamicTuple { } impl_type_path!((in bevy_reflect) DynamicTuple); +impl_cast_partial_reflect!(for DynamicTuple); impl FromIterator> for DynamicTuple { fn from_iter>>(fields: I) -> Self { @@ -481,11 +485,11 @@ pub fn tuple_debug(dyn_tuple: &dyn Tuple, f: &mut Formatter<'_>) -> core::fmt::R macro_rules! impl_reflect_tuple { {$($index:tt : $name:tt),*} => { - impl<$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> Tuple for ($($name,)*) { + impl<$($name: CastPartialReflect + MaybeTyped + TypePath + RegisterForReflection),*> Tuple for ($($name,)*) { #[inline] fn field(&self, index: usize) -> Option<&dyn PartialReflect> { match index { - $($index => Some(&self.$index as &dyn PartialReflect),)* + $($index => Some(CastPartialReflect::as_partial_reflect(&self.$index)),)* _ => None, } } @@ -493,7 +497,7 @@ macro_rules! impl_reflect_tuple { #[inline] fn field_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> { match index { - $($index => Some(&mut self.$index as &mut dyn PartialReflect),)* + $($index => Some(CastPartialReflect::as_partial_reflect_mut(&mut self.$index)),)* _ => None, } } @@ -515,7 +519,7 @@ macro_rules! impl_reflect_tuple { #[inline] fn drain(self: Box) -> Vec> { vec![ - $(Box::new(self.$index),)* + $(CastPartialReflect::into_partial_reflect(Box::new(self.$index)),)* ] } @@ -532,7 +536,7 @@ macro_rules! impl_reflect_tuple { } } - impl<$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> PartialReflect for ($($name,)*) { + impl<$($name: CastPartialReflect + MaybeTyped + TypePath + RegisterForReflection),*> PartialReflect for ($($name,)*) { fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } @@ -595,7 +599,7 @@ macro_rules! impl_reflect_tuple { } } - impl<$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> Reflect for ($($name,)*) { + impl<$($name: CastPartialReflect + MaybeTyped + TypePath + RegisterForReflection),*> Reflect for ($($name,)*) { fn into_any(self: Box) -> Box { self } @@ -626,7 +630,35 @@ macro_rules! impl_reflect_tuple { } } - impl <$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> Typed for ($($name,)*) { + impl<$($name: CastPartialReflect + MaybeTyped + TypePath + RegisterForReflection),*> CastPartialReflect for ($($name,)*) { + fn as_partial_reflect(&self) -> &dyn PartialReflect { + self + } + + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { + self + } + + fn into_partial_reflect(self: Box) -> Box { + self + } + } + + impl<$($name: CastPartialReflect + MaybeTyped + TypePath + RegisterForReflection),*> CastReflect for ($($name,)*) { + fn as_reflect(&self) -> &dyn Reflect { + self + } + + fn as_reflect_mut(&mut self) -> &mut dyn Reflect { + self + } + + fn into_reflect(self: Box) -> Box { + self + } + } + + impl<$($name: CastPartialReflect + MaybeTyped + TypePath + RegisterForReflection),*> Typed for ($($name,)*) { fn type_info() -> &'static TypeInfo { static CELL: $crate::utility::GenericTypeInfoCell = $crate::utility::GenericTypeInfoCell::new(); CELL.get_or_insert::(|| { @@ -639,17 +671,17 @@ macro_rules! impl_reflect_tuple { } } - impl<$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> GetTypeRegistration for ($($name,)*) { + impl<$($name: CastPartialReflect + MaybeTyped + TypePath + RegisterForReflection),*> GetTypeRegistration for ($($name,)*) { fn get_type_registration() -> TypeRegistration { TypeRegistration::of::<($($name,)*)>() } fn register_type_dependencies(_registry: &mut TypeRegistry) { - $(_registry.register::<$name>();)* + $(<$name as RegisterForReflection>::__register(_registry);)* } } - impl<$($name: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> FromReflect for ($($name,)*) + impl<$($name: FromReflect + CastPartialReflect + MaybeTyped + TypePath + RegisterForReflection),*> FromReflect for ($($name,)*) { fn from_reflect(reflect: &dyn PartialReflect) -> Option { let _ref_tuple = reflect.reflect_ref().as_tuple().ok()?; @@ -765,7 +797,7 @@ const _: () = { macro_rules! impl_from_arg_tuple { ($(#[$meta:meta])* $($name: ident),*) => { $(#[$meta])* - $crate::func::args::impl_from_arg!(($($name,)*); <$($name: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration),*>); + $crate::func::args::impl_from_arg!(($($name,)*); <$($name: FromReflect + Reflect + MaybeTyped + TypePath + RegisterForReflection),*>); }; } @@ -780,7 +812,7 @@ const _: () = { macro_rules! impl_into_return_tuple { ($(#[$meta:meta])* $($name: ident),+) => { $(#[$meta])* - $crate::func::impl_into_return!(($($name,)*); <$($name: FromReflect + Reflect + MaybeTyped + TypePath + GetTypeRegistration),*>); + $crate::func::impl_into_return!(($($name,)*); <$($name: FromReflect + Reflect + MaybeTyped + TypePath + RegisterForReflection),*>); }; } diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index 8348ca7740861..a0b874bc6135b 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -3,6 +3,7 @@ use bevy_reflect_derive::impl_type_path; use crate::generics::impl_generic_info_methods; use crate::{ attributes::{impl_custom_attribute_methods, CustomAttributes}, + cast::impl_cast_partial_reflect, type_info::impl_type_methods, ApplyError, DynamicTuple, Generics, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Tuple, Type, TypeInfo, TypePath, UnnamedField, @@ -380,6 +381,7 @@ impl PartialReflect for DynamicTupleStruct { } impl_type_path!((in bevy_reflect) DynamicTupleStruct); +impl_cast_partial_reflect!(for DynamicTupleStruct); impl Debug for DynamicTupleStruct { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { From d77257d0dbfb0cd81d041637fb985c7d03cff87f Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 29 Sep 2024 13:58:20 -0700 Subject: [PATCH 09/17] Set casting traits as supertraits of `PartialReflect`/`Reflect` --- .../bevy_reflect/derive/src/impls/casting.rs | 6 + .../bevy_reflect/derive/src/impls/common.rs | 30 ---- crates/bevy_reflect/src/array.rs | 17 +- crates/bevy_reflect/src/cast.rs | 42 ----- crates/bevy_reflect/src/enums/dynamic_enum.rs | 15 -- .../bevy_reflect/src/func/dynamic_function.rs | 12 -- crates/bevy_reflect/src/impls/smallvec.rs | 11 -- crates/bevy_reflect/src/impls/std.rs | 160 ------------------ crates/bevy_reflect/src/list.rs | 24 +-- crates/bevy_reflect/src/map.rs | 15 -- crates/bevy_reflect/src/reflect.rs | 43 +---- crates/bevy_reflect/src/serde/ser/mod.rs | 1 + crates/bevy_reflect/src/set.rs | 15 -- crates/bevy_reflect/src/struct_trait.rs | 15 -- crates/bevy_reflect/src/tuple.rs | 36 ---- crates/bevy_reflect/src/tuple_struct.rs | 15 -- .../bevy_scene/src/dynamic_scene_builder.rs | 3 +- crates/bevy_scene/src/serde.rs | 3 +- examples/reflection/dynamic_types.rs | 8 +- 19 files changed, 24 insertions(+), 447 deletions(-) diff --git a/crates/bevy_reflect/derive/src/impls/casting.rs b/crates/bevy_reflect/derive/src/impls/casting.rs index 2d635c74af67a..f5578a19e2678 100644 --- a/crates/bevy_reflect/derive/src/impls/casting.rs +++ b/crates/bevy_reflect/derive/src/impls/casting.rs @@ -15,28 +15,34 @@ pub(crate) fn impl_casting_traits( quote! { impl #impl_generics #bevy_reflect_path::cast::CastPartialReflect for #type_path #ty_generics #where_reflect_clause { + #[inline] fn as_partial_reflect(&self) -> &dyn #bevy_reflect_path::PartialReflect { self } + #[inline] fn as_partial_reflect_mut(&mut self) -> &mut dyn #bevy_reflect_path::PartialReflect { self } + #[inline] fn into_partial_reflect(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box { self } } impl #impl_generics #bevy_reflect_path::cast::CastReflect for #type_path #ty_generics #where_reflect_clause { + #[inline] fn as_reflect(&self) -> &dyn #bevy_reflect_path::Reflect { self } + #[inline] fn as_reflect_mut(&mut self) -> &mut dyn #bevy_reflect_path::Reflect { self } + #[inline] fn into_reflect(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box { self } diff --git a/crates/bevy_reflect/derive/src/impls/common.rs b/crates/bevy_reflect/derive/src/impls/common.rs index 680dc972f1a6b..a936ec43e8c36 100644 --- a/crates/bevy_reflect/derive/src/impls/common.rs +++ b/crates/bevy_reflect/derive/src/impls/common.rs @@ -57,21 +57,6 @@ pub fn impl_full_reflect( impl #impl_generics #bevy_reflect_path::Reflect for #type_path #ty_generics #where_reflect_clause { #any_impls - #[inline] - fn into_reflect(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box { - self - } - - #[inline] - fn as_reflect(&self) -> &dyn #bevy_reflect_path::Reflect { - self - } - - #[inline] - fn as_reflect_mut(&mut self) -> &mut dyn #bevy_reflect_path::Reflect { - self - } - #[inline] fn set( &mut self, @@ -139,21 +124,6 @@ pub fn common_partial_reflect_methods( #FQOption::Some(self) } - #[inline] - fn into_partial_reflect(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box { - self - } - - #[inline] - fn as_partial_reflect(&self) -> &dyn #bevy_reflect_path::PartialReflect { - self - } - - #[inline] - fn as_partial_reflect_mut(&mut self) -> &mut dyn #bevy_reflect_path::PartialReflect { - self - } - #hash_fn #partial_eq_fn diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index b8cf70983921b..3178054781237 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -201,21 +201,6 @@ impl PartialReflect for DynamicArray { self.represented_type } - #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - - #[inline] - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - #[inline] - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } - fn try_into_reflect(self: Box) -> Result, Box> { Err(self) } @@ -520,7 +505,7 @@ mod tests { usize::MAX }; - let b = Box::new([(); SIZE]).into_reflect(); + let b = (Box::new([(); SIZE]) as Box).into_reflect(); let array = b.reflect_ref().as_array().unwrap(); diff --git a/crates/bevy_reflect/src/cast.rs b/crates/bevy_reflect/src/cast.rs index cfa5d7b61c96a..52f44ea434bab 100644 --- a/crates/bevy_reflect/src/cast.rs +++ b/crates/bevy_reflect/src/cast.rs @@ -27,34 +27,6 @@ impl CastPartialReflect for Box { } } -impl CastPartialReflect for dyn PartialReflect { - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } - - fn into_partial_reflect(self: Box) -> Box { - self - } -} - -impl CastPartialReflect for dyn Reflect { - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self.as_partial_reflect() - } - - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self.as_partial_reflect_mut() - } - - fn into_partial_reflect(self: Box) -> Box { - self.into_partial_reflect() - } -} - impl CastPartialReflect for Box { fn as_partial_reflect(&self) -> &dyn PartialReflect { self.as_ref() @@ -103,20 +75,6 @@ impl CastReflect for Box { } } -impl CastReflect for dyn Reflect { - fn as_reflect(&self) -> &dyn Reflect { - self - } - - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self - } - - fn into_reflect(self: Box) -> Box { - self - } -} - impl CastReflect for Box { fn as_reflect(&self) -> &dyn Reflect { self.as_ref() diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index aab1bd214c88f..744d73e335851 100644 --- a/crates/bevy_reflect/src/enums/dynamic_enum.rs +++ b/crates/bevy_reflect/src/enums/dynamic_enum.rs @@ -281,21 +281,6 @@ impl PartialReflect for DynamicEnum { self.represented_type } - #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - - #[inline] - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - #[inline] - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } - fn try_into_reflect(self: Box) -> Result, Box> { Err(self) } diff --git a/crates/bevy_reflect/src/func/dynamic_function.rs b/crates/bevy_reflect/src/func/dynamic_function.rs index f7ff56d0ac79e..0b28f62203f61 100644 --- a/crates/bevy_reflect/src/func/dynamic_function.rs +++ b/crates/bevy_reflect/src/func/dynamic_function.rs @@ -369,18 +369,6 @@ impl PartialReflect for DynamicFunction<'static> { None } - fn into_partial_reflect(self: Box) -> Box { - self - } - - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } - fn try_into_reflect(self: Box) -> Result, Box> { Err(self) } diff --git a/crates/bevy_reflect/src/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index 61d3486f73ce8..0e652196e6563 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -85,17 +85,6 @@ where } #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } fn try_into_reflect(self: Box) -> Result, Box> { Ok(self) diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 5ff1f97864594..88361a7e42a49 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -283,18 +283,6 @@ macro_rules! impl_reflect_for_atomic { Some(::type_info()) } #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - #[inline] - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - #[inline] - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } - #[inline] fn try_into_reflect( self: Box, ) -> Result, Box> { @@ -475,20 +463,6 @@ macro_rules! impl_reflect_for_veclike { Some(::type_info()) } - fn into_partial_reflect(self: Box) -> Box { - self - } - - #[inline] - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - #[inline] - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } - fn try_into_reflect( self: Box, ) -> Result, Box> { @@ -715,19 +689,6 @@ macro_rules! impl_reflect_for_hashmap { Some(::type_info()) } - #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } - fn try_into_reflect( self: Box, ) -> Result, Box> { @@ -951,19 +912,6 @@ macro_rules! impl_reflect_for_hashset { Some(::type_info()) } - #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } - #[inline] fn try_into_reflect( self: Box, @@ -1210,18 +1158,6 @@ where Some(::type_info()) } #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } - #[inline] fn try_into_reflect(self: Box) -> Result, Box> { Ok(self) } @@ -1370,17 +1306,6 @@ impl P } #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } fn try_into_reflect(self: Box) -> Result, Box> { Ok(self) @@ -1455,21 +1380,6 @@ impl R self } - #[inline] - fn into_reflect(self: Box) -> Box { - self - } - - #[inline] - fn as_reflect(&self) -> &dyn Reflect { - self - } - - #[inline] - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self - } - #[inline] fn set(&mut self, value: Box) -> Result<(), Box> { *self = value.take()?; @@ -1605,17 +1515,6 @@ impl PartialReflect for Cow<'static, str> { } #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } fn try_into_reflect(self: Box) -> Result, Box> { Ok(self) @@ -1792,19 +1691,6 @@ impl::type_info()) } - #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } - fn try_into_reflect(self: Box) -> Result, Box> { Ok(self) } @@ -1906,17 +1792,6 @@ impl PartialReflect for &'static str { } #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } fn try_into_reflect(self: Box) -> Result, Box> { Ok(self) @@ -2012,17 +1887,6 @@ impl PartialReflect for &'static Path { } #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } fn try_into_reflect(self: Box) -> Result, Box> { Ok(self) @@ -2122,17 +1986,6 @@ impl PartialReflect for Cow<'static, Path> { } #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } fn try_into_reflect(self: Box) -> Result, Box> { Ok(self) @@ -2250,19 +2103,6 @@ impl PartialReflect for &'static Location<'static> { Some(::type_info()) } - #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } - fn try_into_reflect(self: Box) -> Result, Box> { Ok(self) } diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index fe9eee6944bcc..c9b522cb6bfe4 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -9,11 +9,10 @@ use bevy_reflect_derive::impl_type_path; use crate::generics::impl_generic_info_methods; use crate::{ - type_info::impl_type_methods, utility::reflect_hasher, ApplyError, FromReflect, Generics, - MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Type, - TypeInfo, TypePath, + cast::impl_cast_partial_reflect, type_info::impl_type_methods, utility::reflect_hasher, + ApplyError, FromReflect, Generics, MaybeTyped, PartialReflect, Reflect, ReflectKind, + ReflectMut, ReflectOwned, ReflectRef, Type, TypeInfo, TypePath, }; -use crate::cast::impl_cast_partial_reflect; /// A trait used to power [list-like] operations via [reflection]. /// @@ -266,21 +265,6 @@ impl PartialReflect for DynamicList { self.represented_type } - #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - - #[inline] - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - #[inline] - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } - fn try_into_reflect(self: Box) -> Result, Box> { Err(self) } @@ -563,7 +547,7 @@ mod tests { // If compiled in release mode, verify we dont overflow usize::MAX }; - let b = Box::new(vec![(); SIZE]).into_reflect(); + let b = (Box::new(vec![(); SIZE]) as Box).into_reflect(); let list = b.reflect_ref().as_list().unwrap(); diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index a7754cce9768f..77e7d3d15e7dc 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -380,21 +380,6 @@ impl PartialReflect for DynamicMap { self.represented_type } - #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - - #[inline] - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - #[inline] - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } - fn try_into_reflect(self: Box) -> Result, Box> { Err(self) } diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index c97764c29ce9d..2fcec0934594a 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -79,7 +79,7 @@ impl From for ApplyError { message = "`{Self}` does not implement `PartialReflect` so cannot be introspected", note = "consider annotating `{Self}` with `#[derive(Reflect)]`" )] -pub trait PartialReflect: DynamicTypePath + Send + Sync +pub trait PartialReflect: CastPartialReflect + DynamicTypePath + Send + Sync where // NB: we don't use `Self: Any` since for downcasting, `Reflect` should be used. Self: 'static, @@ -101,21 +101,6 @@ where /// [`TypeRegistry::get_type_info`]: crate::TypeRegistry::get_type_info fn get_represented_type_info(&self) -> Option<&'static TypeInfo>; - /// Casts this type to a boxed, reflected value. - /// - /// This is useful for coercing trait objects. - fn into_partial_reflect(self: Box) -> Box; - - /// Casts this type to a reflected value. - /// - /// This is useful for coercing trait objects. - fn as_partial_reflect(&self) -> &dyn PartialReflect; - - /// Casts this type to a mutable, reflected value. - /// - /// This is useful for coercing trait objects. - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect; - /// Attempts to cast this type to a boxed, [fully-reflected] value. /// /// [fully-reflected]: Reflect @@ -312,7 +297,7 @@ where message = "`{Self}` does not implement `Reflect` so cannot be fully reflected", note = "consider annotating `{Self}` with `#[derive(Reflect)]`" )] -pub trait Reflect: PartialReflect + DynamicTyped + Any { +pub trait Reflect: PartialReflect + CastReflect + DynamicTyped + Any { /// Returns the value as a [`Box`][core::any::Any]. /// /// For remote wrapper types, this will return the remote type instead. @@ -328,15 +313,6 @@ pub trait Reflect: PartialReflect + DynamicTyped + Any { /// For remote wrapper types, this will return the remote type instead. fn as_any_mut(&mut self) -> &mut dyn Any; - /// Casts this type to a boxed, fully-reflected value. - fn into_reflect(self: Box) -> Box; - - /// Casts this type to a fully-reflected value. - fn as_reflect(&self) -> &dyn Reflect; - - /// Casts this type to a mutable, fully-reflected value. - fn as_reflect_mut(&mut self) -> &mut dyn Reflect; - /// Performs a type-checked assignment of a reflected value to this value. /// /// If `value` does not contain a value of type `T`, returns an `Err` @@ -366,7 +342,7 @@ impl dyn PartialReflect { ) -> Result, Box> { self.try_into_reflect()? .downcast() - .map_err(PartialReflect::into_partial_reflect) + .map_err(CastPartialReflect::into_partial_reflect) } /// Downcasts the value to type `T`, unboxing and consuming the trait object. @@ -523,18 +499,6 @@ macro_rules! impl_full_reflect { self } - fn into_reflect(self: Box) -> Box { - self - } - - fn as_reflect(&self) -> &dyn $crate::Reflect { - self - } - - fn as_reflect_mut(&mut self) -> &mut dyn $crate::Reflect { - self - } - fn set( &mut self, value: Box, @@ -546,4 +510,5 @@ macro_rules! impl_full_reflect { }; } +use crate::cast::{CastPartialReflect, CastReflect}; pub(crate) use impl_full_reflect; diff --git a/crates/bevy_reflect/src/serde/ser/mod.rs b/crates/bevy_reflect/src/serde/ser/mod.rs index 6cfebc747f285..f77c6c81a0a22 100644 --- a/crates/bevy_reflect/src/serde/ser/mod.rs +++ b/crates/bevy_reflect/src/serde/ser/mod.rs @@ -21,6 +21,7 @@ mod tuples; #[cfg(test)] mod tests { use crate::{ + cast::CastPartialReflect, serde::{ReflectSerializer, ReflectSerializerProcessor}, PartialReflect, Reflect, ReflectSerialize, Struct, TypeRegistry, }; diff --git a/crates/bevy_reflect/src/set.rs b/crates/bevy_reflect/src/set.rs index 89fe503737b48..c27fb30a3923b 100644 --- a/crates/bevy_reflect/src/set.rs +++ b/crates/bevy_reflect/src/set.rs @@ -264,21 +264,6 @@ impl PartialReflect for DynamicSet { self.represented_type } - #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - - #[inline] - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - #[inline] - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } - #[inline] fn try_into_reflect(self: Box) -> Result, Box> { Err(self) diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index 29f67d664842d..fe389da29b937 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -392,21 +392,6 @@ impl PartialReflect for DynamicStruct { self.represented_type } - #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - - #[inline] - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - #[inline] - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } - fn try_into_reflect(self: Box) -> Result, Box> { Err(self) } diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index 8a4de93638444..5b23bd7ec4941 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -294,17 +294,6 @@ impl PartialReflect for DynamicTuple { } #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } fn try_into_reflect(self: Box) -> Result, Box> { Err(self) @@ -541,19 +530,6 @@ macro_rules! impl_reflect_tuple { Some(::type_info()) } - #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } - fn try_into_reflect(self: Box) -> Result, Box> { Ok(self) } @@ -612,18 +588,6 @@ macro_rules! impl_reflect_tuple { self } - fn into_reflect(self: Box) -> Box { - self - } - - fn as_reflect(&self) -> &dyn Reflect { - self - } - - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self - } - fn set(&mut self, value: Box) -> Result<(), Box> { *self = value.take()?; Ok(()) diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index a0b874bc6135b..c796427be4666 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -299,21 +299,6 @@ impl PartialReflect for DynamicTupleStruct { self.represented_type } - #[inline] - fn into_partial_reflect(self: Box) -> Box { - self - } - - #[inline] - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self - } - - #[inline] - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self - } - fn try_into_reflect(self: Box) -> Result, Box> { Err(self) } diff --git a/crates/bevy_scene/src/dynamic_scene_builder.rs b/crates/bevy_scene/src/dynamic_scene_builder.rs index c33346373bcc7..591fbe0344a57 100644 --- a/crates/bevy_scene/src/dynamic_scene_builder.rs +++ b/crates/bevy_scene/src/dynamic_scene_builder.rs @@ -10,6 +10,7 @@ use bevy_ecs::{ resource::Resource, world::World, }; +use bevy_reflect::cast::CastPartialReflect; use bevy_reflect::{PartialReflect, ReflectFromReflect}; use bevy_utils::default; @@ -309,7 +310,7 @@ impl<'w> DynamicSceneBuilder<'w> { let component = type_registration .data::() .and_then(|fr| fr.from_reflect(component.as_partial_reflect())) - .map(PartialReflect::into_partial_reflect) + .map(CastPartialReflect::into_partial_reflect) .unwrap_or_else(|| component.clone_value()); entry.components.push(component); diff --git a/crates/bevy_scene/src/serde.rs b/crates/bevy_scene/src/serde.rs index 103e48e50a004..a7d703469e6c4 100644 --- a/crates/bevy_scene/src/serde.rs +++ b/crates/bevy_scene/src/serde.rs @@ -4,6 +4,7 @@ use crate::{DynamicEntity, DynamicScene}; use bevy_ecs::entity::Entity; use bevy_platform_support::collections::HashSet; use bevy_reflect::{ + cast::CastPartialReflect, serde::{ ReflectDeserializer, TypeRegistrationDeserializer, TypedReflectDeserializer, TypedReflectSerializer, @@ -497,7 +498,7 @@ impl<'a, 'de> Visitor<'de> for SceneMapVisitor<'a> { .get(registration.type_id()) .and_then(|tr| tr.data::()) .and_then(|fr| fr.from_reflect(value.as_partial_reflect())) - .map(PartialReflect::into_partial_reflect) + .map(CastPartialReflect::into_partial_reflect) .unwrap_or(value); entries.push(value); diff --git a/examples/reflection/dynamic_types.rs b/examples/reflection/dynamic_types.rs index 387fe7d0ed34d..95bdd7773e494 100644 --- a/examples/reflection/dynamic_types.rs +++ b/examples/reflection/dynamic_types.rs @@ -1,10 +1,10 @@ //! This example demonstrates the use of dynamic types in Bevy's reflection system. use bevy::reflect::{ - reflect_trait, serde::TypedReflectDeserializer, std_traits::ReflectDefault, DynamicArray, - DynamicEnum, DynamicList, DynamicMap, DynamicSet, DynamicStruct, DynamicTuple, - DynamicTupleStruct, DynamicVariant, FromReflect, PartialReflect, Reflect, ReflectFromReflect, - Set, TypeRegistry, Typed, + cast::CastPartialReflect, reflect_trait, serde::TypedReflectDeserializer, + std_traits::ReflectDefault, DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicSet, + DynamicStruct, DynamicTuple, DynamicTupleStruct, DynamicVariant, FromReflect, PartialReflect, + Reflect, ReflectFromReflect, Set, TypeRegistry, Typed, }; use serde::de::DeserializeSeed; use std::collections::{HashMap, HashSet}; From 90f30a6882512a2af1d1fd748c6d808af5965d1a Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 29 Sep 2024 14:56:54 -0700 Subject: [PATCH 10/17] Merged impls to simplify custom boxed trait impl --- crates/bevy_reflect/src/cast.rs | 94 ++++++++++++++------------------- 1 file changed, 39 insertions(+), 55 deletions(-) diff --git a/crates/bevy_reflect/src/cast.rs b/crates/bevy_reflect/src/cast.rs index 52f44ea434bab..04e016f234a0a 100644 --- a/crates/bevy_reflect/src/cast.rs +++ b/crates/bevy_reflect/src/cast.rs @@ -1,8 +1,7 @@ -use crate::__macro_exports::RegisterForReflection; use crate::utility::GenericTypeInfoCell; use crate::{ - GetTypeRegistration, MaybeTyped, OpaqueInfo, PartialReflect, Reflect, TypeInfo, TypePath, - TypeRegistration, Typed, + GetTypeRegistration, OpaqueInfo, PartialReflect, Reflect, TypeInfo, TypePath, TypeRegistration, + Typed, }; use alloc::boxed::Box; use bevy_reflect_derive::impl_type_path; @@ -13,7 +12,7 @@ pub trait CastPartialReflect: Send + Sync + 'static { fn into_partial_reflect(self: Box) -> Box; } -impl CastPartialReflect for Box { +impl CastPartialReflect for Box { fn as_partial_reflect(&self) -> &dyn PartialReflect { T::as_partial_reflect(self) } @@ -27,41 +26,13 @@ impl CastPartialReflect for Box { } } -impl CastPartialReflect for Box { - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self.as_ref() - } - - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self.as_mut() - } - - fn into_partial_reflect(self: Box) -> Box { - *self - } -} - -impl CastPartialReflect for Box { - fn as_partial_reflect(&self) -> &dyn PartialReflect { - self.as_ref().as_partial_reflect() - } - - fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { - self.as_mut().as_partial_reflect_mut() - } - - fn into_partial_reflect(self: Box) -> Box { - self.into_reflect().into_partial_reflect() - } -} - pub trait CastReflect: CastPartialReflect { fn as_reflect(&self) -> &dyn Reflect; fn as_reflect_mut(&mut self) -> &mut dyn Reflect; fn into_reflect(self: Box) -> Box; } -impl CastReflect for Box { +impl CastReflect for Box { fn as_reflect(&self) -> &dyn Reflect { T::as_reflect(self) } @@ -75,36 +46,16 @@ impl CastReflect for Box { } } -impl CastReflect for Box { - fn as_reflect(&self) -> &dyn Reflect { - self.as_ref() - } - - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self.as_mut() - } - - fn into_reflect(self: Box) -> Box { - *self - } -} - impl_type_path!(::alloc::boxed::Box); -impl MaybeTyped for Box {} -impl MaybeTyped for Box {} - -impl Typed for Box { +impl Typed for Box { fn type_info() -> &'static TypeInfo { static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); CELL.get_or_insert::(|| TypeInfo::Opaque(OpaqueInfo::new::())) } } -impl RegisterForReflection for Box {} -impl RegisterForReflection for Box {} - -impl GetTypeRegistration for Box { +impl GetTypeRegistration for Box { fn get_type_registration() -> TypeRegistration { TypeRegistration::of::() } @@ -210,4 +161,37 @@ mod tests { let field_info = field.get_represented_type_info().unwrap(); assert!(field_info.ty().is::()); } + + #[test] + fn should_allow_custom_trait_objects() { + trait Equippable: Reflect {} + + impl TypePath for dyn Equippable { + fn type_path() -> &'static str { + "dyn my_crate::Equippable" + } + + fn short_type_path() -> &'static str { + "dyn Equippable" + } + } + + #[derive(Reflect)] + struct Sword(u32); + + impl Equippable for Sword {} + + #[derive(Reflect)] + #[reflect(from_reflect = false)] + struct Player { + weapon: Box, + } + + let player: Box = Box::new(Player { + weapon: Box::new(Sword(123)), + }); + + let weapon = player.field("weapon").unwrap(); + assert!(weapon.reflect_partial_eq(&Sword(123)).unwrap_or_default()); + } } From 4602e24adde3570538fba944c7d28de8b4314924 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 29 Sep 2024 15:15:12 -0700 Subject: [PATCH 11/17] Fixed docs --- crates/bevy_reflect/src/enums/dynamic_enum.rs | 1 + crates/bevy_reflect/src/lib.rs | 14 +++++--- crates/bevy_reflect/src/type_info.rs | 17 ++++++---- crates/bevy_reflect/src/utility.rs | 34 ++++++++++++------- 4 files changed, 43 insertions(+), 23 deletions(-) diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index 744d73e335851..e428211abeafa 100644 --- a/crates/bevy_reflect/src/enums/dynamic_enum.rs +++ b/crates/bevy_reflect/src/enums/dynamic_enum.rs @@ -43,6 +43,7 @@ impl From<()> for DynamicVariant { /// /// ``` /// # use bevy_reflect::{DynamicEnum, DynamicVariant, Reflect, PartialReflect}; +/// # use bevy_reflect::cast::CastPartialReflect; /// /// // The original enum value /// let mut value: Option = Some(123); diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 03e0cd2fbcc4a..f54f24bbf4de7 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -70,9 +70,9 @@ //! Since `T: Reflect` implies `T: PartialReflect`, conversion from a `dyn Reflect` to a `dyn PartialReflect` //! trait object (upcasting) is infallible and can be performed with one of the following methods. //! Note that these are temporary while [the language feature for dyn upcasting coercion] is experimental: -//! * [`PartialReflect::as_partial_reflect`] for `&dyn PartialReflect` -//! * [`PartialReflect::as_partial_reflect_mut`] for `&mut dyn PartialReflect` -//! * [`PartialReflect::into_partial_reflect`] for `Box` +//! * [`CastPartialReflect::as_partial_reflect`] for `&dyn PartialReflect` +//! * [`CastPartialReflect::as_partial_reflect_mut`] for `&mut dyn PartialReflect` +//! * [`CastPartialReflect::into_partial_reflect`] for `Box` //! //! For conversion in the other direction — downcasting `dyn PartialReflect` to `dyn Reflect` — //! there are fallible methods: @@ -165,8 +165,8 @@ //! ``` //! //! And to go back to a general-purpose `dyn PartialReflect`, -//! we can just use the matching [`PartialReflect::as_partial_reflect`], [`PartialReflect::as_partial_reflect_mut`], -//! or [`PartialReflect::into_partial_reflect`] methods. +//! we can just use the matching [`CastPartialReflect::as_partial_reflect`], [`CastPartialReflect::as_partial_reflect_mut`], +//! or [`CastPartialReflect::into_partial_reflect`] methods. //! //! ## Opaque Types //! @@ -413,6 +413,7 @@ //! ``` //! # use serde::de::DeserializeSeed; //! # use bevy_reflect::{ +//! # cast::CastPartialReflect, //! # serde::{ReflectSerializer, ReflectDeserializer}, //! # Reflect, PartialReflect, FromReflect, TypeRegistry //! # }; @@ -529,6 +530,9 @@ //! [the type registry]: #type-registration //! [runtime cost]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#trait-objects-perform-dynamic-dispatch //! [the language feature for dyn upcasting coercion]: https://github.com/rust-lang/rust/issues/65991 +//! [`CastPartialReflect::as_partial_reflect`]: cast::CastPartialReflect::as_partial_reflect +//! [`CastPartialReflect::as_partial_reflect_mut`]: cast::CastPartialReflect::as_partial_reflect_mut +//! [`CastPartialReflect::into_partial_reflect`]: cast::CastPartialReflect::into_partial_reflect //! [derive macro]: derive@crate::Reflect //! [`'static` lifetime]: https://doc.rust-lang.org/rust-by-example/scope/lifetime/static_lifetime.html#trait-bound //! [`Function`]: crate::func::Function diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index fd090ec3be310..c87a728127803 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -34,6 +34,7 @@ use thiserror::Error; /// ``` /// # use core::any::Any; /// # use bevy_reflect::{DynamicTypePath, NamedField, PartialReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, TypeInfo, TypePath, OpaqueInfo, ApplyError}; +/// # use bevy_reflect::cast::{CastPartialReflect, CastReflect}; /// # use bevy_reflect::utility::NonGenericTypeInfoCell; /// use bevy_reflect::Typed; /// @@ -62,9 +63,6 @@ use thiserror::Error; /// # } /// # impl PartialReflect for MyStruct { /// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } -/// # fn into_partial_reflect(self: Box) -> Box { todo!() } -/// # fn as_partial_reflect(&self) -> &dyn PartialReflect { todo!() } -/// # fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { todo!() } /// # fn try_into_reflect(self: Box) -> Result, Box> { todo!() } /// # fn try_as_reflect(&self) -> Option<&dyn Reflect> { todo!() } /// # fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { todo!() } @@ -78,11 +76,18 @@ use thiserror::Error; /// # fn into_any(self: Box) -> Box { todo!() } /// # fn as_any(&self) -> &dyn Any { todo!() } /// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() } -/// # fn into_reflect(self: Box) -> Box { todo!() } -/// # fn as_reflect(&self) -> &dyn Reflect { todo!() } -/// # fn as_reflect_mut(&mut self) -> &mut dyn Reflect { todo!() } /// # fn set(&mut self, value: Box) -> Result<(), Box> { todo!() } /// # } +/// # impl CastPartialReflect for MyStruct { +/// # fn as_partial_reflect(&self) -> &dyn PartialReflect { self } +/// # fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } +/// # fn into_partial_reflect(self: Box) -> Box { self } +/// # } +/// # impl CastReflect for MyStruct { +/// # fn as_reflect(&self) -> &dyn Reflect { self } +/// # fn as_reflect_mut(&mut self) -> &mut dyn Reflect { self } +/// # fn into_reflect(self: Box) -> Box { self } +/// # } /// ``` /// /// [`Reflectable`]: crate::Reflectable diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index aa340c6363aab..da02a51a8cfe8 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -56,6 +56,7 @@ mod sealed { /// ``` /// # use core::any::Any; /// # use bevy_reflect::{DynamicTypePath, NamedField, PartialReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, Typed, TypeInfo, TypePath, ApplyError}; +/// # use bevy_reflect::cast::{CastPartialReflect, CastReflect}; /// use bevy_reflect::utility::NonGenericTypeInfoCell; /// /// struct Foo { @@ -78,9 +79,6 @@ mod sealed { /// # } /// # impl PartialReflect for Foo { /// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } -/// # fn into_partial_reflect(self: Box) -> Box { todo!() } -/// # fn as_partial_reflect(&self) -> &dyn PartialReflect { todo!() } -/// # fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { todo!() } /// # fn try_into_reflect(self: Box) -> Result, Box> { todo!() } /// # fn try_as_reflect(&self) -> Option<&dyn Reflect> { todo!() } /// # fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { todo!() } @@ -94,11 +92,18 @@ mod sealed { /// # fn into_any(self: Box) -> Box { todo!() } /// # fn as_any(&self) -> &dyn Any { todo!() } /// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() } -/// # fn into_reflect(self: Box) -> Box { todo!() } -/// # fn as_reflect(&self) -> &dyn Reflect { todo!() } -/// # fn as_reflect_mut(&mut self) -> &mut dyn Reflect { todo!() } /// # fn set(&mut self, value: Box) -> Result<(), Box> { todo!() } /// # } +/// # impl CastPartialReflect for Foo { +/// # fn as_partial_reflect(&self) -> &dyn PartialReflect { self } +/// # fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } +/// # fn into_partial_reflect(self: Box) -> Box { self } +/// # } +/// # impl CastReflect for Foo { +/// # fn as_reflect(&self) -> &dyn Reflect { self } +/// # fn as_reflect_mut(&mut self) -> &mut dyn Reflect { self } +/// # fn into_reflect(self: Box) -> Box { self } +/// # } /// ``` /// /// [`TypePath`]: crate::TypePath @@ -145,6 +150,7 @@ impl Default for NonGenericTypeCell { /// ``` /// # use core::any::Any; /// # use bevy_reflect::{DynamicTypePath, PartialReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TupleStructInfo, Typed, TypeInfo, TypePath, UnnamedField, ApplyError, Generics, TypeParamInfo}; +/// # use bevy_reflect::cast::{CastPartialReflect, CastReflect}; /// use bevy_reflect::utility::GenericTypeInfoCell; /// /// struct Foo(T); @@ -166,9 +172,6 @@ impl Default for NonGenericTypeCell { /// # } /// # impl PartialReflect for Foo { /// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } -/// # fn into_partial_reflect(self: Box) -> Box { todo!() } -/// # fn as_partial_reflect(&self) -> &dyn PartialReflect { todo!() } -/// # fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { todo!() } /// # fn try_into_reflect(self: Box) -> Result, Box> { todo!() } /// # fn try_as_reflect(&self) -> Option<&dyn Reflect> { todo!() } /// # fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { todo!() } @@ -182,11 +185,18 @@ impl Default for NonGenericTypeCell { /// # fn into_any(self: Box) -> Box { todo!() } /// # fn as_any(&self) -> &dyn Any { todo!() } /// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() } -/// # fn into_reflect(self: Box) -> Box { todo!() } -/// # fn as_reflect(&self) -> &dyn Reflect { todo!() } -/// # fn as_reflect_mut(&mut self) -> &mut dyn Reflect { todo!() } /// # fn set(&mut self, value: Box) -> Result<(), Box> { todo!() } /// # } +/// # impl CastPartialReflect for Foo { +/// # fn as_partial_reflect(&self) -> &dyn PartialReflect { self } +/// # fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } +/// # fn into_partial_reflect(self: Box) -> Box { self } +/// # } +/// # impl CastReflect for Foo { +/// # fn as_reflect(&self) -> &dyn Reflect { self } +/// # fn as_reflect_mut(&mut self) -> &mut dyn Reflect { self } +/// # fn into_reflect(self: Box) -> Box { self } +/// # } /// ``` /// /// Implementing [`TypePath`] with generics. From 07610e24ab007644ebee46784721ce12264ca691 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 29 Sep 2024 15:21:30 -0700 Subject: [PATCH 12/17] Added docs --- crates/bevy_reflect/src/cast.rs | 105 +++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) diff --git a/crates/bevy_reflect/src/cast.rs b/crates/bevy_reflect/src/cast.rs index 04e016f234a0a..9d42ce79cc5e9 100644 --- a/crates/bevy_reflect/src/cast.rs +++ b/crates/bevy_reflect/src/cast.rs @@ -1,3 +1,58 @@ +//! Traits for casting types to [`dyn PartialReflect`] and [`dyn Reflect`] trait objects. +//! +//! These traits are used internally by the [derive macro] and other [`Reflect`] implementations, +//! to allow for transparent wrapper types, such as [`Box`], to be used as fields. +//! +//! # Custom Trait Objects +//! +//! These traits also enable the usage of custom trait objects as reflected fields. +//! +//! The only requirements are: +//! - The trait must have at least [`CastPartialReflect`] as a supertrait. +//! This includes using [`CastReflect`], [`PartialReflect`], or [`Reflect`] as supertraits, +//! since they are all subtraits of [`CastPartialReflect`]. +//! - The trait must implement [`TypePath`] for its trait object +//! +//! ``` +//! # use bevy_reflect::{PartialReflect, Reflect, Struct, TypePath}; +//! # +//! trait Equippable: PartialReflect {} +//! +//! impl TypePath for dyn Equippable { +//! fn type_path() -> &'static str { +//! "dyn my_crate::Equippable" +//! } +//! +//! fn short_type_path() -> &'static str { +//! "dyn Equippable" +//! } +//! } +//! +//! #[derive(Reflect)] +//! struct Sword(u32); +//! +//! impl Equippable for Sword {} +//! +//! #[derive(Reflect)] +//! #[reflect(from_reflect = false)] +//! struct Player { +//! weapon: Box, +//! } +//! +//! let player: Box = Box::new(Player { +//! weapon: Box::new(Sword(123)), +//! }); +//! +//! let weapon = player.field("weapon").unwrap(); +//! assert!(weapon.reflect_partial_eq(&Sword(123)).unwrap_or_default()); +//! ``` +//! +//! [`dyn PartialReflect`]: PartialReflect +//! [`dyn Reflect`]: crate::Reflect +//! [derive macro]: derive@crate::Reflect +//! [`Reflect`]: crate::Reflect +//! [`TypePath`]: crate::TypePath + use crate::utility::GenericTypeInfoCell; use crate::{ GetTypeRegistration, OpaqueInfo, PartialReflect, Reflect, TypeInfo, TypePath, TypeRegistration, @@ -6,9 +61,33 @@ use crate::{ use alloc::boxed::Box; use bevy_reflect_derive::impl_type_path; +/// A trait used to cast `Self` to a [`dyn PartialReflect`] trait object. +/// +/// This is automatically implemented for any type that [derives `Reflect`], +/// as well as [`Box`] where `T` also implements [`CastPartialReflect`]. +/// +/// [`dyn PartialReflect`]: PartialReflect +/// [derives `Reflect`]: derive@crate::Reflect pub trait CastPartialReflect: Send + Sync + 'static { + /// Casts this type to a [`dyn PartialReflect`] reference. + /// + /// This is useful for coercing trait objects. + /// + /// [`dyn PartialReflect`]: PartialReflect fn as_partial_reflect(&self) -> &dyn PartialReflect; + + /// Casts this type to a mutable [`dyn PartialReflect`] reference. + /// + /// This is useful for coercing trait objects. + /// + /// [`dyn PartialReflect`]: PartialReflect fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect; + + /// Casts this type into a boxed [`dyn PartialReflect`] instance. + /// + /// This is useful for coercing trait objects. + /// + /// [`dyn PartialReflect`]: PartialReflect fn into_partial_reflect(self: Box) -> Box; } @@ -26,9 +105,33 @@ impl CastPartialReflect for Box { } } +/// A trait used to cast `Self` to a [`dyn Reflect`] trait object. +/// +/// This is automatically implemented for any type that [derives `Reflect`], +/// as well as [`Box`] where `T` also implements [`CastReflect`]. +/// +/// [`dyn Reflect`]: Reflect +/// [derives `Reflect`]: derive@crate::Reflect pub trait CastReflect: CastPartialReflect { + /// Casts this type to a [`dyn Reflect`] reference. + /// + /// This is useful for coercing trait objects. + /// + /// [`dyn Reflect`]: Reflect fn as_reflect(&self) -> &dyn Reflect; + + /// Casts this type to a mutable [`dyn Reflect`] reference. + /// + /// This is useful for coercing trait objects. + /// + /// [`dyn Reflect`]: Reflect fn as_reflect_mut(&mut self) -> &mut dyn Reflect; + + /// Casts this type into a boxed [`dyn Reflect`] instance. + /// + /// This is useful for coercing trait objects. + /// + /// [`dyn Reflect`]: Reflect fn into_reflect(self: Box) -> Box; } @@ -164,7 +267,7 @@ mod tests { #[test] fn should_allow_custom_trait_objects() { - trait Equippable: Reflect {} + trait Equippable: CastPartialReflect {} impl TypePath for dyn Equippable { fn type_path() -> &'static str { From 1c7b2aa0d5cc3094f5b156ecb359d2d87b65bef8 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 29 Sep 2024 15:22:01 -0700 Subject: [PATCH 13/17] Added trivial `#[inline]` annotations --- crates/bevy_reflect/src/cast.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/bevy_reflect/src/cast.rs b/crates/bevy_reflect/src/cast.rs index 9d42ce79cc5e9..cb5e26e4685e7 100644 --- a/crates/bevy_reflect/src/cast.rs +++ b/crates/bevy_reflect/src/cast.rs @@ -167,14 +167,17 @@ impl GetTypeRegistration for Box { macro_rules! impl_cast_partial_reflect { ($(<$($id:ident),* $(,)?>)? for $ty:ty $(where $($tt:tt)*)?) => { impl $(<$($id),*>)? $crate::cast::CastPartialReflect for $ty $(where $($tt)*)? { + #[inline] fn as_partial_reflect(&self) -> &dyn $crate::PartialReflect { self } + #[inline] fn as_partial_reflect_mut(&mut self) -> &mut dyn $crate::PartialReflect { self } + #[inline] fn into_partial_reflect(self: Box) -> Box { self } @@ -190,14 +193,17 @@ macro_rules! impl_casting_traits { $crate::cast::impl_cast_partial_reflect!($(<$($id),*>)? for $ty $(where $($tt)*)?); impl $(<$($id),*>)? $crate::cast::CastReflect for $ty $(where $($tt)*)? { + #[inline] fn as_reflect(&self) -> &dyn $crate::Reflect { self } + #[inline] fn as_reflect_mut(&mut self) -> &mut dyn $crate::Reflect { self } + #[inline] fn into_reflect(self: Box) -> Box { self } From be027590db234cff4a5bdc6cc10b90d6269d7dc8 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 29 Sep 2024 16:28:06 -0700 Subject: [PATCH 14/17] Added test for type parameters --- crates/bevy_reflect/src/cast.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/crates/bevy_reflect/src/cast.rs b/crates/bevy_reflect/src/cast.rs index cb5e26e4685e7..2648cb7cbe371 100644 --- a/crates/bevy_reflect/src/cast.rs +++ b/crates/bevy_reflect/src/cast.rs @@ -271,6 +271,25 @@ mod tests { assert!(field_info.ty().is::()); } + #[test] + fn should_allow_boxed_type_parameter() { + #[derive(Reflect)] + #[reflect(from_reflect = false)] + struct MyStruct { + value: T, + } + + let my_struct: Box = Box::new(MyStruct { + value: Box::new(123_i32), + }); + + let field = my_struct.field("value").unwrap(); + assert_eq!(field.try_downcast_ref::(), Some(&123)); + + let field_info = field.get_represented_type_info().unwrap(); + assert!(field_info.ty().is::()); + } + #[test] fn should_allow_custom_trait_objects() { trait Equippable: CastPartialReflect {} From 95409f7732558d5baf4bdfe247043ccec496fdef Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 29 Sep 2024 16:42:46 -0700 Subject: [PATCH 15/17] Added custom `diagnostic::on_unimplemented` attributes --- crates/bevy_reflect/src/cast.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/bevy_reflect/src/cast.rs b/crates/bevy_reflect/src/cast.rs index 2648cb7cbe371..9228858c29ef6 100644 --- a/crates/bevy_reflect/src/cast.rs +++ b/crates/bevy_reflect/src/cast.rs @@ -68,6 +68,10 @@ use bevy_reflect_derive::impl_type_path; /// /// [`dyn PartialReflect`]: PartialReflect /// [derives `Reflect`]: derive@crate::Reflect +#[diagnostic::on_unimplemented( + message = "`{Self}` does not implement `CastPartialReflect` so cannot be cast to `dyn PartialReflect`", + note = "consider annotating `{Self}` with `#[derive(Reflect)]`" +)] pub trait CastPartialReflect: Send + Sync + 'static { /// Casts this type to a [`dyn PartialReflect`] reference. /// @@ -112,6 +116,10 @@ impl CastPartialReflect for Box { /// /// [`dyn Reflect`]: Reflect /// [derives `Reflect`]: derive@crate::Reflect +#[diagnostic::on_unimplemented( + message = "`{Self}` does not implement `CastReflect` so cannot be cast to `dyn Reflect`", + note = "consider annotating `{Self}` with `#[derive(Reflect)]`" +)] pub trait CastReflect: CastPartialReflect { /// Casts this type to a [`dyn Reflect`] reference. /// From 287dc32defa8a53851dbe70efe8f6b821faf12d1 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Sun, 29 Sep 2024 16:43:03 -0700 Subject: [PATCH 16/17] Fixed compile fail tests --- .../compile_fail/tests/reflect_derive/generics_fail.rs | 1 + .../compile_fail/tests/reflect_remote/nested_fail.rs | 9 +++------ .../compile_fail/tests/reflect_remote/nested_pass.rs | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/crates/bevy_reflect/compile_fail/tests/reflect_derive/generics_fail.rs b/crates/bevy_reflect/compile_fail/tests/reflect_derive/generics_fail.rs index 6f90097828b64..3485a56e5a903 100644 --- a/crates/bevy_reflect/compile_fail/tests/reflect_derive/generics_fail.rs +++ b/crates/bevy_reflect/compile_fail/tests/reflect_derive/generics_fail.rs @@ -14,6 +14,7 @@ fn main() { let mut foo: Box = Box::new(Foo:: { a: NoReflect(42.0) }); //~^ ERROR: `NoReflect` does not implement `GetTypeRegistration` so cannot provide type registration information //~| ERROR: `NoReflect` does not implement `Typed` so cannot provide static type information + //~| ERROR: `NoReflect` does not implement `CastPartialReflect` so cannot be cast to `dyn PartialReflect` // foo doesn't implement Reflect because NoReflect doesn't implement Reflect foo.get_field::("a").unwrap(); diff --git a/crates/bevy_reflect/compile_fail/tests/reflect_remote/nested_fail.rs b/crates/bevy_reflect/compile_fail/tests/reflect_remote/nested_fail.rs index 0f8ade8e234ca..4b8b0072fcd69 100644 --- a/crates/bevy_reflect/compile_fail/tests/reflect_remote/nested_fail.rs +++ b/crates/bevy_reflect/compile_fail/tests/reflect_remote/nested_fail.rs @@ -19,15 +19,12 @@ mod missing_attribute { } mod incorrect_inner_type { - use bevy_reflect::{FromReflect, GetTypeRegistration, reflect_remote}; + use bevy_reflect::{FromReflect, GetTypeRegistration, Reflect, reflect_remote}; #[reflect_remote(super::external_crate::TheirOuter)] - //~^ ERROR: `TheirInner` does not implement `PartialReflect` so cannot be introspected - //~| ERROR: `TheirInner` does not implement `PartialReflect` so cannot be introspected - //~| ERROR: `TheirInner` does not implement `PartialReflect` so cannot be introspected - //~| ERROR: `TheirInner` does not implement `TypePath` so cannot provide dynamic type path information + //~^ ERROR: `TheirInner` does not implement `CastPartialReflect` so cannot be cast to `dyn PartialReflect` //~| ERROR: `?` operator has incompatible types - struct MyOuter { + struct MyOuter { // Reason: Should not use `MyInner` directly pub inner: MyInner, //~^ ERROR: mismatched types diff --git a/crates/bevy_reflect/compile_fail/tests/reflect_remote/nested_pass.rs b/crates/bevy_reflect/compile_fail/tests/reflect_remote/nested_pass.rs index cd79ede57ab5d..7a5d56f954004 100644 --- a/crates/bevy_reflect/compile_fail/tests/reflect_remote/nested_pass.rs +++ b/crates/bevy_reflect/compile_fail/tests/reflect_remote/nested_pass.rs @@ -9,7 +9,7 @@ mod external_crate { } #[reflect_remote(external_crate::TheirOuter)] -struct MyOuter { +struct MyOuter { #[reflect(remote = MyInner)] pub inner: external_crate::TheirInner, } From 79d864f600cfddce0ad1d815ad15d912db7ac826 Mon Sep 17 00:00:00 2001 From: Gino Valente Date: Mon, 3 Mar 2025 17:22:58 -0700 Subject: [PATCH 17/17] Fix formatting and clippy --- crates/bevy_reflect/src/impls/smallvec.rs | 1 - crates/bevy_reflect/src/impls/std.rs | 5 ----- crates/bevy_reflect/src/tuple.rs | 1 - crates/bevy_reflect/src/type_info.rs | 4 ++-- crates/bevy_scene/src/dynamic_scene_builder.rs | 2 +- 5 files changed, 3 insertions(+), 10 deletions(-) diff --git a/crates/bevy_reflect/src/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index 0e652196e6563..bf2ecf1c4debd 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -85,7 +85,6 @@ where } #[inline] - fn try_into_reflect(self: Box) -> Result, Box> { Ok(self) } diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 88361a7e42a49..a8c88b22aeffb 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -1306,7 +1306,6 @@ impl P } #[inline] - fn try_into_reflect(self: Box) -> Result, Box> { Ok(self) } @@ -1515,7 +1514,6 @@ impl PartialReflect for Cow<'static, str> { } #[inline] - fn try_into_reflect(self: Box) -> Result, Box> { Ok(self) } @@ -1792,7 +1790,6 @@ impl PartialReflect for &'static str { } #[inline] - fn try_into_reflect(self: Box) -> Result, Box> { Ok(self) } @@ -1887,7 +1884,6 @@ impl PartialReflect for &'static Path { } #[inline] - fn try_into_reflect(self: Box) -> Result, Box> { Ok(self) } @@ -1986,7 +1982,6 @@ impl PartialReflect for Cow<'static, Path> { } #[inline] - fn try_into_reflect(self: Box) -> Result, Box> { Ok(self) } diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index 5b23bd7ec4941..dd445cf27f753 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -294,7 +294,6 @@ impl PartialReflect for DynamicTuple { } #[inline] - fn try_into_reflect(self: Box) -> Result, Box> { Err(self) } diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index c87a728127803..1b70b98360ec1 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -1,7 +1,7 @@ use crate::{ ArrayInfo, DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicStruct, DynamicTuple, - DynamicTupleStruct, EnumInfo, Generics, ListInfo, MapInfo, ReflectKind, SetInfo, - StructInfo, TupleInfo, TupleStructInfo, TypePath, TypePathTable, + DynamicTupleStruct, EnumInfo, Generics, ListInfo, MapInfo, ReflectKind, SetInfo, StructInfo, + TupleInfo, TupleStructInfo, TypePath, TypePathTable, }; use core::{ any::{Any, TypeId}, diff --git a/crates/bevy_scene/src/dynamic_scene_builder.rs b/crates/bevy_scene/src/dynamic_scene_builder.rs index 591fbe0344a57..330e0e262b7f9 100644 --- a/crates/bevy_scene/src/dynamic_scene_builder.rs +++ b/crates/bevy_scene/src/dynamic_scene_builder.rs @@ -387,7 +387,7 @@ impl<'w> DynamicSceneBuilder<'w> { let resource = type_registration .data::() .and_then(|fr| fr.from_reflect(resource.as_partial_reflect())) - .map(PartialReflect::into_partial_reflect) + .map(CastPartialReflect::into_partial_reflect) .unwrap_or_else(|| resource.clone_value()); self.extracted_resources.insert(component_id, resource);