diff --git a/crates/bevy_asset/src/handle.rs b/crates/bevy_asset/src/handle.rs index 24d01bc58315f..95e480493a4c4 100644 --- a/crates/bevy_asset/src/handle.rs +++ b/crates/bevy_asset/src/handle.rs @@ -515,6 +515,8 @@ pub enum UntypedAssetConversionError { #[cfg(test)] mod tests { + use bevy_reflect::PartialReflect; + use super::*; type TestAsset = (); @@ -651,7 +653,7 @@ mod tests { ); let reflected: &dyn Reflect = &handle; - let cloned_handle: Box = reflected.clone_value(); + let cloned_handle: Box = reflected.clone_value(); assert_eq!( Arc::strong_count(strong), diff --git a/crates/bevy_asset/src/reflect.rs b/crates/bevy_asset/src/reflect.rs index 7c36571c3e537..a74a8b7fa5a0f 100644 --- a/crates/bevy_asset/src/reflect.rs +++ b/crates/bevy_asset/src/reflect.rs @@ -1,7 +1,7 @@ use std::any::{Any, TypeId}; use bevy_ecs::world::{unsafe_world_cell::UnsafeWorldCell, World}; -use bevy_reflect::{FromReflect, FromType, Reflect}; +use bevy_reflect::{FromReflect, FromType, PartialReflect, Reflect}; use crate::{Asset, AssetId, Assets, Handle, UntypedAssetId, UntypedHandle}; @@ -22,8 +22,8 @@ pub struct ReflectAsset { // - may only be called with an [`UnsafeWorldCell`] which can be used to access the corresponding `Assets` resource mutably // - may only be used to access **at most one** access at once get_unchecked_mut: unsafe fn(UnsafeWorldCell<'_>, UntypedHandle) -> Option<&mut dyn Reflect>, - add: fn(&mut World, &dyn Reflect) -> UntypedHandle, - insert: fn(&mut World, UntypedHandle, &dyn Reflect), + add: fn(&mut World, &dyn PartialReflect) -> UntypedHandle, + insert: fn(&mut World, UntypedHandle, &dyn PartialReflect), len: fn(&World) -> usize, ids: for<'w> fn(&'w World) -> Box + 'w>, remove: fn(&mut World, UntypedHandle) -> Option>, @@ -94,11 +94,11 @@ impl ReflectAsset { } /// Equivalent of [`Assets::add`] - pub fn add(&self, world: &mut World, value: &dyn Reflect) -> UntypedHandle { + pub fn add(&self, world: &mut World, value: &dyn PartialReflect) -> UntypedHandle { (self.add)(world, value) } /// Equivalent of [`Assets::insert`] - pub fn insert(&self, world: &mut World, handle: UntypedHandle, value: &dyn Reflect) { + pub fn insert(&self, world: &mut World, handle: UntypedHandle, value: &dyn PartialReflect) { (self.insert)(world, handle, value); } diff --git a/crates/bevy_ecs/src/reflect/bundle.rs b/crates/bevy_ecs/src/reflect/bundle.rs index 7f905015458d5..b594506c7a824 100644 --- a/crates/bevy_ecs/src/reflect/bundle.rs +++ b/crates/bevy_ecs/src/reflect/bundle.rs @@ -4,13 +4,15 @@ //! This module exports two types: [`ReflectBundleFns`] and [`ReflectBundle`]. //! //! Same as [`super::component`], but for bundles. -use std::any::TypeId; +use std::any::{Any, TypeId}; use crate::{ prelude::Bundle, world::{EntityMut, EntityWorldMut}, }; -use bevy_reflect::{FromReflect, FromType, Reflect, ReflectRef, TypeRegistry}; +use bevy_reflect::{ + FromReflect, FromType, PartialReflect, Reflect, ReflectRef, TypePath, TypeRegistry, +}; use super::{from_reflect_with_fallback, ReflectComponent}; @@ -27,11 +29,11 @@ pub struct ReflectBundle(ReflectBundleFns); #[derive(Clone)] pub struct ReflectBundleFns { /// Function pointer implementing [`ReflectBundle::insert()`]. - pub insert: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry), + pub insert: fn(&mut EntityWorldMut, &dyn PartialReflect, &TypeRegistry), /// Function pointer implementing [`ReflectBundle::apply()`]. - pub apply: fn(EntityMut, &dyn Reflect, &TypeRegistry), + pub apply: fn(EntityMut, &dyn PartialReflect, &TypeRegistry), /// Function pointer implementing [`ReflectBundle::apply_or_insert()`]. - pub apply_or_insert: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry), + pub apply_or_insert: fn(&mut EntityWorldMut, &dyn PartialReflect, &TypeRegistry), /// Function pointer implementing [`ReflectBundle::remove()`]. pub remove: fn(&mut EntityWorldMut), } @@ -42,7 +44,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 } } @@ -52,7 +54,7 @@ impl ReflectBundle { pub fn insert( &self, entity: &mut EntityWorldMut, - bundle: &dyn Reflect, + bundle: &dyn PartialReflect, registry: &TypeRegistry, ) { (self.0.insert)(entity, bundle, registry); @@ -66,7 +68,7 @@ impl ReflectBundle { pub fn apply<'a>( &self, entity: impl Into>, - bundle: &dyn Reflect, + bundle: &dyn PartialReflect, registry: &TypeRegistry, ) { (self.0.apply)(entity.into(), bundle, registry); @@ -76,7 +78,7 @@ impl ReflectBundle { pub fn apply_or_insert( &self, entity: &mut EntityWorldMut, - bundle: &dyn Reflect, + bundle: &dyn PartialReflect, registry: &TypeRegistry, ) { (self.0.apply_or_insert)(entity, bundle, registry); @@ -122,7 +124,7 @@ impl ReflectBundle { } } -impl FromType for ReflectBundle { +impl FromType for ReflectBundle { fn from_type() -> Self { ReflectBundle(ReflectBundleFns { insert: |entity, reflected_bundle, registry| { @@ -180,10 +182,16 @@ impl FromType for ReflectBundle { } } -fn apply_field(entity: &mut EntityMut, field: &dyn Reflect, registry: &TypeRegistry) { - if let Some(reflect_component) = registry.get_type_data::(field.type_id()) { +fn apply_field(entity: &mut EntityMut, field: &dyn PartialReflect, registry: &TypeRegistry) { + let Some(type_id) = field.try_as_reflect().map(Any::type_id) else { + panic!( + "`{}` did not implement `Reflect`", + field.reflect_type_path() + ); + }; + if let Some(reflect_component) = registry.get_type_data::(type_id) { reflect_component.apply(entity.reborrow(), field); - } else if let Some(reflect_bundle) = registry.get_type_data::(field.type_id()) { + } else if let Some(reflect_bundle) = registry.get_type_data::(type_id) { reflect_bundle.apply(entity.reborrow(), field, registry); } else { panic!( @@ -195,19 +203,22 @@ fn apply_field(entity: &mut EntityMut, field: &dyn Reflect, registry: &TypeRegis fn apply_or_insert_field( entity: &mut EntityWorldMut, - field: &dyn Reflect, + field: &dyn PartialReflect, registry: &TypeRegistry, ) { - if let Some(reflect_component) = registry.get_type_data::(field.type_id()) { + let Some(type_id) = field.try_as_reflect().map(Any::type_id) else { + panic!( + "`{}` did not implement `Reflect`", + field.reflect_type_path() + ); + }; + + if let Some(reflect_component) = registry.get_type_data::(type_id) { reflect_component.apply_or_insert(entity, field, registry); - } else if let Some(reflect_bundle) = registry.get_type_data::(field.type_id()) { + } else if let Some(reflect_bundle) = registry.get_type_data::(type_id) { reflect_bundle.apply_or_insert(entity, field, registry); } else { - let is_component = entity - .world() - .components() - .get_id(field.type_id()) - .is_some(); + let is_component = entity.world().components().get_id(type_id).is_some(); if is_component { panic!( diff --git a/crates/bevy_ecs/src/reflect/component.rs b/crates/bevy_ecs/src/reflect/component.rs index b41d206dd8884..d1b99ca2edcc9 100644 --- a/crates/bevy_ecs/src/reflect/component.rs +++ b/crates/bevy_ecs/src/reflect/component.rs @@ -67,7 +67,7 @@ use crate::{ FilteredEntityRef, World, }, }; -use bevy_reflect::{FromReflect, FromType, Reflect, TypeRegistry}; +use bevy_reflect::{FromReflect, FromType, PartialReflect, Reflect, TypePath, TypeRegistry}; /// A struct used to operate on reflected [`Component`] trait of a type. /// @@ -99,11 +99,11 @@ pub struct ReflectComponent(ReflectComponentFns); #[derive(Clone)] pub struct ReflectComponentFns { /// Function pointer implementing [`ReflectComponent::insert()`]. - pub insert: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry), + pub insert: fn(&mut EntityWorldMut, &dyn PartialReflect, &TypeRegistry), /// Function pointer implementing [`ReflectComponent::apply()`]. - pub apply: fn(EntityMut, &dyn Reflect), + pub apply: fn(EntityMut, &dyn PartialReflect), /// Function pointer implementing [`ReflectComponent::apply_or_insert()`]. - pub apply_or_insert: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry), + pub apply_or_insert: fn(&mut EntityWorldMut, &dyn PartialReflect, &TypeRegistry), /// Function pointer implementing [`ReflectComponent::remove()`]. pub remove: fn(&mut EntityWorldMut), /// Function pointer implementing [`ReflectComponent::contains()`]. @@ -127,7 +127,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 } } @@ -137,7 +137,7 @@ impl ReflectComponent { pub fn insert( &self, entity: &mut EntityWorldMut, - component: &dyn Reflect, + component: &dyn PartialReflect, registry: &TypeRegistry, ) { (self.0.insert)(entity, component, registry); @@ -148,7 +148,7 @@ impl ReflectComponent { /// # Panics /// /// Panics if there is no [`Component`] of the given type. - pub fn apply<'a>(&self, entity: impl Into>, component: &dyn Reflect) { + pub fn apply<'a>(&self, entity: impl Into>, component: &dyn PartialReflect) { (self.0.apply)(entity.into(), component); } @@ -156,7 +156,7 @@ impl ReflectComponent { pub fn apply_or_insert( &self, entity: &mut EntityWorldMut, - component: &dyn Reflect, + component: &dyn PartialReflect, registry: &TypeRegistry, ) { (self.0.apply_or_insert)(entity, component, registry); @@ -256,7 +256,7 @@ impl ReflectComponent { } } -impl FromType for ReflectComponent { +impl FromType for ReflectComponent { fn from_type() -> Self { ReflectComponent(ReflectComponentFns { insert: |entity, reflected_component, registry| { @@ -271,7 +271,7 @@ impl FromType for ReflectComponent { }, apply_or_insert: |entity, reflected_component, registry| { if let Some(mut component) = entity.get_mut::() { - component.apply(reflected_component); + component.apply(reflected_component.as_partial_reflect()); } else { let component = entity.world_scope(|world| { from_reflect_with_fallback::(reflected_component, world, registry) diff --git a/crates/bevy_ecs/src/reflect/entity_commands.rs b/crates/bevy_ecs/src/reflect/entity_commands.rs index 1a3a0138fe896..a48d1299bd3a6 100644 --- a/crates/bevy_ecs/src/reflect/entity_commands.rs +++ b/crates/bevy_ecs/src/reflect/entity_commands.rs @@ -3,7 +3,7 @@ use crate::reflect::AppTypeRegistry; use crate::system::{EntityCommands, Resource}; use crate::world::Command; use crate::{entity::Entity, reflect::ReflectComponent, world::World}; -use bevy_reflect::{Reflect, TypeRegistry}; +use bevy_reflect::{PartialReflect, TypeRegistry}; use std::borrow::Cow; use std::marker::PhantomData; @@ -18,7 +18,7 @@ pub trait ReflectCommandExt { /// /// - If the entity doesn't exist. /// - If [`AppTypeRegistry`] does not have the reflection data for the given [`Component`](crate::component::Component). - /// - If the component data is invalid. See [`Reflect::apply`] for further details. + /// - If the component data is invalid. See [`PartialReflect::apply`] for further details. /// - If [`AppTypeRegistry`] is not present in the [`World`]. /// /// # Note @@ -69,7 +69,7 @@ pub trait ReflectCommandExt { /// } /// /// ``` - fn insert_reflect(&mut self, component: Box) -> &mut Self; + fn insert_reflect(&mut self, component: Box) -> &mut Self; /// Same as [`insert_reflect`](ReflectCommandExt::insert_reflect), but using the `T` resource as type registry instead of /// `AppTypeRegistry`. @@ -83,7 +83,7 @@ pub trait ReflectCommandExt { /// - The given [`Resource`] is removed from the [`World`] before the command is applied. fn insert_reflect_with_registry>( &mut self, - component: Box, + component: Box, ) -> &mut Self; /// Removes from the entity the component with the given type name registered in [`AppTypeRegistry`]. @@ -142,7 +142,7 @@ pub trait ReflectCommandExt { } impl ReflectCommandExt for EntityCommands<'_> { - fn insert_reflect(&mut self, component: Box) -> &mut Self { + fn insert_reflect(&mut self, component: Box) -> &mut Self { self.commands.add(InsertReflect { entity: self.entity, component, @@ -152,7 +152,7 @@ impl ReflectCommandExt for EntityCommands<'_> { fn insert_reflect_with_registry>( &mut self, - component: Box, + component: Box, ) -> &mut Self { self.commands.add(InsertReflectWithRegistry:: { entity: self.entity, @@ -188,7 +188,7 @@ fn insert_reflect( world: &mut World, entity: Entity, type_registry: &TypeRegistry, - component: Box, + component: Box, ) { let type_info = component .get_represented_type_info() @@ -197,13 +197,13 @@ fn insert_reflect( let Some(mut entity) = world.get_entity_mut(entity) else { panic!("error[B0003]: Could not insert a reflected component (of type {type_path}) for entity {entity:?} because it doesn't exist in this World. See: https://bevyengine.org/learn/errors/b0003"); }; - let Some(type_registration) = type_registry.get_with_type_path(type_path) else { + let Some(type_registration) = type_registry.get(type_info.type_id()) else { panic!("Could not get type registration (for component type {type_path}) because it doesn't exist in the TypeRegistry."); }; let Some(reflect_component) = type_registration.data::() else { panic!("Could not get ReflectComponent data (for component type {type_path}) because it doesn't exist in this TypeRegistration."); }; - reflect_component.insert(&mut entity, &*component, type_registry); + reflect_component.insert(&mut entity, component.as_partial_reflect(), type_registry); } /// A [`Command`] that adds the boxed reflect component to an entity using the data in @@ -214,7 +214,7 @@ pub struct InsertReflect { /// The entity on which the component will be inserted. pub entity: Entity, /// The reflect [`Component`](crate::component::Component) that will be added to the entity. - pub component: Box, + pub component: Box, } impl Command for InsertReflect { @@ -233,7 +233,7 @@ pub struct InsertReflectWithRegistry> { pub entity: Entity, pub _t: PhantomData, /// The reflect [`Component`](crate::component::Component) that will be added to the entity. - pub component: Box, + pub component: Box, } impl> Command for InsertReflectWithRegistry { @@ -317,7 +317,7 @@ mod tests { use crate::system::{Commands, SystemState}; use crate::{self as bevy_ecs, component::Component, world::World}; use bevy_ecs_macros::Resource; - use bevy_reflect::{Reflect, TypeRegistry}; + use bevy_reflect::{PartialReflect, Reflect, TypeRegistry}; #[derive(Resource)] struct TypeRegistryResource { @@ -352,7 +352,7 @@ mod tests { let entity = commands.spawn_empty().id(); let entity2 = commands.spawn_empty().id(); - let boxed_reflect_component_a = Box::new(ComponentA(916)) as Box; + let boxed_reflect_component_a = Box::new(ComponentA(916)) as Box; let boxed_reflect_component_a_clone = boxed_reflect_component_a.clone_value(); commands @@ -388,7 +388,7 @@ mod tests { let entity = commands.spawn_empty().id(); - let boxed_reflect_component_a = Box::new(ComponentA(916)) as Box; + let boxed_reflect_component_a = Box::new(ComponentA(916)) as Box; commands .entity(entity) diff --git a/crates/bevy_ecs/src/reflect/mod.rs b/crates/bevy_ecs/src/reflect/mod.rs index 832c5b9d1e9a3..ae02af891314f 100644 --- a/crates/bevy_ecs/src/reflect/mod.rs +++ b/crates/bevy_ecs/src/reflect/mod.rs @@ -6,7 +6,9 @@ use std::ops::{Deref, DerefMut}; use crate as bevy_ecs; use crate::{system::Resource, world::World}; use bevy_reflect::std_traits::ReflectDefault; -use bevy_reflect::{Reflect, ReflectFromReflect, TypeRegistry, TypeRegistryArc}; +use bevy_reflect::{ + PartialReflect, Reflect, ReflectFromReflect, TypePath, TypeRegistry, TypeRegistryArc, +}; mod bundle; mod component; @@ -69,7 +71,7 @@ impl DerefMut for AppFunctionRegistry { } } -/// Creates a `T` from a `&dyn Reflect`. +/// Creates a `T` from a `&dyn PartialReflect`. /// /// This will try the following strategies, in this order: /// @@ -85,18 +87,17 @@ impl DerefMut for AppFunctionRegistry { /// this method will panic. /// /// If none of the strategies succeed, this method will panic. -pub fn from_reflect_with_fallback( - reflected: &dyn Reflect, +pub fn from_reflect_with_fallback( + reflected: &dyn PartialReflect, world: &mut World, registry: &TypeRegistry, ) -> T { - fn different_type_error(reflected: &str) -> ! { + fn different_type_error(reflected: &str) -> ! { panic!( "The registration for the reflected `{}` trait for the type `{}` produced \ a value of a different type", reflected, - // FIXME: once we have unique reflect, use `TypePath`. - std::any::type_name::(), + T::type_path(), ); } diff --git a/crates/bevy_ecs/src/reflect/resource.rs b/crates/bevy_ecs/src/reflect/resource.rs index f38a61d2f6845..9a14cb88c7253 100644 --- a/crates/bevy_ecs/src/reflect/resource.rs +++ b/crates/bevy_ecs/src/reflect/resource.rs @@ -9,7 +9,7 @@ use crate::{ system::Resource, world::{unsafe_world_cell::UnsafeWorldCell, World}, }; -use bevy_reflect::{FromReflect, FromType, Reflect, TypeRegistry}; +use bevy_reflect::{FromReflect, FromType, PartialReflect, Reflect, TypePath, TypeRegistry}; use super::from_reflect_with_fallback; @@ -43,11 +43,11 @@ pub struct ReflectResource(ReflectResourceFns); #[derive(Clone)] pub struct ReflectResourceFns { /// Function pointer implementing [`ReflectResource::insert()`]. - pub insert: fn(&mut World, &dyn Reflect, &TypeRegistry), + pub insert: fn(&mut World, &dyn PartialReflect, &TypeRegistry), /// Function pointer implementing [`ReflectResource::apply()`]. - pub apply: fn(&mut World, &dyn Reflect), + pub apply: fn(&mut World, &dyn PartialReflect), /// Function pointer implementing [`ReflectResource::apply_or_insert()`]. - pub apply_or_insert: fn(&mut World, &dyn Reflect, &TypeRegistry), + pub apply_or_insert: fn(&mut World, &dyn PartialReflect, &TypeRegistry), /// Function pointer implementing [`ReflectResource::remove()`]. pub remove: fn(&mut World), /// Function pointer implementing [`ReflectResource::reflect()`]. @@ -67,14 +67,19 @@ 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 } } impl ReflectResource { /// Insert a reflected [`Resource`] into the world like [`insert()`](World::insert_resource). - pub fn insert(&self, world: &mut World, resource: &dyn Reflect, registry: &TypeRegistry) { + pub fn insert( + &self, + world: &mut World, + resource: &dyn PartialReflect, + registry: &TypeRegistry, + ) { (self.0.insert)(world, resource, registry); } @@ -83,7 +88,7 @@ impl ReflectResource { /// # Panics /// /// Panics if there is no [`Resource`] of the given type. - pub fn apply(&self, world: &mut World, resource: &dyn Reflect) { + pub fn apply(&self, world: &mut World, resource: &dyn PartialReflect) { (self.0.apply)(world, resource); } @@ -91,7 +96,7 @@ impl ReflectResource { pub fn apply_or_insert( &self, world: &mut World, - resource: &dyn Reflect, + resource: &dyn PartialReflect, registry: &TypeRegistry, ) { (self.0.apply_or_insert)(world, resource, registry); @@ -176,7 +181,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/README.md b/crates/bevy_reflect/README.md index 4289f869fff91..8a145c7a67955 100644 --- a/crates/bevy_reflect/README.md +++ b/crates/bevy_reflect/README.md @@ -8,7 +8,7 @@ This crate enables you to dynamically interact with Rust types: -* Derive the Reflect traits +* Derive the `Reflect` traits * Interact with fields using their names (for named structs) or indices (for tuple structs) * "Patch" your types with new values * Look up nested fields using "path strings" @@ -18,10 +18,10 @@ This crate enables you to dynamically interact with Rust types: ## Features -### Derive the Reflect traits +### Derive the `Reflect` traits ```rust ignore -// this will automatically implement the Reflect trait and the Struct trait (because the type is a struct) +// this will automatically implement the `Reflect` trait and the `Struct` trait (because the type is a struct) #[derive(Reflect)] struct Foo { a: u32, @@ -30,7 +30,7 @@ struct Foo { d: Vec, } -// this will automatically implement the Reflect trait and the TupleStruct trait (because the type is a tuple struct) +// this will automatically implement the `Reflect` trait and the `TupleStruct` trait (because the type is a tuple struct) #[derive(Reflect)] struct Bar(String); 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 b555b533186b7..92b16288c407c 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 @@ -17,5 +17,5 @@ fn main() { // foo doesn't implement Reflect because NoReflect doesn't implement Reflect foo.get_field::("a").unwrap(); - //~^ ERROR: `NoReflect` can not be reflected + //~^ ERROR: `NoReflect` does not implement `Reflect` so cannot be fully reflected } diff --git a/crates/bevy_reflect/derive/src/container_attributes.rs b/crates/bevy_reflect/derive/src/container_attributes.rs index 73637c252b39f..b5f0f906b3bcc 100644 --- a/crates/bevy_reflect/derive/src/container_attributes.rs +++ b/crates/bevy_reflect/derive/src/container_attributes.rs @@ -444,7 +444,7 @@ impl ContainerAttributes { &self.type_path_attrs } - /// Returns the implementation of `Reflect::reflect_hash` as a `TokenStream`. + /// Returns the implementation of `PartialReflect::reflect_hash` as a `TokenStream`. /// /// If `Hash` was not registered, returns `None`. pub fn get_hash_impl(&self, bevy_reflect_path: &Path) -> Option { @@ -467,7 +467,7 @@ impl ContainerAttributes { } } - /// Returns the implementation of `Reflect::reflect_partial_eq` as a `TokenStream`. + /// Returns the implementation of `PartialReflect::reflect_partial_eq` as a `TokenStream`. /// /// If `PartialEq` was not registered, returns `None`. pub fn get_partial_eq_impl( @@ -476,9 +476,9 @@ impl ContainerAttributes { ) -> Option { match &self.partial_eq { &TraitImpl::Implemented(span) => Some(quote_spanned! {span=> - fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> #FQOption { - let value = ::as_any(value); - if let #FQOption::Some(value) = ::downcast_ref::(value) { + fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::PartialReflect) -> #FQOption { + let value = ::try_downcast_ref::(value); + if let #FQOption::Some(value) = value { #FQOption::Some(::core::cmp::PartialEq::eq(self, value)) } else { #FQOption::Some(false) @@ -486,7 +486,7 @@ impl ContainerAttributes { } }), &TraitImpl::Custom(ref impl_fn, span) => Some(quote_spanned! {span=> - fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> #FQOption { + fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::PartialReflect) -> #FQOption { #FQOption::Some(#impl_fn(self, value)) } }), @@ -494,7 +494,7 @@ impl ContainerAttributes { } } - /// Returns the implementation of `Reflect::debug` as a `TokenStream`. + /// Returns the implementation of `PartialReflect::debug` as a `TokenStream`. /// /// If `Debug` was not registered, returns `None`. pub fn get_debug_impl(&self) -> Option { diff --git a/crates/bevy_reflect/derive/src/enum_utility.rs b/crates/bevy_reflect/derive/src/enum_utility.rs index 9f7a12aa70df7..50ea343b7a10a 100644 --- a/crates/bevy_reflect/derive/src/enum_utility.rs +++ b/crates/bevy_reflect/derive/src/enum_utility.rs @@ -209,7 +209,7 @@ impl<'a> VariantBuilder for FromReflectVariantBuilder<'a> { } } -/// Generates the enum variant output data needed to build the `Reflect::try_apply` implementation. +/// Generates the enum variant output data needed to build the `PartialReflect::try_apply` implementation. pub(crate) struct TryApplyVariantBuilder<'a> { reflect_enum: &'a ReflectEnum<'a>, } diff --git a/crates/bevy_reflect/derive/src/from_reflect.rs b/crates/bevy_reflect/derive/src/from_reflect.rs index abc7fb8929ce9..5aa637794ad5b 100644 --- a/crates/bevy_reflect/derive/src/from_reflect.rs +++ b/crates/bevy_reflect/derive/src/from_reflect.rs @@ -4,7 +4,7 @@ use crate::enum_utility::{EnumVariantOutputData, FromReflectVariantBuilder, Vari use crate::field_attributes::DefaultBehavior; use crate::utility::{ident_or_index, WhereClauseOptions}; use crate::{ReflectMeta, ReflectStruct}; -use bevy_macro_utils::fq_std::{FQAny, FQClone, FQDefault, FQOption}; +use bevy_macro_utils::fq_std::{FQClone, FQDefault, FQOption}; use proc_macro2::Span; use quote::{quote, ToTokens}; use syn::{Field, Ident, Lit, LitInt, LitStr, Member}; @@ -26,8 +26,12 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream { let where_from_reflect_clause = WhereClauseOptions::new(meta).extend_where_clause(where_clause); quote! { impl #impl_generics #bevy_reflect_path::FromReflect for #type_path #ty_generics #where_from_reflect_clause { - fn from_reflect(reflect: &dyn #bevy_reflect_path::Reflect) -> #FQOption { - #FQOption::Some(#FQClone::clone(::downcast_ref::<#type_path #ty_generics>(::as_any(reflect))?)) + fn from_reflect(reflect: &dyn #bevy_reflect_path::PartialReflect) -> #FQOption { + #FQOption::Some( + #FQClone::clone( + ::try_downcast_ref::<#type_path #ty_generics>(reflect)? + ) + ) } } } @@ -57,8 +61,10 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream quote! { impl #impl_generics #bevy_reflect_path::FromReflect for #enum_path #ty_generics #where_from_reflect_clause { - fn from_reflect(#ref_value: &dyn #bevy_reflect_path::Reflect) -> #FQOption { - if let #bevy_reflect_path::ReflectRef::Enum(#ref_value) = #bevy_reflect_path::Reflect::reflect_ref(#ref_value) { + fn from_reflect(#ref_value: &dyn #bevy_reflect_path::PartialReflect) -> #FQOption { + if let #bevy_reflect_path::ReflectRef::Enum(#ref_value) = + #bevy_reflect_path::PartialReflect::reflect_ref(#ref_value) + { match #bevy_reflect_path::Enum::variant_name(#ref_value) { #(#variant_names => #fqoption::Some(#variant_constructors),)* name => panic!("variant with name `{}` does not exist on enum `{}`", name, ::type_path()), @@ -138,8 +144,10 @@ fn impl_struct_internal( quote! { impl #impl_generics #bevy_reflect_path::FromReflect for #struct_path #ty_generics #where_from_reflect_clause { - fn from_reflect(reflect: &dyn #bevy_reflect_path::Reflect) -> #FQOption { - if let #bevy_reflect_path::ReflectRef::#ref_struct_type(#ref_struct) = #bevy_reflect_path::Reflect::reflect_ref(reflect) { + fn from_reflect(reflect: &dyn #bevy_reflect_path::PartialReflect) -> #FQOption { + if let #bevy_reflect_path::ReflectRef::#ref_struct_type(#ref_struct) + = #bevy_reflect_path::PartialReflect::reflect_ref(reflect) + { #constructor } else { #FQOption::None diff --git a/crates/bevy_reflect/derive/src/impls/common.rs b/crates/bevy_reflect/derive/src/impls/common.rs new file mode 100644 index 0000000000000..00c573152cc14 --- /dev/null +++ b/crates/bevy_reflect/derive/src/impls/common.rs @@ -0,0 +1,135 @@ +use bevy_macro_utils::fq_std::{FQAny, FQBox, FQOption, FQResult}; + +use quote::quote; + +use crate::{derive_data::ReflectMeta, utility::WhereClauseOptions}; + +pub fn impl_full_reflect( + meta: &ReflectMeta, + where_clause_options: &WhereClauseOptions, +) -> proc_macro2::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::Reflect for #type_path #ty_generics #where_reflect_clause { + #[inline] + fn into_any(self: #FQBox) -> #FQBox { + self + } + + #[inline] + fn as_any(&self) -> &dyn #FQAny { + self + } + + #[inline] + fn as_any_mut(&mut self) -> &mut dyn #FQAny { + self + } + + #[inline] + fn into_reflect(self: #FQBox) -> #FQBox { + 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, + value: #FQBox + ) -> #FQResult<(), #FQBox> { + *self = ::take(value)?; + #FQResult::Ok(()) + } + } + } +} + +pub fn common_partial_reflect_methods( + meta: &ReflectMeta, + default_partial_eq_delegate: impl FnOnce() -> Option, + default_hash_delegate: impl FnOnce() -> Option, +) -> proc_macro2::TokenStream { + let bevy_reflect_path = meta.bevy_reflect_path(); + + let debug_fn = meta.attrs().get_debug_impl(); + let partial_eq_fn = meta + .attrs() + .get_partial_eq_impl(bevy_reflect_path) + .or_else(move || { + let default_delegate = default_partial_eq_delegate(); + default_delegate.map(|func| { + quote! { + fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::PartialReflect) -> #FQOption { + (#func)(self, value) + } + } + }) + }); + let hash_fn = meta + .attrs() + .get_hash_impl(bevy_reflect_path) + .or_else(move || { + let default_delegate = default_hash_delegate(); + default_delegate.map(|func| { + quote! { + fn reflect_hash(&self) -> #FQOption { + (#func)(self) + } + } + }) + }); + + quote! { + #[inline] + fn try_into_reflect( + self: #FQBox + ) -> #FQResult<#FQBox, #FQBox> { + #FQResult::Ok(self) + } + + #[inline] + fn try_as_reflect(&self) -> #FQOption<&dyn #bevy_reflect_path::Reflect> { + #FQOption::Some(self) + } + + #[inline] + fn try_as_reflect_mut(&mut self) -> #FQOption<&mut dyn #bevy_reflect_path::Reflect> { + #FQOption::Some(self) + } + + #[inline] + fn into_partial_reflect(self: #FQBox) -> #FQBox { + 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 + + #debug_fn + } +} diff --git a/crates/bevy_reflect/derive/src/impls/enums.rs b/crates/bevy_reflect/derive/src/impls/enums.rs index 2dac5092176a0..74c7848afe768 100644 --- a/crates/bevy_reflect/derive/src/impls/enums.rs +++ b/crates/bevy_reflect/derive/src/impls/enums.rs @@ -1,7 +1,7 @@ use crate::derive_data::{EnumVariantFields, ReflectEnum, StructField}; use crate::enum_utility::{EnumVariantOutputData, TryApplyVariantBuilder, VariantBuilder}; -use crate::impls::{impl_type_path, impl_typed}; -use bevy_macro_utils::fq_std::{FQAny, FQBox, FQOption, FQResult}; +use crate::impls::{common_partial_reflect_methods, impl_full_reflect, impl_type_path, impl_typed}; +use bevy_macro_utils::fq_std::{FQBox, FQOption, FQResult}; use proc_macro2::{Ident, Span}; use quote::quote; use syn::Fields; @@ -33,30 +33,6 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream .. } = TryApplyVariantBuilder::new(reflect_enum).build(&ref_value); - let hash_fn = reflect_enum - .meta() - .attrs() - .get_hash_impl(bevy_reflect_path) - .unwrap_or_else(|| { - quote! { - fn reflect_hash(&self) -> #FQOption { - #bevy_reflect_path::enum_hash(self) - } - } - }); - let debug_fn = reflect_enum.meta().attrs().get_debug_impl(); - let partial_eq_fn = reflect_enum - .meta() - .attrs() - .get_partial_eq_impl(bevy_reflect_path) - .unwrap_or_else(|| { - quote! { - fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> #FQOption { - #bevy_reflect_path::enum_partial_eq(self, value) - } - } - }); - let typed_impl = impl_typed( reflect_enum.meta(), &where_clause_options, @@ -64,6 +40,12 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream ); let type_path_impl = impl_type_path(reflect_enum.meta()); + let full_reflect_impl = impl_full_reflect(reflect_enum.meta(), &where_clause_options); + let common_methods = common_partial_reflect_methods( + reflect_enum.meta(), + || Some(quote!(#bevy_reflect_path::enum_partial_eq)), + || Some(quote!(#bevy_reflect_path::enum_hash)), + ); #[cfg(not(feature = "functions"))] let function_impls = None::; @@ -85,31 +67,33 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream #type_path_impl + #full_reflect_impl + #function_impls impl #impl_generics #bevy_reflect_path::Enum for #enum_path #ty_generics #where_reflect_clause { - fn field(&self, #ref_name: &str) -> #FQOption<&dyn #bevy_reflect_path::Reflect> { + fn field(&self, #ref_name: &str) -> #FQOption<&dyn #bevy_reflect_path::PartialReflect> { match self { #(#enum_field,)* _ => #FQOption::None, } } - fn field_at(&self, #ref_index: usize) -> #FQOption<&dyn #bevy_reflect_path::Reflect> { + fn field_at(&self, #ref_index: usize) -> #FQOption<&dyn #bevy_reflect_path::PartialReflect> { match self { #(#enum_field_at,)* _ => #FQOption::None, } } - fn field_mut(&mut self, #ref_name: &str) -> #FQOption<&mut dyn #bevy_reflect_path::Reflect> { + fn field_mut(&mut self, #ref_name: &str) -> #FQOption<&mut dyn #bevy_reflect_path::PartialReflect> { match self { #(#enum_field,)* _ => #FQOption::None, } } - fn field_at_mut(&mut self, #ref_index: usize) -> #FQOption<&mut dyn #bevy_reflect_path::Reflect> { + fn field_at_mut(&mut self, #ref_index: usize) -> #FQOption<&mut dyn #bevy_reflect_path::PartialReflect> { match self { #(#enum_field_at,)* _ => #FQOption::None, @@ -171,56 +155,24 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream } } - impl #impl_generics #bevy_reflect_path::Reflect for #enum_path #ty_generics #where_reflect_clause { + impl #impl_generics #bevy_reflect_path::PartialReflect for #enum_path #ty_generics #where_reflect_clause { #[inline] fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { #FQOption::Some(::type_info()) } #[inline] - fn into_any(self: #FQBox) -> #FQBox { - self - } - - #[inline] - fn as_any(&self) -> &dyn #FQAny { - self - } - - #[inline] - fn as_any_mut(&mut self) -> &mut dyn #FQAny { - self - } - - #[inline] - fn into_reflect(self: #FQBox) -> #FQBox { - 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 clone_value(&self) -> #FQBox { + fn clone_value(&self) -> #FQBox { #FQBox::new(#bevy_reflect_path::Enum::clone_dynamic(self)) } #[inline] - fn set(&mut self, #ref_value: #FQBox) -> #FQResult<(), #FQBox> { - *self = ::take(#ref_value)?; - #FQResult::Ok(()) - } - - #[inline] - fn try_apply(&mut self, #ref_value: &dyn #bevy_reflect_path::Reflect) -> #FQResult<(), #bevy_reflect_path::ApplyError> { - if let #bevy_reflect_path::ReflectRef::Enum(#ref_value) = #bevy_reflect_path::Reflect::reflect_ref(#ref_value) { + fn try_apply( + &mut self, + #ref_value: &dyn #bevy_reflect_path::PartialReflect + ) -> #FQResult<(), #bevy_reflect_path::ApplyError> { + if let #bevy_reflect_path::ReflectRef::Enum(#ref_value) = + #bevy_reflect_path::PartialReflect::reflect_ref(#ref_value) { if #bevy_reflect_path::Enum::variant_name(self) == #bevy_reflect_path::Enum::variant_name(#ref_value) { // Same variant -> just update fields match #bevy_reflect_path::Enum::variant_type(#ref_value) { @@ -228,14 +180,14 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream for field in #bevy_reflect_path::Enum::iter_fields(#ref_value) { let name = field.name().unwrap(); if let #FQOption::Some(v) = #bevy_reflect_path::Enum::field_mut(self, name) { - #bevy_reflect_path::Reflect::try_apply(v, field.value())?; + #bevy_reflect_path::PartialReflect::try_apply(v, field.value())?; } } } #bevy_reflect_path::VariantType::Tuple => { for (index, field) in ::core::iter::Iterator::enumerate(#bevy_reflect_path::Enum::iter_fields(#ref_value)) { if let #FQOption::Some(v) = #bevy_reflect_path::Enum::field_at_mut(self, index) { - #bevy_reflect_path::Reflect::try_apply(v, field.value())?; + #bevy_reflect_path::PartialReflect::try_apply(v, field.value())?; } } } @@ -260,7 +212,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream } else { return #FQResult::Err( #bevy_reflect_path::ApplyError::MismatchedKinds { - from_kind: #bevy_reflect_path::Reflect::reflect_kind(#ref_value), + from_kind: #bevy_reflect_path::PartialReflect::reflect_kind(#ref_value), to_kind: #bevy_reflect_path::ReflectKind::Enum, } ); @@ -284,11 +236,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream #bevy_reflect_path::ReflectOwned::Enum(self) } - #hash_fn - - #partial_eq_fn - - #debug_fn + #common_methods } } } diff --git a/crates/bevy_reflect/derive/src/impls/mod.rs b/crates/bevy_reflect/derive/src/impls/mod.rs index 85f50d1a205ca..5974d85d9f3da 100644 --- a/crates/bevy_reflect/derive/src/impls/mod.rs +++ b/crates/bevy_reflect/derive/src/impls/mod.rs @@ -1,3 +1,4 @@ +mod common; mod enums; #[cfg(feature = "functions")] mod func; @@ -6,6 +7,7 @@ mod tuple_structs; mod typed; mod values; +pub(crate) use common::{common_partial_reflect_methods, impl_full_reflect}; pub(crate) use enums::impl_enum; #[cfg(feature = "functions")] pub(crate) use func::impl_function_traits; diff --git a/crates/bevy_reflect/derive/src/impls/structs.rs b/crates/bevy_reflect/derive/src/impls/structs.rs index 2ac44136aa862..964b91e788396 100644 --- a/crates/bevy_reflect/derive/src/impls/structs.rs +++ b/crates/bevy_reflect/derive/src/impls/structs.rs @@ -1,7 +1,7 @@ -use crate::impls::{impl_type_path, impl_typed}; +use crate::impls::{common_partial_reflect_methods, impl_full_reflect, impl_type_path, impl_typed}; use crate::utility::ident_or_index; use crate::ReflectStruct; -use bevy_macro_utils::fq_std::{FQAny, FQBox, FQDefault, FQOption, FQResult}; +use bevy_macro_utils::fq_std::{FQBox, FQDefault, FQOption, FQResult}; use quote::{quote, ToTokens}; /// Implements `Struct`, `GetTypeRegistration`, and `Reflect` for the given derive data. @@ -29,22 +29,6 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS let field_count = field_idents.len(); let field_indices = (0..field_count).collect::>(); - let hash_fn = reflect_struct - .meta() - .attrs() - .get_hash_impl(bevy_reflect_path); - let debug_fn = reflect_struct.meta().attrs().get_debug_impl(); - let partial_eq_fn = reflect_struct.meta() - .attrs() - .get_partial_eq_impl(bevy_reflect_path) - .unwrap_or_else(|| { - quote! { - fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> #FQOption { - #bevy_reflect_path::struct_partial_eq(self, value) - } - } - }); - let where_clause_options = reflect_struct.where_clause_options(); let typed_impl = impl_typed( reflect_struct.meta(), @@ -53,6 +37,12 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS ); let type_path_impl = impl_type_path(reflect_struct.meta()); + let full_reflect_impl = impl_full_reflect(reflect_struct.meta(), &where_clause_options); + let common_methods = common_partial_reflect_methods( + reflect_struct.meta(), + || Some(quote!(#bevy_reflect_path::struct_partial_eq)), + || None, + ); #[cfg(not(feature = "functions"))] let function_impls = None::; @@ -77,31 +67,33 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS #type_path_impl + #full_reflect_impl + #function_impls impl #impl_generics #bevy_reflect_path::Struct for #struct_path #ty_generics #where_reflect_clause { - fn field(&self, name: &str) -> #FQOption<&dyn #bevy_reflect_path::Reflect> { + fn field(&self, name: &str) -> #FQOption<&dyn #bevy_reflect_path::PartialReflect> { match name { #(#field_names => #fqoption::Some(&self.#field_idents),)* _ => #FQOption::None, } } - fn field_mut(&mut self, name: &str) -> #FQOption<&mut dyn #bevy_reflect_path::Reflect> { + fn field_mut(&mut self, name: &str) -> #FQOption<&mut dyn #bevy_reflect_path::PartialReflect> { match name { #(#field_names => #fqoption::Some(&mut self.#field_idents),)* _ => #FQOption::None, } } - fn field_at(&self, index: usize) -> #FQOption<&dyn #bevy_reflect_path::Reflect> { + fn field_at(&self, index: usize) -> #FQOption<&dyn #bevy_reflect_path::PartialReflect> { match index { #(#field_indices => #fqoption::Some(&self.#field_idents),)* _ => #FQOption::None, } } - fn field_at_mut(&mut self, index: usize) -> #FQOption<&mut dyn #bevy_reflect_path::Reflect> { + fn field_at_mut(&mut self, index: usize) -> #FQOption<&mut dyn #bevy_reflect_path::PartialReflect> { match index { #(#field_indices => #fqoption::Some(&mut self.#field_idents),)* _ => #FQOption::None, @@ -125,72 +117,40 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS fn clone_dynamic(&self) -> #bevy_reflect_path::DynamicStruct { let mut dynamic: #bevy_reflect_path::DynamicStruct = #FQDefault::default(); - dynamic.set_represented_type(#bevy_reflect_path::Reflect::get_represented_type_info(self)); - #(dynamic.insert_boxed(#field_names, #bevy_reflect_path::Reflect::clone_value(&self.#field_idents));)* + dynamic.set_represented_type(#bevy_reflect_path::PartialReflect::get_represented_type_info(self)); + #(dynamic.insert_boxed(#field_names, #bevy_reflect_path::PartialReflect::clone_value(&self.#field_idents));)* dynamic } } - impl #impl_generics #bevy_reflect_path::Reflect for #struct_path #ty_generics #where_reflect_clause { + impl #impl_generics #bevy_reflect_path::PartialReflect for #struct_path #ty_generics #where_reflect_clause { #[inline] fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { #FQOption::Some(::type_info()) } #[inline] - fn into_any(self: #FQBox) -> #FQBox { - self - } - - #[inline] - fn as_any(&self) -> &dyn #FQAny { - self - } - - #[inline] - fn as_any_mut(&mut self) -> &mut dyn #FQAny { - self - } - - #[inline] - fn into_reflect(self: #FQBox) -> #FQBox { - 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 clone_value(&self) -> #FQBox { + fn clone_value(&self) -> #FQBox { #FQBox::new(#bevy_reflect_path::Struct::clone_dynamic(self)) } #[inline] - fn set(&mut self, value: #FQBox) -> #FQResult<(), #FQBox> { - *self = ::take(value)?; - #FQResult::Ok(()) - } - - #[inline] - fn try_apply(&mut self, value: &dyn #bevy_reflect_path::Reflect) -> #FQResult<(), #bevy_reflect_path::ApplyError> { - if let #bevy_reflect_path::ReflectRef::Struct(struct_value) = #bevy_reflect_path::Reflect::reflect_ref(value) { + fn try_apply( + &mut self, + value: &dyn #bevy_reflect_path::PartialReflect + ) -> #FQResult<(), #bevy_reflect_path::ApplyError> { + if let #bevy_reflect_path::ReflectRef::Struct(struct_value) + = #bevy_reflect_path::PartialReflect::reflect_ref(value) { for (i, value) in ::core::iter::Iterator::enumerate(#bevy_reflect_path::Struct::iter_fields(struct_value)) { let name = #bevy_reflect_path::Struct::name_at(struct_value, i).unwrap(); if let #FQOption::Some(v) = #bevy_reflect_path::Struct::field_mut(self, name) { - #bevy_reflect_path::Reflect::try_apply(v, value)?; + #bevy_reflect_path::PartialReflect::try_apply(v, value)?; } } } else { return #FQResult::Err( #bevy_reflect_path::ApplyError::MismatchedKinds { - from_kind: #bevy_reflect_path::Reflect::reflect_kind(value), + from_kind: #bevy_reflect_path::PartialReflect::reflect_kind(value), to_kind: #bevy_reflect_path::ReflectKind::Struct } ); @@ -214,11 +174,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS #bevy_reflect_path::ReflectOwned::Struct(self) } - #hash_fn - - #partial_eq_fn - - #debug_fn + #common_methods } } } diff --git a/crates/bevy_reflect/derive/src/impls/tuple_structs.rs b/crates/bevy_reflect/derive/src/impls/tuple_structs.rs index 4401f65e70e4e..50424c5dbf2fe 100644 --- a/crates/bevy_reflect/derive/src/impls/tuple_structs.rs +++ b/crates/bevy_reflect/derive/src/impls/tuple_structs.rs @@ -1,6 +1,6 @@ -use crate::impls::{impl_type_path, impl_typed}; +use crate::impls::{common_partial_reflect_methods, impl_full_reflect, impl_type_path, impl_typed}; use crate::ReflectStruct; -use bevy_macro_utils::fq_std::{FQAny, FQBox, FQDefault, FQOption, FQResult}; +use bevy_macro_utils::fq_std::{FQBox, FQDefault, FQOption, FQResult}; use quote::{quote, ToTokens}; use syn::{Index, Member}; @@ -21,23 +21,6 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> proc_macro2:: let where_clause_options = reflect_struct.where_clause_options(); let get_type_registration_impl = reflect_struct.get_type_registration(&where_clause_options); - let hash_fn = reflect_struct - .meta() - .attrs() - .get_hash_impl(bevy_reflect_path); - let debug_fn = reflect_struct.meta().attrs().get_debug_impl(); - let partial_eq_fn = reflect_struct - .meta() - .attrs() - .get_partial_eq_impl(bevy_reflect_path) - .unwrap_or_else(|| { - quote! { - fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> #FQOption { - #bevy_reflect_path::tuple_struct_partial_eq(self, value) - } - } - }); - let typed_impl = impl_typed( reflect_struct.meta(), &where_clause_options, @@ -45,6 +28,12 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> proc_macro2:: ); let type_path_impl = impl_type_path(reflect_struct.meta()); + let full_reflect_impl = impl_full_reflect(reflect_struct.meta(), &where_clause_options); + let common_methods = common_partial_reflect_methods( + reflect_struct.meta(), + || Some(quote!(#bevy_reflect_path::tuple_struct_partial_eq)), + || None, + ); #[cfg(not(feature = "functions"))] let function_impls = None::; @@ -67,17 +56,19 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> proc_macro2:: #type_path_impl + #full_reflect_impl + #function_impls impl #impl_generics #bevy_reflect_path::TupleStruct for #struct_path #ty_generics #where_reflect_clause { - fn field(&self, index: usize) -> #FQOption<&dyn #bevy_reflect_path::Reflect> { + fn field(&self, index: usize) -> #FQOption<&dyn #bevy_reflect_path::PartialReflect> { match index { #(#field_indices => #fqoption::Some(&self.#field_idents),)* _ => #FQOption::None, } } - fn field_mut(&mut self, index: usize) -> #FQOption<&mut dyn #bevy_reflect_path::Reflect> { + fn field_mut(&mut self, index: usize) -> #FQOption<&mut dyn #bevy_reflect_path::PartialReflect> { match index { #(#field_indices => #fqoption::Some(&mut self.#field_idents),)* _ => #FQOption::None, @@ -94,71 +85,38 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> proc_macro2:: fn clone_dynamic(&self) -> #bevy_reflect_path::DynamicTupleStruct { let mut dynamic: #bevy_reflect_path::DynamicTupleStruct = #FQDefault::default(); - dynamic.set_represented_type(#bevy_reflect_path::Reflect::get_represented_type_info(self)); - #(dynamic.insert_boxed(#bevy_reflect_path::Reflect::clone_value(&self.#field_idents));)* + dynamic.set_represented_type(#bevy_reflect_path::PartialReflect::get_represented_type_info(self)); + #(dynamic.insert_boxed(#bevy_reflect_path::PartialReflect::clone_value(&self.#field_idents));)* dynamic } } - impl #impl_generics #bevy_reflect_path::Reflect for #struct_path #ty_generics #where_reflect_clause { + impl #impl_generics #bevy_reflect_path::PartialReflect for #struct_path #ty_generics #where_reflect_clause { #[inline] fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { #FQOption::Some(::type_info()) } - - #[inline] - fn into_any(self: #FQBox) -> #FQBox { - self - } - - #[inline] - fn as_any(&self) -> &dyn #FQAny { - self - } - - #[inline] - fn as_any_mut(&mut self) -> &mut dyn #FQAny { - self - } - - #[inline] - fn into_reflect(self: #FQBox) -> #FQBox { - 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 clone_value(&self) -> #FQBox { + fn clone_value(&self) -> #FQBox { #FQBox::new(#bevy_reflect_path::TupleStruct::clone_dynamic(self)) } #[inline] - fn set(&mut self, value: #FQBox) -> #FQResult<(), #FQBox> { - *self = ::take(value)?; - #FQResult::Ok(()) - } - - #[inline] - fn try_apply(&mut self, value: &dyn #bevy_reflect_path::Reflect) -> #FQResult<(), #bevy_reflect_path::ApplyError> { - if let #bevy_reflect_path::ReflectRef::TupleStruct(struct_value) = #bevy_reflect_path::Reflect::reflect_ref(value) { + fn try_apply( + &mut self, + value: &dyn #bevy_reflect_path::PartialReflect + ) -> #FQResult<(), #bevy_reflect_path::ApplyError> { + if let #bevy_reflect_path::ReflectRef::TupleStruct(struct_value) = + #bevy_reflect_path::PartialReflect::reflect_ref(value) { for (i, value) in ::core::iter::Iterator::enumerate(#bevy_reflect_path::TupleStruct::iter_fields(struct_value)) { if let #FQOption::Some(v) = #bevy_reflect_path::TupleStruct::field_mut(self, i) { - #bevy_reflect_path::Reflect::try_apply(v, value)?; + #bevy_reflect_path::PartialReflect::try_apply(v, value)?; } } } else { return #FQResult::Err( #bevy_reflect_path::ApplyError::MismatchedKinds { - from_kind: #bevy_reflect_path::Reflect::reflect_kind(value), + from_kind: #bevy_reflect_path::PartialReflect::reflect_kind(value), to_kind: #bevy_reflect_path::ReflectKind::TupleStruct, } ); @@ -182,11 +140,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> proc_macro2:: #bevy_reflect_path::ReflectOwned::TupleStruct(self) } - #hash_fn - - #partial_eq_fn - - #debug_fn + #common_methods } } } diff --git a/crates/bevy_reflect/derive/src/impls/values.rs b/crates/bevy_reflect/derive/src/impls/values.rs index 92c14bc1df4a7..e50e0a756ad4e 100644 --- a/crates/bevy_reflect/derive/src/impls/values.rs +++ b/crates/bevy_reflect/derive/src/impls/values.rs @@ -1,7 +1,7 @@ -use crate::impls::{impl_type_path, impl_typed}; +use crate::impls::{common_partial_reflect_methods, impl_full_reflect, impl_type_path, impl_typed}; use crate::utility::WhereClauseOptions; use crate::ReflectMeta; -use bevy_macro_utils::fq_std::{FQAny, FQBox, FQClone, FQOption, FQResult}; +use bevy_macro_utils::fq_std::{FQBox, FQClone, FQOption, FQResult}; use quote::quote; /// Implements `GetTypeRegistration` and `Reflect` for the given type data. @@ -9,10 +9,6 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream { let bevy_reflect_path = meta.bevy_reflect_path(); let type_path = meta.type_path(); - let hash_fn = meta.attrs().get_hash_impl(bevy_reflect_path); - let partial_eq_fn = meta.attrs().get_partial_eq_impl(bevy_reflect_path); - let debug_fn = meta.attrs().get_debug_impl(); - #[cfg(feature = "documentation")] let with_docs = { let doc = quote::ToTokens::to_token_stream(meta.doc()); @@ -32,6 +28,8 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream { ); let type_path_impl = impl_type_path(meta); + let full_reflect_impl = impl_full_reflect(meta, &where_clause_options); + let common_methods = common_partial_reflect_methods(meta, || None, || None); #[cfg(not(feature = "functions"))] let function_impls = None::; @@ -49,53 +47,27 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream { #typed_impl + #full_reflect_impl + #function_impls - impl #impl_generics #bevy_reflect_path::Reflect for #type_path #ty_generics #where_reflect_clause { + impl #impl_generics #bevy_reflect_path::PartialReflect for #type_path #ty_generics #where_reflect_clause { #[inline] fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { #FQOption::Some(::type_info()) } #[inline] - fn into_any(self: #FQBox) -> #FQBox { - self - } - - #[inline] - fn as_any(&self) -> &dyn #FQAny { - self - } - - #[inline] - fn as_any_mut(&mut self) -> &mut dyn #FQAny { - self - } - - #[inline] - fn into_reflect(self: #FQBox) -> #FQBox { - 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 clone_value(&self) -> #FQBox { + fn clone_value(&self) -> #FQBox { #FQBox::new(#FQClone::clone(self)) } #[inline] - fn try_apply(&mut self, value: &dyn #bevy_reflect_path::Reflect) -> #FQResult<(), #bevy_reflect_path::ApplyError> { - let any = #bevy_reflect_path::Reflect::as_any(value); - if let #FQOption::Some(value) = ::downcast_ref::(any) { + fn try_apply( + &mut self, + value: &dyn #bevy_reflect_path::PartialReflect + ) -> #FQResult<(), #bevy_reflect_path::ApplyError> { + if let #FQOption::Some(value) = ::try_downcast_ref::(value) { *self = #FQClone::clone(value); } else { return #FQResult::Err( @@ -108,12 +80,6 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream { #FQResult::Ok(()) } - #[inline] - fn set(&mut self, value: #FQBox) -> #FQResult<(), #FQBox> { - *self = ::take(value)?; - #FQResult::Ok(()) - } - #[inline] fn reflect_kind(&self) -> #bevy_reflect_path::ReflectKind { #bevy_reflect_path::ReflectKind::Value @@ -134,11 +100,7 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream { #bevy_reflect_path::ReflectOwned::Value(self) } - #hash_fn - - #partial_eq_fn - - #debug_fn + #common_methods } } } diff --git a/crates/bevy_reflect/derive/src/utility.rs b/crates/bevy_reflect/derive/src/utility.rs index 843b278672f79..0670c0fe012e2 100644 --- a/crates/bevy_reflect/derive/src/utility.rs +++ b/crates/bevy_reflect/derive/src/utility.rs @@ -94,7 +94,7 @@ impl<'a, 'b> WhereClauseOptions<'a, 'b> { /// The default bounds added are as follows: /// - `Self` has the bounds `Any + Send + Sync` /// - Type parameters have the bound `TypePath` unless `#[reflect(type_path = false)]` is present - /// - Active fields have the bounds `TypePath` and either `Reflect` if `#[reflect(from_reflect = false)]` is present + /// - Active fields have the bounds `TypePath` and either `PartialReflect` if `#[reflect(from_reflect = false)]` is present /// or `FromReflect` otherwise (or no bounds at all if `#[reflect(no_field_bounds)]` is present) /// /// When the derive is used with `#[reflect(where)]`, the bounds specified in the attribute are added as well. @@ -236,14 +236,14 @@ impl<'a, 'b> WhereClauseOptions<'a, 'b> { } } - /// The `Reflect` or `FromReflect` bound to use based on `#[reflect(from_reflect = false)]`. + /// The `PartialReflect` 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::Reflect) + quote!(#bevy_reflect_path::PartialReflect) } } diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index 0f2d6466e85db..3377a60cd2162 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -1,6 +1,6 @@ use crate::{ - self as bevy_reflect, utility::reflect_hasher, ApplyError, MaybeTyped, Reflect, ReflectKind, - ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable, + self as bevy_reflect, utility::reflect_hasher, ApplyError, MaybeTyped, PartialReflect, Reflect, + ReflectKind, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable, }; use bevy_reflect_derive::impl_type_path; use std::{ @@ -28,13 +28,13 @@ use std::{ /// # Example /// /// ``` -/// use bevy_reflect::{Reflect, Array}; +/// use bevy_reflect::{PartialReflect, Array}; /// /// let foo: &dyn Array = &[123_u32, 456_u32, 789_u32]; /// assert_eq!(foo.len(), 3); /// -/// let field: &dyn Reflect = foo.get(0).unwrap(); -/// assert_eq!(field.downcast_ref::(), Some(&123)); +/// let field: &dyn PartialReflect = foo.get(0).unwrap(); +/// assert_eq!(field.try_downcast_ref::(), Some(&123)); /// ``` /// /// [array-like]: https://doc.rust-lang.org/book/ch03-02-data-types.html#the-array-type @@ -44,12 +44,12 @@ use std::{ /// [`GetTypeRegistration`]: crate::GetTypeRegistration /// [limitation]: https://github.com/serde-rs/serde/issues/1937 /// [`Deserialize`]: ::serde::Deserialize -pub trait Array: Reflect { +pub trait Array: PartialReflect { /// Returns a reference to the element at `index`, or `None` if out of bounds. - fn get(&self, index: usize) -> Option<&dyn Reflect>; + fn get(&self, index: usize) -> Option<&dyn PartialReflect>; /// Returns a mutable reference to the element at `index`, or `None` if out of bounds. - fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>; + fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>; /// Returns the number of elements in the array. fn len(&self) -> usize; @@ -63,13 +63,13 @@ pub trait Array: Reflect { fn iter(&self) -> ArrayIter; /// Drain the elements of this array to get a vector of owned values. - fn drain(self: Box) -> Vec>; + fn drain(self: Box) -> Vec>; /// Clones the list, producing a [`DynamicArray`]. fn clone_dynamic(&self) -> DynamicArray { DynamicArray { represented_type: self.get_represented_type_info(), - values: self.iter().map(Reflect::clone_value).collect(), + values: self.iter().map(PartialReflect::clone_value).collect(), } } } @@ -191,12 +191,12 @@ impl ArrayInfo { #[derive(Debug)] pub struct DynamicArray { pub(crate) represented_type: Option<&'static TypeInfo>, - pub(crate) values: Box<[Box]>, + pub(crate) values: Box<[Box]>, } impl DynamicArray { #[inline] - pub fn new(values: Box<[Box]>) -> Self { + pub fn new(values: Box<[Box]>) -> Self { Self { represented_type: None, values, @@ -204,7 +204,7 @@ impl DynamicArray { } #[deprecated(since = "0.15.0", note = "use from_iter")] - pub fn from_vec(values: Vec) -> Self { + pub fn from_vec(values: Vec) -> Self { Self::from_iter(values) } @@ -228,56 +228,47 @@ impl DynamicArray { } } -impl Reflect for DynamicArray { +impl PartialReflect for DynamicArray { #[inline] fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } #[inline] - fn into_any(self: Box) -> Box { + fn into_partial_reflect(self: Box) -> Box { self } #[inline] - fn as_any(&self) -> &dyn Any { + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } #[inline] - fn as_any_mut(&mut self) -> &mut dyn Any { + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } - #[inline] - fn into_reflect(self: Box) -> Box { - self + fn try_into_reflect(self: Box) -> Result, Box> { + Err(self) } - #[inline] - fn as_reflect(&self) -> &dyn Reflect { - self + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + None } - #[inline] - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + None } - fn apply(&mut self, value: &dyn Reflect) { + fn apply(&mut self, value: &dyn PartialReflect) { array_apply(self, value); } - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { array_try_apply(self, value) } - #[inline] - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - #[inline] fn reflect_kind(&self) -> ReflectKind { ReflectKind::Array @@ -299,7 +290,7 @@ impl Reflect for DynamicArray { } #[inline] - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone_dynamic()) } @@ -308,7 +299,7 @@ impl Reflect for DynamicArray { array_hash(self) } - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { + fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option { array_partial_eq(self, value) } @@ -326,12 +317,12 @@ impl Reflect for DynamicArray { impl Array for DynamicArray { #[inline] - fn get(&self, index: usize) -> Option<&dyn Reflect> { + fn get(&self, index: usize) -> Option<&dyn PartialReflect> { self.values.get(index).map(|value| &**value) } #[inline] - fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> { + fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> { self.values.get_mut(index).map(|value| &mut **value) } @@ -346,7 +337,7 @@ impl Array for DynamicArray { } #[inline] - fn drain(self: Box) -> Vec> { + fn drain(self: Box) -> Vec> { self.values.into_vec() } @@ -363,8 +354,8 @@ impl Array for DynamicArray { } } -impl FromIterator> for DynamicArray { - fn from_iter>>(values: I) -> Self { +impl FromIterator> for DynamicArray { + fn from_iter>>(values: I) -> Self { Self { represented_type: None, values: values.into_iter().collect::>().into_boxed_slice(), @@ -372,17 +363,17 @@ impl FromIterator> for DynamicArray { } } -impl FromIterator for DynamicArray { +impl FromIterator for DynamicArray { fn from_iter>(values: I) -> Self { values .into_iter() - .map(|value| Box::new(value).into_reflect()) + .map(|value| Box::new(value).into_partial_reflect()) .collect() } } impl IntoIterator for DynamicArray { - type Item = Box; + type Item = Box; type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { @@ -391,7 +382,7 @@ impl IntoIterator for DynamicArray { } impl<'a> IntoIterator for &'a DynamicArray { - type Item = &'a dyn Reflect; + type Item = &'a dyn PartialReflect; type IntoIter = ArrayIter<'a>; fn into_iter(self) -> Self::IntoIter { @@ -400,8 +391,6 @@ impl<'a> IntoIterator for &'a DynamicArray { } impl_type_path!((in bevy_reflect) DynamicArray); -#[cfg(feature = "functions")] -crate::func::macros::impl_function_traits!(DynamicArray); /// An iterator over an [`Array`]. pub struct ArrayIter<'a> { @@ -418,7 +407,7 @@ impl<'a> ArrayIter<'a> { } impl<'a> Iterator for ArrayIter<'a> { - type Item = &'a dyn Reflect; + type Item = &'a dyn PartialReflect; #[inline] fn next(&mut self) -> Option { @@ -438,7 +427,7 @@ impl<'a> ExactSizeIterator for ArrayIter<'a> {} /// Returns the `u64` hash of the given [array](Array). #[inline] -pub fn array_hash(array: &A) -> Option { +pub fn array_hash(array: &A) -> Option { let mut hasher = reflect_hasher(); Any::type_id(array).hash(&mut hasher); array.len().hash(&mut hasher); @@ -456,7 +445,7 @@ pub fn array_hash(array: &A) -> Option { /// * Panics if the reflected value is not a [valid array](ReflectRef::Array). /// #[inline] -pub fn array_apply(array: &mut A, reflect: &dyn Reflect) { +pub fn array_apply(array: &mut A, reflect: &dyn PartialReflect) { if let ReflectRef::Array(reflect_array) = reflect.reflect_ref() { if array.len() != reflect_array.len() { panic!("Attempted to apply different sized `Array` types."); @@ -481,7 +470,10 @@ pub fn array_apply(array: &mut A, reflect: &dyn Reflect) { /// * Returns any error that is generated while applying elements to each other. /// #[inline] -pub fn array_try_apply(array: &mut A, reflect: &dyn Reflect) -> Result<(), ApplyError> { +pub fn array_try_apply( + array: &mut A, + reflect: &dyn PartialReflect, +) -> Result<(), ApplyError> { if let ReflectRef::Array(reflect_array) = reflect.reflect_ref() { if array.len() != reflect_array.len() { return Err(ApplyError::DifferentSize { @@ -507,7 +499,10 @@ pub fn array_try_apply(array: &mut A, reflect: &dyn Reflect) -> Result /// /// Returns [`None`] if the comparison couldn't even be performed. #[inline] -pub fn array_partial_eq(array: &A, reflect: &dyn Reflect) -> Option { +pub fn array_partial_eq( + array: &A, + reflect: &dyn PartialReflect, +) -> Option { match reflect.reflect_ref() { ReflectRef::Array(reflect_array) if reflect_array.len() == array.len() => { for (a, b) in array.iter().zip(reflect_array.iter()) { diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index ff39e6ef41517..c4aa8555cbff8 100644 --- a/crates/bevy_reflect/src/enums/dynamic_enum.rs +++ b/crates/bevy_reflect/src/enums/dynamic_enum.rs @@ -2,10 +2,10 @@ use bevy_reflect_derive::impl_type_path; use crate::{ self as bevy_reflect, enum_debug, enum_hash, enum_partial_eq, ApplyError, DynamicStruct, - DynamicTuple, Enum, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Struct, Tuple, - TypeInfo, VariantFieldIter, VariantType, + DynamicTuple, Enum, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, + Struct, Tuple, TypeInfo, VariantFieldIter, VariantType, }; -use std::any::Any; + use std::fmt::Formatter; /// A dynamic representation of an enum variant. @@ -52,7 +52,7 @@ impl From<()> for DynamicVariant { /// # Example /// /// ``` -/// # use bevy_reflect::{DynamicEnum, DynamicVariant, Reflect}; +/// # use bevy_reflect::{DynamicEnum, DynamicVariant, Reflect, PartialReflect}; /// /// // The original enum value /// let mut value: Option = Some(123); @@ -64,7 +64,7 @@ impl From<()> for DynamicVariant { /// ); /// /// // Apply the DynamicEnum as a patch to the original value -/// value.apply(&dyn_enum); +/// value.apply(dyn_enum.as_partial_reflect()); /// /// // Tada! /// assert_eq!(None, value); @@ -201,7 +201,7 @@ impl DynamicEnum { } impl Enum for DynamicEnum { - fn field(&self, name: &str) -> Option<&dyn Reflect> { + fn field(&self, name: &str) -> Option<&dyn PartialReflect> { if let DynamicVariant::Struct(data) = &self.variant { data.field(name) } else { @@ -209,7 +209,7 @@ impl Enum for DynamicEnum { } } - fn field_at(&self, index: usize) -> Option<&dyn Reflect> { + fn field_at(&self, index: usize) -> Option<&dyn PartialReflect> { if let DynamicVariant::Tuple(data) = &self.variant { data.field(index) } else { @@ -217,7 +217,7 @@ impl Enum for DynamicEnum { } } - fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect> { + fn field_mut(&mut self, name: &str) -> Option<&mut dyn PartialReflect> { if let DynamicVariant::Struct(data) = &mut self.variant { data.field_mut(name) } else { @@ -225,7 +225,7 @@ impl Enum for DynamicEnum { } } - fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> { + fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> { if let DynamicVariant::Tuple(data) = &mut self.variant { data.field_mut(index) } else { @@ -287,44 +287,41 @@ impl Enum for DynamicEnum { } } -impl Reflect for DynamicEnum { +impl PartialReflect for DynamicEnum { #[inline] fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } #[inline] - fn into_any(self: Box) -> Box { + fn into_partial_reflect(self: Box) -> Box { self } #[inline] - fn as_any(&self) -> &dyn Any { + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } #[inline] - fn as_any_mut(&mut self) -> &mut dyn Any { + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } - #[inline] - fn into_reflect(self: Box) -> Box { - self + fn try_into_reflect(self: Box) -> Result, Box> { + Err(self) } - #[inline] - fn as_reflect(&self) -> &dyn Reflect { - self + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + None } - #[inline] - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + None } #[inline] - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { if let ReflectRef::Enum(value) = value.reflect_ref() { if Enum::variant_name(self) == value.variant_name() { // Same variant -> just update fields @@ -377,12 +374,6 @@ impl Reflect for DynamicEnum { Ok(()) } - #[inline] - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - #[inline] fn reflect_kind(&self) -> ReflectKind { ReflectKind::Enum @@ -404,7 +395,7 @@ impl Reflect for DynamicEnum { } #[inline] - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone_dynamic()) } @@ -414,7 +405,7 @@ impl Reflect for DynamicEnum { } #[inline] - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { + fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option { enum_partial_eq(self, value) } @@ -427,5 +418,3 @@ impl Reflect for DynamicEnum { } impl_type_path!((in bevy_reflect) DynamicEnum); -#[cfg(feature = "functions")] -crate::func::macros::impl_function_traits!(DynamicEnum); diff --git a/crates/bevy_reflect/src/enums/enum_trait.rs b/crates/bevy_reflect/src/enums/enum_trait.rs index a81dc50148660..993f08a7c110f 100644 --- a/crates/bevy_reflect/src/enums/enum_trait.rs +++ b/crates/bevy_reflect/src/enums/enum_trait.rs @@ -1,5 +1,5 @@ use crate::attributes::{impl_custom_attribute_methods, CustomAttributes}; -use crate::{DynamicEnum, Reflect, TypePath, TypePathTable, VariantInfo, VariantType}; +use crate::{DynamicEnum, PartialReflect, TypePath, TypePathTable, VariantInfo, VariantType}; use bevy_utils::HashMap; use std::any::{Any, TypeId}; use std::slice::Iter; @@ -89,19 +89,19 @@ use std::sync::Arc; /// [`None`]: Option::None /// [`Some`]: Option::Some /// [`Reflect`]: bevy_reflect_derive::Reflect -pub trait Enum: Reflect { +pub trait Enum: PartialReflect { /// Returns a reference to the value of the field (in the current variant) with the given name. /// /// For non-[`VariantType::Struct`] variants, this should return `None`. - fn field(&self, name: &str) -> Option<&dyn Reflect>; + fn field(&self, name: &str) -> Option<&dyn PartialReflect>; /// Returns a reference to the value of the field (in the current variant) at the given index. - fn field_at(&self, index: usize) -> Option<&dyn Reflect>; + fn field_at(&self, index: usize) -> Option<&dyn PartialReflect>; /// Returns a mutable reference to the value of the field (in the current variant) with the given name. /// /// For non-[`VariantType::Struct`] variants, this should return `None`. - fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect>; + fn field_mut(&mut self, name: &str) -> Option<&mut dyn PartialReflect>; /// Returns a mutable reference to the value of the field (in the current variant) at the given index. - fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>; + fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>; /// Returns the index of the field (in the current variant) with the given name. /// /// For non-[`VariantType::Struct`] variants, this should return `None`. @@ -307,8 +307,8 @@ impl<'a> Iterator for VariantFieldIter<'a> { impl<'a> ExactSizeIterator for VariantFieldIter<'a> {} pub enum VariantField<'a> { - Struct(&'a str, &'a dyn Reflect), - Tuple(&'a dyn Reflect), + Struct(&'a str, &'a dyn PartialReflect), + Tuple(&'a dyn PartialReflect), } impl<'a> VariantField<'a> { @@ -320,7 +320,7 @@ impl<'a> VariantField<'a> { } } - pub fn value(&self) -> &'a dyn Reflect { + pub fn value(&self) -> &'a dyn PartialReflect { match *self { Self::Struct(_, value) | Self::Tuple(value) => value, } diff --git a/crates/bevy_reflect/src/enums/helpers.rs b/crates/bevy_reflect/src/enums/helpers.rs index 09a3516c79d46..6771b1b1655ab 100644 --- a/crates/bevy_reflect/src/enums/helpers.rs +++ b/crates/bevy_reflect/src/enums/helpers.rs @@ -1,4 +1,5 @@ -use crate::{utility::reflect_hasher, Enum, Reflect, ReflectRef, VariantType}; +use crate::PartialReflect; +use crate::{utility::reflect_hasher, Enum, ReflectRef, VariantType}; use std::fmt::Debug; use std::hash::{Hash, Hasher}; @@ -15,16 +16,16 @@ pub fn enum_hash(value: &TEnum) -> Option { Some(hasher.finish()) } -/// Compares an [`Enum`] with a [`Reflect`] value. +/// Compares an [`Enum`] with a [`PartialReflect`] value. /// /// Returns true if and only if all of the following are true: /// - `b` is an enum; /// - `b` is the same variant as `a`; /// - For each field in `a`, `b` contains a field with the same name and -/// [`Reflect::reflect_partial_eq`] returns `Some(true)` for the two field +/// [`PartialReflect::reflect_partial_eq`] returns `Some(true)` for the two field /// values. #[inline] -pub fn enum_partial_eq(a: &TEnum, b: &dyn Reflect) -> Option { +pub fn enum_partial_eq(a: &TEnum, b: &dyn PartialReflect) -> Option { // Both enums? let ReflectRef::Enum(b) = b.reflect_ref() else { return Some(false); diff --git a/crates/bevy_reflect/src/enums/mod.rs b/crates/bevy_reflect/src/enums/mod.rs index 9f15bd6319f5e..043aaad49be87 100644 --- a/crates/bevy_reflect/src/enums/mod.rs +++ b/crates/bevy_reflect/src/enums/mod.rs @@ -614,71 +614,71 @@ mod tests { C2 { value: f32 }, } - let a: &dyn Reflect = &TestEnum::A; - let b: &dyn Reflect = &TestEnum::A; + let a: &dyn PartialReflect = &TestEnum::A; + let b: &dyn PartialReflect = &TestEnum::A; assert!( a.reflect_partial_eq(b).unwrap_or_default(), "expected TestEnum::A == TestEnum::A" ); - let a: &dyn Reflect = &TestEnum::A; - let b: &dyn Reflect = &TestEnum::A1; + let a: &dyn PartialReflect = &TestEnum::A; + let b: &dyn PartialReflect = &TestEnum::A1; assert!( !a.reflect_partial_eq(b).unwrap_or_default(), "expected TestEnum::A != TestEnum::A1" ); - let a: &dyn Reflect = &TestEnum::B(123); - let b: &dyn Reflect = &TestEnum::B(123); + let a: &dyn PartialReflect = &TestEnum::B(123); + let b: &dyn PartialReflect = &TestEnum::B(123); assert!( a.reflect_partial_eq(b).unwrap_or_default(), "expected TestEnum::B(123) == TestEnum::B(123)" ); - let a: &dyn Reflect = &TestEnum::B(123); - let b: &dyn Reflect = &TestEnum::B(321); + let a: &dyn PartialReflect = &TestEnum::B(123); + let b: &dyn PartialReflect = &TestEnum::B(321); assert!( !a.reflect_partial_eq(b).unwrap_or_default(), "expected TestEnum::B(123) != TestEnum::B(321)" ); - let a: &dyn Reflect = &TestEnum::B(123); - let b: &dyn Reflect = &TestEnum::B1(123); + let a: &dyn PartialReflect = &TestEnum::B(123); + let b: &dyn PartialReflect = &TestEnum::B1(123); assert!( !a.reflect_partial_eq(b).unwrap_or_default(), "expected TestEnum::B(123) != TestEnum::B1(123)" ); - let a: &dyn Reflect = &TestEnum::B(123); - let b: &dyn Reflect = &TestEnum::B2(123, 123); + let a: &dyn PartialReflect = &TestEnum::B(123); + let b: &dyn PartialReflect = &TestEnum::B2(123, 123); assert!( !a.reflect_partial_eq(b).unwrap_or_default(), "expected TestEnum::B(123) != TestEnum::B2(123, 123)" ); - let a: &dyn Reflect = &TestEnum::C { value: 123 }; - let b: &dyn Reflect = &TestEnum::C { value: 123 }; + let a: &dyn PartialReflect = &TestEnum::C { value: 123 }; + let b: &dyn PartialReflect = &TestEnum::C { value: 123 }; assert!( a.reflect_partial_eq(b).unwrap_or_default(), "expected TestEnum::C{{value: 123}} == TestEnum::C{{value: 123}}" ); - let a: &dyn Reflect = &TestEnum::C { value: 123 }; - let b: &dyn Reflect = &TestEnum::C { value: 321 }; + let a: &dyn PartialReflect = &TestEnum::C { value: 123 }; + let b: &dyn PartialReflect = &TestEnum::C { value: 321 }; assert!( !a.reflect_partial_eq(b).unwrap_or_default(), "expected TestEnum::C{{value: 123}} != TestEnum::C{{value: 321}}" ); - let a: &dyn Reflect = &TestEnum::C { value: 123 }; - let b: &dyn Reflect = &TestEnum::C1 { value: 123 }; + let a: &dyn PartialReflect = &TestEnum::C { value: 123 }; + let b: &dyn PartialReflect = &TestEnum::C1 { value: 123 }; assert!( !a.reflect_partial_eq(b).unwrap_or_default(), "expected TestEnum::C{{value: 123}} != TestEnum::C1{{value: 123}}" ); - let a: &dyn Reflect = &TestEnum::C { value: 123 }; - let b: &dyn Reflect = &TestEnum::C2 { value: 1.23 }; + let a: &dyn PartialReflect = &TestEnum::C { value: 123 }; + let b: &dyn PartialReflect = &TestEnum::C2 { value: 1.23 }; assert!( !a.reflect_partial_eq(b).unwrap_or_default(), "expected TestEnum::C{{value: 123}} != TestEnum::C2{{value: 1.23}}" diff --git a/crates/bevy_reflect/src/fields.rs b/crates/bevy_reflect/src/fields.rs index 4a58cd24ad0c1..e20d952ac5097 100644 --- a/crates/bevy_reflect/src/fields.rs +++ b/crates/bevy_reflect/src/fields.rs @@ -1,5 +1,5 @@ use crate::attributes::{impl_custom_attribute_methods, CustomAttributes}; -use crate::{MaybeTyped, Reflect, TypeInfo, TypePath, TypePathTable}; +use crate::{MaybeTyped, PartialReflect, TypeInfo, TypePath, TypePathTable}; use std::any::{Any, TypeId}; use std::sync::Arc; @@ -17,7 +17,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, @@ -106,7 +106,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 aacb7d9d2516f..b1ca70f52894d 100644 --- a/crates/bevy_reflect/src/from_reflect.rs +++ b/crates/bevy_reflect/src/from_reflect.rs @@ -1,4 +1,4 @@ -use crate::{FromType, Reflect}; +use crate::{FromType, PartialReflect, Reflect}; /// A trait that enables types to be dynamically constructed from reflected data. /// @@ -27,7 +27,7 @@ use crate::{FromType, Reflect}; )] pub trait FromReflect: Reflect + Sized { /// Constructs a concrete instance of `Self` from a reflected value. - fn from_reflect(reflect: &dyn Reflect) -> Option; + fn from_reflect(reflect: &dyn PartialReflect) -> Option; /// Attempts to downcast the given value to `Self` using, /// constructing the value using [`from_reflect`] if that fails. @@ -39,8 +39,10 @@ pub trait FromReflect: Reflect + Sized { /// [`from_reflect`]: Self::from_reflect /// [`DynamicStruct`]: crate::DynamicStruct /// [`DynamicList`]: crate::DynamicList - fn take_from_reflect(reflect: Box) -> Result> { - match reflect.take::() { + fn take_from_reflect( + reflect: Box, + ) -> Result> { + match reflect.try_take::() { Ok(value) => Ok(value), Err(value) => match Self::from_reflect(value.as_ref()) { None => Err(value), @@ -101,7 +103,7 @@ pub trait FromReflect: Reflect + Sized { /// [`DynamicEnum`]: crate::DynamicEnum #[derive(Clone)] pub struct ReflectFromReflect { - from_reflect: fn(&dyn Reflect) -> Option>, + from_reflect: fn(&dyn PartialReflect) -> Option>, } impl ReflectFromReflect { @@ -110,7 +112,7 @@ impl ReflectFromReflect { /// This will convert the object to a concrete type if it wasn't already, and return /// the value as `Box`. #[allow(clippy::wrong_self_convention)] - pub fn from_reflect(&self, reflect_value: &dyn Reflect) -> Option> { + pub fn from_reflect(&self, reflect_value: &dyn PartialReflect) -> Option> { (self.from_reflect)(reflect_value) } } diff --git a/crates/bevy_reflect/src/func/args/arg.rs b/crates/bevy_reflect/src/func/args/arg.rs index e89ce72598ce0..aa0d12b02781b 100644 --- a/crates/bevy_reflect/src/func/args/arg.rs +++ b/crates/bevy_reflect/src/func/args/arg.rs @@ -1,5 +1,5 @@ use crate::func::args::{ArgError, FromArg, Ownership}; -use crate::{Reflect, TypePath}; +use crate::{PartialReflect, Reflect, TypePath}; use std::ops::Deref; /// Represents an argument that can be passed to a [`DynamicFunction`], [`DynamicClosure`], @@ -83,7 +83,7 @@ impl<'a> Arg<'a> { /// ``` pub fn take_owned(self) -> Result { match self.value { - ArgValue::Owned(arg) => arg.take().map_err(|arg| ArgError::UnexpectedType { + ArgValue::Owned(arg) => arg.try_take().map_err(|arg| ArgError::UnexpectedType { index: self.index, expected: std::borrow::Cow::Borrowed(T::type_path()), received: std::borrow::Cow::Owned(arg.reflect_type_path().to_string()), @@ -124,11 +124,13 @@ impl<'a> Arg<'a> { received: Ownership::Owned, }), ArgValue::Ref(arg) => { - Ok(arg.downcast_ref().ok_or_else(|| ArgError::UnexpectedType { - index: self.index, - expected: std::borrow::Cow::Borrowed(T::type_path()), - received: std::borrow::Cow::Owned(arg.reflect_type_path().to_string()), - })?) + Ok(arg + .try_downcast_ref() + .ok_or_else(|| ArgError::UnexpectedType { + index: self.index, + expected: std::borrow::Cow::Borrowed(T::type_path()), + received: std::borrow::Cow::Owned(arg.reflect_type_path().to_string()), + })?) } ArgValue::Mut(_) => Err(ArgError::InvalidOwnership { index: self.index, @@ -167,11 +169,13 @@ impl<'a> Arg<'a> { }), ArgValue::Mut(arg) => { let received = std::borrow::Cow::Owned(arg.reflect_type_path().to_string()); - Ok(arg.downcast_mut().ok_or_else(|| ArgError::UnexpectedType { - index: self.index, - expected: std::borrow::Cow::Borrowed(T::type_path()), - received, - })?) + Ok(arg + .try_downcast_mut() + .ok_or_else(|| ArgError::UnexpectedType { + index: self.index, + expected: std::borrow::Cow::Borrowed(T::type_path()), + received, + })?) } } } @@ -182,13 +186,13 @@ impl<'a> Arg<'a> { /// [`DynamicFunction`]: crate::func::DynamicFunction #[derive(Debug)] pub enum ArgValue<'a> { - Owned(Box), - Ref(&'a dyn Reflect), - Mut(&'a mut dyn Reflect), + Owned(Box), + Ref(&'a dyn PartialReflect), + Mut(&'a mut dyn PartialReflect), } impl<'a> Deref for ArgValue<'a> { - type Target = dyn Reflect; + type Target = dyn PartialReflect; fn deref(&self) -> &Self::Target { match self { diff --git a/crates/bevy_reflect/src/func/args/list.rs b/crates/bevy_reflect/src/func/args/list.rs index 67703cebc0d73..481df444f21c5 100644 --- a/crates/bevy_reflect/src/func/args/list.rs +++ b/crates/bevy_reflect/src/func/args/list.rs @@ -1,6 +1,6 @@ use crate::func::args::{Arg, ArgValue, FromArg}; use crate::func::ArgError; -use crate::{Reflect, TypePath}; +use crate::{PartialReflect, Reflect, TypePath}; use std::collections::VecDeque; /// A list of arguments that can be passed to a [`DynamicFunction`], [`DynamicClosure`], @@ -70,7 +70,7 @@ impl<'a> ArgList<'a> { /// /// If an argument was previously removed from the beginning of the list, /// this method will also re-index the list. - pub fn push_ref(self, arg: &'a dyn Reflect) -> Self { + pub fn push_ref(self, arg: &'a dyn PartialReflect) -> Self { self.push_arg(ArgValue::Ref(arg)) } @@ -78,7 +78,7 @@ impl<'a> ArgList<'a> { /// /// If an argument was previously removed from the beginning of the list, /// this method will also re-index the list. - pub fn push_mut(self, arg: &'a mut dyn Reflect) -> Self { + pub fn push_mut(self, arg: &'a mut dyn PartialReflect) -> Self { self.push_arg(ArgValue::Mut(arg)) } @@ -86,7 +86,7 @@ impl<'a> ArgList<'a> { /// /// If an argument was previously removed from the beginning of the list, /// this method will also re-index the list. - pub fn push_owned(self, arg: impl Reflect) -> Self { + pub fn push_owned(self, arg: impl PartialReflect) -> Self { self.push_arg(ArgValue::Owned(Box::new(arg))) } @@ -94,7 +94,7 @@ impl<'a> ArgList<'a> { /// /// If an argument was previously removed from the beginning of the list, /// this method will also re-index the list. - pub fn push_boxed(self, arg: Box) -> Self { + pub fn push_boxed(self, arg: Box) -> Self { self.push_arg(ArgValue::Owned(arg)) } diff --git a/crates/bevy_reflect/src/func/closures/dynamic_closure.rs b/crates/bevy_reflect/src/func/closures/dynamic_closure.rs index e409e4967ad51..159e4c30eb64d 100644 --- a/crates/bevy_reflect/src/func/closures/dynamic_closure.rs +++ b/crates/bevy_reflect/src/func/closures/dynamic_closure.rs @@ -40,7 +40,7 @@ use crate::func::{FunctionResult, IntoClosure, ReturnInfo}; /// let value = func.call(args).unwrap().unwrap_owned(); /// /// // Check the result: -/// assert_eq!(value.take::().unwrap(), "Hello, world!!!"); +/// assert_eq!(value.try_take::().unwrap(), "Hello, world!!!"); /// ``` /// /// [`DynamicClosureMut`]: crate::func::closures::DynamicClosureMut @@ -110,7 +110,7 @@ impl<'env> DynamicClosure<'env> { /// let mut func = add.into_closure().with_name("add"); /// let args = ArgList::new().push_owned(25_i32).push_owned(75_i32); /// let result = func.call(args).unwrap().unwrap_owned(); - /// assert_eq!(result.take::().unwrap(), 123); + /// assert_eq!(result.try_take::().unwrap(), 123); /// ``` pub fn call<'a>(&self, args: ArgList<'a>) -> FunctionResult<'a> { (self.func)(args) diff --git a/crates/bevy_reflect/src/func/closures/dynamic_closure_mut.rs b/crates/bevy_reflect/src/func/closures/dynamic_closure_mut.rs index e49fad2203303..e5f1a33c19709 100644 --- a/crates/bevy_reflect/src/func/closures/dynamic_closure_mut.rs +++ b/crates/bevy_reflect/src/func/closures/dynamic_closure_mut.rs @@ -42,7 +42,7 @@ use crate::func::{FunctionResult, IntoClosureMut, ReturnInfo}; /// let value = func.call(args).unwrap().unwrap_owned(); /// /// // Check the result: -/// assert_eq!(value.take::().unwrap(), 2); +/// assert_eq!(value.try_take::().unwrap(), 2); /// /// // Note that `func` still has a reference to `list`, /// // so we need to drop it before we can access `list` again. @@ -125,7 +125,7 @@ impl<'env> DynamicClosureMut<'env> { /// let mut func = add.into_closure_mut().with_name("add"); /// let args = ArgList::new().push_owned(25_i32).push_owned(75_i32); /// let result = func.call(args).unwrap().unwrap_owned(); - /// assert_eq!(result.take::().unwrap(), 100); + /// assert_eq!(result.try_take::().unwrap(), 100); /// ``` /// /// [`call_once`]: DynamicClosureMut::call_once diff --git a/crates/bevy_reflect/src/func/closures/into_closure.rs b/crates/bevy_reflect/src/func/closures/into_closure.rs index a53e2124487c5..6c871c281c2f8 100644 --- a/crates/bevy_reflect/src/func/closures/into_closure.rs +++ b/crates/bevy_reflect/src/func/closures/into_closure.rs @@ -36,7 +36,7 @@ mod tests { let func = (|a: i32, b: i32| a + b + c).into_closure(); let args = ArgList::new().push_owned(25_i32).push_owned(75_i32); let result = func.call(args).unwrap().unwrap_owned(); - assert_eq!(result.downcast_ref::(), Some(&123)); + assert_eq!(result.try_downcast_ref::(), Some(&123)); } #[test] @@ -48,7 +48,7 @@ mod tests { let func = add.into_closure(); let args = ArgList::new().push_owned(25_i32).push_owned(75_i32); let result = func.call(args).unwrap().unwrap_owned(); - assert_eq!(result.downcast_ref::(), Some(&100)); + assert_eq!(result.try_downcast_ref::(), Some(&100)); } #[test] diff --git a/crates/bevy_reflect/src/func/closures/into_closure_mut.rs b/crates/bevy_reflect/src/func/closures/into_closure_mut.rs index 52860cb49a99e..96359fcedcc61 100644 --- a/crates/bevy_reflect/src/func/closures/into_closure_mut.rs +++ b/crates/bevy_reflect/src/func/closures/into_closure_mut.rs @@ -40,7 +40,7 @@ mod tests { let func = (|a: i32, b: i32| a + b + c).into_closure(); let args = ArgList::new().push_owned(25_i32).push_owned(75_i32); let result = func.call(args).unwrap().unwrap_owned(); - assert_eq!(result.downcast_ref::(), Some(&123)); + assert_eq!(result.try_downcast_ref::(), Some(&123)); } #[test] @@ -61,7 +61,7 @@ mod tests { let mut func = add.into_closure_mut(); let args = ArgList::new().push_owned(25_i32).push_owned(75_i32); let result = func.call(args).unwrap().unwrap_owned(); - assert_eq!(result.downcast_ref::(), Some(&100)); + assert_eq!(result.try_downcast_ref::(), Some(&100)); } #[test] diff --git a/crates/bevy_reflect/src/func/function.rs b/crates/bevy_reflect/src/func/function.rs index f2eecc4b1722d..d2d38e422b8ce 100644 --- a/crates/bevy_reflect/src/func/function.rs +++ b/crates/bevy_reflect/src/func/function.rs @@ -41,7 +41,7 @@ use crate::func::{FunctionResult, IntoFunction, ReturnInfo}; /// let value = func.call(args).unwrap().unwrap_owned(); /// /// // Check the result: -/// assert_eq!(value.downcast_ref::(), Some(&100)); +/// assert_eq!(value.try_downcast_ref::(), Some(&100)); /// ``` /// /// However, in some cases, these functions may need to be created manually: @@ -82,7 +82,7 @@ use crate::func::{FunctionResult, IntoFunction, ReturnInfo}; /// let value = func.call(args).unwrap().unwrap_mut(); /// /// // Mutate the return value: -/// value.downcast_mut::().unwrap().push_str("!!!"); +/// value.try_downcast_mut::().unwrap().push_str("!!!"); /// /// // Check the result: /// assert_eq!(list, vec!["Hello, World!!!"]); @@ -151,7 +151,7 @@ impl DynamicFunction { /// let func = add.into_function(); /// let args = ArgList::new().push_owned(25_i32).push_owned(75_i32); /// let result = func.call(args).unwrap().unwrap_owned(); - /// assert_eq!(result.take::().unwrap(), 100); + /// assert_eq!(result.try_take::().unwrap(), 100); /// ``` pub fn call<'a>(&self, args: ArgList<'a>) -> FunctionResult<'a> { (self.func)(args) @@ -269,7 +269,7 @@ mod tests { .call(ArgList::new().push_owned(0_usize).push_ref(&list)) .unwrap() .unwrap_ref() - .downcast_ref::() + .try_downcast_ref::() .unwrap(); assert_eq!(value, "foo"); } diff --git a/crates/bevy_reflect/src/func/into_function.rs b/crates/bevy_reflect/src/func/into_function.rs index a42f91fcfee6d..965661aa7ac9a 100644 --- a/crates/bevy_reflect/src/func/into_function.rs +++ b/crates/bevy_reflect/src/func/into_function.rs @@ -67,7 +67,7 @@ mod tests { let func = add.into_function(); let args = ArgList::new().push_owned(25_i32).push_owned(75_i32); let result = func.call(args).unwrap().unwrap_owned(); - assert_eq!(result.downcast_ref::(), Some(&100)); + assert_eq!(result.try_downcast_ref::(), Some(&100)); } #[test] @@ -79,7 +79,7 @@ mod tests { let func = (add as fn(i32, i32) -> i32).into_function(); let args = ArgList::new().push_owned(25_i32).push_owned(75_i32); let result = func.call(args).unwrap().unwrap_owned(); - assert_eq!(result.downcast_ref::(), Some(&100)); + assert_eq!(result.try_downcast_ref::(), Some(&100)); } #[test] @@ -87,7 +87,7 @@ mod tests { let func = (|a: i32, b: i32| a + b).into_function(); let args = ArgList::new().push_owned(25_i32).push_owned(75_i32); let result = func.call(args).unwrap().unwrap_owned(); - assert_eq!(result.downcast_ref::(), Some(&100)); + assert_eq!(result.try_downcast_ref::(), Some(&100)); } #[test] @@ -107,7 +107,7 @@ mod tests { let func = Foo::add.into_function(); let args = ArgList::new().push_ref(&foo_a).push_ref(&foo_b); let result = func.call(args).unwrap().unwrap_owned(); - assert_eq!(result.downcast_ref::(), Some(&Foo(100))); + assert_eq!(result.try_downcast_ref::(), Some(&Foo(100))); } #[test] @@ -120,7 +120,7 @@ mod tests { let args = ArgList::new(); let result = func.call(args).unwrap().unwrap_owned(); assert_eq!( - result.downcast_ref::(), + result.try_downcast_ref::(), Some(&String::from("Hello, World!")) ); } @@ -148,7 +148,7 @@ mod tests { .push_owned(String::from("Hello, World!")) .push_ref(&true); let result = func.call(args).unwrap().unwrap_ref(); - assert_eq!(result.downcast_ref::(), Some(&123)); + assert_eq!(result.try_downcast_ref::(), Some(&123)); } #[test] @@ -164,7 +164,7 @@ mod tests { .push_owned(String::from("Hello, World!")) .push_ref(&true); let result = func.call(args).unwrap().unwrap_mut(); - assert_eq!(result.downcast_mut::(), Some(&mut 123)); + assert_eq!(result.try_downcast_mut::(), Some(&mut 123)); } #[test] diff --git a/crates/bevy_reflect/src/func/mod.rs b/crates/bevy_reflect/src/func/mod.rs index 4bf4ce149d11b..172c1a0409474 100644 --- a/crates/bevy_reflect/src/func/mod.rs +++ b/crates/bevy_reflect/src/func/mod.rs @@ -10,12 +10,12 @@ //! via an [`ArgList`]. //! //! This returns a [`FunctionResult`] containing the [`Return`] value, -//! which can be used to extract a [`Reflect`] trait object. +//! which can be used to extract a [`PartialReflect`] trait object. //! //! # Example //! //! ``` -//! # use bevy_reflect::Reflect; +//! # use bevy_reflect::PartialReflect; //! # use bevy_reflect::func::args::ArgList; //! # use bevy_reflect::func::{DynamicFunction, FunctionResult, IntoFunction, Return}; //! fn add(a: i32, b: i32) -> i32 { @@ -27,10 +27,10 @@ //! // Pushing a known type with owned ownership //! .push_owned(25_i32) //! // Pushing a reflected type with owned ownership -//! .push_boxed(Box::new(75_i32) as Box); +//! .push_boxed(Box::new(75_i32) as Box); //! let result: FunctionResult = func.call(args); //! let value: Return = result.unwrap(); -//! assert_eq!(value.unwrap_owned().downcast_ref::(), Some(&100)); +//! assert_eq!(value.unwrap_owned().try_downcast_ref::(), Some(&100)); //! ``` //! //! # Functions vs Closures @@ -95,6 +95,7 @@ //! For other functions that don't conform to one of the above signatures, //! [`DynamicFunction`] and [`DynamicClosure`] can instead be created manually. //! +//! [`PartialReflect`]: crate::PartialReflect //! [`Reflect`]: crate::Reflect //! [lack of variadic generics]: https://poignardazur.github.io/2024/05/25/report-on-rustnl-variadics/ //! [coherence issues]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#coherence-leak-check diff --git a/crates/bevy_reflect/src/func/reflect_fn.rs b/crates/bevy_reflect/src/func/reflect_fn.rs index 83c77b6b2bef2..51a028941cd8b 100644 --- a/crates/bevy_reflect/src/func/reflect_fn.rs +++ b/crates/bevy_reflect/src/func/reflect_fn.rs @@ -42,7 +42,7 @@ use crate::{Reflect, TypePath}; /// let args = ArgList::new().push_owned(25_i32).push_owned(75_i32); /// /// let value = add.reflect_call(args).unwrap().unwrap_owned(); -/// assert_eq!(value.take::().unwrap(), 100); +/// assert_eq!(value.try_take::().unwrap(), 100); /// ``` /// /// # Trait Parameters diff --git a/crates/bevy_reflect/src/func/registry.rs b/crates/bevy_reflect/src/func/registry.rs index e10af437e6439..2fad8a60c35f4 100644 --- a/crates/bevy_reflect/src/func/registry.rs +++ b/crates/bevy_reflect/src/func/registry.rs @@ -351,7 +351,7 @@ mod tests { let function = registry.get(std::any::type_name_of_val(&foo)).unwrap(); let value = function.call(ArgList::new()).unwrap().unwrap_owned(); - assert_eq!(value.downcast_ref::(), Some(&123)); + assert_eq!(value.try_downcast_ref::(), Some(&123)); } #[test] @@ -361,7 +361,7 @@ mod tests { let function = registry.get("foo").unwrap(); let value = function.call(ArgList::new()).unwrap().unwrap_owned(); - assert_eq!(value.downcast_ref::(), Some(&123)); + assert_eq!(value.try_downcast_ref::(), Some(&123)); } #[test] @@ -377,7 +377,7 @@ mod tests { let function = registry.get("custom_name").unwrap(); let value = function.call(ArgList::new()).unwrap().unwrap_owned(); - assert_eq!(value.downcast_ref::(), Some(&123)); + assert_eq!(value.try_downcast_ref::(), Some(&123)); } #[test] @@ -404,7 +404,7 @@ mod tests { let function = registry.get(name).unwrap(); let value = function.call(ArgList::new()).unwrap().unwrap_owned(); - assert_eq!(value.downcast_ref::(), Some(&123)); + assert_eq!(value.try_downcast_ref::(), Some(&123)); } #[test] @@ -429,7 +429,7 @@ mod tests { let function = registry.get(name).unwrap(); let value = function.call(ArgList::new()).unwrap().unwrap_owned(); - assert_eq!(value.downcast_ref::(), Some(&321)); + assert_eq!(value.try_downcast_ref::(), Some(&321)); } #[test] diff --git a/crates/bevy_reflect/src/func/return_type.rs b/crates/bevy_reflect/src/func/return_type.rs index b20dd62d1c950..02f76c974ee22 100644 --- a/crates/bevy_reflect/src/func/return_type.rs +++ b/crates/bevy_reflect/src/func/return_type.rs @@ -1,4 +1,4 @@ -use crate::Reflect; +use crate::PartialReflect; /// The return type of a [`DynamicFunction`] or [`DynamicClosure`]. /// @@ -9,11 +9,11 @@ pub enum Return<'a> { /// The function returns nothing (i.e. it returns `()`). Unit, /// The function returns an owned value. - Owned(Box), + Owned(Box), /// The function returns a reference to a value. - Ref(&'a dyn Reflect), + Ref(&'a dyn PartialReflect), /// The function returns a mutable reference to a value. - Mut(&'a mut dyn Reflect), + Mut(&'a mut dyn PartialReflect), } impl<'a> Return<'a> { @@ -27,7 +27,7 @@ impl<'a> Return<'a> { /// # Panics /// /// Panics if the return value is not [`Self::Owned`]. - pub fn unwrap_owned(self) -> Box { + pub fn unwrap_owned(self) -> Box { match self { Return::Owned(value) => value, _ => panic!("expected owned value"), @@ -39,7 +39,7 @@ impl<'a> Return<'a> { /// # Panics /// /// Panics if the return value is not [`Self::Ref`]. - pub fn unwrap_ref(self) -> &'a dyn Reflect { + pub fn unwrap_ref(self) -> &'a dyn PartialReflect { match self { Return::Ref(value) => value, _ => panic!("expected reference value"), @@ -51,7 +51,7 @@ impl<'a> Return<'a> { /// # Panics /// /// Panics if the return value is not [`Self::Mut`]. - pub fn unwrap_mut(self) -> &'a mut dyn Reflect { + pub fn unwrap_mut(self) -> &'a mut dyn PartialReflect { match self { Return::Mut(value) => value, _ => panic!("expected mutable reference value"), diff --git a/crates/bevy_reflect/src/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index ece76288fa9c3..6addd3a9468e7 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -6,32 +6,32 @@ use std::any::Any; use crate::utility::GenericTypeInfoCell; use crate::{ self as bevy_reflect, ApplyError, FromReflect, FromType, GetTypeRegistration, List, ListInfo, - ListIter, MaybeTyped, Reflect, ReflectFromPtr, ReflectKind, ReflectMut, ReflectOwned, - ReflectRef, TypeInfo, TypePath, TypeRegistration, Typed, + ListIter, MaybeTyped, PartialReflect, Reflect, ReflectFromPtr, ReflectKind, ReflectMut, + ReflectOwned, ReflectRef, TypeInfo, TypePath, TypeRegistration, Typed, }; impl List for SmallVec where T::Item: FromReflect + MaybeTyped + TypePath, { - fn get(&self, index: usize) -> Option<&dyn Reflect> { + fn get(&self, index: usize) -> Option<&dyn PartialReflect> { if index < SmallVec::len(self) { - Some(&self[index] as &dyn Reflect) + Some(&self[index] as &dyn PartialReflect) } else { None } } - fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> { + fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> { if index < SmallVec::len(self) { - Some(&mut self[index] as &mut dyn Reflect) + Some(&mut self[index] as &mut dyn PartialReflect) } else { None } } - fn insert(&mut self, index: usize, value: Box) { - let value = value.take::().unwrap_or_else(|value| { + fn insert(&mut self, index: usize, value: Box) { + let value = value.try_take::().unwrap_or_else(|value| { ::Item::from_reflect(&*value).unwrap_or_else(|| { panic!( "Attempted to insert invalid value of type {}.", @@ -42,12 +42,12 @@ where SmallVec::insert(self, index, value); } - fn remove(&mut self, index: usize) -> Box { + fn remove(&mut self, index: usize) -> Box { Box::new(self.remove(index)) } - fn push(&mut self, value: Box) { - let value = value.take::().unwrap_or_else(|value| { + fn push(&mut self, value: Box) { + let value = value.try_take::().unwrap_or_else(|value| { ::Item::from_reflect(&*value).unwrap_or_else(|| { panic!( "Attempted to push invalid value of type {}.", @@ -58,8 +58,9 @@ where SmallVec::push(self, value); } - fn pop(&mut self) -> Option> { - self.pop().map(|value| Box::new(value) as Box) + fn pop(&mut self) -> Option> { + self.pop() + .map(|value| Box::new(value) as Box) } fn len(&self) -> usize { @@ -70,14 +71,13 @@ where ListIter::new(self) } - fn drain(self: Box) -> Vec> { + fn drain(self: Box) -> Vec> { self.into_iter() - .map(|value| Box::new(value) as Box) + .map(|value| Box::new(value) as Box) .collect() } } - -impl Reflect for SmallVec +impl PartialReflect for SmallVec where T::Item: FromReflect + MaybeTyped + TypePath, { @@ -85,43 +85,39 @@ where Some(::type_info()) } - fn into_any(self: Box) -> Box { + #[inline] + fn into_partial_reflect(self: Box) -> Box { self } - fn as_any(&self) -> &dyn Any { + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } - fn as_any_mut(&mut self) -> &mut dyn Any { + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } - fn into_reflect(self: Box) -> Box { - self + fn try_into_reflect(self: Box) -> Result, Box> { + Ok(self) } - fn as_reflect(&self) -> &dyn Reflect { - self + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + Some(self) } - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + Some(self) } - fn apply(&mut self, value: &dyn Reflect) { + fn apply(&mut self, value: &dyn PartialReflect) { crate::list_apply(self, value); } - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { crate::list_try_apply(self, value) } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - fn reflect_kind(&self) -> ReflectKind { ReflectKind::List } @@ -138,15 +134,49 @@ where ReflectOwned::List(self) } - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone_dynamic()) } - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { + fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option { crate::list_partial_eq(self, value) } } +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 Typed for SmallVec where T::Item: FromReflect + MaybeTyped + TypePath, @@ -163,7 +193,7 @@ impl FromReflect for SmallVec where T::Item: FromReflect + MaybeTyped + TypePath, { - fn from_reflect(reflect: &dyn Reflect) -> Option { + fn from_reflect(reflect: &dyn PartialReflect) -> Option { if let ReflectRef::List(ref_list) = reflect.reflect_ref() { let mut new_list = Self::with_capacity(ref_list.len()); for field in ref_list.iter() { diff --git a/crates/bevy_reflect/src/impls/smol_str.rs b/crates/bevy_reflect/src/impls/smol_str.rs index 0375c1544f238..d8e3251c91d35 100644 --- a/crates/bevy_reflect/src/impls/smol_str.rs +++ b/crates/bevy_reflect/src/impls/smol_str.rs @@ -6,14 +6,14 @@ impl_reflect_value!(::smol_str::SmolStr(Debug, Hash, PartialEq, Default)); #[cfg(test)] mod tests { - use crate::{FromReflect, Reflect}; + use crate::{FromReflect, PartialReflect}; use smol_str::SmolStr; #[test] fn should_partial_eq_smolstr() { - let a: &dyn Reflect = &SmolStr::new("A"); - let a2: &dyn Reflect = &SmolStr::new("A"); - let b: &dyn Reflect = &SmolStr::new("B"); + let a: &dyn PartialReflect = &SmolStr::new("A"); + let a2: &dyn PartialReflect = &SmolStr::new("A"); + let b: &dyn PartialReflect = &SmolStr::new("B"); assert_eq!(Some(true), a.reflect_partial_eq(a2)); assert_eq!(Some(false), a.reflect_partial_eq(b)); } diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index ca7986ca9d55c..8ced4d7caabe6 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -3,12 +3,13 @@ use crate::utility::{ reflect_hasher, GenericTypeInfoCell, GenericTypePathCell, NonGenericTypeInfoCell, }; use crate::{ - self as bevy_reflect, impl_type_path, map_apply, map_partial_eq, map_try_apply, set_apply, - set_partial_eq, set_try_apply, ApplyError, Array, ArrayInfo, ArrayIter, DynamicMap, DynamicSet, - DynamicTypePath, FromReflect, FromType, GetTypeRegistration, List, ListInfo, ListIter, Map, - MapInfo, MapIter, MaybeTyped, Reflect, ReflectDeserialize, ReflectFromPtr, ReflectFromReflect, - ReflectKind, ReflectMut, ReflectOwned, ReflectRef, ReflectSerialize, Set, SetInfo, TypeInfo, - TypePath, TypeRegistration, TypeRegistry, Typed, ValueInfo, + self as bevy_reflect, impl_type_path, map_apply, map_partial_eq, map_try_apply, + reflect::impl_full_reflect, set_apply, set_partial_eq, set_try_apply, ApplyError, Array, + ArrayInfo, ArrayIter, DynamicMap, DynamicSet, DynamicTypePath, FromReflect, FromType, + GetTypeRegistration, List, ListInfo, ListIter, Map, MapInfo, MapIter, MaybeTyped, + PartialReflect, Reflect, ReflectDeserialize, ReflectFromPtr, ReflectFromReflect, ReflectKind, + ReflectMut, ReflectOwned, ReflectRef, ReflectSerialize, Set, SetInfo, TypeInfo, TypePath, + TypeRegistration, TypeRegistry, Typed, ValueInfo, }; use bevy_reflect_derive::{impl_reflect, impl_reflect_value}; use std::fmt; @@ -251,7 +252,7 @@ macro_rules! impl_reflect_for_atomic { } } - impl Reflect for $ty + impl PartialReflect for $ty where $ty: Any + Send + Sync, { @@ -260,37 +261,38 @@ macro_rules! impl_reflect_for_atomic { Some(::type_info()) } #[inline] - fn into_any(self: Box) -> Box { + fn into_partial_reflect(self: Box) -> Box { self } #[inline] - fn as_any(&self) -> &dyn Any { + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } #[inline] - fn as_any_mut(&mut self) -> &mut dyn Any { + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } #[inline] - fn into_reflect(self: Box) -> Box { - self + fn try_into_reflect( + self: Box, + ) -> Result, Box> { + Ok(self) } #[inline] - fn as_reflect(&self) -> &dyn Reflect { - self + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + Some(self) } #[inline] - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + Some(self) } #[inline] - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(<$ty>::new(self.load($ordering))) } #[inline] - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { - let any = Reflect::as_any(value); - if let Some(value) = ::downcast_ref::(any) { + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { + if let Some(value) = value.try_downcast_ref::() { *self = <$ty>::new(value.load($ordering)); } else { return Err(ApplyError::MismatchedTypes { @@ -301,11 +303,6 @@ macro_rules! impl_reflect_for_atomic { Ok(()) } #[inline] - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = ::take(value)?; - Ok(()) - } - #[inline] fn reflect_kind(&self) -> ReflectKind { ReflectKind::Value } @@ -326,14 +323,17 @@ macro_rules! impl_reflect_for_atomic { } } + // strange rustfmt bug gives this invocation the wrong indentation! + #[rustfmt::skip] + impl_full_reflect!(for $ty where $ty: Any + Send + Sync); + impl FromReflect for $ty where $ty: Any + Send + Sync, { - fn from_reflect(reflect: &dyn Reflect) -> Option { + fn from_reflect(reflect: &dyn PartialReflect) -> Option { Some(<$ty>::new( - ::downcast_ref::<$ty>(::as_any(reflect))? - .load($ordering), + reflect.try_downcast_ref::<$ty>()?.load($ordering), )) } } @@ -387,20 +387,20 @@ impl_reflect_for_atomic!( ); macro_rules! impl_reflect_for_veclike { - ($ty:path, $insert:expr, $remove:expr, $push:expr, $pop:expr, $sub:ty) => { + ($ty:ty, $insert:expr, $remove:expr, $push:expr, $pop:expr, $sub:ty) => { impl List for $ty { #[inline] - fn get(&self, index: usize) -> Option<&dyn Reflect> { - <$sub>::get(self, index).map(|value| value as &dyn Reflect) + fn get(&self, index: usize) -> Option<&dyn PartialReflect> { + <$sub>::get(self, index).map(|value| value as &dyn PartialReflect) } #[inline] - fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> { - <$sub>::get_mut(self, index).map(|value| value as &mut dyn Reflect) + fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> { + <$sub>::get_mut(self, index).map(|value| value as &mut dyn PartialReflect) } - fn insert(&mut self, index: usize, value: Box) { - let value = value.take::().unwrap_or_else(|value| { + fn insert(&mut self, index: usize, value: Box) { + let value = value.try_take::().unwrap_or_else(|value| { T::from_reflect(&*value).unwrap_or_else(|| { panic!( "Attempted to insert invalid value of type {}.", @@ -411,11 +411,11 @@ macro_rules! impl_reflect_for_veclike { $insert(self, index, value); } - fn remove(&mut self, index: usize) -> Box { + fn remove(&mut self, index: usize) -> Box { Box::new($remove(self, index)) } - fn push(&mut self, value: Box) { + fn push(&mut self, value: Box) { let value = T::take_from_reflect(value).unwrap_or_else(|value| { panic!( "Attempted to push invalid value of type {}.", @@ -425,8 +425,8 @@ macro_rules! impl_reflect_for_veclike { $push(self, value); } - fn pop(&mut self) -> Option> { - $pop(self).map(|value| Box::new(value) as Box) + fn pop(&mut self) -> Option> { + $pop(self).map(|value| Box::new(value) as Box) } #[inline] @@ -440,53 +440,42 @@ macro_rules! impl_reflect_for_veclike { } #[inline] - fn drain(self: Box) -> Vec> { + fn drain(self: Box) -> Vec> { self.into_iter() - .map(|value| Box::new(value) as Box) + .map(|value| Box::new(value) as Box) .collect() } } - impl Reflect for $ty { + impl PartialReflect for $ty { fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } - fn into_any(self: Box) -> Box { + fn into_partial_reflect(self: Box) -> Box { self } - fn as_any(&self) -> &dyn Any { + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } - fn as_any_mut(&mut self) -> &mut dyn Any { + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } - fn into_reflect(self: Box) -> Box { - self + fn try_into_reflect( + self: Box, + ) -> Result, Box> { + Ok(self) } - fn as_reflect(&self) -> &dyn Reflect { - self + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + Some(self) } - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self - } - - fn apply(&mut self, value: &dyn Reflect) { - crate::list_apply(self, value); - } - - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { - crate::list_try_apply(self, value) - } - - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + Some(self) } fn reflect_kind(&self) -> ReflectKind { @@ -505,7 +494,7 @@ macro_rules! impl_reflect_for_veclike { ReflectOwned::List(self) } - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone_dynamic()) } @@ -513,11 +502,21 @@ macro_rules! impl_reflect_for_veclike { crate::list_hash(self) } - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { + fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option { crate::list_partial_eq(self, value) } + + fn apply(&mut self, value: &dyn PartialReflect) { + crate::list_apply(self, value); + } + + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { + crate::list_try_apply(self, value) + } } + impl_full_reflect!( for $ty where T: FromReflect + MaybeTyped + TypePath + GetTypeRegistration); + impl Typed for $ty { fn type_info() -> &'static TypeInfo { static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); @@ -525,8 +524,6 @@ macro_rules! impl_reflect_for_veclike { } } - impl_type_path!($ty); - impl GetTypeRegistration for $ty { @@ -542,7 +539,7 @@ macro_rules! impl_reflect_for_veclike { } impl FromReflect for $ty { - fn from_reflect(reflect: &dyn Reflect) -> Option { + fn from_reflect(reflect: &dyn PartialReflect) -> Option { if let ReflectRef::List(ref_list) = reflect.reflect_ref() { let mut new_list = Self::with_capacity(ref_list.len()); for field in ref_list.iter() { @@ -557,25 +554,20 @@ macro_rules! impl_reflect_for_veclike { }; } -impl_reflect_for_veclike!( - ::alloc::vec::Vec, - Vec::insert, - Vec::remove, - Vec::push, - Vec::pop, - [T] -); +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; ); impl_reflect_for_veclike!( - ::alloc::collections::VecDeque, + VecDeque, VecDeque::insert, VecDeque::remove, VecDeque::push_back, VecDeque::pop_back, VecDeque:: ); +impl_type_path!(::alloc::collections::VecDeque); #[cfg(feature = "functions")] crate::func::macros::impl_function_traits!(VecDeque; ); @@ -587,28 +579,31 @@ macro_rules! impl_reflect_for_hashmap { V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, S: TypePath + BuildHasher + Send + Sync, { - fn get(&self, key: &dyn Reflect) -> Option<&dyn Reflect> { - key.downcast_ref::() + fn get(&self, key: &dyn PartialReflect) -> Option<&dyn PartialReflect> { + key.try_downcast_ref::() .and_then(|key| Self::get(self, key)) - .map(|value| value as &dyn Reflect) + .map(|value| value as &dyn PartialReflect) } - fn get_mut(&mut self, key: &dyn Reflect) -> Option<&mut dyn Reflect> { - key.downcast_ref::() + fn get_mut(&mut self, key: &dyn PartialReflect) -> Option<&mut dyn PartialReflect> { + key.try_downcast_ref::() .and_then(move |key| Self::get_mut(self, key)) - .map(|value| value as &mut dyn Reflect) + .map(|value| value as &mut dyn PartialReflect) } - fn get_at(&self, index: usize) -> Option<(&dyn Reflect, &dyn Reflect)> { + fn get_at(&self, index: usize) -> Option<(&dyn PartialReflect, &dyn PartialReflect)> { self.iter() .nth(index) - .map(|(key, value)| (key as &dyn Reflect, value as &dyn Reflect)) + .map(|(key, value)| (key as &dyn PartialReflect, value as &dyn PartialReflect)) } - fn get_at_mut(&mut self, index: usize) -> Option<(&dyn Reflect, &mut dyn Reflect)> { - self.iter_mut() - .nth(index) - .map(|(key, value)| (key as &dyn Reflect, value as &mut dyn Reflect)) + fn get_at_mut( + &mut self, + index: usize, + ) -> Option<(&dyn PartialReflect, &mut dyn PartialReflect)> { + self.iter_mut().nth(index).map(|(key, value)| { + (key as &dyn PartialReflect, value as &mut dyn PartialReflect) + }) } fn len(&self) -> usize { @@ -619,12 +614,12 @@ macro_rules! impl_reflect_for_hashmap { MapIter::new(self) } - fn drain(self: Box) -> Vec<(Box, Box)> { + fn drain(self: Box) -> Vec<(Box, Box)> { self.into_iter() .map(|(key, value)| { ( - Box::new(key) as Box, - Box::new(value) as Box, + Box::new(key) as Box, + Box::new(value) as Box, ) }) .collect() @@ -647,9 +642,9 @@ macro_rules! impl_reflect_for_hashmap { fn insert_boxed( &mut self, - key: Box, - value: Box, - ) -> Option> { + key: Box, + value: Box, + ) -> Option> { let key = K::take_from_reflect(key).unwrap_or_else(|key| { panic!( "Attempted to insert invalid key of type {}.", @@ -663,22 +658,22 @@ macro_rules! impl_reflect_for_hashmap { ) }); self.insert(key, value) - .map(|old_value| Box::new(old_value) as Box) + .map(|old_value| Box::new(old_value) as Box) } - fn remove(&mut self, key: &dyn Reflect) -> Option> { + fn remove(&mut self, key: &dyn PartialReflect) -> Option> { let mut from_reflect = None; - key.downcast_ref::() + key.try_downcast_ref::() .or_else(|| { from_reflect = K::from_reflect(key); from_reflect.as_ref() }) .and_then(|key| self.remove(key)) - .map(|value| Box::new(value) as Box) + .map(|value| Box::new(value) as Box) } } - impl Reflect for $ty + impl PartialReflect for $ty where K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Hash, V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, @@ -688,42 +683,31 @@ macro_rules! impl_reflect_for_hashmap { Some(::type_info()) } - fn into_any(self: Box) -> Box { - self - } - - fn as_any(&self) -> &dyn Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn Any { - self - } - #[inline] - fn into_reflect(self: Box) -> Box { + fn into_partial_reflect(self: Box) -> Box { self } - fn as_reflect(&self) -> &dyn Reflect { + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } - fn apply(&mut self, value: &dyn Reflect) { - map_apply(self, value); + fn try_into_reflect( + self: Box, + ) -> Result, Box> { + Ok(self) } - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { - map_try_apply(self, value) + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + Some(self) } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + Some(self) } fn reflect_kind(&self) -> ReflectKind { @@ -742,15 +726,31 @@ macro_rules! impl_reflect_for_hashmap { ReflectOwned::Map(self) } - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone_dynamic()) } - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { + fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option { map_partial_eq(self, value) } + + fn apply(&mut self, value: &dyn PartialReflect) { + map_apply(self, value); + } + + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { + map_try_apply(self, value) + } } + impl_full_reflect!( + for $ty + where + K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Hash, + V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, + S: TypePath + BuildHasher + Send + Sync, + ); + impl Typed for $ty where K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Hash, @@ -787,7 +787,7 @@ macro_rules! impl_reflect_for_hashmap { V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, S: TypePath + BuildHasher + Default + Send + Sync, { - fn from_reflect(reflect: &dyn Reflect) -> Option { + fn from_reflect(reflect: &dyn PartialReflect) -> Option { if let ReflectRef::Map(ref_map) = reflect.reflect_ref() { let mut new_map = Self::with_capacity_and_hasher(ref_map.len(), S::default()); for (key, value) in ref_map.iter() { @@ -835,25 +835,25 @@ macro_rules! impl_reflect_for_hashset { V: FromReflect + TypePath + GetTypeRegistration + Eq + Hash, S: TypePath + BuildHasher + Send + Sync, { - fn get(&self, value: &dyn Reflect) -> Option<&dyn Reflect> { + fn get(&self, value: &dyn PartialReflect) -> Option<&dyn PartialReflect> { value - .downcast_ref::() + .try_downcast_ref::() .and_then(|value| Self::get(self, value)) - .map(|value| value as &dyn Reflect) + .map(|value| value as &dyn PartialReflect) } fn len(&self) -> usize { Self::len(self) } - fn iter(&self) -> Box + '_> { - let iter = self.iter().map(|v| v as &dyn Reflect); + fn iter(&self) -> Box + '_> { + let iter = self.iter().map(|v| v as &dyn PartialReflect); Box::new(iter) } - fn drain(self: Box) -> Vec> { + fn drain(self: Box) -> Vec> { self.into_iter() - .map(|value| Box::new(value) as Box) + .map(|value| Box::new(value) as Box) .collect() } @@ -866,7 +866,7 @@ macro_rules! impl_reflect_for_hashset { dynamic_set } - fn insert_boxed(&mut self, value: Box) -> bool { + fn insert_boxed(&mut self, value: Box) -> bool { let value = V::take_from_reflect(value).unwrap_or_else(|value| { panic!( "Attempted to insert invalid value of type {}.", @@ -876,10 +876,10 @@ macro_rules! impl_reflect_for_hashset { self.insert(value) } - fn remove(&mut self, value: &dyn Reflect) -> bool { + fn remove(&mut self, value: &dyn PartialReflect) -> bool { let mut from_reflect = None; value - .downcast_ref::() + .try_downcast_ref::() .or_else(|| { from_reflect = V::from_reflect(value); from_reflect.as_ref() @@ -887,10 +887,10 @@ macro_rules! impl_reflect_for_hashset { .map_or(false, |value| self.remove(value)) } - fn contains(&self, value: &dyn Reflect) -> bool { + fn contains(&self, value: &dyn PartialReflect) -> bool { let mut from_reflect = None; value - .downcast_ref::() + .try_downcast_ref::() .or_else(|| { from_reflect = V::from_reflect(value); from_reflect.as_ref() @@ -899,7 +899,7 @@ macro_rules! impl_reflect_for_hashset { } } - impl Reflect for $ty + impl PartialReflect for $ty where V: FromReflect + TypePath + GetTypeRegistration + Eq + Hash, S: TypePath + BuildHasher + Send + Sync, @@ -908,44 +908,42 @@ macro_rules! impl_reflect_for_hashset { Some(::type_info()) } - fn into_any(self: Box) -> Box { + #[inline] + fn into_partial_reflect(self: Box) -> Box { self } - fn as_any(&self) -> &dyn Any { + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } - fn as_any_mut(&mut self) -> &mut dyn Any { + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } #[inline] - fn into_reflect(self: Box) -> Box { - self + fn try_into_reflect( + self: Box, + ) -> Result, Box> { + Ok(self) } - fn as_reflect(&self) -> &dyn Reflect { - self + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + Some(self) } - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + Some(self) } - fn apply(&mut self, value: &dyn Reflect) { + fn apply(&mut self, value: &dyn PartialReflect) { set_apply(self, value); } - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { set_try_apply(self, value) } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - fn reflect_kind(&self) -> ReflectKind { ReflectKind::Set } @@ -962,11 +960,11 @@ macro_rules! impl_reflect_for_hashset { ReflectOwned::Set(self) } - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone_dynamic()) } - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { + fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option { set_partial_eq(self, value) } } @@ -998,12 +996,19 @@ macro_rules! impl_reflect_for_hashset { } } + impl_full_reflect!( + for $ty + where + V: FromReflect + TypePath + GetTypeRegistration + Eq + Hash, + S: TypePath + BuildHasher + Send + Sync, + ); + impl FromReflect for $ty where V: FromReflect + TypePath + GetTypeRegistration + Eq + Hash, S: TypePath + BuildHasher + Default + Send + Sync, { - fn from_reflect(reflect: &dyn Reflect) -> Option { + fn from_reflect(reflect: &dyn PartialReflect) -> Option { if let ReflectRef::Set(ref_set) = reflect.reflect_ref() { let mut new_set = Self::with_capacity_and_hasher(ref_set.len(), S::default()); for value in ref_set.iter() { @@ -1048,28 +1053,31 @@ where K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Ord, V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, { - fn get(&self, key: &dyn Reflect) -> Option<&dyn Reflect> { - key.downcast_ref::() + fn get(&self, key: &dyn PartialReflect) -> Option<&dyn PartialReflect> { + key.try_downcast_ref::() .and_then(|key| Self::get(self, key)) - .map(|value| value as &dyn Reflect) + .map(|value| value as &dyn PartialReflect) } - fn get_mut(&mut self, key: &dyn Reflect) -> Option<&mut dyn Reflect> { - key.downcast_ref::() + fn get_mut(&mut self, key: &dyn PartialReflect) -> Option<&mut dyn PartialReflect> { + key.try_downcast_ref::() .and_then(move |key| Self::get_mut(self, key)) - .map(|value| value as &mut dyn Reflect) + .map(|value| value as &mut dyn PartialReflect) } - fn get_at(&self, index: usize) -> Option<(&dyn Reflect, &dyn Reflect)> { + fn get_at(&self, index: usize) -> Option<(&dyn PartialReflect, &dyn PartialReflect)> { self.iter() .nth(index) - .map(|(key, value)| (key as &dyn Reflect, value as &dyn Reflect)) + .map(|(key, value)| (key as &dyn PartialReflect, value as &dyn PartialReflect)) } - fn get_at_mut(&mut self, index: usize) -> Option<(&dyn Reflect, &mut dyn Reflect)> { + fn get_at_mut( + &mut self, + index: usize, + ) -> Option<(&dyn PartialReflect, &mut dyn PartialReflect)> { self.iter_mut() .nth(index) - .map(|(key, value)| (key as &dyn Reflect, value as &mut dyn Reflect)) + .map(|(key, value)| (key as &dyn PartialReflect, value as &mut dyn PartialReflect)) } fn len(&self) -> usize { @@ -1080,12 +1088,12 @@ where MapIter::new(self) } - fn drain(self: Box) -> Vec<(Box, Box)> { + fn drain(self: Box) -> Vec<(Box, Box)> { self.into_iter() .map(|(key, value)| { ( - Box::new(key) as Box, - Box::new(value) as Box, + Box::new(key) as Box, + Box::new(value) as Box, ) }) .collect() @@ -1108,9 +1116,9 @@ where fn insert_boxed( &mut self, - key: Box, - value: Box, - ) -> Option> { + key: Box, + value: Box, + ) -> Option> { let key = K::take_from_reflect(key).unwrap_or_else(|key| { panic!( "Attempted to insert invalid key of type {}.", @@ -1124,22 +1132,22 @@ where ) }); self.insert(key, value) - .map(|old_value| Box::new(old_value) as Box) + .map(|old_value| Box::new(old_value) as Box) } - fn remove(&mut self, key: &dyn Reflect) -> Option> { + fn remove(&mut self, key: &dyn PartialReflect) -> Option> { let mut from_reflect = None; - key.downcast_ref::() + key.try_downcast_ref::() .or_else(|| { from_reflect = K::from_reflect(key); from_reflect.as_ref() }) .and_then(|key| self.remove(key)) - .map(|value| Box::new(value) as Box) + .map(|value| Box::new(value) as Box) } } -impl Reflect for ::std::collections::BTreeMap +impl PartialReflect for ::std::collections::BTreeMap where K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Ord, V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, @@ -1147,45 +1155,30 @@ where fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } - - fn into_any(self: Box) -> Box { - self - } - - fn as_any(&self) -> &dyn Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn Any { - self - } - #[inline] - fn into_reflect(self: Box) -> Box { + fn into_partial_reflect(self: Box) -> Box { self } - fn as_reflect(&self) -> &dyn Reflect { + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } - - fn apply(&mut self, value: &dyn Reflect) { - map_apply(self, value); + #[inline] + fn try_into_reflect(self: Box) -> Result, Box> { + Ok(self) } - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { - map_try_apply(self, value) + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + Some(self) } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + Some(self) } - fn reflect_kind(&self) -> ReflectKind { ReflectKind::Map } @@ -1202,15 +1195,30 @@ where ReflectOwned::Map(self) } - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone_dynamic()) } - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { + fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option { map_partial_eq(self, value) } + + fn apply(&mut self, value: &dyn PartialReflect) { + map_apply(self, value); + } + + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { + map_try_apply(self, value) + } } +impl_full_reflect!( + for ::std::collections::BTreeMap + where + K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Ord, + V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, +); + impl Typed for ::std::collections::BTreeMap where K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Ord, @@ -1239,7 +1247,7 @@ where K: FromReflect + MaybeTyped + TypePath + GetTypeRegistration + Eq + Ord, V: FromReflect + MaybeTyped + TypePath + GetTypeRegistration, { - fn from_reflect(reflect: &dyn Reflect) -> Option { + fn from_reflect(reflect: &dyn PartialReflect) -> Option { if let ReflectRef::Map(ref_map) = reflect.reflect_ref() { let mut new_map = Self::new(); for (key, value) in ref_map.iter() { @@ -1265,13 +1273,13 @@ crate::func::macros::impl_function_traits!(::std::collections::BTreeMap; impl Array for [T; N] { #[inline] - fn get(&self, index: usize) -> Option<&dyn Reflect> { - <[T]>::get(self, index).map(|value| value as &dyn Reflect) + fn get(&self, index: usize) -> Option<&dyn PartialReflect> { + <[T]>::get(self, index).map(|value| value as &dyn PartialReflect) } #[inline] - fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> { - <[T]>::get_mut(self, index).map(|value| value as &mut dyn Reflect) + fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> { + <[T]>::get_mut(self, index).map(|value| value as &mut dyn PartialReflect) } #[inline] @@ -1285,62 +1293,43 @@ impl A } #[inline] - fn drain(self: Box) -> Vec> { + fn drain(self: Box) -> Vec> { self.into_iter() - .map(|value| Box::new(value) as Box) + .map(|value| Box::new(value) as Box) .collect() } } -impl Reflect for [T; N] { +impl PartialReflect + for [T; N] +{ fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } #[inline] - fn into_any(self: Box) -> Box { - self - } - - #[inline] - fn as_any(&self) -> &dyn Any { + fn into_partial_reflect(self: Box) -> Box { self } - #[inline] - fn as_any_mut(&mut self) -> &mut dyn Any { + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } - #[inline] - fn into_reflect(self: Box) -> Box { + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } - #[inline] - fn as_reflect(&self) -> &dyn Reflect { - self + fn try_into_reflect(self: Box) -> Result, Box> { + Ok(self) } - #[inline] - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + Some(self) } - #[inline] - fn apply(&mut self, value: &dyn Reflect) { - crate::array_apply(self, value); - } - - #[inline] - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { - crate::array_try_apply(self, value) - } - - #[inline] - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + Some(self) } #[inline] @@ -1364,7 +1353,7 @@ impl R } #[inline] - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone_dynamic()) } @@ -1374,15 +1363,62 @@ impl R } #[inline] - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { + fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option { crate::array_partial_eq(self, value) } + + fn apply(&mut self, value: &dyn PartialReflect) { + crate::array_apply(self, value); + } + + #[inline] + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { + crate::array_try_apply(self, value) + } +} + +impl Reflect for [T; N] { + #[inline] + fn into_any(self: Box) -> Box { + self + } + + #[inline] + fn as_any(&self) -> &dyn Any { + self + } + + #[inline] + fn as_any_mut(&mut self) -> &mut dyn Any { + 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()?; + Ok(()) + } } impl FromReflect for [T; N] { - fn from_reflect(reflect: &dyn Reflect) -> Option { + fn from_reflect(reflect: &dyn PartialReflect) -> Option { if let ReflectRef::Array(ref_array) = reflect.reflect_ref() { let mut temp_vec = Vec::with_capacity(ref_array.len()); for field in ref_array.iter() { @@ -1469,52 +1505,34 @@ impl TypePath for &'static mut T { } } -impl Reflect for Cow<'static, str> { +impl PartialReflect for Cow<'static, str> { fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } - fn into_any(self: Box) -> Box { - self - } - - fn as_any(&self) -> &dyn Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn Any { + #[inline] + fn into_partial_reflect(self: Box) -> Box { self } - fn into_reflect(self: Box) -> Box { + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } - fn as_reflect(&self) -> &dyn Reflect { + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self + fn try_into_reflect(self: Box) -> Result, Box> { + Ok(self) } - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { - let any = value.as_any(); - if let Some(value) = any.downcast_ref::() { - self.clone_from(value); - } else { - return Err(ApplyError::MismatchedTypes { - from_type: value.reflect_type_path().into(), - // If we invoke the reflect_type_path on self directly the borrow checker complains that the lifetime of self must outlive 'static - to_type: Self::type_path().into(), - }); - } - Ok(()) + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + Some(self) } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + Some(self) } fn reflect_kind(&self) -> ReflectKind { @@ -1533,7 +1551,7 @@ impl Reflect for Cow<'static, str> { ReflectOwned::Value(self) } - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone()) } @@ -1544,9 +1562,8 @@ impl Reflect for Cow<'static, str> { Some(hasher.finish()) } - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { - let value = value.as_any(); - if let Some(value) = value.downcast_ref::() { + fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option { + if let Some(value) = value.try_downcast_ref::() { Some(std::cmp::PartialEq::eq(self, value)) } else { Some(false) @@ -1556,8 +1573,23 @@ impl Reflect for Cow<'static, str> { fn debug(&self, f: &mut fmt::Formatter<'_>) -> core::fmt::Result { fmt::Debug::fmt(self, f) } + + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { + if let Some(value) = value.try_downcast_ref::() { + self.clone_from(value); + } else { + return Err(ApplyError::MismatchedTypes { + from_type: value.reflect_type_path().into(), + // If we invoke the reflect_type_path on self directly the borrow checker complains that the lifetime of self must outlive 'static + to_type: Self::type_path().into(), + }); + } + Ok(()) + } } +impl_full_reflect!(for Cow<'static, str>); + impl Typed for Cow<'static, str> { fn type_info() -> &'static TypeInfo { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); @@ -1576,13 +1608,8 @@ impl GetTypeRegistration for Cow<'static, str> { } impl FromReflect for Cow<'static, str> { - fn from_reflect(reflect: &dyn crate::Reflect) -> Option { - Some( - reflect - .as_any() - .downcast_ref::>()? - .clone(), - ) + fn from_reflect(reflect: &dyn crate::PartialReflect) -> Option { + Some(reflect.try_downcast_ref::>()?.clone()) } } @@ -1607,31 +1634,31 @@ where impl List for Cow<'static, [T]> { - fn get(&self, index: usize) -> Option<&dyn Reflect> { - self.as_ref().get(index).map(|x| x as &dyn Reflect) + fn get(&self, index: usize) -> Option<&dyn PartialReflect> { + self.as_ref().get(index).map(|x| x as &dyn PartialReflect) } - fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> { - self.to_mut().get_mut(index).map(|x| x as &mut dyn Reflect) + fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> { + self.to_mut() + .get_mut(index) + .map(|x| x as &mut dyn PartialReflect) } - fn insert(&mut self, index: usize, element: Box) { - let value = element.take::().unwrap_or_else(|value| { - T::from_reflect(&*value).unwrap_or_else(|| { - panic!( - "Attempted to insert invalid value of type {}.", - value.reflect_type_path() - ) - }) + fn insert(&mut self, index: usize, element: Box) { + let value = T::take_from_reflect(element).unwrap_or_else(|value| { + panic!( + "Attempted to insert invalid value of type {}.", + value.reflect_type_path() + ); }); self.to_mut().insert(index, value); } - fn remove(&mut self, index: usize) -> Box { + fn remove(&mut self, index: usize) -> Box { Box::new(self.to_mut().remove(index)) } - fn push(&mut self, value: Box) { + fn push(&mut self, value: Box) { let value = T::take_from_reflect(value).unwrap_or_else(|value| { panic!( "Attempted to push invalid value of type {}.", @@ -1641,10 +1668,10 @@ impl List self.to_mut().push(value); } - fn pop(&mut self) -> Option> { + fn pop(&mut self) -> Option> { self.to_mut() .pop() - .map(|value| Box::new(value) as Box) + .map(|value| Box::new(value) as Box) } fn len(&self) -> usize { @@ -1655,7 +1682,7 @@ impl List ListIter::new(self) } - fn drain(self: Box) -> Vec> { + fn drain(self: Box) -> Vec> { // into_owned() is not unnecessary here because it avoids cloning whenever you have a Cow::Owned already #[allow(clippy::unnecessary_to_owned)] self.into_owned() @@ -1665,48 +1692,36 @@ impl List } } -impl Reflect +impl PartialReflect for Cow<'static, [T]> { fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } - 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 { + #[inline] + fn into_partial_reflect(self: Box) -> Box { self } - fn as_reflect(&self) -> &dyn Reflect { + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } - fn apply(&mut self, value: &dyn Reflect) { - crate::list_apply(self, value); + fn try_into_reflect(self: Box) -> Result, Box> { + Ok(self) } - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { - crate::list_try_apply(self, value) + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + Some(self) } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + Some(self) } fn reflect_kind(&self) -> ReflectKind { @@ -1725,7 +1740,7 @@ impl Refle ReflectOwned::List(self) } - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(List::clone_dynamic(self)) } @@ -1733,11 +1748,25 @@ impl Refle crate::list_hash(self) } - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { + fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option { crate::list_partial_eq(self, value) } + + fn apply(&mut self, value: &dyn PartialReflect) { + crate::list_apply(self, value); + } + + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { + crate::list_try_apply(self, value) + } } +impl_full_reflect!( + for Cow<'static, [T]> + where + T: FromReflect + Clone + MaybeTyped + TypePath + GetTypeRegistration, +); + impl Typed for Cow<'static, [T]> { @@ -1762,7 +1791,7 @@ impl GetTy impl FromReflect for Cow<'static, [T]> { - fn from_reflect(reflect: &dyn Reflect) -> Option { + fn from_reflect(reflect: &dyn PartialReflect) -> Option { if let ReflectRef::List(ref_list) = reflect.reflect_ref() { let mut temp_vec = Vec::with_capacity(ref_list.len()); for field in ref_list.iter() { @@ -1778,51 +1807,34 @@ impl FromR #[cfg(feature = "functions")] crate::func::macros::impl_function_traits!(Cow<'static, [T]>; ); -impl Reflect for &'static str { +impl PartialReflect for &'static str { fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } - fn into_any(self: Box) -> Box { - self - } - - fn as_any(&self) -> &dyn Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn Any { + #[inline] + fn into_partial_reflect(self: Box) -> Box { self } - fn into_reflect(self: Box) -> Box { + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } - fn as_reflect(&self) -> &dyn Reflect { + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self + fn try_into_reflect(self: Box) -> Result, Box> { + Ok(self) } - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { - let any = value.as_any(); - if let Some(&value) = any.downcast_ref::() { - *self = value; - } else { - return Err(ApplyError::MismatchedTypes { - from_type: value.reflect_type_path().into(), - to_type: Self::type_path().into(), - }); - } - Ok(()) + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + Some(self) } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + Some(self) } fn reflect_ref(&self) -> ReflectRef { @@ -1837,7 +1849,7 @@ impl Reflect for &'static str { ReflectOwned::Value(self) } - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(*self) } @@ -1848,9 +1860,8 @@ impl Reflect for &'static str { Some(hasher.finish()) } - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { - let value = value.as_any(); - if let Some(value) = value.downcast_ref::() { + fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option { + if let Some(value) = value.try_downcast_ref::() { Some(std::cmp::PartialEq::eq(self, value)) } else { Some(false) @@ -1860,6 +1871,49 @@ impl Reflect for &'static str { fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self, f) } + + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { + if let Some(value) = value.try_downcast_ref::() { + self.clone_from(value); + } else { + return Err(ApplyError::MismatchedTypes { + from_type: value.reflect_type_path().into(), + to_type: Self::type_path().into(), + }); + } + Ok(()) + } +} + +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 { @@ -1879,59 +1933,42 @@ impl GetTypeRegistration for &'static str { } impl FromReflect for &'static str { - fn from_reflect(reflect: &dyn crate::Reflect) -> Option { - reflect.as_any().downcast_ref::().copied() + fn from_reflect(reflect: &dyn PartialReflect) -> Option { + reflect.try_downcast_ref::().copied() } } #[cfg(feature = "functions")] crate::func::macros::impl_function_traits!(&'static str); -impl Reflect for &'static Path { +impl PartialReflect for &'static Path { fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } - fn into_any(self: Box) -> Box { - self - } - - fn as_any(&self) -> &dyn Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn Any { + #[inline] + fn into_partial_reflect(self: Box) -> Box { self } - fn into_reflect(self: Box) -> Box { + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } - fn as_reflect(&self) -> &dyn Reflect { + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self + fn try_into_reflect(self: Box) -> Result, Box> { + Ok(self) } - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { - let any = value.as_any(); - if let Some(&value) = any.downcast_ref::() { - *self = value; - Ok(()) - } else { - Err(ApplyError::MismatchedTypes { - from_type: value.reflect_type_path().into(), - to_type: ::reflect_type_path(self).into(), - }) - } + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + Some(self) } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + Some(self) } fn reflect_kind(&self) -> ReflectKind { @@ -1950,7 +1987,7 @@ impl Reflect for &'static Path { ReflectOwned::Value(self) } - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(*self) } @@ -1961,14 +1998,56 @@ impl Reflect for &'static Path { Some(hasher.finish()) } - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { - let value = value.as_any(); - if let Some(value) = value.downcast_ref::() { + fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option { + if let Some(value) = value.try_downcast_ref::() { Some(std::cmp::PartialEq::eq(self, value)) } else { Some(false) } } + + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { + if let Some(value) = value.try_downcast_ref::() { + self.clone_from(value); + Ok(()) + } else { + Err(ApplyError::MismatchedTypes { + from_type: value.reflect_type_path().into(), + to_type: ::reflect_type_path(self).into(), + }) + } + } +} + +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(()) + } } impl Typed for &'static Path { @@ -1987,59 +2066,42 @@ impl GetTypeRegistration for &'static Path { } impl FromReflect for &'static Path { - fn from_reflect(reflect: &dyn crate::Reflect) -> Option { - reflect.as_any().downcast_ref::().copied() + fn from_reflect(reflect: &dyn PartialReflect) -> Option { + reflect.try_downcast_ref::().copied() } } #[cfg(feature = "functions")] crate::func::macros::impl_function_traits!(&'static Path); -impl Reflect for Cow<'static, Path> { +impl PartialReflect for Cow<'static, Path> { fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } - fn into_any(self: Box) -> Box { - self - } - - fn as_any(&self) -> &dyn Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn Any { + #[inline] + fn into_partial_reflect(self: Box) -> Box { self } - fn into_reflect(self: Box) -> Box { + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } - fn as_reflect(&self) -> &dyn Reflect { + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self + fn try_into_reflect(self: Box) -> Result, Box> { + Ok(self) } - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { - let any = value.as_any(); - if let Some(value) = any.downcast_ref::() { - self.clone_from(value); - Ok(()) - } else { - Err(ApplyError::MismatchedTypes { - from_type: value.reflect_type_path().into(), - to_type: ::reflect_type_path(self).into(), - }) - } + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + Some(self) } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + Some(self) } fn reflect_kind(&self) -> ReflectKind { @@ -2058,7 +2120,7 @@ impl Reflect for Cow<'static, Path> { ReflectOwned::Value(self) } - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone()) } @@ -2069,9 +2131,8 @@ impl Reflect for Cow<'static, Path> { Some(hasher.finish()) } - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { - let value = value.as_any(); - if let Some(value) = value.downcast_ref::() { + fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option { + if let Some(value) = value.try_downcast_ref::() { Some(std::cmp::PartialEq::eq(self, value)) } else { Some(false) @@ -2081,6 +2142,49 @@ impl Reflect for Cow<'static, Path> { fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self, f) } + + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { + if let Some(value) = value.try_downcast_ref::() { + self.clone_from(value); + Ok(()) + } else { + Err(ApplyError::MismatchedTypes { + from_type: value.reflect_type_path().into(), + to_type: ::reflect_type_path(self).into(), + }) + } + } +} + +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(()) + } } impl Typed for Cow<'static, Path> { @@ -2094,8 +2198,8 @@ impl_type_path!(::std::path::Path); impl_type_path!(::alloc::borrow::Cow<'a: 'static, T: ToOwned + ?Sized>); impl FromReflect for Cow<'static, Path> { - fn from_reflect(reflect: &dyn Reflect) -> Option { - Some(reflect.as_any().downcast_ref::()?.clone()) + fn from_reflect(reflect: &dyn PartialReflect) -> Option { + Some(reflect.try_downcast_ref::()?.clone()) } } @@ -2115,7 +2219,7 @@ crate::func::macros::impl_function_traits!(Cow<'static, Path>); #[cfg(test)] mod tests { - use crate as bevy_reflect; + use crate::{self as bevy_reflect, PartialReflect}; use crate::{ Enum, FromReflect, Reflect, ReflectSerialize, TypeInfo, TypeRegistry, Typed, VariantInfo, VariantType, @@ -2140,45 +2244,45 @@ mod tests { #[test] fn should_partial_eq_char() { - let a: &dyn Reflect = &'x'; - let b: &dyn Reflect = &'x'; - let c: &dyn Reflect = &'o'; + let a: &dyn PartialReflect = &'x'; + let b: &dyn PartialReflect = &'x'; + let c: &dyn PartialReflect = &'o'; assert!(a.reflect_partial_eq(b).unwrap_or_default()); assert!(!a.reflect_partial_eq(c).unwrap_or_default()); } #[test] fn should_partial_eq_i32() { - let a: &dyn Reflect = &123_i32; - let b: &dyn Reflect = &123_i32; - let c: &dyn Reflect = &321_i32; + let a: &dyn PartialReflect = &123_i32; + let b: &dyn PartialReflect = &123_i32; + let c: &dyn PartialReflect = &321_i32; assert!(a.reflect_partial_eq(b).unwrap_or_default()); assert!(!a.reflect_partial_eq(c).unwrap_or_default()); } #[test] fn should_partial_eq_f32() { - let a: &dyn Reflect = &PI; - let b: &dyn Reflect = &PI; - let c: &dyn Reflect = &TAU; + let a: &dyn PartialReflect = &PI; + let b: &dyn PartialReflect = &PI; + let c: &dyn PartialReflect = &TAU; assert!(a.reflect_partial_eq(b).unwrap_or_default()); assert!(!a.reflect_partial_eq(c).unwrap_or_default()); } #[test] fn should_partial_eq_string() { - let a: &dyn Reflect = &String::from("Hello"); - let b: &dyn Reflect = &String::from("Hello"); - let c: &dyn Reflect = &String::from("World"); + let a: &dyn PartialReflect = &String::from("Hello"); + let b: &dyn PartialReflect = &String::from("Hello"); + let c: &dyn PartialReflect = &String::from("World"); assert!(a.reflect_partial_eq(b).unwrap_or_default()); assert!(!a.reflect_partial_eq(c).unwrap_or_default()); } #[test] fn should_partial_eq_vec() { - let a: &dyn Reflect = &vec![1, 2, 3]; - let b: &dyn Reflect = &vec![1, 2, 3]; - let c: &dyn Reflect = &vec![3, 2, 1]; + let a: &dyn PartialReflect = &vec![1, 2, 3]; + let b: &dyn PartialReflect = &vec![1, 2, 3]; + let c: &dyn PartialReflect = &vec![3, 2, 1]; assert!(a.reflect_partial_eq(b).unwrap_or_default()); assert!(!a.reflect_partial_eq(c).unwrap_or_default()); } @@ -2191,9 +2295,9 @@ mod tests { let mut c = HashMap::new(); c.insert(0usize, 3.21_f64); - let a: &dyn Reflect = &a; - let b: &dyn Reflect = &b; - let c: &dyn Reflect = &c; + let a: &dyn PartialReflect = &a; + let b: &dyn PartialReflect = &b; + let c: &dyn PartialReflect = &c; assert!(a.reflect_partial_eq(b).unwrap_or_default()); assert!(!a.reflect_partial_eq(c).unwrap_or_default()); } @@ -2209,14 +2313,18 @@ mod tests { let a: &dyn Reflect = &a; let b: &dyn Reflect = &b; let c: &dyn Reflect = &c; - assert!(a.reflect_partial_eq(b).unwrap_or_default()); - assert!(!a.reflect_partial_eq(c).unwrap_or_default()); + assert!(a + .reflect_partial_eq(b.as_partial_reflect()) + .unwrap_or_default()); + assert!(!a + .reflect_partial_eq(c.as_partial_reflect()) + .unwrap_or_default()); } #[test] fn should_partial_eq_option() { - let a: &dyn Reflect = &Some(123); - let b: &dyn Reflect = &Some(123); + let a: &dyn PartialReflect = &Some(123); + let b: &dyn PartialReflect = &Some(123); assert_eq!(Some(true), a.reflect_partial_eq(b)); } @@ -2239,7 +2347,7 @@ mod tests { if value.is_variant(VariantType::Tuple) { if let Some(field) = value .field_at_mut(0) - .and_then(|field| field.downcast_mut::()) + .and_then(|field| field.try_downcast_mut::()) { *field = 321; } @@ -2269,28 +2377,28 @@ mod tests { // === None on None === // let patch = None::; let mut value = None::; - Reflect::apply(&mut value, &patch); + PartialReflect::apply(&mut value, &patch); assert_eq!(patch, value, "None apply onto None"); // === Some on None === // let patch = Some(Foo(123)); let mut value = None::; - Reflect::apply(&mut value, &patch); + PartialReflect::apply(&mut value, &patch); assert_eq!(patch, value, "Some apply onto None"); // === None on Some === // let patch = None::; let mut value = Some(Foo(321)); - Reflect::apply(&mut value, &patch); + PartialReflect::apply(&mut value, &patch); assert_eq!(patch, value, "None apply onto Some"); // === Some on Some === // let patch = Some(Foo(123)); let mut value = Some(Foo(321)); - Reflect::apply(&mut value, &patch); + PartialReflect::apply(&mut value, &patch); assert_eq!(patch, value, "Some apply onto Some"); } @@ -2332,8 +2440,8 @@ mod tests { #[test] fn nonzero_usize_impl_reflect_from_reflect() { - let a: &dyn Reflect = &std::num::NonZeroUsize::new(42).unwrap(); - let b: &dyn Reflect = &std::num::NonZeroUsize::new(42).unwrap(); + let a: &dyn PartialReflect = &std::num::NonZeroUsize::new(42).unwrap(); + let b: &dyn PartialReflect = &std::num::NonZeroUsize::new(42).unwrap(); assert!(a.reflect_partial_eq(b).unwrap_or_default()); let forty_two: std::num::NonZeroUsize = crate::FromReflect::from_reflect(a).unwrap(); assert_eq!(forty_two, std::num::NonZeroUsize::new(42).unwrap()); diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 37957c098ad9e..1c5d9d12c6322 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -26,15 +26,60 @@ //! It's important to note that because of missing features in Rust, //! there are some [limitations] with this crate. //! -//! # The `Reflect` Trait +//! # The `Reflect` and `PartialReflect` traits //! -//! At the core of [`bevy_reflect`] is the [`Reflect`] trait. +//! At the root of [`bevy_reflect`] is the [`PartialReflect`] trait. //! -//! One of its primary purposes is to allow all implementors to be passed around -//! as a `dyn Reflect` trait object. -//! This allows any such type to be operated upon completely dynamically (at a small [runtime cost]). +//! Its purpose is to allow dynamic [introspection] of values, +//! following Rust's type system through a system of [subtraits]. //! -//! Implementing the trait is easily done using the provided [derive macro]: +//! Its primary purpose is to allow all implementors to be passed around +//! as a `dyn PartialReflect` trait object in one of the following forms: +//! * `&dyn PartialReflect` +//! * `&mut dyn PartialReflect` +//! * `Box` +//! +//! This allows values of types implementing `PartialReflect` +//! to be operated upon completely dynamically (at a small [runtime cost]). +//! +//! Building on `PartialReflect` is the [`Reflect`] trait. +//! +//! `PartialReflect` is a supertrait of `Reflect` +//! so any type implementing `Reflect` implements `PartialReflect` by definition. +//! `dyn Reflect` trait objects can be used similarly to `dyn PartialReflect`, +//! but `Reflect` is also often used in trait bounds (like `T: Reflect`). +//! +//! The distinction between `PartialReflect` and `Reflect` is summarised in the following: +//! * `PartialReflect` is a trait for interacting with values under `bevy_reflect`'s data model. +//! This means values implementing `PartialReflect` can be dynamically constructed and introspected. +//! * The `Reflect` trait, however, ensures that the interface exposed by `PartialReflect` +//! on types which additionally implement `Reflect` mirrors the structure of a single Rust type. +//! * This means `dyn Reflect` trait objects can be directly downcasted to concrete types, +//! where `dyn PartialReflect` trait object cannot. +//! * `Reflect`, since it provides a stronger type-correctness guarantee, +//! is the trait used to interact with [the type registry]. +//! +//! ## Converting between `PartialReflect` and `Reflect` +//! +//! 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` +//! +//! For conversion in the other direction — downcasting `dyn PartialReflect` to `dyn Reflect` — +//! there are fallible methods: +//! * [`PartialReflect::try_as_reflect`] for `&dyn Reflect` +//! * [`PartialReflect::try_as_reflect_mut`] for `&mut dyn Reflect` +//! * [`PartialReflect::try_into_reflect`] for `Box` +//! +//! Additionally, [`FromReflect::from_reflect`] can be used to convert a `dyn PartialReflect` to a concrete type +//! which implements `Reflect`. +//! +//! # Implementing `Reflect` +//! +//! Implementing `Reflect` (and `PartialReflect`) is easily done using the provided [derive macro]: //! //! ``` //! # use bevy_reflect::Reflect; @@ -54,8 +99,8 @@ //! ## Requirements //! //! We can implement `Reflect` on any type that satisfies _both_ of the following conditions: -//! * The type implements `Any`. -//! This is true if and only if the type itself has a [`'static` lifetime]. +//! * The type implements `Any`, `Send`, and `Sync`. +//! For the `Any` requirement to be satisfied, the type itself must have a [`'static` lifetime]. //! * All fields and sub-elements themselves implement `Reflect` //! (see the [derive macro documentation] for details on how to ignore certain fields when deriving). //! @@ -63,11 +108,11 @@ //! * All fields and sub-elements must implement [`FromReflect`]— //! another important reflection trait discussed in a later section. //! -//! # The `Reflect` Subtraits +//! # The Reflection Subtraits //! -//! Since [`Reflect`] is meant to cover any and every type, this crate also comes with a few -//! more traits to accompany `Reflect` and provide more specific interactions. -//! We refer to these traits as the _reflection subtraits_ since they all have `Reflect` as a supertrait. +//! Since [`PartialReflect`] is meant to cover any and every type, this crate also comes with a few +//! more traits to accompany `PartialReflect` and provide more specific interactions. +//! We refer to these traits as the _reflection subtraits_ since they all have `PartialReflect` as a supertrait. //! The current list of reflection subtraits include: //! * [`Tuple`] //! * [`Array`] @@ -83,7 +128,7 @@ //! For example, we can access our struct's fields by name using the [`Struct::field`] method. //! //! ``` -//! # use bevy_reflect::{Reflect, Struct}; +//! # use bevy_reflect::{PartialReflect, Reflect, Struct}; //! # #[derive(Reflect)] //! # struct MyStruct { //! # foo: i32 @@ -91,28 +136,29 @@ //! let my_struct: Box = Box::new(MyStruct { //! foo: 123 //! }); -//! let foo: &dyn Reflect = my_struct.field("foo").unwrap(); -//! assert_eq!(Some(&123), foo.downcast_ref::()); +//! let foo: &dyn PartialReflect = my_struct.field("foo").unwrap(); +//! assert_eq!(Some(&123), foo.try_downcast_ref::()); //! ``` //! -//! Since most data is passed around as `dyn Reflect`, -//! the `Reflect` trait has methods for going to and from these subtraits. +//! Since most data is passed around as `dyn PartialReflect` or `dyn Reflect` trait objects, +//! the `PartialReflect` trait has methods for going to and from these subtraits. //! -//! [`Reflect::reflect_kind`], [`Reflect::reflect_ref`], [`Reflect::reflect_mut`], and [`Reflect::reflect_owned`] all return +//! [`PartialReflect::reflect_kind`], [`PartialReflect::reflect_ref`], +//! [`PartialReflect::reflect_mut`], and [`PartialReflect::reflect_owned`] all return //! an enum that respectively contains zero-sized, immutable, mutable, and owned access to the type as a subtrait object. //! //! For example, we can get out a `dyn Tuple` from our reflected tuple type using one of these methods. //! //! ``` -//! # use bevy_reflect::{Reflect, ReflectRef}; -//! let my_tuple: Box = Box::new((1, 2, 3)); +//! # use bevy_reflect::{PartialReflect, ReflectRef}; +//! let my_tuple: Box = Box::new((1, 2, 3)); //! let ReflectRef::Tuple(my_tuple) = my_tuple.reflect_ref() else { unreachable!() }; //! assert_eq!(3, my_tuple.field_len()); //! ``` //! -//! And to go back to a general-purpose `dyn Reflect`, -//! we can just use the matching [`Reflect::as_reflect`], [`Reflect::as_reflect_mut`], -//! or [`Reflect::into_reflect`] methods. +//! 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. //! //! ## Value Types //! @@ -120,7 +166,7 @@ //! such as for primitives (e.g. `bool`, `usize`, etc.) //! and simple types (e.g. `String`, `Duration`), //! are referred to as _value_ types -//! since methods like [`Reflect::reflect_ref`] return a [`ReflectRef::Value`] variant. +//! since methods like [`PartialReflect::reflect_ref`] return a [`ReflectRef::Value`] variant. //! While most other types contain their own `dyn Reflect` fields and data, //! these types generally cannot be broken down any further. //! @@ -143,18 +189,18 @@ //! # use bevy_reflect::{DynamicStruct, Struct}; //! let mut data = DynamicStruct::default(); //! data.insert("foo", 123_i32); -//! assert_eq!(Some(&123), data.field("foo").unwrap().downcast_ref::()) +//! assert_eq!(Some(&123), data.field("foo").unwrap().try_downcast_ref::()) //! ``` //! //! They are most commonly used as "proxies" for other types, //! where they contain the same data as— and therefore, represent— a concrete type. -//! The [`Reflect::clone_value`] method will return a dynamic type for all non-value types, +//! The [`PartialReflect::clone_value`] method will return a dynamic type for all non-value types, //! allowing all types to essentially be "cloned". -//! And since dynamic types themselves implement [`Reflect`], -//! we may pass them around just like any other reflected type. +//! And since dynamic types themselves implement [`PartialReflect`], +//! we may pass them around just like most other reflected types. //! //! ``` -//! # use bevy_reflect::{DynamicStruct, Reflect}; +//! # use bevy_reflect::{DynamicStruct, PartialReflect, Reflect}; //! # #[derive(Reflect)] //! # struct MyStruct { //! # foo: i32 @@ -164,18 +210,17 @@ //! }); //! //! // `cloned` will be a `DynamicStruct` representing a `MyStruct` -//! let cloned: Box = original.clone_value(); +//! let cloned: Box = original.clone_value(); //! assert!(cloned.represents::()); -//! assert!(cloned.is::()); //! ``` //! //! ## Patching //! //! These dynamic types come in handy when needing to apply multiple changes to another type. -//! This is known as "patching" and is done using the [`Reflect::apply`] and [`Reflect::try_apply`] methods. +//! This is known as "patching" and is done using the [`PartialReflect::apply`] and [`PartialReflect::try_apply`] methods. //! //! ``` -//! # use bevy_reflect::{DynamicEnum, Reflect}; +//! # use bevy_reflect::{DynamicEnum, PartialReflect}; //! let mut value = Some(123_i32); //! let patch = DynamicEnum::new("None", ()); //! value.apply(&patch); @@ -189,7 +234,7 @@ //! or when trying to make use of a reflected trait which expects the actual type. //! //! ```should_panic -//! # use bevy_reflect::{DynamicStruct, Reflect}; +//! # use bevy_reflect::{DynamicStruct, PartialReflect, Reflect}; //! # #[derive(Reflect)] //! # struct MyStruct { //! # foo: i32 @@ -198,8 +243,8 @@ //! foo: 123 //! }); //! -//! let cloned: Box = original.clone_value(); -//! let value = cloned.take::().unwrap(); // PANIC! +//! let cloned: Box = original.clone_value(); +//! let value = cloned.try_take::().unwrap(); // PANIC! //! ``` //! //! To resolve this issue, we'll need to convert the dynamic type to the concrete one. @@ -214,7 +259,7 @@ //! using `#[reflect(from_reflect = false)]` on the item. //! //! ``` -//! # use bevy_reflect::{Reflect, FromReflect}; +//! # use bevy_reflect::{FromReflect, PartialReflect, Reflect}; //! #[derive(Reflect)] //! struct MyStruct { //! foo: i32 @@ -223,7 +268,7 @@ //! foo: 123 //! }); //! -//! let cloned: Box = original.clone_value(); +//! let cloned: Box = original.clone_value(); //! let value = ::from_reflect(&*cloned).unwrap(); // OK! //! ``` //! @@ -239,7 +284,7 @@ //! //! # Path navigation //! -//! The [`GetPath`] trait allows accessing arbitrary nested fields of a [`Reflect`] type. +//! The [`GetPath`] trait allows accessing arbitrary nested fields of an [`PartialReflect`] type. //! //! Using `GetPath`, it is possible to use a path string to access a specific field //! of a reflected type. @@ -306,7 +351,8 @@ //! ## Reflecting Traits //! //! Type data doesn't have to be tied to a trait, but it's often extremely useful to create trait type data. -//! These allow traits to be used directly on a `dyn Reflect` while utilizing the underlying type's implementation. +//! These allow traits to be used directly on a `dyn Reflect` (and not a `dyn PartialReflect`) +//! while utilizing the underlying type's implementation. //! //! For any [object-safe] trait, we can easily generate a corresponding `ReflectTrait` type for our trait //! using the [`#[reflect_trait]`](reflect_trait) macro. @@ -358,7 +404,7 @@ //! # use serde::de::DeserializeSeed; //! # use bevy_reflect::{ //! # serde::{ReflectSerializer, ReflectDeserializer}, -//! # Reflect, FromReflect, TypeRegistry +//! # Reflect, PartialReflect, FromReflect, TypeRegistry //! # }; //! #[derive(Reflect, PartialEq, Debug)] //! struct MyStruct { @@ -374,12 +420,12 @@ //! registry.register::(); //! //! // Serialize -//! let reflect_serializer = ReflectSerializer::new(&original_value, ®istry); +//! let reflect_serializer = ReflectSerializer::new(original_value.as_partial_reflect(), ®istry); //! let serialized_value: String = ron::to_string(&reflect_serializer).unwrap(); //! //! // Deserialize //! let reflect_deserializer = ReflectDeserializer::new(®istry); -//! let deserialized_value: Box = reflect_deserializer.deserialize( +//! let deserialized_value: Box = reflect_deserializer.deserialize( //! &mut ron::Deserializer::from_str(&serialized_value).unwrap() //! ).unwrap(); //! @@ -449,7 +495,11 @@ //! [Bevy]: https://bevyengine.org/ //! [limitations]: #limitations //! [`bevy_reflect`]: crate +//! [introspection]: https://en.wikipedia.org/wiki/Type_introspection +//! [subtraits]: #the-reflection-subtraits +//! [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 //! [derive macro]: derive@crate::Reflect //! [`'static` lifetime]: https://doc.rust-lang.org/rust-by-example/scope/lifetime/static_lifetime.html#trait-bound //! [derive macro documentation]: derive@crate::Reflect @@ -515,9 +565,9 @@ pub mod prelude { pub use crate::std_traits::*; #[doc(hidden)] pub use crate::{ - reflect_trait, FromReflect, GetField, GetPath, GetTupleStructField, Reflect, - ReflectDeserialize, ReflectFromReflect, ReflectPath, ReflectSerialize, Struct, TupleStruct, - TypePath, + reflect_trait, FromReflect, GetField, GetPath, GetTupleStructField, PartialReflect, + Reflect, ReflectDeserialize, ReflectFromReflect, ReflectPath, ReflectSerialize, Struct, + TupleStruct, TypePath, }; #[cfg(feature = "functions")] @@ -732,10 +782,19 @@ mod tests { let mut map = DynamicMap::default(); map.insert(key_a, 10u32); - assert_eq!(10, *map.get(&key_b).unwrap().downcast_ref::().unwrap()); + assert_eq!( + 10, + *map.get(&key_b).unwrap().try_downcast_ref::().unwrap() + ); assert!(map.get(&key_c).is_none()); - *map.get_mut(&key_b).unwrap().downcast_mut::().unwrap() = 20; - assert_eq!(20, *map.get(&key_b).unwrap().downcast_ref::().unwrap()); + *map.get_mut(&key_b) + .unwrap() + .try_downcast_mut::() + .unwrap() = 20; + assert_eq!( + 20, + *map.get(&key_b).unwrap().try_downcast_ref::().unwrap() + ); } #[test] @@ -751,16 +810,22 @@ mod tests { let mut patch = DynamicTupleStruct::default(); patch.insert(3u32); patch.insert(4u64); - assert_eq!(3, *patch.field(0).unwrap().downcast_ref::().unwrap()); - assert_eq!(4, *patch.field(1).unwrap().downcast_ref::().unwrap()); + assert_eq!( + 3, + *patch.field(0).unwrap().try_downcast_ref::().unwrap() + ); + assert_eq!( + 4, + *patch.field(1).unwrap().try_downcast_ref::().unwrap() + ); foo.apply(&patch); assert_eq!(3, foo.0); assert_eq!(4, foo.1); let mut iter = patch.iter_fields(); - assert_eq!(3, *iter.next().unwrap().downcast_ref::().unwrap()); - assert_eq!(4, *iter.next().unwrap().downcast_ref::().unwrap()); + assert_eq!(3, *iter.next().unwrap().try_downcast_ref::().unwrap()); + assert_eq!(4, *iter.next().unwrap().try_downcast_ref::().unwrap()); } #[test] @@ -831,7 +896,7 @@ mod tests { let values: Vec = foo .iter_fields() - .map(|value| *value.downcast_ref::().unwrap()) + .map(|value| *value.try_downcast_ref::().unwrap()) .collect(); assert_eq!(values, vec![1]); } @@ -863,11 +928,11 @@ mod tests { // Assert let expected = MyStruct { foo: 123 }; assert!(expected - .reflect_partial_eq(reflected.as_ref()) + .reflect_partial_eq(reflected.as_partial_reflect()) .unwrap_or_default()); let not_expected = MyStruct { foo: 321 }; assert!(!not_expected - .reflect_partial_eq(reflected.as_ref()) + .reflect_partial_eq(reflected.as_partial_reflect()) .unwrap_or_default()); } @@ -1314,9 +1379,9 @@ mod tests { let mut deserializer = Deserializer::from_str(&serialized).unwrap(); let reflect_deserializer = ReflectDeserializer::new(®istry); let value = reflect_deserializer.deserialize(&mut deserializer).unwrap(); - let dynamic_struct = value.take::().unwrap(); + let roundtrip_foo = Foo::from_reflect(value.as_partial_reflect()).unwrap(); - assert!(foo.reflect_partial_eq(&dynamic_struct).unwrap()); + assert!(foo.reflect_partial_eq(&roundtrip_foo).unwrap()); } #[test] @@ -2071,7 +2136,7 @@ bevy_reflect::tests::Test { } let foo = Foo(123); - let foo: &dyn Reflect = &foo; + let foo: &dyn PartialReflect = &foo; assert!(foo.reflect_hash().is_some()); assert_eq!(Some(true), foo.reflect_partial_eq(foo)); @@ -2092,7 +2157,7 @@ bevy_reflect::tests::Test { } let foo = Foo(123); - let foo: &dyn Reflect = &foo; + let foo: &dyn PartialReflect = &foo; assert!(foo.reflect_hash().is_some()); assert_eq!(Some(true), foo.reflect_partial_eq(foo)); @@ -2341,7 +2406,7 @@ bevy_reflect::tests::Test { } let mut map = HashMap::new(); map.insert(9, 10); - let mut test_struct = TestStruct { + let mut test_struct: DynamicStruct = TestStruct { tuple: (0, 1), list: vec![2, 3, 4], array: [5, 6, 7], @@ -2350,8 +2415,7 @@ bevy_reflect::tests::Test { map, value: 12, } - .clone_value(); - let test_struct = test_struct.downcast_mut::().unwrap(); + .clone_dynamic(); // test unknown DynamicStruct let mut test_unknown_struct = DynamicStruct::default(); @@ -2472,7 +2536,7 @@ bevy_reflect::tests::Test { let mut result = Quat::default(); - result.apply(&*dynamic_struct); + result.apply(dynamic_struct.as_partial_reflect()); assert_eq!(result, quat(1.0, 2.0, 3.0, 4.0)); } @@ -2529,7 +2593,7 @@ bevy_reflect::tests::Test { let mut result = Vec3::default(); - result.apply(&*dynamic_struct); + result.apply(dynamic_struct.as_partial_reflect()); assert_eq!(result, vec3(12.0, 3.0, -6.9)); } @@ -2550,13 +2614,16 @@ bevy_reflect::tests::Test { let mut v = vec3(1.0, 2.0, 3.0); assert_eq!( - *v.reflect_path("x").unwrap().downcast_ref::().unwrap(), + *v.reflect_path("x") + .unwrap() + .try_downcast_ref::() + .unwrap(), 1.0 ); *v.reflect_path_mut("y") .unwrap() - .downcast_mut::() + .try_downcast_mut::() .unwrap() = 6.0; assert_eq!(v.y, 6.0); diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index 6f0f7ee555337..3a29c5733e659 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -6,8 +6,8 @@ use bevy_reflect_derive::impl_type_path; use crate::utility::reflect_hasher; use crate::{ - self as bevy_reflect, ApplyError, FromReflect, MaybeTyped, Reflect, ReflectKind, ReflectMut, - ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable, + self as bevy_reflect, ApplyError, FromReflect, MaybeTyped, PartialReflect, Reflect, + ReflectKind, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable, }; /// A trait used to power [list-like] operations via [reflection]. @@ -35,46 +35,46 @@ use crate::{ /// # Example /// /// ``` -/// use bevy_reflect::{Reflect, List}; +/// use bevy_reflect::{PartialReflect, Reflect, List}; /// /// let foo: &mut dyn List = &mut vec![123_u32, 456_u32, 789_u32]; /// assert_eq!(foo.len(), 3); /// -/// let last_field: Box = foo.pop().unwrap(); -/// assert_eq!(last_field.downcast_ref::(), Some(&789)); +/// let last_field: Box = foo.pop().unwrap(); +/// assert_eq!(last_field.try_downcast_ref::(), Some(&789)); /// ``` /// /// [list-like]: https://doc.rust-lang.org/book/ch08-01-vectors.html /// [reflection]: crate /// [type-erasing]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html -pub trait List: Reflect { +pub trait List: PartialReflect { /// Returns a reference to the element at `index`, or `None` if out of bounds. - fn get(&self, index: usize) -> Option<&dyn Reflect>; + fn get(&self, index: usize) -> Option<&dyn PartialReflect>; /// Returns a mutable reference to the element at `index`, or `None` if out of bounds. - fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>; + fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>; /// Inserts an element at position `index` within the list, /// shifting all elements after it towards the back of the list. /// /// # Panics /// Panics if `index > len`. - fn insert(&mut self, index: usize, element: Box); + fn insert(&mut self, index: usize, element: Box); /// Removes and returns the element at position `index` within the list, /// shifting all elements before it towards the front of the list. /// /// # Panics /// Panics if `index` is out of bounds. - fn remove(&mut self, index: usize) -> Box; + fn remove(&mut self, index: usize) -> Box; /// Appends an element to the _back_ of the list. - fn push(&mut self, value: Box) { + fn push(&mut self, value: Box) { self.insert(self.len(), value); } /// Removes the _back_ element from the list and returns it, or [`None`] if it is empty. - fn pop(&mut self) -> Option> { + fn pop(&mut self) -> Option> { if self.is_empty() { None } else { @@ -94,13 +94,13 @@ pub trait List: Reflect { fn iter(&self) -> ListIter; /// Drain the elements of this list to get a vector of owned values. - fn drain(self: Box) -> Vec>; + fn drain(self: Box) -> Vec>; /// Clones the list, producing a [`DynamicList`]. fn clone_dynamic(&self) -> DynamicList { DynamicList { represented_type: self.get_represented_type_info(), - values: self.iter().map(Reflect::clone_value).collect(), + values: self.iter().map(PartialReflect::clone_value).collect(), } } } @@ -200,7 +200,7 @@ impl ListInfo { #[derive(Default)] pub struct DynamicList { represented_type: Option<&'static TypeInfo>, - values: Vec>, + values: Vec>, } impl DynamicList { @@ -223,38 +223,38 @@ impl DynamicList { } /// Appends a typed value to the list. - pub fn push(&mut self, value: T) { + pub fn push(&mut self, value: T) { self.values.push(Box::new(value)); } /// Appends a [`Reflect`] trait object to the list. - pub fn push_box(&mut self, value: Box) { + pub fn push_box(&mut self, value: Box) { self.values.push(value); } } impl List for DynamicList { - fn get(&self, index: usize) -> Option<&dyn Reflect> { + fn get(&self, index: usize) -> Option<&dyn PartialReflect> { self.values.get(index).map(|value| &**value) } - fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> { + fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> { self.values.get_mut(index).map(|value| &mut **value) } - fn insert(&mut self, index: usize, element: Box) { + fn insert(&mut self, index: usize, element: Box) { self.values.insert(index, element); } - fn remove(&mut self, index: usize) -> Box { + fn remove(&mut self, index: usize) -> Box { self.values.remove(index) } - fn push(&mut self, value: Box) { + fn push(&mut self, value: Box) { DynamicList::push_box(self, value); } - fn pop(&mut self) -> Option> { + fn pop(&mut self) -> Option> { self.values.pop() } @@ -266,7 +266,7 @@ impl List for DynamicList { ListIter::new(self) } - fn drain(self: Box) -> Vec> { + fn drain(self: Box) -> Vec> { self.values } @@ -282,56 +282,47 @@ impl List for DynamicList { } } -impl Reflect for DynamicList { +impl PartialReflect for DynamicList { #[inline] fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } #[inline] - fn into_any(self: Box) -> Box { + fn into_partial_reflect(self: Box) -> Box { self } #[inline] - fn as_any(&self) -> &dyn Any { + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } #[inline] - fn as_any_mut(&mut self) -> &mut dyn Any { + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } - #[inline] - fn into_reflect(self: Box) -> Box { - self + fn try_into_reflect(self: Box) -> Result, Box> { + Err(self) } - #[inline] - fn as_reflect(&self) -> &dyn Reflect { - self + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + None } - #[inline] - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + None } - fn apply(&mut self, value: &dyn Reflect) { + fn apply(&mut self, value: &dyn PartialReflect) { list_apply(self, value); } - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { list_try_apply(self, value) } - #[inline] - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - #[inline] fn reflect_kind(&self) -> ReflectKind { ReflectKind::List @@ -353,7 +344,7 @@ impl Reflect for DynamicList { } #[inline] - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone_dynamic()) } @@ -362,7 +353,7 @@ impl Reflect for DynamicList { list_hash(self) } - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { + fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option { list_partial_eq(self, value) } @@ -379,8 +370,6 @@ impl Reflect for DynamicList { } impl_type_path!((in bevy_reflect) DynamicList); -#[cfg(feature = "functions")] -crate::func::macros::impl_function_traits!(DynamicList); impl Debug for DynamicList { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { @@ -388,8 +377,8 @@ impl Debug for DynamicList { } } -impl FromIterator> for DynamicList { - fn from_iter>>(values: I) -> Self { +impl FromIterator> for DynamicList { + fn from_iter>>(values: I) -> Self { Self { represented_type: None, values: values.into_iter().collect(), @@ -397,17 +386,17 @@ impl FromIterator> for DynamicList { } } -impl FromIterator for DynamicList { +impl FromIterator for DynamicList { fn from_iter>(values: I) -> Self { values .into_iter() - .map(|field| Box::new(field).into_reflect()) + .map(|field| Box::new(field).into_partial_reflect()) .collect() } } impl IntoIterator for DynamicList { - type Item = Box; + type Item = Box; type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { @@ -416,7 +405,7 @@ impl IntoIterator for DynamicList { } impl<'a> IntoIterator for &'a DynamicList { - type Item = &'a dyn Reflect; + type Item = &'a dyn PartialReflect; type IntoIter = ListIter<'a>; fn into_iter(self) -> Self::IntoIter { @@ -439,7 +428,7 @@ impl<'a> ListIter<'a> { } impl<'a> Iterator for ListIter<'a> { - type Item = &'a dyn Reflect; + type Item = &'a dyn PartialReflect; #[inline] fn next(&mut self) -> Option { @@ -478,7 +467,7 @@ pub fn list_hash(list: &L) -> Option { /// /// This function panics if `b` is not a list. #[inline] -pub fn list_apply(a: &mut L, b: &dyn Reflect) { +pub fn list_apply(a: &mut L, b: &dyn PartialReflect) { if let Err(err) = list_try_apply(a, b) { panic!("{err}"); } @@ -495,7 +484,7 @@ pub fn list_apply(a: &mut L, b: &dyn Reflect) { /// This function returns an [`ApplyError::MismatchedKinds`] if `b` is not a list or if /// applying elements to each other fails. #[inline] -pub fn list_try_apply(a: &mut L, b: &dyn Reflect) -> Result<(), ApplyError> { +pub fn list_try_apply(a: &mut L, b: &dyn PartialReflect) -> Result<(), ApplyError> { if let ReflectRef::List(list_value) = b.reflect_ref() { for (i, value) in list_value.iter().enumerate() { if i < a.len() { @@ -520,11 +509,11 @@ pub fn list_try_apply(a: &mut L, b: &dyn Reflect) -> Result<(), ApplyEr /// Returns true if and only if all of the following are true: /// - `b` is a list; /// - `b` is the same length as `a`; -/// - [`Reflect::reflect_partial_eq`] returns `Some(true)` for pairwise elements of `a` and `b`. +/// - [`PartialReflect::reflect_partial_eq`] returns `Some(true)` for pairwise elements of `a` and `b`. /// /// Returns [`None`] if the comparison couldn't even be performed. #[inline] -pub fn list_partial_eq(a: &L, b: &dyn Reflect) -> Option { +pub fn list_partial_eq(a: &L, b: &dyn PartialReflect) -> Option { let ReflectRef::List(list) = b.reflect_ref() else { return Some(false); }; @@ -583,7 +572,9 @@ mod tests { list.push(2usize); let items = list.into_iter(); for (index, item) in items.into_iter().enumerate() { - let value = item.take::().expect("couldn't downcast to usize"); + let value = item + .try_take::() + .expect("couldn't downcast to usize"); assert_eq!(index, value); } } diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index 04102f65bce3f..b619a091eff2c 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -5,8 +5,8 @@ use bevy_reflect_derive::impl_type_path; use bevy_utils::{Entry, HashMap}; use crate::{ - self as bevy_reflect, ApplyError, MaybeTyped, Reflect, ReflectKind, ReflectMut, ReflectOwned, - ReflectRef, TypeInfo, TypePath, TypePathTable, + self as bevy_reflect, ApplyError, MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut, + ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable, }; /// A trait used to power [map-like] operations via [reflection]. @@ -17,7 +17,7 @@ use crate::{ /// /// # Hashing /// -/// All keys are expected to return a valid hash value from [`Reflect::reflect_hash`]. +/// All keys are expected to return a valid hash value from [`PartialReflect::reflect_hash`]. /// If using the [`#[derive(Reflect)]`](derive@crate::Reflect) macro, this can be done by adding `#[reflect(Hash)]` /// to the entire struct or enum. /// This is true even for manual implementors who do not use the hashed value, @@ -26,7 +26,7 @@ use crate::{ /// # Example /// /// ``` -/// use bevy_reflect::{Reflect, Map}; +/// use bevy_reflect::{PartialReflect, Reflect, Map}; /// use bevy_utils::HashMap; /// /// @@ -34,28 +34,31 @@ use crate::{ /// foo.insert_boxed(Box::new(123_u32), Box::new(true)); /// assert_eq!(foo.len(), 1); /// -/// let field: &dyn Reflect = foo.get(&123_u32).unwrap(); -/// assert_eq!(field.downcast_ref::(), Some(&true)); +/// let field: &dyn PartialReflect = foo.get(&123_u32).unwrap(); +/// assert_eq!(field.try_downcast_ref::(), Some(&true)); /// ``` /// /// [map-like]: https://doc.rust-lang.org/book/ch08-03-hash-maps.html /// [reflection]: crate -pub trait Map: Reflect { +pub trait Map: PartialReflect { /// Returns a reference to the value associated with the given key. /// /// If no value is associated with `key`, returns `None`. - fn get(&self, key: &dyn Reflect) -> Option<&dyn Reflect>; + fn get(&self, key: &dyn PartialReflect) -> Option<&dyn PartialReflect>; /// Returns a mutable reference to the value associated with the given key. /// /// If no value is associated with `key`, returns `None`. - fn get_mut(&mut self, key: &dyn Reflect) -> Option<&mut dyn Reflect>; + fn get_mut(&mut self, key: &dyn PartialReflect) -> Option<&mut dyn PartialReflect>; /// Returns the key-value pair at `index` by reference, or `None` if out of bounds. - fn get_at(&self, index: usize) -> Option<(&dyn Reflect, &dyn Reflect)>; + fn get_at(&self, index: usize) -> Option<(&dyn PartialReflect, &dyn PartialReflect)>; /// Returns the key-value pair at `index` by reference where the value is a mutable reference, or `None` if out of bounds. - fn get_at_mut(&mut self, index: usize) -> Option<(&dyn Reflect, &mut dyn Reflect)>; + fn get_at_mut( + &mut self, + index: usize, + ) -> Option<(&dyn PartialReflect, &mut dyn PartialReflect)>; /// Returns the number of elements in the map. fn len(&self) -> usize; @@ -69,7 +72,7 @@ pub trait Map: Reflect { fn iter(&self) -> MapIter; /// Drain the key-value pairs of this map to get a vector of owned values. - fn drain(self: Box) -> Vec<(Box, Box)>; + fn drain(self: Box) -> Vec<(Box, Box)>; /// Clones the map, producing a [`DynamicMap`]. fn clone_dynamic(&self) -> DynamicMap; @@ -80,15 +83,15 @@ pub trait Map: Reflect { /// If the map did have this key present, the value is updated, and the old value is returned. fn insert_boxed( &mut self, - key: Box, - value: Box, - ) -> Option>; + key: Box, + value: Box, + ) -> Option>; /// Removes an entry from the map. /// /// If the map did not have this key present, `None` is returned. /// If the map did have this key present, the removed value is returned. - fn remove(&mut self, key: &dyn Reflect) -> Option>; + fn remove(&mut self, key: &dyn PartialReflect) -> Option>; } /// A container for compile-time map info. @@ -246,7 +249,7 @@ macro_rules! hash_error { #[derive(Default)] pub struct DynamicMap { represented_type: Option<&'static TypeInfo>, - values: Vec<(Box, Box)>, + values: Vec<(Box, Box)>, indices: HashMap, } @@ -271,32 +274,35 @@ impl DynamicMap { } /// Inserts a typed key-value pair into the map. - pub fn insert(&mut self, key: K, value: V) { + pub fn insert(&mut self, key: K, value: V) { self.insert_boxed(Box::new(key), Box::new(value)); } } impl Map for DynamicMap { - fn get(&self, key: &dyn Reflect) -> Option<&dyn Reflect> { + fn get(&self, key: &dyn PartialReflect) -> Option<&dyn PartialReflect> { self.indices .get(&key.reflect_hash().expect(hash_error!(key))) .map(|index| &*self.values.get(*index).unwrap().1) } - fn get_mut(&mut self, key: &dyn Reflect) -> Option<&mut dyn Reflect> { + fn get_mut(&mut self, key: &dyn PartialReflect) -> Option<&mut dyn PartialReflect> { self.indices .get(&key.reflect_hash().expect(hash_error!(key))) .cloned() .map(move |index| &mut *self.values.get_mut(index).unwrap().1) } - fn get_at(&self, index: usize) -> Option<(&dyn Reflect, &dyn Reflect)> { + fn get_at(&self, index: usize) -> Option<(&dyn PartialReflect, &dyn PartialReflect)> { self.values .get(index) .map(|(key, value)| (&**key, &**value)) } - fn get_at_mut(&mut self, index: usize) -> Option<(&dyn Reflect, &mut dyn Reflect)> { + fn get_at_mut( + &mut self, + index: usize, + ) -> Option<(&dyn PartialReflect, &mut dyn PartialReflect)> { self.values .get_mut(index) .map(|(key, value)| (&**key, &mut **value)) @@ -310,7 +316,7 @@ impl Map for DynamicMap { MapIter::new(self) } - fn drain(self: Box) -> Vec<(Box, Box)> { + fn drain(self: Box) -> Vec<(Box, Box)> { self.values } @@ -328,9 +334,9 @@ impl Map for DynamicMap { fn insert_boxed( &mut self, - key: Box, - mut value: Box, - ) -> Option> { + key: Box, + mut value: Box, + ) -> Option> { match self .indices .entry(key.reflect_hash().expect(hash_error!(key))) @@ -348,7 +354,7 @@ impl Map for DynamicMap { } } - fn remove(&mut self, key: &dyn Reflect) -> Option> { + fn remove(&mut self, key: &dyn PartialReflect) -> Option> { let index = self .indices .remove(&key.reflect_hash().expect(hash_error!(key)))?; @@ -357,52 +363,47 @@ impl Map for DynamicMap { } } -impl Reflect for DynamicMap { +impl PartialReflect for DynamicMap { #[inline] fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } - fn into_any(self: Box) -> Box { + #[inline] + fn into_partial_reflect(self: Box) -> Box { self } - fn as_any(&self) -> &dyn Any { + #[inline] + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } - fn as_any_mut(&mut self) -> &mut dyn Any { + #[inline] + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } - #[inline] - fn into_reflect(self: Box) -> Box { - self + fn try_into_reflect(self: Box) -> Result, Box> { + Err(self) } - #[inline] - fn as_reflect(&self) -> &dyn Reflect { - self + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + None } - #[inline] - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + None } - fn apply(&mut self, value: &dyn Reflect) { + fn apply(&mut self, value: &dyn PartialReflect) { map_apply(self, value); } - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { map_try_apply(self, value) } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - fn reflect_kind(&self) -> ReflectKind { ReflectKind::Map } @@ -419,11 +420,11 @@ impl Reflect for DynamicMap { ReflectOwned::Map(self) } - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone_dynamic()) } - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { + fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option { map_partial_eq(self, value) } @@ -440,8 +441,6 @@ impl Reflect for DynamicMap { } impl_type_path!((in bevy_reflect) DynamicMap); -#[cfg(feature = "functions")] -crate::func::macros::impl_function_traits!(DynamicMap); impl Debug for DynamicMap { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { @@ -464,7 +463,7 @@ impl<'a> MapIter<'a> { } impl<'a> Iterator for MapIter<'a> { - type Item = (&'a dyn Reflect, &'a dyn Reflect); + type Item = (&'a dyn PartialReflect, &'a dyn PartialReflect); fn next(&mut self) -> Option { let value = self.map.get_at(self.index); @@ -478,8 +477,10 @@ impl<'a> Iterator for MapIter<'a> { } } -impl FromIterator<(Box, Box)> for DynamicMap { - fn from_iter, Box)>>(items: I) -> Self { +impl FromIterator<(Box, Box)> for DynamicMap { + fn from_iter, Box)>>( + items: I, + ) -> Self { let mut map = Self::default(); for (key, value) in items.into_iter() { map.insert_boxed(key, value); @@ -499,7 +500,7 @@ impl FromIterator<(K, V)> for DynamicMap { } impl IntoIterator for DynamicMap { - type Item = (Box, Box); + type Item = (Box, Box); type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { @@ -508,7 +509,7 @@ impl IntoIterator for DynamicMap { } impl<'a> IntoIterator for &'a DynamicMap { - type Item = (&'a dyn Reflect, &'a dyn Reflect); + type Item = (&'a dyn PartialReflect, &'a dyn PartialReflect); type IntoIter = MapIter<'a>; fn into_iter(self) -> Self::IntoIter { @@ -518,17 +519,17 @@ impl<'a> IntoIterator for &'a DynamicMap { impl<'a> ExactSizeIterator for MapIter<'a> {} -/// Compares a [`Map`] with a [`Reflect`] value. +/// Compares a [`Map`] with a [`PartialReflect`] value. /// /// Returns true if and only if all of the following are true: /// - `b` is a map; /// - `b` is the same length as `a`; /// - For each key-value pair in `a`, `b` contains a value for the given key, -/// and [`Reflect::reflect_partial_eq`] returns `Some(true)` for the two values. +/// and [`PartialReflect::reflect_partial_eq`] returns `Some(true)` for the two values. /// /// Returns [`None`] if the comparison couldn't even be performed. #[inline] -pub fn map_partial_eq(a: &M, b: &dyn Reflect) -> Option { +pub fn map_partial_eq(a: &M, b: &dyn PartialReflect) -> Option { let ReflectRef::Map(map) = b.reflect_ref() else { return Some(false); }; @@ -585,7 +586,7 @@ pub fn map_debug(dyn_map: &dyn Map, f: &mut Formatter<'_>) -> std::fmt::Result { /// /// This function panics if `b` is not a reflected map. #[inline] -pub fn map_apply(a: &mut M, b: &dyn Reflect) { +pub fn map_apply(a: &mut M, b: &dyn PartialReflect) { if let Err(err) = map_try_apply(a, b) { panic!("{err}"); } @@ -601,7 +602,7 @@ pub fn map_apply(a: &mut M, b: &dyn Reflect) { /// This function returns an [`ApplyError::MismatchedKinds`] if `b` is not a reflected map or if /// applying elements to each other fails. #[inline] -pub fn map_try_apply(a: &mut M, b: &dyn Reflect) -> Result<(), ApplyError> { +pub fn map_try_apply(a: &mut M, b: &dyn PartialReflect) -> Result<(), ApplyError> { if let ReflectRef::Map(map_value) = b.reflect_ref() { for (key, b_value) in map_value.iter() { if let Some(a_value) = a.get_mut(key) { @@ -623,7 +624,6 @@ pub fn map_try_apply(a: &mut M, b: &dyn Reflect) -> Result<(), ApplyErro mod tests { use super::DynamicMap; use super::Map; - use crate::reflect::Reflect; #[test] fn test_into_iter() { @@ -635,10 +635,13 @@ mod tests { map.insert(2usize, expected[2].to_string()); for (index, item) in map.into_iter().enumerate() { - let key = item.0.take::().expect("couldn't downcast to usize"); + let key = item + .0 + .try_take::() + .expect("couldn't downcast to usize"); let value = item .1 - .take::() + .try_take::() .expect("couldn't downcast to String"); assert_eq!(index, key); assert_eq!(expected[index], value); @@ -655,16 +658,16 @@ mod tests { let (key_r, value_r) = map.get_at(1).expect("Item wasn't found"); let value = value_r - .downcast_ref::() + .try_downcast_ref::() .expect("Couldn't downcast to String"); let key = key_r - .downcast_ref::() + .try_downcast_ref::() .expect("Couldn't downcast to usize"); assert_eq!(key, &1usize); assert_eq!(value, &values[2].to_owned()); assert!(map.get_at(2).is_none()); - map.remove(&1usize as &dyn Reflect); + map.remove(&1usize); assert!(map.get_at(1).is_none()); } @@ -678,10 +681,10 @@ mod tests { let (key_r, value_r) = map.get_at_mut(1).expect("Item wasn't found"); let value = value_r - .downcast_mut::() + .try_downcast_mut::() .expect("Couldn't downcast to String"); let key = key_r - .downcast_ref::() + .try_downcast_ref::() .expect("Couldn't downcast to usize"); assert_eq!(key, &1usize); assert_eq!(value, &mut values[2].to_owned()); @@ -689,9 +692,9 @@ mod tests { value.clone_from(&values[0].to_owned()); assert_eq!( - map.get(&1usize as &dyn Reflect) + map.get(&1usize) .expect("Item wasn't found") - .downcast_ref::() + .try_downcast_ref::() .expect("Couldn't downcast to String"), &values[0].to_owned() ); diff --git a/crates/bevy_reflect/src/path/access.rs b/crates/bevy_reflect/src/path/access.rs index ebeeade160808..4648b9dfa6349 100644 --- a/crates/bevy_reflect/src/path/access.rs +++ b/crates/bevy_reflect/src/path/access.rs @@ -3,14 +3,14 @@ use std::{borrow::Cow, fmt}; use super::error::AccessErrorKind; -use crate::{AccessError, Reflect, ReflectKind, ReflectMut, ReflectRef, VariantType}; +use crate::{AccessError, PartialReflect, ReflectKind, ReflectMut, ReflectRef, VariantType}; type InnerResult = Result; /// A singular element access within a path. /// Multiple accesses can be combined into a [`ParsedPath`](super::ParsedPath). /// -/// Can be applied to a [`dyn Reflect`](Reflect) to get a reference to the targeted element. +/// Can be applied to a [`dyn Reflect`](crate::Reflect) to get a reference to the targeted element. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum Access<'a> { /// A name-based field access on a struct. @@ -51,15 +51,18 @@ impl<'a> Access<'a> { pub(super) fn element<'r>( &self, - base: &'r dyn Reflect, + base: &'r dyn PartialReflect, offset: Option, - ) -> Result<&'r dyn Reflect, AccessError<'a>> { + ) -> Result<&'r dyn PartialReflect, AccessError<'a>> { self.element_inner(base) .and_then(|opt| opt.ok_or(AccessErrorKind::MissingField(base.reflect_kind()))) .map_err(|err| err.with_access(self.clone(), offset)) } - fn element_inner<'r>(&self, base: &'r dyn Reflect) -> InnerResult> { + fn element_inner<'r>( + &self, + base: &'r dyn PartialReflect, + ) -> InnerResult> { use ReflectRef::*; let invalid_variant = @@ -105,9 +108,9 @@ impl<'a> Access<'a> { pub(super) fn element_mut<'r>( &self, - base: &'r mut dyn Reflect, + base: &'r mut dyn PartialReflect, offset: Option, - ) -> Result<&'r mut dyn Reflect, AccessError<'a>> { + ) -> Result<&'r mut dyn PartialReflect, AccessError<'a>> { let kind = base.reflect_kind(); self.element_inner_mut(base) @@ -117,8 +120,8 @@ impl<'a> Access<'a> { fn element_inner_mut<'r>( &self, - base: &'r mut dyn Reflect, - ) -> InnerResult> { + base: &'r mut dyn PartialReflect, + ) -> InnerResult> { use ReflectMut::*; let invalid_variant = diff --git a/crates/bevy_reflect/src/path/mod.rs b/crates/bevy_reflect/src/path/mod.rs index 6a38faad59595..c3d8ccfa2de21 100644 --- a/crates/bevy_reflect/src/path/mod.rs +++ b/crates/bevy_reflect/src/path/mod.rs @@ -8,7 +8,7 @@ mod parse; pub use parse::ParseError; use parse::PathParser; -use crate::Reflect; +use crate::{PartialReflect, Reflect}; use std::fmt; use thiserror::Error; @@ -49,19 +49,22 @@ pub trait ReflectPath<'a>: Sized { /// /// See [`GetPath::reflect_path`] for more details, /// see [`element`](Self::element) if you want a typed return value. - fn reflect_element(self, root: &dyn Reflect) -> PathResult<'a, &dyn Reflect>; + fn reflect_element(self, root: &dyn PartialReflect) -> PathResult<'a, &dyn PartialReflect>; /// Gets a mutable reference to the specified element on the given [`Reflect`] object. /// /// See [`GetPath::reflect_path_mut`] for more details. - fn reflect_element_mut(self, root: &mut dyn Reflect) -> PathResult<'a, &mut dyn Reflect>; + fn reflect_element_mut( + self, + root: &mut dyn PartialReflect, + ) -> PathResult<'a, &mut dyn PartialReflect>; /// Gets a `&T` to the specified element on the given [`Reflect`] object. /// /// See [`GetPath::path`] for more details. - fn element(self, root: &dyn Reflect) -> PathResult<'a, &T> { + fn element(self, root: &dyn PartialReflect) -> PathResult<'a, &T> { self.reflect_element(root).and_then(|p| { - p.downcast_ref::() + p.try_downcast_ref::() .ok_or(ReflectPathError::InvalidDowncast) }) } @@ -69,22 +72,25 @@ pub trait ReflectPath<'a>: Sized { /// Gets a `&mut T` to the specified element on the given [`Reflect`] object. /// /// See [`GetPath::path_mut`] for more details. - fn element_mut(self, root: &mut dyn Reflect) -> PathResult<'a, &mut T> { + fn element_mut(self, root: &mut dyn PartialReflect) -> PathResult<'a, &mut T> { self.reflect_element_mut(root).and_then(|p| { - p.downcast_mut::() + p.try_downcast_mut::() .ok_or(ReflectPathError::InvalidDowncast) }) } } impl<'a> ReflectPath<'a> for &'a str { - fn reflect_element(self, mut root: &dyn Reflect) -> PathResult<'a, &dyn Reflect> { + fn reflect_element(self, mut root: &dyn PartialReflect) -> PathResult<'a, &dyn PartialReflect> { for (access, offset) in PathParser::new(self) { let a = access?; root = a.element(root, Some(offset))?; } Ok(root) } - fn reflect_element_mut(self, mut root: &mut dyn Reflect) -> PathResult<'a, &mut dyn Reflect> { + fn reflect_element_mut( + self, + mut root: &mut dyn PartialReflect, + ) -> PathResult<'a, &mut dyn PartialReflect> { for (access, offset) in PathParser::new(self) { root = access?.element_mut(root, Some(offset))?; } @@ -234,13 +240,13 @@ impl<'a> ReflectPath<'a> for &'a str { message = "`{Self}` does not provide a reflection path", note = "consider annotating `{Self}` with `#[derive(Reflect)]`" )] -pub trait GetPath: Reflect { +pub trait GetPath: PartialReflect { /// Returns a reference to the value specified by `path`. /// /// To retrieve a statically typed reference, use /// [`path`][GetPath::path]. - fn reflect_path<'p>(&self, path: impl ReflectPath<'p>) -> PathResult<'p, &dyn Reflect> { - path.reflect_element(self.as_reflect()) + fn reflect_path<'p>(&self, path: impl ReflectPath<'p>) -> PathResult<'p, &dyn PartialReflect> { + path.reflect_element(self.as_partial_reflect()) } /// Returns a mutable reference to the value specified by `path`. @@ -250,8 +256,8 @@ pub trait GetPath: Reflect { fn reflect_path_mut<'p>( &mut self, path: impl ReflectPath<'p>, - ) -> PathResult<'p, &mut dyn Reflect> { - path.reflect_element_mut(self.as_reflect_mut()) + ) -> PathResult<'p, &mut dyn PartialReflect> { + path.reflect_element_mut(self.as_partial_reflect_mut()) } /// Returns a statically typed reference to the value specified by `path`. @@ -262,7 +268,7 @@ pub trait GetPath: Reflect { /// /// [`DynamicStruct`]: crate::DynamicStruct fn path<'p, T: Reflect>(&self, path: impl ReflectPath<'p>) -> PathResult<'p, &T> { - path.element(self.as_reflect()) + path.element(self.as_partial_reflect()) } /// Returns a statically typed mutable reference to the value specified by `path`. @@ -273,7 +279,7 @@ pub trait GetPath: Reflect { /// /// [`DynamicStruct`]: crate::DynamicStruct fn path_mut<'p, T: Reflect>(&mut self, path: impl ReflectPath<'p>) -> PathResult<'p, &mut T> { - path.element_mut(self.as_reflect_mut()) + path.element_mut(self.as_partial_reflect_mut()) } } @@ -427,13 +433,16 @@ impl ParsedPath { } } impl<'a> ReflectPath<'a> for &'a ParsedPath { - fn reflect_element(self, mut root: &dyn Reflect) -> PathResult<'a, &dyn Reflect> { + fn reflect_element(self, mut root: &dyn PartialReflect) -> PathResult<'a, &dyn PartialReflect> { for OffsetAccess { access, offset } in &self.0 { root = access.element(root, *offset)?; } Ok(root) } - fn reflect_element_mut(self, mut root: &mut dyn Reflect) -> PathResult<'a, &mut dyn Reflect> { + fn reflect_element_mut( + self, + mut root: &mut dyn PartialReflect, + ) -> PathResult<'a, &mut dyn PartialReflect> { for OffsetAccess { access, offset } in &self.0 { root = access.element_mut(root, *offset)?; } diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index 2063cf317095f..59b8a81d54e56 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -54,7 +54,7 @@ macro_rules! impl_reflect_enum { /// Each variant contains a trait object with methods specific to a kind of /// type. /// -/// A [`ReflectRef`] is obtained via [`Reflect::reflect_ref`]. +/// A [`ReflectRef`] is obtained via [`PartialReflect::reflect_ref`]. pub enum ReflectRef<'a> { Struct(&'a dyn Struct), TupleStruct(&'a dyn TupleStruct), @@ -64,7 +64,7 @@ pub enum ReflectRef<'a> { Map(&'a dyn Map), Set(&'a dyn Set), Enum(&'a dyn Enum), - Value(&'a dyn Reflect), + Value(&'a dyn PartialReflect), } impl_reflect_enum!(ReflectRef<'_>); @@ -73,7 +73,7 @@ impl_reflect_enum!(ReflectRef<'_>); /// Each variant contains a trait object with methods specific to a kind of /// type. /// -/// A [`ReflectMut`] is obtained via [`Reflect::reflect_mut`]. +/// A [`ReflectMut`] is obtained via [`PartialReflect::reflect_mut`]. pub enum ReflectMut<'a> { Struct(&'a mut dyn Struct), TupleStruct(&'a mut dyn TupleStruct), @@ -83,7 +83,7 @@ pub enum ReflectMut<'a> { Map(&'a mut dyn Map), Set(&'a mut dyn Set), Enum(&'a mut dyn Enum), - Value(&'a mut dyn Reflect), + Value(&'a mut dyn PartialReflect), } impl_reflect_enum!(ReflectMut<'_>); @@ -92,7 +92,7 @@ impl_reflect_enum!(ReflectMut<'_>); /// Each variant contains a trait object with methods specific to a kind of /// type. /// -/// A [`ReflectOwned`] is obtained via [`Reflect::reflect_owned`]. +/// A [`ReflectOwned`] is obtained via [`PartialReflect::reflect_owned`]. pub enum ReflectOwned { Struct(Box), TupleStruct(Box), @@ -102,11 +102,11 @@ pub enum ReflectOwned { Map(Box), Set(Box), Enum(Box), - Value(Box), + Value(Box), } impl_reflect_enum!(ReflectOwned); -/// A enumeration of all error outcomes that might happen when running [`try_apply`](Reflect::try_apply). +/// A enumeration of all error outcomes that might happen when running [`try_apply`](PartialReflect::try_apply). #[derive(Error, Debug)] pub enum ApplyError { #[error("attempted to apply `{from_kind}` to `{to_kind}`")] @@ -144,7 +144,7 @@ pub enum ApplyError { /// A zero-sized enumuration of the "kinds" of a reflected type. /// -/// A [`ReflectKind`] is obtained via [`Reflect::reflect_kind`], +/// A [`ReflectKind`] is obtained via [`PartialReflect::reflect_kind`], /// or via [`ReflectRef::kind`],[`ReflectMut::kind`] or [`ReflectOwned::kind`]. #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum ReflectKind { @@ -175,22 +175,29 @@ impl std::fmt::Display for ReflectKind { } } -/// The core trait of [`bevy_reflect`], used for accessing and modifying data dynamically. +/// The foundational trait of [`bevy_reflect`], used for accessing and modifying data dynamically. /// -/// It's recommended to use the [derive macro] rather than manually implementing this trait. -/// Doing so will automatically implement many other useful traits for reflection, +/// This is a supertrait of [`Reflect`], +/// meaning any type which implements `Reflect` implements `PartialReflect` by definition. +/// +/// It's recommended to use [the derive macro for `Reflect`] rather than manually implementing this trait. +/// Doing so will automatically implement this trait as well as many other useful traits for reflection, /// including one of the appropriate subtraits: [`Struct`], [`TupleStruct`] or [`Enum`]. /// /// See the [crate-level documentation] to see how this trait and its subtraits can be used. /// /// [`bevy_reflect`]: crate -/// [derive macro]: bevy_reflect_derive::Reflect +/// [the derive macro for `Reflect`]: bevy_reflect_derive::Reflect /// [crate-level documentation]: crate #[diagnostic::on_unimplemented( - message = "`{Self}` can not be reflected", + message = "`{Self}` does not implement `PartialReflect` so cannot be introspected", note = "consider annotating `{Self}` with `#[derive(Reflect)]`" )] -pub trait Reflect: DynamicTypePath + Any + Send + Sync { +pub trait PartialReflect: DynamicTypePath + Send + Sync +where + // NB: we don't use `Self: Any` since for downcasting, `Reflect` should be used. + Self: 'static, +{ /// Returns the [`TypeInfo`] of the type _represented_ by this value. /// /// For most types, this will simply return their own `TypeInfo`. @@ -208,27 +215,39 @@ pub trait Reflect: DynamicTypePath + Any + Send + Sync { /// [`TypeRegistry::get_type_info`]: crate::TypeRegistry::get_type_info fn get_represented_type_info(&self) -> Option<&'static TypeInfo>; - /// Returns the value as a [`Box`][std::any::Any]. - fn into_any(self: Box) -> Box; + /// Casts this type to a boxed, reflected value. + /// + /// This is useful for coercing trait objects. + fn into_partial_reflect(self: Box) -> Box; - /// Returns the value as a [`&dyn Any`][std::any::Any]. - fn as_any(&self) -> &dyn Any; + /// Casts this type to a reflected value. + /// + /// This is useful for coercing trait objects. + fn as_partial_reflect(&self) -> &dyn PartialReflect; - /// Returns the value as a [`&mut dyn Any`][std::any::Any]. - fn as_any_mut(&mut self) -> &mut dyn Any; + /// 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; - /// Casts this type to a boxed reflected value. - fn into_reflect(self: Box) -> Box; + /// Attempts to cast this type to a boxed, [fully-reflected] value. + /// + /// [fully-reflected]: Reflect + fn try_into_reflect(self: Box) -> Result, Box>; - /// Casts this type to a reflected value. - fn as_reflect(&self) -> &dyn Reflect; + /// Attempts to cast this type to a [fully-reflected] value. + /// + /// [fully-reflected]: Reflect + fn try_as_reflect(&self) -> Option<&dyn Reflect>; - /// Casts this type to a mutable reflected value. - fn as_reflect_mut(&mut self) -> &mut dyn Reflect; + /// Attempts to cast this type to a mutable, [fully-reflected] value. + /// + /// [fully-reflected]: Reflect + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect>; /// Applies a reflected value to this value. /// - /// If a type implements a subtrait of `Reflect`, then the semantics of this + /// If a type implements an [introspection subtrait], then the semantics of this /// method are as follows: /// - If `T` is a [`Struct`], then the value of each named field of `value` is /// applied to the corresponding named field of `self`. Fields which are @@ -255,6 +274,7 @@ pub trait Reflect: DynamicTypePath + Any + Send + Sync { /// or none of the above depending on the kind of type. For lists and maps, use the /// [`list_apply`] and [`map_apply`] helper functions when implementing this method. /// + /// [introspection subtrait]: crate#the-introspection-subtraits /// [`list_apply`]: crate::list_apply /// [`map_apply`]: crate::map_apply /// @@ -266,26 +286,20 @@ pub trait Reflect: DynamicTypePath + Any + Send + Sync { /// - If `T` is any complex type and the corresponding fields or elements of /// `self` and `value` are not of the same type. /// - If `T` is a value type and `self` cannot be downcast to `T` - fn apply(&mut self, value: &dyn Reflect) { - Reflect::try_apply(self, value).unwrap(); + fn apply(&mut self, value: &dyn PartialReflect) { + PartialReflect::try_apply(self, value).unwrap(); } - /// Tries to [`apply`](Reflect::apply) a reflected value to this value. + /// Tries to [`apply`](PartialReflect::apply) a reflected value to this value. /// - /// Functions the same as the [`apply`](Reflect::apply) function but returns an error instead of + /// Functions the same as the [`apply`](PartialReflect::apply) function but returns an error instead of /// panicking. /// /// # Handling Errors /// /// This function may leave `self` in a partially mutated state if a error was encountered on the way. /// consider maintaining a cloned instance of this data you can switch to if a error is encountered. - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError>; - - /// 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` - /// containing the trait object. - fn set(&mut self, value: Box) -> Result<(), Box>; + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError>; /// Returns a zero-sized enumeration of "kinds" of type. /// @@ -316,7 +330,7 @@ pub trait Reflect: DynamicTypePath + Any + Send + Sync { /// or [`Enum::clone_dynamic`], respectively. /// Implementors of other `Reflect` subtraits (e.g. [`List`], [`Map`]) should /// use those subtraits' respective `clone_dynamic` methods. - fn clone_value(&self) -> Box; + fn clone_value(&self) -> Box; /// Returns a hash of the value (which includes the type). /// @@ -328,7 +342,7 @@ pub trait Reflect: DynamicTypePath + Any + Send + Sync { /// Returns a "partial equality" comparison result. /// /// If the underlying type does not support equality testing, returns `None`. - fn reflect_partial_eq(&self, _value: &dyn Reflect) -> Option { + fn reflect_partial_eq(&self, _value: &dyn PartialReflect) -> Option { None } @@ -376,29 +390,116 @@ pub trait Reflect: DynamicTypePath + Any + Send + Sync { } } -impl Debug for dyn Reflect { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.debug(f) +/// A core trait of [`bevy_reflect`], used for downcasting to concrete types. +/// +/// This is a subtrait of [`PartialReflect`], +/// meaning any type which implements `Reflect` implements `PartialReflect` by definition. +/// +/// It's recommended to use [the derive macro] rather than manually implementing this trait. +/// Doing so will automatically implement this trait, [`PartialReflect`], and many other useful traits for reflection, +/// including one of the appropriate subtraits: [`Struct`], [`TupleStruct`] or [`Enum`]. +/// +/// See the [crate-level documentation] to see how this trait can be used. +/// +/// [`bevy_reflect`]: crate +/// [the derive macro]: bevy_reflect_derive::Reflect +/// [crate-level documentation]: crate +#[diagnostic::on_unimplemented( + message = "`{Self}` does not implement `Reflect` so cannot be fully reflected", + note = "consider annotating `{Self}` with `#[derive(Reflect)]`" +)] +pub trait Reflect: PartialReflect + Any { + /// Returns the value as a [`Box`][std::any::Any]. + fn into_any(self: Box) -> Box; + + /// Returns the value as a [`&dyn Any`][std::any::Any]. + fn as_any(&self) -> &dyn Any; + + /// Returns the value as a [`&mut dyn Any`][std::any::Any]. + 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` + /// containing the trait object. + fn set(&mut self, value: Box) -> Result<(), Box>; +} + +impl dyn PartialReflect { + /// Returns `true` if the underlying value represents a value of type `T`, or `false` + /// otherwise. + /// + /// Read `is` for more information on underlying values and represented types. + #[inline] + pub fn represents(&self) -> bool { + self.get_represented_type_info() + .map(|t| t.type_path() == T::type_path()) + .unwrap_or(false) + } + + /// Downcasts the value to type `T`, consuming the trait object. + /// + /// If the underlying value does not implement [`Reflect`] + /// or is not of type `T`, returns `Err(self)`. + pub fn try_downcast( + self: Box, + ) -> Result, Box> { + self.try_into_reflect()? + .downcast() + .map_err(PartialReflect::into_partial_reflect) + } + + /// Downcasts the value to type `T`, unboxing and consuming the trait object. + /// + /// If the underlying value does not implement [`Reflect`] + /// or is not of type `T`, returns `Err(self)`. + pub fn try_take( + self: Box, + ) -> Result> { + self.try_downcast().map(|value| *value) + } + + /// Downcasts the value to type `T` by reference. + /// + /// If the underlying value does not implement [`Reflect`] + /// or is not of type `T`, returns [`None`]. + pub fn try_downcast_ref(&self) -> Option<&T> { + self.try_as_reflect()?.downcast_ref() + } + + /// Downcasts the value to type `T` by mutable reference. + /// + /// If the underlying value does not implement [`Reflect`] + /// or is not of type `T`, returns [`None`]. + pub fn try_downcast_mut(&mut self) -> Option<&mut T> { + self.try_as_reflect_mut()?.downcast_mut() } } -impl Typed for dyn Reflect { - fn type_info() -> &'static TypeInfo { - static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); - CELL.get_or_set(|| TypeInfo::Value(ValueInfo::new::())) +impl Debug for dyn PartialReflect { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.debug(f) } } // The following implementation never actually shadows the concrete TypePath implementation. - -// See this playground (https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=589064053f27bc100d90da89c6a860aa). -impl TypePath for dyn Reflect { +// See the comment on `dyn Reflect`'s `TypePath` implementation. +impl TypePath for dyn PartialReflect { fn type_path() -> &'static str { - "dyn bevy_reflect::Reflect" + "dyn bevy_reflect::PartialReflect" } fn short_type_path() -> &'static str { - "dyn Reflect" + "dyn PartialReflect" } } @@ -422,17 +523,6 @@ impl dyn Reflect { self.downcast::().map(|value| *value) } - /// Returns `true` if the underlying value represents a value of type `T`, or `false` - /// otherwise. - /// - /// Read `is` for more information on underlying values and represented types. - #[inline] - pub fn represents(&self) -> bool { - self.get_represented_type_info() - .map(|t| t.type_path() == T::type_path()) - .unwrap_or(false) - } - /// Returns `true` if the underlying value is of type `T`, or `false` /// otherwise. /// @@ -464,3 +554,68 @@ impl dyn Reflect { self.as_any_mut().downcast_mut::() } } + +impl Debug for dyn Reflect { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.debug(f) + } +} + +impl Typed for dyn Reflect { + fn type_info() -> &'static TypeInfo { + static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); + CELL.get_or_set(|| TypeInfo::Value(ValueInfo::new::())) + } +} + +// The following implementation never actually shadows the concrete `TypePath` implementation. +// See this playground (https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=589064053f27bc100d90da89c6a860aa). +impl TypePath for dyn Reflect { + fn type_path() -> &'static str { + "dyn bevy_reflect::Reflect" + } + + fn short_type_path() -> &'static str { + "dyn Reflect" + } +} + +macro_rules! impl_full_reflect { + ($(<$($id:ident),* $(,)?>)? for $ty:ty $(where $($tt:tt)*)?) => { + impl $(<$($id),*>)? $crate::Reflect for $ty $(where $($tt)*)? { + fn into_any(self: Box) -> Box { + self + } + + fn as_any(&self) -> &dyn ::std::any::Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any { + 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, + ) -> Result<(), Box> { + *self = ::take(value)?; + Ok(()) + } + } + }; +} + +pub(crate) use impl_full_reflect; diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 88efb1cafce1e..26fff47100e48 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -2,8 +2,9 @@ use crate::serde::SerializationData; use crate::{ ArrayInfo, DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicSet, DynamicStruct, DynamicTuple, DynamicTupleStruct, DynamicVariant, EnumInfo, ListInfo, Map, MapInfo, NamedField, - Reflect, ReflectDeserialize, Set, SetInfo, StructInfo, StructVariantInfo, TupleInfo, - TupleStructInfo, TupleVariantInfo, TypeInfo, TypeRegistration, TypeRegistry, VariantInfo, + PartialReflect, Reflect, ReflectDeserialize, Set, SetInfo, StructInfo, StructVariantInfo, + TupleInfo, TupleStructInfo, TupleVariantInfo, TypeInfo, TypeRegistration, TypeRegistry, + VariantInfo, }; use erased_serde::Deserializer; use serde::de::{ @@ -339,21 +340,21 @@ impl<'a, 'de> DeserializeSeed<'de> for TypeRegistrationDeserializer<'a> { /// let mut deserializer = ron::Deserializer::from_str(input).unwrap(); /// let reflect_deserializer = ReflectDeserializer::new(®istry); /// -/// let output: Box = reflect_deserializer.deserialize(&mut deserializer).unwrap(); +/// let output: Box = reflect_deserializer.deserialize(&mut deserializer).unwrap(); /// /// // Since `MyStruct` is not a value type and does not register `ReflectDeserialize`, -/// // we know that its deserialized representation will be a `DynamicStruct`. -/// assert!(output.is::()); -/// assert!(output.represents::()); +/// // we know that its deserialized value will be a `DynamicStruct`, +/// // although it will represent `MyStruct`. +/// assert!(output.as_partial_reflect().represents::()); /// /// // We can convert back to `MyStruct` using `FromReflect`. -/// let value: MyStruct = ::from_reflect(&*output).unwrap(); +/// let value: MyStruct = ::from_reflect(output.as_partial_reflect()).unwrap(); /// assert_eq!(value, MyStruct { value: 123 }); /// /// // We can also do this dynamically with `ReflectFromReflect`. /// let type_id = output.get_represented_type_info().unwrap().type_id(); /// let reflect_from_reflect = registry.get_type_data::(type_id).unwrap(); -/// let value: Box = reflect_from_reflect.from_reflect(&*output).unwrap(); +/// let value: Box = reflect_from_reflect.from_reflect(output.as_partial_reflect()).unwrap(); /// assert!(value.is::()); /// assert_eq!(value.take::().unwrap(), MyStruct { value: 123 }); /// ``` @@ -378,7 +379,7 @@ impl<'a> ReflectDeserializer<'a> { } impl<'a, 'de> DeserializeSeed<'de> for ReflectDeserializer<'a> { - type Value = Box; + type Value = Box; fn deserialize(self, deserializer: D) -> Result where @@ -389,7 +390,7 @@ impl<'a, 'de> DeserializeSeed<'de> for ReflectDeserializer<'a> { } impl<'a, 'de> Visitor<'de> for UntypedReflectDeserializerVisitor<'a> { - type Value = Box; + type Value = Box; fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { formatter @@ -472,21 +473,21 @@ impl<'a, 'de> DeserializeSeed<'de> for ReflectDeserializer<'a> { /// let mut deserializer = ron::Deserializer::from_str(input).unwrap(); /// let reflect_deserializer = TypedReflectDeserializer::new(registration, ®istry); /// -/// let output: Box = reflect_deserializer.deserialize(&mut deserializer).unwrap(); +/// let output: Box = reflect_deserializer.deserialize(&mut deserializer).unwrap(); /// /// // Since `MyStruct` is not a value type and does not register `ReflectDeserialize`, -/// // we know that its deserialized representation will be a `DynamicStruct`. -/// assert!(output.is::()); -/// assert!(output.represents::()); +/// // we know that its deserialized value will be a `DynamicStruct`, +/// // although it will represent `MyStruct`. +/// assert!(output.as_partial_reflect().represents::()); /// /// // We can convert back to `MyStruct` using `FromReflect`. -/// let value: MyStruct = ::from_reflect(&*output).unwrap(); +/// let value: MyStruct = ::from_reflect(output.as_partial_reflect()).unwrap(); /// assert_eq!(value, MyStruct { value: 123 }); /// /// // We can also do this dynamically with `ReflectFromReflect`. /// let type_id = output.get_represented_type_info().unwrap().type_id(); /// let reflect_from_reflect = registry.get_type_data::(type_id).unwrap(); -/// let value: Box = reflect_from_reflect.from_reflect(&*output).unwrap(); +/// let value: Box = reflect_from_reflect.from_reflect(output.as_partial_reflect()).unwrap(); /// assert!(value.is::()); /// assert_eq!(value.take::().unwrap(), MyStruct { value: 123 }); /// ``` @@ -514,7 +515,7 @@ impl<'a> TypedReflectDeserializer<'a> { } impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { - type Value = Box; + type Value = Box; fn deserialize(self, deserializer: D) -> Result where @@ -525,7 +526,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { // Handle both Value case and types that have a custom `ReflectDeserialize` if let Some(deserialize_reflect) = self.registration.data::() { let value = deserialize_reflect.deserialize(deserializer)?; - return Ok(value); + return Ok(value.into_partial_reflect()); } match self.registration.type_info() { @@ -1107,7 +1108,10 @@ where let Some(field) = info.field_at(*skipped_index) else { continue; }; - dynamic_struct.insert_boxed(field.name(), skipped_field.generate_default()); + dynamic_struct.insert_boxed( + field.name(), + skipped_field.generate_default().into_partial_reflect(), + ); } } @@ -1137,7 +1141,7 @@ where for index in 0..len { if let Some(value) = serialization_data.and_then(|data| data.generate_default(index)) { - tuple.insert_boxed(value); + tuple.insert_boxed(value.into_partial_reflect()); continue; } @@ -1182,7 +1186,7 @@ where .unwrap_or_default() { if let Some(value) = serialization_data.unwrap().generate_default(index) { - dynamic_struct.insert_boxed(name, value); + dynamic_struct.insert_boxed(name, value.into_partial_reflect()); } continue; } @@ -1224,7 +1228,9 @@ mod tests { use crate as bevy_reflect; use crate::serde::{ReflectDeserializer, ReflectSerializer, TypedReflectDeserializer}; - use crate::{DynamicEnum, FromReflect, Reflect, ReflectDeserialize, TypeRegistry}; + use crate::{ + DynamicEnum, FromReflect, PartialReflect, Reflect, ReflectDeserialize, TypeRegistry, + }; #[derive(Reflect, Debug, PartialEq)] struct MyStruct { @@ -1445,7 +1451,7 @@ mod tests { .deserialize(&mut ron_deserializer) .unwrap(); let output = dynamic_output - .take::() + .try_take::() .expect("underlying type should be f32"); assert_eq!(1.23, output); } @@ -1472,7 +1478,9 @@ mod tests { .deserialize(&mut ron_deserializer) .unwrap(); - let output = ::from_reflect(dynamic_output.as_ref()).unwrap(); + let output = + ::from_reflect(dynamic_output.as_ref().as_partial_reflect()) + .unwrap(); assert_eq!(expected, output); } @@ -1585,7 +1593,9 @@ mod tests { let output = reflect_deserializer.deserialize(&mut deserializer).unwrap(); let expected = DynamicEnum::from(MyEnum::Tuple(1.23, 3.21)); - assert!(expected.reflect_partial_eq(output.as_ref()).unwrap()); + assert!(expected + .reflect_partial_eq(output.as_partial_reflect()) + .unwrap()); // === Struct Variant === // let input = r#"{ @@ -1600,7 +1610,9 @@ mod tests { let expected = DynamicEnum::from(MyEnum::Struct { value: String::from("I <3 Enums"), }); - assert!(expected.reflect_partial_eq(output.as_ref()).unwrap()); + assert!(expected + .reflect_partial_eq(output.as_partial_reflect()) + .unwrap()); } // Regression test for https://github.com/bevyengine/bevy/issues/12462 @@ -1616,7 +1628,7 @@ mod tests { let reflect_deserializer = ReflectDeserializer::new(®istry); let input2 = reflect_deserializer.deserialize(&mut deserializer).unwrap(); - let serializer2 = ReflectSerializer::new(&*input2, ®istry); + let serializer2 = ReflectSerializer::new(input2.as_partial_reflect(), ®istry); let serialized2 = ron::ser::to_string(&serializer2).unwrap(); assert_eq!(serialized1, serialized2); diff --git a/crates/bevy_reflect/src/serde/mod.rs b/crates/bevy_reflect/src/serde/mod.rs index 0f9833c57efe4..a962c36bd04bd 100644 --- a/crates/bevy_reflect/src/serde/mod.rs +++ b/crates/bevy_reflect/src/serde/mod.rs @@ -8,7 +8,7 @@ pub use type_data::*; #[cfg(test)] mod tests { - use crate::{self as bevy_reflect, DynamicTupleStruct, Struct}; + use crate::{self as bevy_reflect, DynamicTupleStruct, PartialReflect, Struct}; use crate::{ serde::{ReflectDeserializer, ReflectSerializer}, type_registry::TypeRegistry, @@ -53,8 +53,7 @@ mod tests { let mut deserializer = ron::de::Deserializer::from_str(&serialized).unwrap(); let reflect_deserializer = ReflectDeserializer::new(®istry); - let value = reflect_deserializer.deserialize(&mut deserializer).unwrap(); - let deserialized = value.take::().unwrap(); + let deserialized = reflect_deserializer.deserialize(&mut deserializer).unwrap(); let mut expected = DynamicStruct::default(); expected.insert("a", 3); @@ -64,7 +63,9 @@ mod tests { expected.insert("e", 7); assert!( - expected.reflect_partial_eq(&deserialized).unwrap(), + expected + .reflect_partial_eq(deserialized.as_partial_reflect()) + .unwrap(), "Deserialization failed: expected {expected:?} found {deserialized:?}" ); @@ -75,7 +76,8 @@ mod tests { d: -1, e: 7, }; - let received = ::from_reflect(&deserialized).unwrap(); + let received = + ::from_reflect(deserialized.as_partial_reflect()).unwrap(); assert_eq!( expected, received, @@ -112,8 +114,7 @@ mod tests { let mut deserializer = ron::de::Deserializer::from_str(&serialized).unwrap(); let reflect_deserializer = ReflectDeserializer::new(®istry); - let value = reflect_deserializer.deserialize(&mut deserializer).unwrap(); - let deserialized = value.take::().unwrap(); + let deserialized = reflect_deserializer.deserialize(&mut deserializer).unwrap(); let mut expected = DynamicTupleStruct::default(); expected.insert(3); @@ -123,12 +124,15 @@ mod tests { expected.insert(7); assert!( - expected.reflect_partial_eq(&deserialized).unwrap(), + expected + .reflect_partial_eq(deserialized.as_partial_reflect()) + .unwrap(), "Deserialization failed: expected {expected:?} found {deserialized:?}" ); let expected = TestStruct(3, 0, 0, -1, 7); - let received = ::from_reflect(&deserialized).unwrap(); + let received = + ::from_reflect(deserialized.as_partial_reflect()).unwrap(); assert_eq!( expected, received, @@ -173,12 +177,10 @@ mod tests { let reflect_deserializer = ReflectDeserializer::new(®istry); let expected = value.clone_value(); - let result = reflect_deserializer - .deserialize(&mut deserializer) - .unwrap() - .take::() - .unwrap(); + let result = reflect_deserializer.deserialize(&mut deserializer).unwrap(); - assert!(expected.reflect_partial_eq(&result).unwrap()); + assert!(expected + .reflect_partial_eq(result.as_partial_reflect()) + .unwrap()); } } diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index 61d1948749118..8615171238035 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -1,6 +1,6 @@ use crate::{ - Array, Enum, List, Map, Reflect, ReflectRef, ReflectSerialize, Set, Struct, Tuple, TupleStruct, - TypeInfo, TypeRegistry, VariantInfo, VariantType, + Array, Enum, List, Map, PartialReflect, ReflectRef, ReflectSerialize, Set, Struct, Tuple, + TupleStruct, TypeInfo, TypeRegistry, VariantInfo, VariantType, }; use serde::ser::{ Error, SerializeStruct, SerializeStructVariant, SerializeTuple, SerializeTupleStruct, @@ -29,9 +29,15 @@ impl<'a> Serializable<'a> { } fn get_serializable<'a, E: Error>( - reflect_value: &'a dyn Reflect, + reflect_value: &'a dyn PartialReflect, type_registry: &TypeRegistry, ) -> Result, E> { + let Some(reflect_value) = reflect_value.try_as_reflect() else { + return Err(Error::custom(format_args!( + "Type '{}' does not implement `Reflect`", + reflect_value.reflect_type_path() + ))); + }; let info = reflect_value.get_represented_type_info().ok_or_else(|| { Error::custom(format_args!( "Type '{}' does not represent any type", @@ -93,12 +99,12 @@ fn get_serializable<'a, E: Error>( /// [`ReflectDeserializer`]: crate::serde::ReflectDeserializer /// [type path]: crate::TypePath::type_path pub struct ReflectSerializer<'a> { - pub value: &'a dyn Reflect, + pub value: &'a dyn PartialReflect, pub registry: &'a TypeRegistry, } impl<'a> ReflectSerializer<'a> { - pub fn new(value: &'a dyn Reflect, registry: &'a TypeRegistry) -> Self { + pub fn new(value: &'a dyn PartialReflect, registry: &'a TypeRegistry) -> Self { ReflectSerializer { value, registry } } } @@ -171,12 +177,12 @@ impl<'a> Serialize for ReflectSerializer<'a> { /// [`TypedReflectDeserializer`]: crate::serde::TypedReflectDeserializer /// [type path]: crate::TypePath::type_path pub struct TypedReflectSerializer<'a> { - pub value: &'a dyn Reflect, + pub value: &'a dyn PartialReflect, pub registry: &'a TypeRegistry, } impl<'a> TypedReflectSerializer<'a> { - pub fn new(value: &'a dyn Reflect, registry: &'a TypeRegistry) -> Self { + pub fn new(value: &'a dyn PartialReflect, registry: &'a TypeRegistry) -> Self { TypedReflectSerializer { value, registry } } } @@ -240,7 +246,7 @@ impl<'a> Serialize for TypedReflectSerializer<'a> { pub struct ReflectValueSerializer<'a> { pub registry: &'a TypeRegistry, - pub value: &'a dyn Reflect, + pub value: &'a dyn PartialReflect, } impl<'a> Serialize for ReflectValueSerializer<'a> { @@ -565,7 +571,7 @@ impl<'a> Serialize for ArraySerializer<'a> { #[cfg(test)] mod tests { use crate::serde::ReflectSerializer; - use crate::{self as bevy_reflect, Struct}; + use crate::{self as bevy_reflect, PartialReflect, Struct}; use crate::{Reflect, ReflectSerialize, TypeRegistry}; use bevy_utils::{HashMap, HashSet}; use ron::extensions::Extensions; @@ -946,7 +952,7 @@ mod tests { none: None, }; let dynamic = value.clone_dynamic(); - let reflect = dynamic.as_reflect(); + let reflect = dynamic.as_partial_reflect(); let registry = get_registry(); diff --git a/crates/bevy_reflect/src/set.rs b/crates/bevy_reflect/src/set.rs index 7319308d4cab9..08bcf4c163ece 100644 --- a/crates/bevy_reflect/src/set.rs +++ b/crates/bevy_reflect/src/set.rs @@ -6,8 +6,8 @@ use bevy_utils::hashbrown::hash_table::OccupiedEntry as HashTableOccupiedEntry; use bevy_utils::hashbrown::HashTable; use crate::{ - self as bevy_reflect, hash_error, ApplyError, Reflect, ReflectKind, ReflectMut, ReflectOwned, - ReflectRef, TypeInfo, TypePath, TypePathTable, + self as bevy_reflect, hash_error, ApplyError, PartialReflect, Reflect, ReflectKind, ReflectMut, + ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable, }; /// A trait used to power [set-like] operations via [reflection]. @@ -17,7 +17,7 @@ use crate::{ /// /// # Hashing /// -/// All values are expected to return a valid hash value from [`Reflect::reflect_hash`]. +/// All values are expected to return a valid hash value from [`PartialReflect::reflect_hash`]. /// If using the [`#[derive(Reflect)]`](derive@crate::Reflect) macro, this can be done by adding `#[reflect(Hash)]` /// to the entire struct or enum. /// This is true even for manual implementors who do not use the hashed value, @@ -26,7 +26,7 @@ use crate::{ /// # Example /// /// ``` -/// use bevy_reflect::{Reflect, Set}; +/// use bevy_reflect::{PartialReflect, Set}; /// use bevy_utils::HashSet; /// /// @@ -34,17 +34,17 @@ use crate::{ /// foo.insert_boxed(Box::new(123_u32)); /// assert_eq!(foo.len(), 1); /// -/// let field: &dyn Reflect = foo.get(&123_u32).unwrap(); -/// assert_eq!(field.downcast_ref::(), Some(&123_u32)); +/// let field: &dyn PartialReflect = foo.get(&123_u32).unwrap(); +/// assert_eq!(field.try_downcast_ref::(), Some(&123_u32)); /// ``` /// /// [set-like]: https://doc.rust-lang.org/stable/std/collections/struct.HashSet.html /// [reflection]: crate -pub trait Set: Reflect { +pub trait Set: PartialReflect { /// Returns a reference to the value. /// /// If no value is contained, returns `None`. - fn get(&self, value: &dyn Reflect) -> Option<&dyn Reflect>; + fn get(&self, value: &dyn PartialReflect) -> Option<&dyn PartialReflect>; /// Returns the number of elements in the set. fn len(&self) -> usize; @@ -55,10 +55,10 @@ pub trait Set: Reflect { } /// Returns an iterator over the values of the set. - fn iter(&self) -> Box + '_>; + fn iter(&self) -> Box + '_>; /// Drain the values of this set to get a vector of owned values. - fn drain(self: Box) -> Vec>; + fn drain(self: Box) -> Vec>; /// Clones the set, producing a [`DynamicSet`]. fn clone_dynamic(&self) -> DynamicSet; @@ -67,16 +67,16 @@ pub trait Set: Reflect { /// /// If the set did not have this value present, `true` is returned. /// If the set did have this value present, `false` is returned. - fn insert_boxed(&mut self, value: Box) -> bool; + fn insert_boxed(&mut self, value: Box) -> bool; /// Removes a value from the set. /// /// If the set did not have this value present, `true` is returned. /// If the set did have this value present, `false` is returned. - fn remove(&mut self, value: &dyn Reflect) -> bool; + fn remove(&mut self, value: &dyn PartialReflect) -> bool; /// Checks if the given value is contained in the set - fn contains(&self, value: &dyn Reflect) -> bool; + fn contains(&self, value: &dyn PartialReflect) -> bool; } /// A container for compile-time set info. @@ -164,7 +164,7 @@ impl SetInfo { #[derive(Default)] pub struct DynamicSet { represented_type: Option<&'static TypeInfo>, - hash_table: HashTable>, + hash_table: HashTable>, } impl DynamicSet { @@ -192,13 +192,13 @@ impl DynamicSet { self.insert_boxed(Box::new(value)); } - #[allow(clippy::borrowed_box)] - fn internal_hash(value: &Box) -> u64 { + fn internal_hash(value: &dyn PartialReflect) -> u64 { value.reflect_hash().expect(hash_error!(value)) } - #[allow(clippy::borrowed_box)] - fn internal_eq(value: &Box) -> impl FnMut(&Box) -> bool + '_ { + fn internal_eq( + value: &dyn PartialReflect, + ) -> impl FnMut(&Box) -> bool + '_ { |other| { value .reflect_partial_eq(&**other) @@ -207,18 +207,10 @@ impl DynamicSet { } } -// I just created this function to have only one point where we ignore the rust warning about the -// unused allocation -fn box_and_clone(val: &dyn Reflect) -> Box { - #[allow(unused_allocation)] - Box::new(val).clone_value() -} - impl Set for DynamicSet { - fn get(&self, value: &dyn Reflect) -> Option<&dyn Reflect> { - let boxed = box_and_clone(value); + fn get(&self, value: &dyn PartialReflect) -> Option<&dyn PartialReflect> { self.hash_table - .find(Self::internal_hash(&boxed), Self::internal_eq(&boxed)) + .find(Self::internal_hash(value), Self::internal_eq(value)) .map(|value| &**value) } @@ -226,12 +218,12 @@ impl Set for DynamicSet { self.hash_table.len() } - fn iter(&self) -> Box + '_> { + fn iter(&self) -> Box + '_> { let iter = self.hash_table.iter().map(|v| &**v); Box::new(iter) } - fn drain(self: Box) -> Vec> { + fn drain(self: Box) -> Vec> { self.hash_table.into_iter().collect::>() } @@ -241,7 +233,9 @@ impl Set for DynamicSet { .iter() .map(|value| value.clone_value()) .for_each(|value| { - hash_table.insert_unique(Self::internal_hash(&value), value, Self::internal_hash); + hash_table.insert_unique(Self::internal_hash(value.as_ref()), value, |boxed| { + Self::internal_hash(boxed.as_ref()) + }); }); DynamicSet { @@ -250,7 +244,7 @@ impl Set for DynamicSet { } } - fn insert_boxed(&mut self, value: Box) -> bool { + fn insert_boxed(&mut self, value: Box) -> bool { assert_eq!( value.reflect_partial_eq(&*value), Some(true), @@ -258,7 +252,7 @@ impl Set for DynamicSet { ); match self .hash_table - .find_mut(Self::internal_hash(&value), Self::internal_eq(&value)) + .find_mut(Self::internal_hash(&*value), Self::internal_eq(&*value)) { Some(old) => { *old = value; @@ -266,77 +260,73 @@ impl Set for DynamicSet { } None => { self.hash_table.insert_unique( - Self::internal_hash(&value), + Self::internal_hash(value.as_ref()), value, - Self::internal_hash, + |boxed| Self::internal_hash(boxed.as_ref()), ); true } } } - fn remove(&mut self, value: &dyn Reflect) -> bool { - let boxed = box_and_clone(value); + fn remove(&mut self, value: &dyn PartialReflect) -> bool { self.hash_table - .find_entry(Self::internal_hash(&boxed), Self::internal_eq(&boxed)) + .find_entry(Self::internal_hash(value), Self::internal_eq(value)) .map(HashTableOccupiedEntry::remove) .is_ok() } - fn contains(&self, value: &dyn Reflect) -> bool { - let boxed = box_and_clone(value); + fn contains(&self, value: &dyn PartialReflect) -> bool { self.hash_table - .find(Self::internal_hash(&boxed), Self::internal_eq(&boxed)) + .find(Self::internal_hash(value), Self::internal_eq(value)) .is_some() } } -impl Reflect for DynamicSet { +impl PartialReflect for DynamicSet { #[inline] fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } - fn into_any(self: Box) -> Box { + #[inline] + fn into_partial_reflect(self: Box) -> Box { self } - fn as_any(&self) -> &dyn Any { + #[inline] + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } - fn as_any_mut(&mut self) -> &mut dyn Any { + #[inline] + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } #[inline] - fn into_reflect(self: Box) -> Box { - self + fn try_into_reflect(self: Box) -> Result, Box> { + Err(self) } #[inline] - fn as_reflect(&self) -> &dyn Reflect { - self + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + None } #[inline] - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + None } - fn apply(&mut self, value: &dyn Reflect) { + fn apply(&mut self, value: &dyn PartialReflect) { set_apply(self, value); } - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { set_try_apply(self, value) } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - fn reflect_kind(&self) -> ReflectKind { ReflectKind::Set } @@ -353,11 +343,11 @@ impl Reflect for DynamicSet { ReflectOwned::Set(self) } - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone_dynamic()) } - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { + fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option { set_partial_eq(self, value) } @@ -381,8 +371,8 @@ impl Debug for DynamicSet { } } -impl FromIterator> for DynamicSet { - fn from_iter>>(values: I) -> Self { +impl FromIterator> for DynamicSet { + fn from_iter>>(values: I) -> Self { let mut this = Self { represented_type: None, hash_table: HashTable::new(), @@ -412,7 +402,7 @@ impl FromIterator for DynamicSet { } impl IntoIterator for DynamicSet { - type Item = Box; + type Item = Box; type IntoIter = bevy_utils::hashbrown::hash_table::IntoIter; fn into_iter(self) -> Self::IntoIter { @@ -421,28 +411,28 @@ impl IntoIterator for DynamicSet { } impl<'a> IntoIterator for &'a DynamicSet { - type Item = &'a dyn Reflect; + type Item = &'a dyn PartialReflect; type IntoIter = std::iter::Map< - bevy_utils::hashbrown::hash_table::Iter<'a, Box>, - fn(&'a Box) -> Self::Item, + bevy_utils::hashbrown::hash_table::Iter<'a, Box>, + fn(&'a Box) -> Self::Item, >; fn into_iter(self) -> Self::IntoIter { - self.hash_table.iter().map(|v| v.as_reflect()) + self.hash_table.iter().map(|v| v.as_ref()) } } -/// Compares a [`Set`] with a [`Reflect`] value. +/// Compares a [`Set`] with a [`PartialReflect`] value. /// /// Returns true if and only if all of the following are true: /// - `b` is a set; /// - `b` is the same length as `a`; /// - For each value pair in `a`, `b` contains the value too, -/// and [`Reflect::reflect_partial_eq`] returns `Some(true)` for the two values. +/// and [`PartialReflect::reflect_partial_eq`] returns `Some(true)` for the two values. /// /// Returns [`None`] if the comparison couldn't even be performed. #[inline] -pub fn set_partial_eq(a: &M, b: &dyn Reflect) -> Option { +pub fn set_partial_eq(a: &M, b: &dyn PartialReflect) -> Option { let ReflectRef::Set(set) = b.reflect_ref() else { return Some(false); }; @@ -499,7 +489,7 @@ pub fn set_debug(dyn_set: &dyn Set, f: &mut Formatter<'_>) -> std::fmt::Result { /// /// This function panics if `b` is not a reflected set. #[inline] -pub fn set_apply(a: &mut M, b: &dyn Reflect) { +pub fn set_apply(a: &mut M, b: &dyn PartialReflect) { if let ReflectRef::Set(set_value) = b.reflect_ref() { for b_value in set_value.iter() { if a.get(b_value).is_none() { @@ -521,7 +511,7 @@ pub fn set_apply(a: &mut M, b: &dyn Reflect) { /// This function returns an [`ApplyError::MismatchedKinds`] if `b` is not a reflected set or if /// applying elements to each other fails. #[inline] -pub fn set_try_apply(a: &mut S, b: &dyn Reflect) -> Result<(), ApplyError> { +pub fn set_try_apply(a: &mut S, b: &dyn PartialReflect) -> Result<(), ApplyError> { if let ReflectRef::Set(set_value) = b.reflect_ref() { for b_value in set_value.iter() { if a.get(b_value).is_none() { @@ -551,7 +541,9 @@ mod tests { set.insert(expected[2].to_string()); for item in set.into_iter() { - let value = item.take::().expect("couldn't downcast to String"); + let value = item + .try_take::() + .expect("couldn't downcast to String"); let index = expected .iter() .position(|i| *i == value.as_str()) diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index 1c23dc22c0208..52dce37f91b94 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -1,7 +1,7 @@ use crate::attributes::{impl_custom_attribute_methods, CustomAttributes}; use crate::{ - self as bevy_reflect, ApplyError, NamedField, Reflect, ReflectKind, ReflectMut, ReflectOwned, - ReflectRef, TypeInfo, TypePath, TypePathTable, + self as bevy_reflect, ApplyError, NamedField, PartialReflect, Reflect, ReflectKind, ReflectMut, + ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable, }; use bevy_reflect_derive::impl_type_path; use bevy_utils::HashMap; @@ -25,7 +25,7 @@ use std::{ /// # Example /// /// ``` -/// use bevy_reflect::{Reflect, Struct}; +/// use bevy_reflect::{PartialReflect, Reflect, Struct}; /// /// #[derive(Reflect)] /// struct Foo { @@ -37,30 +37,30 @@ use std::{ /// assert_eq!(foo.field_len(), 1); /// assert_eq!(foo.name_at(0), Some("bar")); /// -/// let field: &dyn Reflect = foo.field("bar").unwrap(); -/// assert_eq!(field.downcast_ref::(), Some(&123)); +/// let field: &dyn PartialReflect = foo.field("bar").unwrap(); +/// assert_eq!(field.try_downcast_ref::(), Some(&123)); /// ``` /// /// [struct-like]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html /// [reflection]: crate /// [unit structs]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#unit-like-structs-without-any-fields -pub trait Struct: Reflect { +pub trait Struct: PartialReflect { /// Returns a reference to the value of the field named `name` as a `&dyn - /// Reflect`. - fn field(&self, name: &str) -> Option<&dyn Reflect>; + /// PartialReflect`. + fn field(&self, name: &str) -> Option<&dyn PartialReflect>; /// Returns a mutable reference to the value of the field named `name` as a - /// `&mut dyn Reflect`. - fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect>; + /// `&mut dyn PartialReflect`. + fn field_mut(&mut self, name: &str) -> Option<&mut dyn PartialReflect>; /// Returns a reference to the value of the field with index `index` as a - /// `&dyn Reflect`. - fn field_at(&self, index: usize) -> Option<&dyn Reflect>; + /// `&dyn PartialReflect`. + fn field_at(&self, index: usize) -> Option<&dyn PartialReflect>; /// Returns a mutable reference to the value of the field with index `index` - /// as a `&mut dyn Reflect`. - fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>; + /// as a `&mut dyn PartialReflect`. + fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>; /// Returns the name of the field with index `index`. fn name_at(&self, index: usize) -> Option<&str>; @@ -214,7 +214,7 @@ impl<'a> FieldIter<'a> { } impl<'a> Iterator for FieldIter<'a> { - type Item = &'a dyn Reflect; + type Item = &'a dyn PartialReflect; fn next(&mut self) -> Option { let value = self.struct_val.field_at(self.index); @@ -262,23 +262,25 @@ pub trait GetField { impl GetField for S { fn get_field(&self, name: &str) -> Option<&T> { - self.field(name).and_then(|value| value.downcast_ref::()) + self.field(name) + .and_then(|value| value.try_downcast_ref::()) } fn get_field_mut(&mut self, name: &str) -> Option<&mut T> { self.field_mut(name) - .and_then(|value| value.downcast_mut::()) + .and_then(|value| value.try_downcast_mut::()) } } impl GetField for dyn Struct { fn get_field(&self, name: &str) -> Option<&T> { - self.field(name).and_then(|value| value.downcast_ref::()) + self.field(name) + .and_then(|value| value.try_downcast_ref::()) } fn get_field_mut(&mut self, name: &str) -> Option<&mut T> { self.field_mut(name) - .and_then(|value| value.downcast_mut::()) + .and_then(|value| value.try_downcast_mut::()) } } @@ -286,7 +288,7 @@ impl GetField for dyn Struct { #[derive(Default)] pub struct DynamicStruct { represented_type: Option<&'static TypeInfo>, - fields: Vec>, + fields: Vec>, field_names: Vec>, field_indices: HashMap, usize>, } @@ -314,7 +316,11 @@ impl DynamicStruct { /// Inserts a field named `name` with value `value` into the struct. /// /// If the field already exists, it is overwritten. - pub fn insert_boxed<'a>(&mut self, name: impl Into>, value: Box) { + pub fn insert_boxed<'a>( + &mut self, + name: impl Into>, + value: Box, + ) { let name: Cow = name.into(); if let Some(index) = self.field_indices.get(&name) { self.fields[*index] = value; @@ -329,7 +335,7 @@ impl DynamicStruct { /// Inserts a field named `name` with the typed value `value` into the struct. /// /// If the field already exists, it is overwritten. - pub fn insert<'a, T: Reflect>(&mut self, name: impl Into>, value: T) { + pub fn insert<'a, T: PartialReflect>(&mut self, name: impl Into>, value: T) { self.insert_boxed(name, Box::new(value)); } @@ -341,14 +347,14 @@ impl DynamicStruct { impl Struct for DynamicStruct { #[inline] - fn field(&self, name: &str) -> Option<&dyn Reflect> { + fn field(&self, name: &str) -> Option<&dyn PartialReflect> { self.field_indices .get(name) .map(|index| &*self.fields[*index]) } #[inline] - fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect> { + fn field_mut(&mut self, name: &str) -> Option<&mut dyn PartialReflect> { if let Some(index) = self.field_indices.get(name) { Some(&mut *self.fields[*index]) } else { @@ -357,12 +363,12 @@ impl Struct for DynamicStruct { } #[inline] - fn field_at(&self, index: usize) -> Option<&dyn Reflect> { + fn field_at(&self, index: usize) -> Option<&dyn PartialReflect> { self.fields.get(index).map(|value| &**value) } #[inline] - fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> { + fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> { self.fields.get_mut(index).map(|value| &mut **value) } @@ -398,43 +404,38 @@ impl Struct for DynamicStruct { } } -impl Reflect for DynamicStruct { +impl PartialReflect for DynamicStruct { #[inline] fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } #[inline] - fn into_any(self: Box) -> Box { + fn into_partial_reflect(self: Box) -> Box { self } #[inline] - fn as_any(&self) -> &dyn Any { + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } #[inline] - fn as_any_mut(&mut self) -> &mut dyn Any { + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } - #[inline] - fn into_reflect(self: Box) -> Box { - self + fn try_into_reflect(self: Box) -> Result, Box> { + Err(self) } - - #[inline] - fn as_reflect(&self) -> &dyn Reflect { - self + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + None } - - #[inline] - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + None } - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { if let ReflectRef::Struct(struct_value) = value.reflect_ref() { for (i, value) in struct_value.iter_fields().enumerate() { let name = struct_value.name_at(i).unwrap(); @@ -451,12 +452,6 @@ impl Reflect for DynamicStruct { Ok(()) } - #[inline] - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - #[inline] fn reflect_kind(&self) -> ReflectKind { ReflectKind::Struct @@ -478,11 +473,11 @@ impl Reflect for DynamicStruct { } #[inline] - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone_dynamic()) } - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { + fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option { struct_partial_eq(self, value) } @@ -499,8 +494,6 @@ impl Reflect for DynamicStruct { } impl_type_path!((in bevy_reflect) DynamicStruct); -#[cfg(feature = "functions")] -crate::func::macros::impl_function_traits!(DynamicStruct); impl Debug for DynamicStruct { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { @@ -508,13 +501,13 @@ impl Debug for DynamicStruct { } } -impl<'a, N> FromIterator<(N, Box)> for DynamicStruct +impl<'a, N> FromIterator<(N, Box)> for DynamicStruct where N: Into>, { /// Create a dynamic struct that doesn't represent a type from the /// field name, field value pairs. - fn from_iter)>>(fields: I) -> Self { + fn from_iter)>>(fields: I) -> Self { let mut dynamic_struct = Self::default(); for (name, value) in fields.into_iter() { dynamic_struct.insert_boxed(name, value); @@ -524,7 +517,7 @@ where } impl IntoIterator for DynamicStruct { - type Item = Box; + type Item = Box; type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { @@ -533,7 +526,7 @@ impl IntoIterator for DynamicStruct { } impl<'a> IntoIterator for &'a DynamicStruct { - type Item = &'a dyn Reflect; + type Item = &'a dyn PartialReflect; type IntoIter = FieldIter<'a>; fn into_iter(self) -> Self::IntoIter { @@ -541,17 +534,17 @@ impl<'a> IntoIterator for &'a DynamicStruct { } } -/// Compares a [`Struct`] with a [`Reflect`] value. +/// Compares a [`Struct`] with a [`PartialReflect`] value. /// /// Returns true if and only if all of the following are true: /// - `b` is a struct; /// - For each field in `a`, `b` contains a field with the same name and -/// [`Reflect::reflect_partial_eq`] returns `Some(true)` for the two field +/// [`PartialReflect::reflect_partial_eq`] returns `Some(true)` for the two field /// values. /// /// Returns [`None`] if the comparison couldn't even be performed. #[inline] -pub fn struct_partial_eq(a: &S, b: &dyn Reflect) -> Option { +pub fn struct_partial_eq(a: &S, b: &dyn PartialReflect) -> Option { let ReflectRef::Struct(struct_value) = b.reflect_ref() else { return Some(false); }; diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index 67a6896f263e1..bacfd9ba3fe25 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -6,7 +6,7 @@ use crate::{ GetTypeRegistration, MaybeTyped, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, TypeRegistration, TypeRegistry, Typed, UnnamedField, }; -use crate::{ReflectKind, TypePathTable}; +use crate::{PartialReflect, ReflectKind, TypePathTable}; use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; use std::slice::Iter; @@ -22,25 +22,25 @@ use std::slice::Iter; /// # Example /// /// ``` -/// use bevy_reflect::{Reflect, Tuple}; +/// use bevy_reflect::{PartialReflect, Tuple}; /// /// let foo = (123_u32, true); /// assert_eq!(foo.field_len(), 2); /// -/// let field: &dyn Reflect = foo.field(0).unwrap(); -/// assert_eq!(field.downcast_ref::(), Some(&123)); +/// let field: &dyn PartialReflect = foo.field(0).unwrap(); +/// assert_eq!(field.try_downcast_ref::(), Some(&123)); /// ``` /// /// [tuple-like]: https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type /// [reflection]: crate -pub trait Tuple: Reflect { +pub trait Tuple: PartialReflect { /// Returns a reference to the value of the field with index `index` as a /// `&dyn Reflect`. - fn field(&self, index: usize) -> Option<&dyn Reflect>; + fn field(&self, index: usize) -> Option<&dyn PartialReflect>; /// Returns a mutable reference to the value of the field with index `index` /// as a `&mut dyn Reflect`. - fn field_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>; + fn field_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>; /// Returns the number of fields in the tuple. fn field_len(&self) -> usize; @@ -49,7 +49,7 @@ pub trait Tuple: Reflect { fn iter_fields(&self) -> TupleFieldIter; /// Drain the fields of this tuple to get a vector of owned values. - fn drain(self: Box) -> Vec>; + fn drain(self: Box) -> Vec>; /// Clones the struct into a [`DynamicTuple`]. fn clone_dynamic(&self) -> DynamicTuple; @@ -71,7 +71,7 @@ impl<'a> TupleFieldIter<'a> { } impl<'a> Iterator for TupleFieldIter<'a> { - type Item = &'a dyn Reflect; + type Item = &'a dyn PartialReflect; fn next(&mut self) -> Option { let value = self.tuple.field(self.index); @@ -115,24 +115,24 @@ pub trait GetTupleField { impl GetTupleField for S { fn get_field(&self, index: usize) -> Option<&T> { self.field(index) - .and_then(|value| value.downcast_ref::()) + .and_then(|value| value.try_downcast_ref::()) } fn get_field_mut(&mut self, index: usize) -> Option<&mut T> { self.field_mut(index) - .and_then(|value| value.downcast_mut::()) + .and_then(|value| value.try_downcast_mut::()) } } impl GetTupleField for dyn Tuple { fn get_field(&self, index: usize) -> Option<&T> { self.field(index) - .and_then(|value| value.downcast_ref::()) + .and_then(|value| value.try_downcast_ref::()) } fn get_field_mut(&mut self, index: usize) -> Option<&mut T> { self.field_mut(index) - .and_then(|value| value.downcast_mut::()) + .and_then(|value| value.try_downcast_mut::()) } } @@ -222,7 +222,7 @@ impl TupleInfo { #[derive(Default, Debug)] pub struct DynamicTuple { represented_type: Option<&'static TypeInfo>, - fields: Vec>, + fields: Vec>, } impl DynamicTuple { @@ -245,13 +245,13 @@ impl DynamicTuple { } /// Appends an element with value `value` to the tuple. - pub fn insert_boxed(&mut self, value: Box) { + pub fn insert_boxed(&mut self, value: Box) { self.represented_type = None; self.fields.push(value); } /// Appends a typed element with value `value` to the tuple. - pub fn insert(&mut self, value: T) { + pub fn insert(&mut self, value: T) { self.represented_type = None; self.insert_boxed(Box::new(value)); } @@ -259,12 +259,12 @@ impl DynamicTuple { impl Tuple for DynamicTuple { #[inline] - fn field(&self, index: usize) -> Option<&dyn Reflect> { + fn field(&self, index: usize) -> Option<&dyn PartialReflect> { self.fields.get(index).map(|field| &**field) } #[inline] - fn field_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> { + fn field_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> { self.fields.get_mut(index).map(|field| &mut **field) } @@ -282,7 +282,7 @@ impl Tuple for DynamicTuple { } #[inline] - fn drain(self: Box) -> Vec> { + fn drain(self: Box) -> Vec> { self.fields } @@ -299,51 +299,41 @@ impl Tuple for DynamicTuple { } } -impl Reflect for DynamicTuple { +impl PartialReflect for DynamicTuple { #[inline] fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } #[inline] - fn into_any(self: Box) -> Box { + fn into_partial_reflect(self: Box) -> Box { self } - #[inline] - fn as_any(&self) -> &dyn Any { + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } - #[inline] - fn as_any_mut(&mut self) -> &mut dyn Any { + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } - #[inline] - fn into_reflect(self: Box) -> Box { - self + fn try_into_reflect(self: Box) -> Result, Box> { + Err(self) } - #[inline] - fn as_reflect(&self) -> &dyn Reflect { - self + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + None } - #[inline] - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + None } - fn apply(&mut self, value: &dyn Reflect) { + fn apply(&mut self, value: &dyn PartialReflect) { tuple_apply(self, value); } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - #[inline] fn reflect_kind(&self) -> ReflectKind { ReflectKind::Tuple @@ -365,15 +355,15 @@ impl Reflect for DynamicTuple { } #[inline] - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone_dynamic()) } - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { tuple_try_apply(self, value) } - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { + fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option { tuple_partial_eq(self, value) } @@ -391,8 +381,8 @@ impl Reflect for DynamicTuple { impl_type_path!((in bevy_reflect) DynamicTuple); -impl FromIterator> for DynamicTuple { - fn from_iter>>(fields: I) -> Self { +impl FromIterator> for DynamicTuple { + fn from_iter>>(fields: I) -> Self { Self { represented_type: None, fields: fields.into_iter().collect(), @@ -401,7 +391,7 @@ impl FromIterator> for DynamicTuple { } impl IntoIterator for DynamicTuple { - type Item = Box; + type Item = Box; type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { @@ -410,7 +400,7 @@ impl IntoIterator for DynamicTuple { } impl<'a> IntoIterator for &'a DynamicTuple { - type Item = &'a dyn Reflect; + type Item = &'a dyn PartialReflect; type IntoIter = TupleFieldIter<'a>; fn into_iter(self) -> Self::IntoIter { @@ -424,7 +414,7 @@ impl<'a> IntoIterator for &'a DynamicTuple { /// /// This function panics if `b` is not a tuple. #[inline] -pub fn tuple_apply(a: &mut T, b: &dyn Reflect) { +pub fn tuple_apply(a: &mut T, b: &dyn PartialReflect) { if let Err(err) = tuple_try_apply(a, b) { panic!("{err}"); } @@ -438,7 +428,7 @@ pub fn tuple_apply(a: &mut T, b: &dyn Reflect) { /// This function returns an [`ApplyError::MismatchedKinds`] if `b` is not a tuple or if /// applying elements to each other fails. #[inline] -pub fn tuple_try_apply(a: &mut T, b: &dyn Reflect) -> Result<(), ApplyError> { +pub fn tuple_try_apply(a: &mut T, b: &dyn PartialReflect) -> Result<(), ApplyError> { if let ReflectRef::Tuple(tuple) = b.reflect_ref() { for (i, value) in tuple.iter_fields().enumerate() { if let Some(v) = a.field_mut(i) { @@ -454,16 +444,16 @@ pub fn tuple_try_apply(a: &mut T, b: &dyn Reflect) -> Result<(), Apply Ok(()) } -/// Compares a [`Tuple`] with a [`Reflect`] value. +/// Compares a [`Tuple`] with a [`PartialReflect`] value. /// /// Returns true if and only if all of the following are true: /// - `b` is a tuple; /// - `b` has the same number of elements as `a`; -/// - [`Reflect::reflect_partial_eq`] returns `Some(true)` for pairwise elements of `a` and `b`. +/// - [`PartialReflect::reflect_partial_eq`] returns `Some(true)` for pairwise elements of `a` and `b`. /// /// Returns [`None`] if the comparison couldn't even be performed. #[inline] -pub fn tuple_partial_eq(a: &T, b: &dyn Reflect) -> Option { +pub fn tuple_partial_eq(a: &T, b: &dyn PartialReflect) -> Option { let ReflectRef::Tuple(b) = b.reflect_ref() else { return Some(false); }; @@ -512,17 +502,17 @@ macro_rules! impl_reflect_tuple { {$($index:tt : $name:tt),*} => { impl<$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> Tuple for ($($name,)*) { #[inline] - fn field(&self, index: usize) -> Option<&dyn Reflect> { + fn field(&self, index: usize) -> Option<&dyn PartialReflect> { match index { - $($index => Some(&self.$index as &dyn Reflect),)* + $($index => Some(&self.$index as &dyn PartialReflect),)* _ => None, } } #[inline] - fn field_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> { + fn field_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> { match index { - $($index => Some(&mut self.$index as &mut dyn Reflect),)* + $($index => Some(&mut self.$index as &mut dyn PartialReflect),)* _ => None, } } @@ -542,7 +532,7 @@ macro_rules! impl_reflect_tuple { } #[inline] - fn drain(self: Box) -> Vec> { + fn drain(self: Box) -> Vec> { vec![ $(Box::new(self.$index),)* ] @@ -561,46 +551,34 @@ macro_rules! impl_reflect_tuple { } } - impl<$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> Reflect for ($($name,)*) { + impl<$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> PartialReflect for ($($name,)*) { fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } - fn into_any(self: Box) -> Box { - self - } - - fn as_any(&self) -> &dyn Any { - self - } - - fn as_any_mut(&mut self) -> &mut dyn Any { + #[inline] + fn into_partial_reflect(self: Box) -> Box { self } - fn into_reflect(self: Box) -> Box { + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } - fn as_reflect(&self) -> &dyn Reflect { + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self + fn try_into_reflect(self: Box) -> Result, Box> { + Ok(self) } - fn apply(&mut self, value: &dyn Reflect) { - crate::tuple_apply(self, value); + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + Some(self) } - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { - crate::tuple_try_apply(self, value) - } - - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + Some(self) } fn reflect_kind(&self) -> ReflectKind { @@ -619,13 +597,52 @@ macro_rules! impl_reflect_tuple { ReflectOwned::Tuple(self) } - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone_dynamic()) } - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { + fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option { crate::tuple_partial_eq(self, value) } + + fn apply(&mut self, value: &dyn PartialReflect) { + crate::tuple_apply(self, value); + } + + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { + crate::tuple_try_apply(self, value) + } + } + + impl<$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> Reflect for ($($name,)*) { + 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 <$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> Typed for ($($name,)*) { @@ -653,7 +670,7 @@ macro_rules! impl_reflect_tuple { impl<$($name: FromReflect + MaybeTyped + TypePath + GetTypeRegistration),*> FromReflect for ($($name,)*) { - fn from_reflect(reflect: &dyn Reflect) -> Option { + fn from_reflect(reflect: &dyn PartialReflect) -> Option { if let ReflectRef::Tuple(_ref_tuple) = reflect.reflect_ref() { Some( ( diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index 7380278eb2f40..dd923e47be795 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -2,8 +2,8 @@ use bevy_reflect_derive::impl_type_path; use crate::attributes::{impl_custom_attribute_methods, CustomAttributes}; use crate::{ - self as bevy_reflect, ApplyError, DynamicTuple, Reflect, ReflectKind, ReflectMut, ReflectOwned, - ReflectRef, Tuple, TypeInfo, TypePath, TypePathTable, UnnamedField, + self as bevy_reflect, ApplyError, DynamicTuple, PartialReflect, Reflect, ReflectKind, + ReflectMut, ReflectOwned, ReflectRef, Tuple, TypeInfo, TypePath, TypePathTable, UnnamedField, }; use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; @@ -21,7 +21,7 @@ use std::sync::Arc; /// # Example /// /// ``` -/// use bevy_reflect::{Reflect, TupleStruct}; +/// use bevy_reflect::{PartialReflect, Reflect, TupleStruct}; /// /// #[derive(Reflect)] /// struct Foo(u32); @@ -30,20 +30,20 @@ use std::sync::Arc; /// /// assert_eq!(foo.field_len(), 1); /// -/// let field: &dyn Reflect = foo.field(0).unwrap(); -/// assert_eq!(field.downcast_ref::(), Some(&123)); +/// let field: &dyn PartialReflect = foo.field(0).unwrap(); +/// assert_eq!(field.try_downcast_ref::(), Some(&123)); /// ``` /// /// [tuple struct-like]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#using-tuple-structs-without-named-fields-to-create-different-types /// [reflection]: crate -pub trait TupleStruct: Reflect { +pub trait TupleStruct: PartialReflect { /// Returns a reference to the value of the field with index `index` as a /// `&dyn Reflect`. - fn field(&self, index: usize) -> Option<&dyn Reflect>; + fn field(&self, index: usize) -> Option<&dyn PartialReflect>; /// Returns a mutable reference to the value of the field with index `index` /// as a `&mut dyn Reflect`. - fn field_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>; + fn field_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>; /// Returns the number of fields in the tuple struct. fn field_len(&self) -> usize; @@ -165,7 +165,7 @@ impl<'a> TupleStructFieldIter<'a> { } impl<'a> Iterator for TupleStructFieldIter<'a> { - type Item = &'a dyn Reflect; + type Item = &'a dyn PartialReflect; fn next(&mut self) -> Option { let value = self.tuple_struct.field(self.index); @@ -212,24 +212,24 @@ pub trait GetTupleStructField { impl GetTupleStructField for S { fn get_field(&self, index: usize) -> Option<&T> { self.field(index) - .and_then(|value| value.downcast_ref::()) + .and_then(|value| value.try_downcast_ref::()) } fn get_field_mut(&mut self, index: usize) -> Option<&mut T> { self.field_mut(index) - .and_then(|value| value.downcast_mut::()) + .and_then(|value| value.try_downcast_mut::()) } } impl GetTupleStructField for dyn TupleStruct { fn get_field(&self, index: usize) -> Option<&T> { self.field(index) - .and_then(|value| value.downcast_ref::()) + .and_then(|value| value.try_downcast_ref::()) } fn get_field_mut(&mut self, index: usize) -> Option<&mut T> { self.field_mut(index) - .and_then(|value| value.downcast_mut::()) + .and_then(|value| value.try_downcast_mut::()) } } @@ -237,7 +237,7 @@ impl GetTupleStructField for dyn TupleStruct { #[derive(Default)] pub struct DynamicTupleStruct { represented_type: Option<&'static TypeInfo>, - fields: Vec>, + fields: Vec>, } impl DynamicTupleStruct { @@ -261,24 +261,24 @@ impl DynamicTupleStruct { } /// Appends an element with value `value` to the tuple struct. - pub fn insert_boxed(&mut self, value: Box) { + pub fn insert_boxed(&mut self, value: Box) { self.fields.push(value); } /// Appends a typed element with value `value` to the tuple struct. - pub fn insert(&mut self, value: T) { + pub fn insert(&mut self, value: T) { self.insert_boxed(Box::new(value)); } } impl TupleStruct for DynamicTupleStruct { #[inline] - fn field(&self, index: usize) -> Option<&dyn Reflect> { + fn field(&self, index: usize) -> Option<&dyn PartialReflect> { self.fields.get(index).map(|field| &**field) } #[inline] - fn field_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> { + fn field_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> { self.fields.get_mut(index).map(|field| &mut **field) } @@ -307,43 +307,40 @@ impl TupleStruct for DynamicTupleStruct { } } -impl Reflect for DynamicTupleStruct { +impl PartialReflect for DynamicTupleStruct { #[inline] fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } #[inline] - fn into_any(self: Box) -> Box { + fn into_partial_reflect(self: Box) -> Box { self } #[inline] - fn as_any(&self) -> &dyn Any { + fn as_partial_reflect(&self) -> &dyn PartialReflect { self } #[inline] - fn as_any_mut(&mut self) -> &mut dyn Any { + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { self } - #[inline] - fn into_reflect(self: Box) -> Box { - self + fn try_into_reflect(self: Box) -> Result, Box> { + Err(self) } - #[inline] - fn as_reflect(&self) -> &dyn Reflect { - self + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + None } - #[inline] - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + None } - fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { + fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { if let ReflectRef::TupleStruct(tuple_struct) = value.reflect_ref() { for (i, value) in tuple_struct.iter_fields().enumerate() { if let Some(v) = self.field_mut(i) { @@ -359,12 +356,6 @@ impl Reflect for DynamicTupleStruct { Ok(()) } - #[inline] - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - #[inline] fn reflect_kind(&self) -> ReflectKind { ReflectKind::TupleStruct @@ -386,12 +377,12 @@ impl Reflect for DynamicTupleStruct { } #[inline] - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone_dynamic()) } #[inline] - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { + fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option { tuple_struct_partial_eq(self, value) } @@ -408,8 +399,6 @@ impl Reflect for DynamicTupleStruct { } impl_type_path!((in bevy_reflect) DynamicTupleStruct); -#[cfg(feature = "functions")] -crate::func::macros::impl_function_traits!(DynamicTupleStruct); impl Debug for DynamicTupleStruct { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { @@ -426,8 +415,8 @@ impl From for DynamicTupleStruct { } } -impl FromIterator> for DynamicTupleStruct { - fn from_iter>>(fields: I) -> Self { +impl FromIterator> for DynamicTupleStruct { + fn from_iter>>(fields: I) -> Self { Self { represented_type: None, fields: fields.into_iter().collect(), @@ -436,7 +425,7 @@ impl FromIterator> for DynamicTupleStruct { } impl IntoIterator for DynamicTupleStruct { - type Item = Box; + type Item = Box; type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { @@ -445,7 +434,7 @@ impl IntoIterator for DynamicTupleStruct { } impl<'a> IntoIterator for &'a DynamicTupleStruct { - type Item = &'a dyn Reflect; + type Item = &'a dyn PartialReflect; type IntoIter = TupleStructFieldIter<'a>; fn into_iter(self) -> Self::IntoIter { @@ -453,16 +442,19 @@ impl<'a> IntoIterator for &'a DynamicTupleStruct { } } -/// Compares a [`TupleStruct`] with a [`Reflect`] value. +/// Compares a [`TupleStruct`] with a [`PartialReflect`] value. /// /// Returns true if and only if all of the following are true: /// - `b` is a tuple struct; /// - `b` has the same number of fields as `a`; -/// - [`Reflect::reflect_partial_eq`] returns `Some(true)` for pairwise fields of `a` and `b`. +/// - [`PartialReflect::reflect_partial_eq`] returns `Some(true)` for pairwise fields of `a` and `b`. /// /// Returns [`None`] if the comparison couldn't even be performed. #[inline] -pub fn tuple_struct_partial_eq(a: &S, b: &dyn Reflect) -> Option { +pub fn tuple_struct_partial_eq( + a: &S, + b: &dyn PartialReflect, +) -> Option { let ReflectRef::TupleStruct(tuple_struct) = b.reflect_ref() else { return Some(false); }; diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index bbd9b22464104..a6a7ceb240424 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, ListInfo, MapInfo, Reflect, ReflectKind, SetInfo, StructInfo, - TupleInfo, TupleStructInfo, TypePath, TypePathTable, + DynamicTupleStruct, EnumInfo, ListInfo, MapInfo, PartialReflect, Reflect, ReflectKind, SetInfo, + StructInfo, TupleInfo, TupleStructInfo, TypePath, TypePathTable, }; use std::any::{Any, TypeId}; use std::fmt::Debug; @@ -27,7 +27,7 @@ use thiserror::Error; /// /// ``` /// # use std::any::Any; -/// # use bevy_reflect::{DynamicTypePath, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, TypeInfo, TypePath, ValueInfo, ApplyError}; +/// # use bevy_reflect::{DynamicTypePath, NamedField, PartialReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, TypeInfo, TypePath, ValueInfo, ApplyError}; /// # use bevy_reflect::utility::NonGenericTypeInfoCell; /// use bevy_reflect::Typed; /// @@ -54,20 +54,28 @@ use thiserror::Error; /// # fn type_path() -> &'static str { todo!() } /// # fn short_type_path() -> &'static str { todo!() } /// # } +/// # 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!() } +/// # fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { todo!() } +/// # fn reflect_ref(&self) -> ReflectRef { todo!() } +/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() } +/// # fn reflect_owned(self: Box) -> ReflectOwned { todo!() } +/// # fn clone_value(&self) -> Box { todo!() } +/// # } /// # impl Reflect for MyStruct { -/// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } -/// # 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 try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { todo!() } -/// # fn set(&mut self, value: Box) -> Result<(), Box> { todo!() } -/// # fn reflect_ref(&self) -> ReflectRef { todo!() } -/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() } -/// # fn reflect_owned(self: Box) -> ReflectOwned { todo!() } -/// # fn clone_value(&self) -> Box { todo!() } +/// # 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!() } /// # } /// ``` /// @@ -93,7 +101,7 @@ pub trait Typed: Reflect + TypePath { /// This trait has a blanket implementation for all types that implement `Typed` /// and manual implementations for all dynamic types (which simply return `None`). #[doc(hidden)] -pub trait MaybeTyped: Reflect { +pub trait MaybeTyped: PartialReflect { /// Returns the compile-time [info] for the underlying type, if it exists. /// /// [info]: TypeInfo @@ -140,12 +148,12 @@ pub enum TypeInfoError { /// Generally, for any given type, this value can be retrieved one of three ways: /// /// 1. [`Typed::type_info`] -/// 2. [`Reflect::get_represented_type_info`] +/// 2. [`PartialReflect::get_represented_type_info`] /// 3. [`TypeRegistry::get_type_info`] /// /// Each return a static reference to [`TypeInfo`], but they all have their own use cases. /// For example, if you know the type at compile time, [`Typed::type_info`] is probably -/// the simplest. If all you have is a `dyn Reflect`, you'll probably want [`Reflect::get_represented_type_info`]. +/// the simplest. If all you have is a `dyn PartialReflect`, you'll probably want [`PartialReflect::get_represented_type_info`]. /// Lastly, if all you have is a [`TypeId`] or [type path], you will need to go through /// [`TypeRegistry::get_type_info`]. /// @@ -153,8 +161,8 @@ pub enum TypeInfoError { /// it can be more performant. This is because those other methods may require attaining a lock on /// the static [`TypeInfo`], while the registry simply checks a map. /// -/// [`Reflect::get_represented_type_info`]: Reflect::get_represented_type_info /// [`TypeRegistry::get_type_info`]: crate::TypeRegistry::get_type_info +/// [`PartialReflect::get_represented_type_info`]: crate::PartialReflect::get_represented_type_info /// [type path]: TypePath::type_path #[derive(Debug, Clone)] pub enum TypeInfo { diff --git a/crates/bevy_reflect/src/type_registry.rs b/crates/bevy_reflect/src/type_registry.rs index eb848d9999705..1263b0bbed523 100644 --- a/crates/bevy_reflect/src/type_registry.rs +++ b/crates/bevy_reflect/src/type_registry.rs @@ -584,7 +584,7 @@ impl FromType for Reflec value .downcast_ref::() .map(|value| Serializable::Borrowed(value)) - .or_else(|| T::from_reflect(value).map(|value| Serializable::Owned(Box::new(value)))) + .or_else(|| T::from_reflect(value.as_partial_reflect()).map(|value| Serializable::Owned(Box::new(value)))) .unwrap_or_else(|| { panic!( "FromReflect::from_reflect failed when called on type `{}` with this value: {value:?}", @@ -788,7 +788,11 @@ mod test { let dyn_reflect = unsafe { reflect_from_ptr.as_reflect(Ptr::from(&value)) }; match dyn_reflect.reflect_ref() { bevy_reflect::ReflectRef::Struct(strukt) => { - let a = strukt.field("a").unwrap().downcast_ref::().unwrap(); + let a = strukt + .field("a") + .unwrap() + .try_downcast_ref::() + .unwrap(); assert_eq!(*a, 2.0); } _ => panic!("invalid reflection"), diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index cb29c13f86f25..92f7a9a8bbfd5 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -49,7 +49,7 @@ mod sealed { /// /// ``` /// # use std::any::Any; -/// # use bevy_reflect::{DynamicTypePath, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, Typed, TypeInfo, TypePath, ApplyError}; +/// # use bevy_reflect::{DynamicTypePath, NamedField, PartialReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, Typed, TypeInfo, TypePath, ApplyError}; /// use bevy_reflect::utility::NonGenericTypeInfoCell; /// /// struct Foo { @@ -70,20 +70,28 @@ mod sealed { /// # fn type_path() -> &'static str { todo!() } /// # fn short_type_path() -> &'static str { todo!() } /// # } -/// # impl Reflect for Foo { +/// # 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!() } +/// # fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { todo!() } +/// # fn reflect_ref(&self) -> ReflectRef { todo!() } +/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() } +/// # fn reflect_owned(self: Box) -> ReflectOwned { todo!() } +/// # fn clone_value(&self) -> Box { todo!() } +/// # } +/// # impl Reflect for Foo { /// # 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 try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { todo!() } /// # fn set(&mut self, value: Box) -> Result<(), Box> { todo!() } -/// # fn reflect_ref(&self) -> ReflectRef { todo!() } -/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() } -/// # fn reflect_owned(self: Box) -> ReflectOwned { todo!() } -/// # fn clone_value(&self) -> Box { todo!() } /// # } /// ``` /// @@ -130,7 +138,7 @@ impl Default for NonGenericTypeCell { /// /// ``` /// # use std::any::Any; -/// # use bevy_reflect::{DynamicTypePath, Reflect, ReflectMut, ReflectOwned, ReflectRef, TupleStructInfo, Typed, TypeInfo, TypePath, UnnamedField, ApplyError}; +/// # use bevy_reflect::{DynamicTypePath, PartialReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TupleStructInfo, Typed, TypeInfo, TypePath, UnnamedField, ApplyError}; /// use bevy_reflect::utility::GenericTypeInfoCell; /// /// struct Foo(T); @@ -149,20 +157,28 @@ impl Default for NonGenericTypeCell { /// # fn type_path() -> &'static str { todo!() } /// # fn short_type_path() -> &'static str { todo!() } /// # } -/// # impl Reflect for Foo { +/// # 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!() } +/// # fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { todo!() } +/// # fn reflect_ref(&self) -> ReflectRef { todo!() } +/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() } +/// # fn reflect_owned(self: Box) -> ReflectOwned { todo!() } +/// # fn clone_value(&self) -> Box { todo!() } +/// # } +/// # impl Reflect for Foo { /// # 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 try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { todo!() } /// # fn set(&mut self, value: Box) -> Result<(), Box> { todo!() } -/// # fn reflect_ref(&self) -> ReflectRef { todo!() } -/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() } -/// # fn reflect_owned(self: Box) -> ReflectOwned { todo!() } -/// # fn clone_value(&self) -> Box { todo!() } /// # } /// ``` /// diff --git a/crates/bevy_scene/src/dynamic_scene.rs b/crates/bevy_scene/src/dynamic_scene.rs index 992d7ef6259c7..6667fe836d735 100644 --- a/crates/bevy_scene/src/dynamic_scene.rs +++ b/crates/bevy_scene/src/dynamic_scene.rs @@ -5,7 +5,7 @@ use bevy_ecs::{ reflect::{AppTypeRegistry, ReflectComponent, ReflectMapEntities}, world::World, }; -use bevy_reflect::{Reflect, TypePath, TypeRegistry}; +use bevy_reflect::{PartialReflect, TypePath, TypeRegistry}; use bevy_utils::TypeIdMap; #[cfg(feature = "serialize")] @@ -28,7 +28,7 @@ use serde::Serialize; #[derive(Asset, TypePath, Default)] pub struct DynamicScene { /// Resources stored in the dynamic scene. - pub resources: Vec>, + pub resources: Vec>, /// Entities contained in the dynamic scene. pub entities: Vec, } @@ -40,8 +40,8 @@ pub struct DynamicEntity { /// Components that reference this entity must consistently use this identifier. pub entity: Entity, /// A vector of boxed components that belong to the given entity and - /// implement the [`Reflect`] trait. - pub components: Vec>, + /// implement the [`PartialReflect`] trait. + pub components: Vec>, } impl DynamicScene { @@ -117,7 +117,11 @@ impl DynamicScene { // If the entity already has the given component attached, // just apply the (possibly) new value, otherwise add the // component to the entity. - reflect_component.apply_or_insert(entity_mut, &**component, &type_registry); + reflect_component.apply_or_insert( + entity_mut, + component.as_partial_reflect(), + &type_registry, + ); } } diff --git a/crates/bevy_scene/src/dynamic_scene_builder.rs b/crates/bevy_scene/src/dynamic_scene_builder.rs index ea14930466cf1..26084c1a3e27f 100644 --- a/crates/bevy_scene/src/dynamic_scene_builder.rs +++ b/crates/bevy_scene/src/dynamic_scene_builder.rs @@ -6,7 +6,7 @@ use bevy_ecs::{ reflect::{AppTypeRegistry, ReflectComponent, ReflectResource}, world::World, }; -use bevy_reflect::Reflect; +use bevy_reflect::PartialReflect; use bevy_utils::default; use std::collections::BTreeMap; @@ -52,8 +52,10 @@ use std::collections::BTreeMap; /// # let entity = world.spawn(ComponentA).id(); /// let dynamic_scene = DynamicSceneBuilder::from_world(&world).extract_entity(entity).build(); /// ``` +/// +/// [`Reflect`]: bevy_reflect::Reflect pub struct DynamicSceneBuilder<'w> { - extracted_resources: BTreeMap>, + extracted_resources: BTreeMap>, extracted_scene: BTreeMap, component_filter: SceneFilter, resource_filter: SceneFilter, diff --git a/crates/bevy_scene/src/serde.rs b/crates/bevy_scene/src/serde.rs index b5ac7478c99c4..497c4c4afcf50 100644 --- a/crates/bevy_scene/src/serde.rs +++ b/crates/bevy_scene/src/serde.rs @@ -3,9 +3,10 @@ use crate::{DynamicEntity, DynamicScene}; use bevy_ecs::entity::Entity; use bevy_reflect::serde::{TypedReflectDeserializer, TypedReflectSerializer}; +use bevy_reflect::PartialReflect; use bevy_reflect::{ serde::{ReflectDeserializer, TypeRegistrationDeserializer}, - Reflect, TypeRegistry, + TypeRegistry, }; use bevy_utils::HashSet; use serde::ser::SerializeMap; @@ -155,7 +156,7 @@ impl<'a> Serialize for EntitySerializer<'a> { /// deserializing through [`SceneMapDeserializer`]. pub struct SceneMapSerializer<'a> { /// List of boxed values of unique type to serialize. - pub entries: &'a [Box], + pub entries: &'a [Box], /// Type registry in which the types used in `entries` are registered. pub registry: &'a TypeRegistry, } @@ -169,7 +170,7 @@ impl<'a> Serialize for SceneMapSerializer<'a> { for reflect in self.entries { state.serialize_entry( reflect.get_represented_type_info().unwrap().type_path(), - &TypedReflectSerializer::new(&**reflect, self.registry), + &TypedReflectSerializer::new(reflect.as_partial_reflect(), self.registry), )?; } state.end() @@ -419,7 +420,7 @@ pub struct SceneMapDeserializer<'a> { } impl<'a, 'de> DeserializeSeed<'de> for SceneMapDeserializer<'a> { - type Value = Vec>; + type Value = Vec>; fn deserialize(self, deserializer: D) -> Result where @@ -436,7 +437,7 @@ struct SceneMapVisitor<'a> { } impl<'a, 'de> Visitor<'de> for SceneMapVisitor<'a> { - type Value = Vec>; + type Value = Vec>; fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { formatter.write_str("map of reflect types") diff --git a/crates/bevy_state/src/reflect.rs b/crates/bevy_state/src/reflect.rs index 89ada5f9938fe..422d4aff1a341 100644 --- a/crates/bevy_state/src/reflect.rs +++ b/crates/bevy_state/src/reflect.rs @@ -2,7 +2,7 @@ use crate::state::{FreelyMutableState, NextState, State, States}; use bevy_ecs::reflect::from_reflect_with_fallback; use bevy_ecs::world::World; -use bevy_reflect::{FromType, Reflect, TypeRegistry}; +use bevy_reflect::{FromType, Reflect, TypePath, TypeRegistry}; /// A struct used to operate on the reflected [`States`] trait of a type. /// @@ -68,7 +68,7 @@ impl ReflectFreelyMutableStateFns { /// /// 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 } } @@ -80,11 +80,15 @@ impl ReflectFreelyMutableState { } } -impl FromType for ReflectFreelyMutableState { +impl FromType for ReflectFreelyMutableState { fn from_type() -> Self { ReflectFreelyMutableState(ReflectFreelyMutableStateFns { set_next_state: |world, reflected_state, registry| { - let new_state: S = from_reflect_with_fallback(reflected_state, world, registry); + let new_state: S = from_reflect_with_fallback( + reflected_state.as_partial_reflect(), + world, + registry, + ); if let Some(mut next_state) = world.get_resource_mut::>() { next_state.set(new_state); } diff --git a/examples/reflection/dynamic_types.rs b/examples/reflection/dynamic_types.rs index 6ccf65addc1fb..18227cb59810e 100644 --- a/examples/reflection/dynamic_types.rs +++ b/examples/reflection/dynamic_types.rs @@ -3,8 +3,8 @@ use bevy::reflect::{ reflect_trait, serde::TypedReflectDeserializer, std_traits::ReflectDefault, DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicSet, DynamicStruct, DynamicTuple, - DynamicTupleStruct, DynamicVariant, FromReflect, Reflect, ReflectFromReflect, ReflectRef, Set, - TypeRegistry, Typed, + DynamicTupleStruct, DynamicVariant, FromReflect, PartialReflect, Reflect, ReflectFromReflect, + ReflectRef, Set, TypeRegistry, Typed, }; use serde::de::DeserializeSeed; use std::collections::{HashMap, HashSet}; @@ -34,6 +34,7 @@ fn main() { // When working with reflected types, however, we often "erase" this type information // using the `Reflect` trait object. + // This trait object also gives us access to all the methods in the `PartialReflect` trait too. // The underlying type is still the same (in this case, `Player`), // but now we've hidden that information from the compiler. let reflected: Box = Box::new(player); @@ -41,23 +42,24 @@ fn main() { // Because it's the same type under the hood, we can still downcast it back to the original type. assert!(reflected.downcast_ref::().is_some()); - // But now let's "clone" our type using `Reflect::clone_value`. - let cloned: Box = reflected.clone_value(); + // But now let's "clone" our type using `PartialReflect::clone_value`. + // Notice here we bind it as a `dyn PartialReflect`. + let cloned: Box = reflected.clone_value(); - // If we try to downcast back to `Player`, we'll get an error. - assert!(cloned.downcast_ref::().is_none()); + // If we try and convert it to a `dyn Reflect` trait object, we'll get an error. + assert!(cloned.try_as_reflect().is_none()); // Why is this? - // Well the reason is that `Reflect::clone_value` actually creates a dynamic type. - // Since `Player` is a struct, we actually get a `DynamicStruct` back. - assert!(cloned.is::()); + // Well the reason is that `PartialReflect::clone_value` actually creates a dynamic type. + // Since `Player` is a struct, our trait object is actually a value of `DynamicStruct`. + assert!(cloned.is_dynamic()); // This dynamic type is used to represent (or "proxy") the original type, // so that we can continue to access its fields and overall structure. let ReflectRef::Struct(cloned_ref) = cloned.reflect_ref() else { panic!("expected struct") }; - let id = cloned_ref.field("id").unwrap().downcast_ref::(); + let id = cloned_ref.field("id").unwrap().try_downcast_ref::(); assert_eq!(id, Some(&123)); // It also enables us to create a representation of a type without having compile-time @@ -73,7 +75,6 @@ fn main() { .unwrap(); // Our deserialized output is a `DynamicStruct` that proxies/represents a `Player`. - assert!(deserialized.downcast_ref::().is_some()); assert!(deserialized.represents::()); // And while this does allow us to access the fields and structure of the type, @@ -84,20 +85,24 @@ fn main() { .data::() .expect("`ReflectIdentifiable` should be registered"); + // Trying to access the registry with our `deserialized` will give a compile error + // since it doesn't implement `Reflect`, only `PartialReflect`. + // Similarly, trying to force the operation will fail. // This fails since the underlying type of `deserialized` is `DynamicStruct` and not `Player`. - assert!(reflect_identifiable - .get(deserialized.as_reflect()) + assert!(deserialized + .try_as_reflect() + .and_then(|reflect_trait_obj| reflect_identifiable.get(reflect_trait_obj)) .is_none()); // So how can we go from a dynamic type to a concrete type? // There are two ways: - // 1. Using `Reflect::apply`. + // 1. Using `PartialReflect::apply`. { // If you know the type at compile time, you can construct a new value and apply the dynamic // value to it. let mut value = Player::default(); - value.apply(deserialized.as_reflect()); + value.apply(deserialized.as_ref()); assert_eq!(value.id, 123); // If you don't know the type at compile time, you need a dynamic way of constructing @@ -107,7 +112,7 @@ fn main() { .expect("`ReflectDefault` should be registered"); let mut value: Box = reflect_default.default(); - value.apply(deserialized.as_reflect()); + value.apply(deserialized.as_ref()); let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap(); assert_eq!(identifiable.id(), 123); @@ -117,7 +122,7 @@ fn main() { { // If you know the type at compile time, you can use the `FromReflect` trait to convert the // dynamic value into the concrete type directly. - let value: Player = Player::from_reflect(deserialized.as_reflect()).unwrap(); + let value: Player = Player::from_reflect(deserialized.as_ref()).unwrap(); assert_eq!(value.id, 123); // If you don't know the type at compile time, you can use the `ReflectFromReflect` type data @@ -127,14 +132,14 @@ fn main() { .expect("`ReflectFromReflect` should be registered"); let value: Box = reflect_from_reflect - .from_reflect(deserialized.as_reflect()) + .from_reflect(deserialized.as_ref()) .unwrap(); let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap(); assert_eq!(identifiable.id(), 123); } // Lastly, while dynamic types are commonly generated via reflection methods like - // `Reflect::clone_value` or via the reflection deserializers, + // `PartialReflect::clone_value` or via the reflection deserializers, // you can also construct them manually. let mut my_dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]); @@ -144,9 +149,13 @@ fn main() { assert_eq!(my_list, vec![1, 2, 3]); // And if you want it to actually proxy a type, you can configure it to do that as well: - assert!(!my_dynamic_list.as_reflect().represents::>()); + assert!(!my_dynamic_list + .as_partial_reflect() + .represents::>()); my_dynamic_list.set_represented_type(Some(>::type_info())); - assert!(my_dynamic_list.as_reflect().represents::>()); + assert!(my_dynamic_list + .as_partial_reflect() + .represents::>()); // ============================= REFERENCE ============================= // // For reference, here are all the available dynamic types: diff --git a/examples/reflection/function_reflection.rs b/examples/reflection/function_reflection.rs index a1de336f66ec4..25fe09e639db0 100644 --- a/examples/reflection/function_reflection.rs +++ b/examples/reflection/function_reflection.rs @@ -10,7 +10,7 @@ use bevy::reflect::func::{ ArgList, DynamicClosure, DynamicClosureMut, DynamicFunction, FunctionError, FunctionInfo, IntoClosure, IntoClosureMut, IntoFunction, Return, }; -use bevy::reflect::Reflect; +use bevy::reflect::{PartialReflect, Reflect}; // Note that the `dbg!` invocations are used purely for demonstration purposes // and are not strictly necessary for the example to work. @@ -52,8 +52,8 @@ fn main() { // The `Return` value can be pattern matched or unwrapped to get the underlying reflection data. // For the sake of brevity, we'll just unwrap it here and downcast it to the expected type of `i32`. - let value: Box = return_value.unwrap_owned(); - assert_eq!(value.take::().unwrap(), 4); + let value: Box = return_value.unwrap_owned(); + assert_eq!(value.try_take::().unwrap(), 4); // The same can also be done for closures that capture references to their environment. // Closures that capture their environment immutably can be converted into a `DynamicClosure` @@ -64,8 +64,8 @@ fn main() { let function: DynamicClosure = dbg!(clamp.into_closure()); let args = dbg!(ArgList::new().push_owned(2_i32)); let return_value = dbg!(function.call(args).unwrap()); - let value: Box = return_value.unwrap_owned(); - assert_eq!(value.take::().unwrap(), 5); + let value: Box = return_value.unwrap_owned(); + assert_eq!(value.try_take::().unwrap(), 5); // We can also handle closures that capture their environment mutably // using the `IntoClosureMut` trait. @@ -112,8 +112,8 @@ fn main() { let get_value = dbg!(Data::get_value.into_function()); let args = dbg!(ArgList::new().push_ref(&data)); let return_value = dbg!(get_value.call(args).unwrap()); - let value: &dyn Reflect = return_value.unwrap_ref(); - assert_eq!(value.downcast_ref::().unwrap(), "Hello, world!"); + let value: &dyn PartialReflect = return_value.unwrap_ref(); + assert_eq!(value.try_downcast_ref::().unwrap(), "Hello, world!"); // Lastly, for more complex use cases, you can always create a custom `DynamicFunction` manually. // This is useful for functions that can't be converted via the `IntoFunction` trait. @@ -172,9 +172,9 @@ fn main() { let args = dbg!(ArgList::new().push_owned(5_i32).push_mut(&mut container)); let value = dbg!(get_or_insert_function.call(args).unwrap()).unwrap_ref(); - assert_eq!(value.downcast_ref::(), Some(&5)); + assert_eq!(value.try_downcast_ref::(), Some(&5)); let args = dbg!(ArgList::new().push_owned(500_i32).push_mut(&mut container)); let value = dbg!(get_or_insert_function.call(args).unwrap()).unwrap_ref(); - assert_eq!(value.downcast_ref::(), Some(&5)); + assert_eq!(value.try_downcast_ref::(), Some(&5)); } diff --git a/examples/reflection/reflection.rs b/examples/reflection/reflection.rs index 03944b7dc9ad6..283c1c6d18257 100644 --- a/examples/reflection/reflection.rs +++ b/examples/reflection/reflection.rs @@ -8,7 +8,7 @@ use bevy::{ prelude::*, reflect::{ serde::{ReflectDeserializer, ReflectSerializer}, - DynamicStruct, + DynamicStruct, PartialReflect, }, }; use serde::de::DeserializeSeed; @@ -65,13 +65,20 @@ fn setup(type_registry: Res) { assert_eq!(value.a, 2); assert_eq!(*value.get_field::("a").unwrap(), 2); - // You can also get the &dyn Reflect value of a field like this + // You can also get the `&dyn PartialReflect` value of a field like this let field = value.field("a").unwrap(); - // you can downcast Reflect values like this: - assert_eq!(*field.downcast_ref::().unwrap(), 2); + // But values introspected via `PartialReflect` will not return `dyn Reflect` trait objects + // (even if the containing type does implement `Reflect`), so we need to convert them: + let fully_reflected_field = field.try_as_reflect().unwrap(); - // DynamicStruct also implements the `Struct` and `Reflect` traits. + // Now, you can downcast your `Reflect` value like this: + assert_eq!(*fully_reflected_field.downcast_ref::().unwrap(), 2); + + // For this specific case, we also support the shortcut `try_downcast_ref`: + assert_eq!(*field.try_downcast_ref::().unwrap(), 2); + + // `DynamicStruct` also implements the `Struct` and `Reflect` traits. let mut patch = DynamicStruct::default(); patch.insert("a", 4usize); @@ -94,10 +101,14 @@ fn setup(type_registry: Res) { let mut deserializer = ron::de::Deserializer::from_str(&ron_string).unwrap(); let reflect_value = reflect_deserializer.deserialize(&mut deserializer).unwrap(); - // Deserializing returns a Box value. Generally, deserializing a value will return - // the "dynamic" variant of a type. For example, deserializing a struct will return the - // DynamicStruct type. "Value types" will be deserialized as themselves. - let _deserialized_struct = reflect_value.downcast_ref::(); + // Deserializing returns a `Box` value. + // Generally, deserializing a value will return the "dynamic" variant of a type. + // For example, deserializing a struct will return the DynamicStruct type. + // "Value types" will be deserialized as themselves. + assert_eq!( + reflect_value.reflect_type_path(), + DynamicStruct::type_path(), + ); // Reflect has its own `partial_eq` implementation, named `reflect_partial_eq`. This behaves // like normal `partial_eq`, but it treats "dynamic" and "non-dynamic" types the same. The diff --git a/examples/reflection/reflection_types.rs b/examples/reflection/reflection_types.rs index b000e7bed5c89..673092a69448b 100644 --- a/examples/reflection/reflection_types.rs +++ b/examples/reflection/reflection_types.rs @@ -4,7 +4,7 @@ use bevy::{ prelude::*, - reflect::{DynamicList, ReflectRef}, + reflect::{DynamicList, PartialReflect, ReflectRef}, utils::HashMap, }; use serde::{Deserialize, Serialize}; @@ -42,8 +42,9 @@ enum D { } /// Reflect has "built in" support for some common traits like `PartialEq`, `Hash`, and `Serialize`. -/// These are exposed via methods like `Reflect::reflect_hash()`, `Reflect::reflect_partial_eq()`, and -/// `Reflect::serializable()`. You can force these implementations to use the actual trait +/// These are exposed via methods like `PartialReflect::reflect_hash()`, +/// `PartialReflect::reflect_partial_eq()`, and `PartialReflect::serializable()`. +/// You can force these implementations to use the actual trait /// implementations (instead of their defaults) like this: #[derive(Reflect, Hash, Serialize, PartialEq, Eq)] #[reflect(Hash, Serialize, PartialEq)]