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/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/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_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/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, } 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..f5578a19e2678 --- /dev/null +++ b/crates/bevy_reflect/derive/src/impls/casting.rs @@ -0,0 +1,51 @@ +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 { + #[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 e8fdadb03e368..a936ec43e8c36 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,25 +51,12 @@ 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 - #[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, @@ -78,6 +66,8 @@ pub fn impl_full_reflect( #FQResult::Ok(()) } } + + #casting_impls } } @@ -134,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/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/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/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/array.rs b/crates/bevy_reflect/src/array.rs index 300e69c2a71e9..3178054781237 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; @@ -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) } @@ -358,6 +343,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> { @@ -519,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 new file mode 100644 index 0000000000000..9228858c29ef6 --- /dev/null +++ b/crates/bevy_reflect/src/cast.rs @@ -0,0 +1,333 @@ +//! 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, + Typed, +}; +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 +#[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. + /// + /// 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; +} + +impl CastPartialReflect for Box { + fn as_partial_reflect(&self) -> &dyn PartialReflect { + T::as_partial_reflect(self) + } + + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { + T::as_partial_reflect_mut(self) + } + + fn into_partial_reflect(self: Box) -> Box { + T::into_partial_reflect(*self) + } +} + +/// 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 +#[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. + /// + /// 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; +} + +impl CastReflect for Box { + fn as_reflect(&self) -> &dyn Reflect { + T::as_reflect(self) + } + + fn as_reflect_mut(&mut self) -> &mut dyn Reflect { + T::as_reflect_mut(self) + } + + fn into_reflect(self: Box) -> Box { + T::into_reflect(*self) + } +} + +impl_type_path!(::alloc::boxed::Box); + +impl Typed for Box { + fn type_info() -> &'static TypeInfo { + static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); + CELL.get_or_insert::(|| TypeInfo::Opaque(OpaqueInfo::new::())) + } +} + +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)*)? { + #[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 + } + } + }; +} + +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)*)? { + #[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 + } + } + }; +} + +pub(crate) use impl_casting_traits; + +#[cfg(test)] +mod tests { + use super::*; + use crate::{Struct, Tuple, 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::()); + } + + #[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::()); + } + + #[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 {} + + 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()); + } +} diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index d9e228c07eaae..e428211abeafa 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}; @@ -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); @@ -281,21 +282,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) } @@ -406,3 +392,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/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, 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/func/dynamic_function.rs b/crates/bevy_reflect/src/func/dynamic_function.rs index 6d1c9776a9f7b..0b28f62203f61 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::{ @@ -368,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) } @@ -446,6 +435,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 afb75aff8d997..bf2ecf1c4debd 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -1,18 +1,17 @@ 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 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,25 +78,13 @@ 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()) } #[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) } @@ -143,43 +130,16 @@ where } } -impl Reflect for SmallVec -where - T::Item: FromReflect + 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 - T::Item: FromReflect + MaybeTyped + TypePath, + T::Item: FromReflect + Reflect + MaybeTyped + TypePath, { fn type_info() -> &'static TypeInfo { static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); @@ -196,7 +156,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 +173,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 +183,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..a8c88b22aeffb 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, @@ -282,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> { @@ -409,7 +398,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,26 +457,12 @@ 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()) } - 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> { @@ -539,9 +514,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 +529,7 @@ macro_rules! impl_reflect_for_veclike { } } - impl GetTypeRegistration + impl GetTypeRegistration for $ty { fn get_type_registration() -> TypeRegistration { @@ -569,7 +544,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 +563,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 +575,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,27 +681,14 @@ 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> { 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> { @@ -777,15 +739,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 +765,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 +784,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 +815,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 +826,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 +836,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,26 +905,13 @@ 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> { 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, @@ -1013,7 +962,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 +979,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 +997,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 +1032,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 +1042,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,25 +1151,13 @@ 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()) } #[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) } @@ -1268,14 +1205,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 +1229,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 +1242,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 +1264,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 > ); @@ -1369,18 +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,29 +1380,46 @@ impl R } #[inline] - fn into_reflect(self: Box) -> Box { + fn set(&mut self, value: Box) -> Result<(), Box> { + *self = value.take()?; + Ok(()) + } +} + +impl CastPartialReflect + for [T; N] +{ + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } - #[inline] + 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 } - #[inline] fn as_reflect_mut(&mut self) -> &mut dyn Reflect { self } - #[inline] - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) + fn into_reflect(self: Box) -> Box { + self } } -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()?; @@ -1572,18 +1514,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) } @@ -1693,7 +1623,7 @@ where } } -impl List +impl List for Cow<'static, [T]> { fn get(&self, index: usize) -> Option<&dyn PartialReflect> { @@ -1752,26 +1682,13 @@ impl List } } -impl PartialReflect +impl PartialReflect for Cow<'static, [T]> { fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { 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) } @@ -1824,10 +1741,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 +1753,8 @@ impl Typed } } -impl GetTypeRegistration - for Cow<'static, [T]> +impl + GetTypeRegistration for Cow<'static, [T]> { fn get_type_registration() -> TypeRegistration { TypeRegistration::of::>() @@ -1848,7 +1765,7 @@ impl GetTy } } -impl FromReflect +impl FromReflect for Cow<'static, [T]> { fn from_reflect(reflect: &dyn PartialReflect) -> Option { @@ -1865,7 +1782,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> { @@ -1873,18 +1790,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) } @@ -1945,37 +1850,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 +1872,8 @@ impl FromReflect for &'static str { } } +impl_full_reflect!(for &'static str); + #[cfg(feature = "functions")] crate::func::macros::impl_function_traits!(&'static str); @@ -2008,18 +1884,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) } @@ -2080,38 +1944,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 +1969,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); @@ -2147,18 +1982,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) } @@ -2223,38 +2046,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 +2077,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>); @@ -2304,19 +2098,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) } @@ -2377,37 +2158,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 +2180,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/lib.rs b/crates/bevy_reflect/src/lib.rs index cf38c1da5086f..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 @@ -568,6 +572,7 @@ extern crate alloc; extern crate self as bevy_reflect; mod array; +pub mod cast; mod fields; mod from_reflect; #[cfg(feature = "functions")] diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index e0f019c4b26dc..c9b522cb6bfe4 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -9,9 +9,9 @@ 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, }; /// A trait used to power [list-like] operations via [reflection]. @@ -265,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) } @@ -347,6 +332,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 { @@ -561,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 1ce685b127854..77e7d3d15e7dc 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}; @@ -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) } @@ -452,6 +437,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..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. @@ -507,6 +483,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 @@ -520,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, @@ -543,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 799499a8adcd7..c27fb30a3923b 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, @@ -263,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) @@ -338,6 +324,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..fe389da29b937 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, @@ -391,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) } @@ -471,6 +457,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 28f95b6886cd8..dd445cf27f753 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::{ @@ -291,18 +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) } @@ -365,6 +356,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 +473,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 +485,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 +507,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,24 +524,11 @@ 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()) } - #[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) } @@ -595,7 +574,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 } @@ -608,10 +587,27 @@ macro_rules! impl_reflect_tuple { self } - fn into_reflect(self: Box) -> Box { + fn set(&mut self, value: Box) -> Result<(), Box> { + *self = value.take()?; + Ok(()) + } + } + + 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 } @@ -620,13 +616,12 @@ macro_rules! impl_reflect_tuple { self } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) + fn into_reflect(self: Box) -> Box { + self } } - impl <$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> Typed for ($($name,)*) { + 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 +634,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 + 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 +760,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 + RegisterForReflection),*>); }; } @@ -780,7 +775,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 + RegisterForReflection),*>); }; } diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index 8348ca7740861..c796427be4666 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, @@ -298,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) } @@ -380,6 +366,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 { diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index 2add261aa2b68..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, PartialReflect, Reflect, - ReflectKind, SetInfo, StructInfo, TupleInfo, TupleStructInfo, TypePath, TypePathTable, + DynamicTupleStruct, EnumInfo, Generics, ListInfo, MapInfo, ReflectKind, SetInfo, StructInfo, + TupleInfo, TupleStructInfo, TypePath, TypePathTable, }; use core::{ any::{Any, TypeId}, @@ -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 @@ -91,7 +96,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 @@ -112,7 +117,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 @@ -558,7 +563,7 @@ pub struct OpaqueInfo { } impl OpaqueInfo { - pub fn new() -> Self { + pub fn new() -> Self { Self { ty: Type::of::(), generics: Generics::new(), 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(), 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. diff --git a/crates/bevy_scene/src/dynamic_scene_builder.rs b/crates/bevy_scene/src/dynamic_scene_builder.rs index c33346373bcc7..330e0e262b7f9 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); @@ -386,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); 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/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 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};