From b8eed136436b343110985126843ce553f9beb76b Mon Sep 17 00:00:00 2001 From: soqb Date: Tue, 20 Feb 2024 15:02:59 +0000 Subject: [PATCH 01/16] downstream usages --- crates/bevy_asset/src/path.rs | 142 +------------------------ crates/bevy_render/src/render_asset.rs | 90 +--------------- 2 files changed, 7 insertions(+), 225 deletions(-) diff --git a/crates/bevy_asset/src/path.rs b/crates/bevy_asset/src/path.rs index 6ec1e8eaa6b78..6d8509ccc8238 100644 --- a/crates/bevy_asset/src/path.rs +++ b/crates/bevy_asset/src/path.rs @@ -1,15 +1,10 @@ use crate::io::AssetSourceId; -use bevy_reflect::{ - std_traits::ReflectDefault, utility::NonGenericTypeInfoCell, FromReflect, FromType, - GetTypeRegistration, Reflect, ReflectDeserialize, ReflectFromPtr, ReflectFromReflect, - ReflectKind, ReflectMut, ReflectOwned, ReflectRef, ReflectSerialize, TypeInfo, TypePath, - TypeRegistration, Typed, ValueInfo, -}; +use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize}; use bevy_utils::CowArc; use serde::{de::Visitor, Deserialize, Serialize}; use std::{ fmt::{Debug, Display}, - hash::{Hash, Hasher}, + hash::Hash, ops::Deref, path::{Path, PathBuf}, }; @@ -52,7 +47,8 @@ use thiserror::Error; /// This means that the common case of `asset_server.load("my_scene.scn")` when it creates and /// clones internal owned [`AssetPaths`](AssetPath). /// This also means that you should use [`AssetPath::parse`] in cases where `&str` is the explicit type. -#[derive(Eq, PartialEq, Hash, Clone, Default)] +#[derive(Eq, PartialEq, Hash, Clone, Default, Reflect)] +#[reflect_value(Debug, PartialEq, Hash, Serialize, Deserialize)] pub struct AssetPath<'a> { source: AssetSourceId<'a>, path: CowArc<'a, Path>, @@ -593,136 +589,6 @@ impl<'de> Visitor<'de> for AssetPathVisitor { } } -// NOTE: We manually implement "reflect value" because deriving Reflect on `AssetPath` breaks dynamic linking -// See https://github.com/bevyengine/bevy/issues/9747 -// NOTE: This could use `impl_reflect_value` if it supported static lifetimes. - -impl GetTypeRegistration for AssetPath<'static> { - fn get_type_registration() -> TypeRegistration { - let mut registration = TypeRegistration::of::(); - registration.insert::(FromType::::from_type()); - registration.insert::(FromType::::from_type()); - registration.insert::(FromType::::from_type()); - registration.insert::(FromType::::from_type()); - registration.insert::(FromType::::from_type()); - registration - } -} - -impl TypePath for AssetPath<'static> { - fn type_path() -> &'static str { - "bevy_asset::path::AssetPath<'static>" - } - fn short_type_path() -> &'static str { - "AssetPath<'static>" - } - fn type_ident() -> Option<&'static str> { - Some("AssetPath<'static>") - } - fn crate_name() -> Option<&'static str> { - None - } - fn module_path() -> Option<&'static str> { - None - } -} -impl Typed for AssetPath<'static> { - fn type_info() -> &'static TypeInfo { - static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); - CELL.get_or_set(|| { - let info = ValueInfo::new::(); - TypeInfo::Value(info) - }) - } -} -impl Reflect for AssetPath<'static> { - #[inline] - 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 core::any::Any { - self - } - #[inline] - fn as_any_mut(&mut self) -> &mut dyn core::any::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 apply(&mut self, value: &dyn Reflect) { - let value = Reflect::as_any(value); - if let Some(value) = value.downcast_ref::() { - *self = value.clone(); - } else { - panic!("Value is not {}.", std::any::type_name::()); - } - } - #[inline] - fn set( - &mut self, - value: Box, - ) -> Result<(), Box> { - *self = ::take(value)?; - Ok(()) - } - fn reflect_kind(&self) -> ReflectKind { - ReflectKind::Value - } - fn reflect_ref(&self) -> ReflectRef { - ReflectRef::Value(self) - } - fn reflect_mut(&mut self) -> ReflectMut { - ReflectMut::Value(self) - } - fn reflect_owned(self: Box) -> ReflectOwned { - ReflectOwned::Value(self) - } - #[inline] - fn clone_value(&self) -> Box { - Box::new(self.clone()) - } - fn reflect_hash(&self) -> Option { - let mut hasher = bevy_reflect::utility::reflect_hasher(); - Hash::hash(&::core::any::Any::type_id(self), &mut hasher); - Hash::hash(self, &mut hasher); - Some(Hasher::finish(&hasher)) - } - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { - let value = ::as_any(value); - if let Some(value) = ::downcast_ref::(value) { - Some(PartialEq::eq(self, value)) - } else { - Some(false) - } - } - fn debug(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - ::core::fmt::Debug::fmt(self, f) - } -} -impl FromReflect for AssetPath<'static> { - fn from_reflect(reflect: &dyn Reflect) -> Option { - Some(Clone::clone(::downcast_ref::< - AssetPath<'static>, - >(::as_any(reflect))?)) - } -} - #[cfg(test)] mod tests { use crate::AssetPath; diff --git a/crates/bevy_render/src/render_asset.rs b/crates/bevy_render/src/render_asset.rs index 3eb0d2f0b610e..9e13c77b79dea 100644 --- a/crates/bevy_render/src/render_asset.rs +++ b/crates/bevy_render/src/render_asset.rs @@ -7,11 +7,7 @@ use bevy_ecs::{ system::{StaticSystemParam, SystemParam, SystemParamItem, SystemState}, world::{FromWorld, Mut}, }; -use bevy_reflect::{ - utility::{reflect_hasher, NonGenericTypeInfoCell}, - FromReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, - Typed, ValueInfo, -}; +use bevy_reflect::Reflect; use bevy_utils::{thiserror::Error, HashMap, HashSet}; use serde::{Deserialize, Serialize}; use std::marker::PhantomData; @@ -67,7 +63,8 @@ bitflags::bitflags! { /// If you have an asset that doesn't actually need to end up in the render world, like an Image /// that will be decoded into another Image asset, use `MAIN_WORLD` only. #[repr(transparent)] - #[derive(Serialize, TypePath, Deserialize, Hash, Clone, Copy, PartialEq, Eq, Debug)] + #[derive(Serialize, Deserialize, Hash, Clone, Copy, PartialEq, Eq, Debug, Reflect)] + #[reflect_value] pub struct RenderAssetUsages: u8 { const MAIN_WORLD = 1 << 0; const RENDER_WORLD = 1 << 1; @@ -88,87 +85,6 @@ impl Default for RenderAssetUsages { } } -impl Reflect for RenderAssetUsages { - fn get_represented_type_info(&self) -> Option<&'static bevy_reflect::TypeInfo> { - Some(::type_info()) - } - 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 Reflect { - self - } - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self - } - fn apply(&mut self, value: &dyn Reflect) { - let value = value.as_any(); - if let Some(&value) = value.downcast_ref::() { - *self = value; - } else { - panic!("Value is not a {}.", Self::type_path()); - } - } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - fn reflect_kind(&self) -> bevy_reflect::ReflectKind { - ReflectKind::Value - } - fn reflect_ref(&self) -> bevy_reflect::ReflectRef { - ReflectRef::Value(self) - } - fn reflect_mut(&mut self) -> bevy_reflect::ReflectMut { - ReflectMut::Value(self) - } - fn reflect_owned(self: Box) -> bevy_reflect::ReflectOwned { - ReflectOwned::Value(self) - } - fn clone_value(&self) -> Box { - Box::new(*self) - } - fn reflect_hash(&self) -> Option { - use std::hash::Hash; - use std::hash::Hasher; - let mut hasher = reflect_hasher(); - Hash::hash(&std::any::Any::type_id(self), &mut hasher); - Hash::hash(self, &mut hasher); - Some(hasher.finish()) - } - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { - let value = value.as_any(); - if let Some(value) = value.downcast_ref::() { - Some(std::cmp::PartialEq::eq(self, value)) - } else { - Some(false) - } - } -} - -impl FromReflect for RenderAssetUsages { - fn from_reflect(reflect: &dyn Reflect) -> Option { - let raw_value = *reflect.as_any().downcast_ref::()?; - Self::from_bits(raw_value) - } -} - -impl Typed for RenderAssetUsages { - fn type_info() -> &'static TypeInfo { - static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); - CELL.get_or_set(|| TypeInfo::Value(ValueInfo::new::())) - } -} - /// This plugin extracts the changed assets from the "app world" into the "render world" /// and prepares them for the GPU. They can then be accessed from the [`RenderAssets`] resource. /// From 334118276d124ef2bd4ab741f1fbb4a2f86b8be0 Mon Sep 17 00:00:00 2001 From: soqb Date: Wed, 21 Feb 2024 09:20:35 +0000 Subject: [PATCH 02/16] option --- crates/bevy_reflect/src/impls/std.rs | 255 ++------------------------- 1 file changed, 10 insertions(+), 245 deletions(-) diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 86f0984a829df..ff36bdff2aa85 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -1,17 +1,16 @@ use crate::std_traits::ReflectDefault; use crate::{self as bevy_reflect, ReflectFromPtr, ReflectFromReflect, ReflectOwned}; use crate::{ - impl_type_path, map_apply, map_partial_eq, Array, ArrayInfo, ArrayIter, DynamicEnum, - DynamicMap, Enum, EnumInfo, FromReflect, FromType, GetTypeRegistration, List, ListInfo, - ListIter, Map, MapInfo, MapIter, Reflect, ReflectDeserialize, ReflectKind, ReflectMut, - ReflectRef, ReflectSerialize, TupleVariantInfo, TypeInfo, TypePath, TypeRegistration, Typed, - UnitVariantInfo, UnnamedField, ValueInfo, VariantFieldIter, VariantInfo, VariantType, + impl_type_path, map_apply, map_partial_eq, Array, ArrayInfo, ArrayIter, DynamicMap, + FromReflect, FromType, GetTypeRegistration, List, ListInfo, ListIter, Map, MapInfo, MapIter, + Reflect, ReflectDeserialize, ReflectKind, ReflectMut, ReflectRef, ReflectSerialize, TypeInfo, + TypePath, TypeRegistration, Typed, ValueInfo, }; use crate::utility::{ reflect_hasher, GenericTypeInfoCell, GenericTypePathCell, NonGenericTypeInfoCell, }; -use bevy_reflect_derive::impl_reflect_value; +use bevy_reflect_derive::{impl_reflect, impl_reflect_value}; use std::fmt; use std::{ any::Any, @@ -787,248 +786,14 @@ impl_array_get_type_registration! { 30 31 32 } -impl GetTypeRegistration for Option { - fn get_type_registration() -> TypeRegistration { - TypeRegistration::of::>() +impl_reflect! { + #[type_path = "core::option"] + enum Option { + None, + Some(T), } } -impl Enum for Option { - fn field(&self, _name: &str) -> Option<&dyn Reflect> { - None - } - - fn field_at(&self, index: usize) -> Option<&dyn Reflect> { - match self { - Some(value) if index == 0 => Some(value), - _ => None, - } - } - - fn field_mut(&mut self, _name: &str) -> Option<&mut dyn Reflect> { - None - } - - fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> { - match self { - Some(value) if index == 0 => Some(value), - _ => None, - } - } - - fn index_of(&self, _name: &str) -> Option { - None - } - - fn name_at(&self, _index: usize) -> Option<&str> { - None - } - - fn iter_fields(&self) -> VariantFieldIter { - VariantFieldIter::new(self) - } - - #[inline] - fn field_len(&self) -> usize { - match self { - Some(..) => 1, - None => 0, - } - } - - #[inline] - fn variant_name(&self) -> &str { - match self { - Some(..) => "Some", - None => "None", - } - } - - fn variant_index(&self) -> usize { - match self { - None => 0, - Some(..) => 1, - } - } - - #[inline] - fn variant_type(&self) -> VariantType { - match self { - Some(..) => VariantType::Tuple, - None => VariantType::Unit, - } - } - - fn clone_dynamic(&self) -> DynamicEnum { - DynamicEnum::from_ref::(self) - } -} - -impl Reflect for Option { - #[inline] - 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 { - self - } - - #[inline] - fn as_any_mut(&mut self) -> &mut dyn Any { - self - } - - #[inline] - fn into_reflect(self: Box) -> Box { - self - } - - fn as_reflect(&self) -> &dyn Reflect { - self - } - - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self - } - - #[inline] - fn apply(&mut self, value: &dyn Reflect) { - if let ReflectRef::Enum(value) = value.reflect_ref() { - if self.variant_name() == value.variant_name() { - // Same variant -> just update fields - for (index, field) in value.iter_fields().enumerate() { - if let Some(v) = self.field_at_mut(index) { - v.apply(field.value()); - } - } - } else { - // New variant -> perform a switch - match value.variant_name() { - "Some" => { - let field = T::take_from_reflect( - value - .field_at(0) - .unwrap_or_else(|| { - panic!( - "Field in `Some` variant of {} should exist", - Self::type_path() - ) - }) - .clone_value(), - ) - .unwrap_or_else(|_| { - panic!( - "Field in `Some` variant of {} should be of type {}", - Self::type_path(), - T::type_path() - ) - }); - *self = Some(field); - } - "None" => { - *self = None; - } - _ => panic!("Enum is not a {}.", Self::type_path()), - } - } - } - } - - #[inline] - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - - fn reflect_kind(&self) -> ReflectKind { - ReflectKind::Enum - } - - fn reflect_ref(&self) -> ReflectRef { - ReflectRef::Enum(self) - } - - fn reflect_mut(&mut self) -> ReflectMut { - ReflectMut::Enum(self) - } - - fn reflect_owned(self: Box) -> ReflectOwned { - ReflectOwned::Enum(self) - } - - #[inline] - fn clone_value(&self) -> Box { - Box::new(Enum::clone_dynamic(self)) - } - - fn reflect_hash(&self) -> Option { - crate::enum_hash(self) - } - - fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { - crate::enum_partial_eq(self, value) - } -} - -impl FromReflect for Option { - fn from_reflect(reflect: &dyn Reflect) -> Option { - if let ReflectRef::Enum(dyn_enum) = reflect.reflect_ref() { - match dyn_enum.variant_name() { - "Some" => { - let field = T::take_from_reflect( - dyn_enum - .field_at(0) - .unwrap_or_else(|| { - panic!( - "Field in `Some` variant of {} should exist", - Option::::type_path() - ) - }) - .clone_value(), - ) - .unwrap_or_else(|_| { - panic!( - "Field in `Some` variant of {} should be of type {}", - Option::::type_path(), - T::type_path() - ) - }); - Some(Some(field)) - } - "None" => Some(None), - name => panic!( - "variant with name `{}` does not exist on enum `{}`", - name, - Self::type_path() - ), - } - } else { - None - } - } -} - -impl Typed for Option { - fn type_info() -> &'static TypeInfo { - static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); - CELL.get_or_insert::(|| { - let none_variant = VariantInfo::Unit(UnitVariantInfo::new("None")); - let some_variant = - VariantInfo::Tuple(TupleVariantInfo::new("Some", &[UnnamedField::new::(0)])); - TypeInfo::Enum(EnumInfo::new::(&[none_variant, some_variant])) - }) - } -} - -impl_type_path!(::core::option::Option); - impl TypePath for &'static T { fn type_path() -> &'static str { static CELL: GenericTypePathCell = GenericTypePathCell::new(); From 5ee176f65b438f03a8c46a6031b71a70a6a6e646 Mon Sep 17 00:00:00 2001 From: soqb Date: Mon, 19 Feb 2024 17:32:19 +0000 Subject: [PATCH 03/16] bevy_reflect` compiles! (+somehow diff is negative) --- .../src/container_attributes.rs | 8 +- .../bevy_reflect_derive/src/from_reflect.rs | 22 +- .../bevy_reflect_derive/src/impls/common.rs | 135 ++++ .../bevy_reflect_derive/src/impls/enums.rs | 96 +-- .../bevy_reflect_derive/src/impls/mod.rs | 2 + .../bevy_reflect_derive/src/impls/structs.rs | 93 +-- .../src/impls/tuple_structs.rs | 90 +-- .../bevy_reflect_derive/src/impls/values.rs | 63 +- crates/bevy_reflect/src/array.rs | 72 +- crates/bevy_reflect/src/enums/dynamic_enum.rs | 49 +- crates/bevy_reflect/src/enums/enum_trait.rs | 18 +- crates/bevy_reflect/src/enums/helpers.rs | 9 +- crates/bevy_reflect/src/enums/mod.rs | 40 +- crates/bevy_reflect/src/from_reflect.rs | 14 +- crates/bevy_reflect/src/impls/smallvec.rs | 100 ++- crates/bevy_reflect/src/impls/smol_str.rs | 8 +- crates/bevy_reflect/src/impls/std.rs | 756 +++++++++++------- crates/bevy_reflect/src/lib.rs | 55 +- crates/bevy_reflect/src/list.rs | 87 +- crates/bevy_reflect/src/map.rs | 123 +-- crates/bevy_reflect/src/path/access.rs | 19 +- crates/bevy_reflect/src/path/mod.rs | 45 +- crates/bevy_reflect/src/reflect.rs | 181 +++-- crates/bevy_reflect/src/serde/de.rs | 32 +- crates/bevy_reflect/src/serde/mod.rs | 32 +- crates/bevy_reflect/src/serde/ser.rs | 26 +- crates/bevy_reflect/src/struct_trait.rs | 94 ++- crates/bevy_reflect/src/tuple.rs | 151 ++-- crates/bevy_reflect/src/tuple_struct.rs | 73 +- crates/bevy_reflect/src/type_registry.rs | 6 +- 30 files changed, 1412 insertions(+), 1087 deletions(-) create mode 100644 crates/bevy_reflect/bevy_reflect_derive/src/impls/common.rs diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/container_attributes.rs b/crates/bevy_reflect/bevy_reflect_derive/src/container_attributes.rs index 9d236d9b5b8a8..23cb5799f3cde 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/container_attributes.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/container_attributes.rs @@ -484,9 +484,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) @@ -494,7 +494,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)) } }), diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs b/crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs index a4559cf81cbf1..f32880701aaf2 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs @@ -4,7 +4,7 @@ use crate::enum_utility::{get_variant_constructors, EnumVariantConstructors}; 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)? + ) + ) } } } @@ -55,8 +59,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()), @@ -136,8 +142,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/bevy_reflect_derive/src/impls/common.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/common.rs new file mode 100644 index 0000000000000..00c573152cc14 --- /dev/null +++ b/crates/bevy_reflect/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/bevy_reflect_derive/src/impls/enums.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs index 65aea76b9627d..1ce893daa43d4 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs @@ -1,7 +1,7 @@ use crate::derive_data::{EnumVariant, EnumVariantFields, ReflectEnum, StructField}; use crate::enum_utility::{get_variant_constructors, EnumVariantConstructors}; -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}; 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 variant_constructors, } = get_variant_constructors(reflect_enum, &ref_value, true); - 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) - } - } - }); - #[cfg(feature = "documentation")] let info_generator = { let doc = reflect_enum.meta().doc(); @@ -83,6 +59,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)), + ); let get_type_registration_impl = reflect_enum .meta() @@ -100,29 +82,31 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream #type_path_impl + #full_reflect_impl + 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, @@ -184,56 +168,22 @@ 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 apply(&mut self, #ref_value: &dyn #bevy_reflect_path::Reflect) { - if let #bevy_reflect_path::ReflectRef::Enum(#ref_value) = #bevy_reflect_path::Reflect::reflect_ref(#ref_value) { + fn apply(&mut self, #ref_value: &dyn #bevy_reflect_path::PartialReflect) { + 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) { @@ -280,11 +230,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/bevy_reflect_derive/src/impls/mod.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/mod.rs index db5418b446348..fe40046bc5371 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/mod.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/mod.rs @@ -1,9 +1,11 @@ +mod common; mod enums; mod structs; mod tuple_structs; mod typed; mod values; +pub(crate) use common::{common_partial_reflect_methods, impl_full_reflect}; pub(crate) use enums::impl_enum; pub(crate) use structs::impl_struct; pub(crate) use tuple_structs::impl_tuple_struct; diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs index 40441aafbcd7e..165e03c68a6bb 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs +++ b/crates/bevy_reflect/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}; use quote::{quote, ToTokens}; /// Implements `Struct`, `GetTypeRegistration`, and `Reflect` for the given derive data. @@ -30,22 +30,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) - } - } - }); - #[cfg(feature = "documentation")] let field_generator = { let docs = reflect_struct @@ -90,7 +74,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, + ); let get_type_registration_impl = reflect_struct.get_type_registration(&where_clause_options); let (impl_generics, ty_generics, where_clause) = reflect_struct @@ -108,29 +97,31 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS #type_path_impl + #full_reflect_impl + 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, @@ -154,62 +145,28 @@ 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 apply(&mut self, value: &dyn #bevy_reflect_path::Reflect) { - if let #bevy_reflect_path::ReflectRef::Struct(struct_value) = #bevy_reflect_path::Reflect::reflect_ref(value) { + fn apply(&mut self, value: &dyn #bevy_reflect_path::PartialReflect) { + 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(); #bevy_reflect_path::Struct::field_mut(self, name).map(|v| v.apply(value)); @@ -235,11 +192,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/bevy_reflect_derive/src/impls/tuple_structs.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/tuple_structs.rs index 659261466cff5..a03b996dbfa6c 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/tuple_structs.rs +++ b/crates/bevy_reflect/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}; use quote::{quote, ToTokens}; use syn::{Index, Member}; @@ -22,23 +22,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) - } - } - }); - #[cfg(feature = "documentation")] let field_generator = { let docs = reflect_struct @@ -82,6 +65,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, + ); let (impl_generics, ty_generics, where_clause) = reflect_struct .meta() @@ -98,15 +87,17 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> proc_macro2:: #type_path_impl + #full_reflect_impl + 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, @@ -123,62 +114,27 @@ 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 apply(&mut self, value: &dyn #bevy_reflect_path::Reflect) { - if let #bevy_reflect_path::ReflectRef::TupleStruct(struct_value) = #bevy_reflect_path::Reflect::reflect_ref(value) { + fn apply(&mut self, value: &dyn #bevy_reflect_path::PartialReflect) { + 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)) { #bevy_reflect_path::TupleStruct::field_mut(self, i).map(|v| v.apply(value)); } @@ -203,11 +159,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/bevy_reflect_derive/src/impls/values.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs index cb9162cc4a734..dc1a75cdf28b9 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs +++ b/crates/bevy_reflect/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}; 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); 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); @@ -44,63 +42,28 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream { #typed_impl - impl #impl_generics #bevy_reflect_path::Reflect for #type_path #ty_generics #where_reflect_clause { + #full_reflect_impl + + 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 apply(&mut self, value: &dyn #bevy_reflect_path::Reflect) { - let value = #bevy_reflect_path::Reflect::as_any(value); - if let #FQOption::Some(value) = ::downcast_ref::(value) { + fn apply(&mut self, value: &dyn #bevy_reflect_path::PartialReflect) { + if let #FQOption::Some(value) = ::try_downcast_ref::(value) { *self = #FQClone::clone(value); } else { panic!("Value is not {}.", ::type_path()); } } - #[inline] - fn set(&mut self, value: #FQBox) -> #FQResult<(), #FQBox> { - *self = ::take(value)?; - #FQResult::Ok(()) - } - fn reflect_kind(&self) -> #bevy_reflect_path::ReflectKind { #bevy_reflect_path::ReflectKind::Value } @@ -117,11 +80,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/src/array.rs b/crates/bevy_reflect/src/array.rs index 0b704a21f77e9..80b2b83328119 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, Reflect, ReflectKind, ReflectMut, ReflectOwned, - ReflectRef, TypeInfo, TypePath, TypePathTable, + self as bevy_reflect, utility::reflect_hasher, PartialReflect, Reflect, ReflectKind, + ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable, }; use bevy_reflect_derive::impl_type_path; use std::{ @@ -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,7 +63,7 @@ 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 { @@ -179,24 +179,24 @@ 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, } } - pub fn from_vec(values: Vec) -> Self { + pub fn from_vec(values: Vec) -> Self { Self { represented_type: None, values: values .into_iter() - .map(|field| Box::new(field) as Box) + .map(|field| Box::new(field) as Box) .collect::>() .into_boxed_slice(), } @@ -222,52 +222,43 @@ 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); } - #[inline] - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - #[inline] fn reflect_kind(&self) -> ReflectKind { ReflectKind::Array @@ -289,7 +280,7 @@ impl Reflect for DynamicArray { } #[inline] - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone_dynamic()) } @@ -298,7 +289,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) } @@ -316,12 +307,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) } @@ -336,7 +327,7 @@ impl Array for DynamicArray { } #[inline] - fn drain(self: Box) -> Vec> { + fn drain(self: Box) -> Vec> { self.values.into_vec() } @@ -369,7 +360,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 { @@ -389,7 +380,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); @@ -407,7 +398,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."); @@ -426,7 +417,10 @@ pub fn array_apply(array: &mut A, reflect: &dyn Reflect) { /// /// 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 d01c351448ae0..234349e8b9a24 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, DynamicStruct, DynamicTuple, - Enum, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Struct, Tuple, TypeInfo, - VariantFieldIter, VariantType, + 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. @@ -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 apply(&mut self, value: &dyn Reflect) { + fn apply(&mut self, value: &dyn PartialReflect) { if let ReflectRef::Enum(value) = value.reflect_ref() { if Enum::variant_name(self) == value.variant_name() { // Same variant -> just update fields @@ -373,12 +370,6 @@ impl Reflect for DynamicEnum { } } - #[inline] - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - #[inline] fn reflect_kind(&self) -> ReflectKind { ReflectKind::Enum @@ -400,7 +391,7 @@ impl Reflect for DynamicEnum { } #[inline] - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone_dynamic()) } @@ -410,7 +401,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) } diff --git a/crates/bevy_reflect/src/enums/enum_trait.rs b/crates/bevy_reflect/src/enums/enum_trait.rs index e6cb09e83ab9c..f87313ed3ab95 100644 --- a/crates/bevy_reflect/src/enums/enum_trait.rs +++ b/crates/bevy_reflect/src/enums/enum_trait.rs @@ -1,4 +1,4 @@ -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; @@ -87,19 +87,19 @@ use std::slice::Iter; /// [`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`. @@ -293,8 +293,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> { @@ -306,7 +306,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 b78af06f86729..47199880f9414 100644 --- a/crates/bevy_reflect/src/enums/mod.rs +++ b/crates/bevy_reflect/src/enums/mod.rs @@ -562,71 +562,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/from_reflect.rs b/crates/bevy_reflect/src/from_reflect.rs index 85de6c6bffd12..96d10fa6975a6 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. /// @@ -23,7 +23,7 @@ use crate::{FromType, Reflect}; /// [crate-level documentation]: crate 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. @@ -35,8 +35,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), @@ -97,7 +99,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 { @@ -106,7 +108,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/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index a911b3b2fdc0e..5c7331529759a 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -7,32 +7,32 @@ use std::any::Any; use crate::utility::GenericTypeInfoCell; use crate::{ self as bevy_reflect, FromReflect, FromType, GetTypeRegistration, List, ListInfo, ListIter, - Reflect, ReflectFromPtr, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, - TypeRegistration, Typed, + PartialReflect, Reflect, ReflectFromPtr, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, + TypeInfo, TypePath, TypeRegistration, Typed, }; impl List for SmallVec where T::Item: FromReflect + 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 {}.", @@ -43,12 +43,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 {}.", @@ -59,8 +59,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 { @@ -71,14 +72,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 + TypePath, { @@ -86,39 +86,35 @@ 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 set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - fn reflect_kind(&self) -> ReflectKind { ReflectKind::List } @@ -135,15 +131,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 + 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 + TypePath, @@ -160,7 +190,7 @@ impl FromReflect for SmallVec where T::Item: FromReflect + 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 ff36bdff2aa85..ea86d98231efd 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -3,8 +3,8 @@ use crate::{self as bevy_reflect, ReflectFromPtr, ReflectFromReflect, ReflectOwn use crate::{ impl_type_path, map_apply, map_partial_eq, Array, ArrayInfo, ArrayIter, DynamicMap, FromReflect, FromType, GetTypeRegistration, List, ListInfo, ListIter, Map, MapInfo, MapIter, - Reflect, ReflectDeserialize, ReflectKind, ReflectMut, ReflectRef, ReflectSerialize, TypeInfo, - TypePath, TypeRegistration, Typed, ValueInfo, + PartialReflect, Reflect, ReflectDeserialize, ReflectKind, ReflectMut, ReflectRef, + ReflectSerialize, TypeInfo, TypePath, TypeRegistration, Typed, ValueInfo, }; use crate::utility::{ @@ -220,17 +220,17 @@ macro_rules! impl_reflect_for_veclike { ($ty:path, $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 {}.", @@ -241,11 +241,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 {}.", @@ -255,8 +255,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] @@ -270,51 +270,48 @@ 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 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 set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - fn reflect_kind(&self) -> ReflectKind { ReflectKind::List } @@ -331,7 +328,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()) } @@ -339,11 +336,42 @@ 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) } } + impl Reflect for $ty { + 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 $ty { fn type_info() -> &'static TypeInfo { static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); @@ -362,7 +390,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() { @@ -402,28 +430,31 @@ macro_rules! impl_reflect_for_hashmap { V: FromReflect + TypePath, 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 { @@ -434,12 +465,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() @@ -462,9 +493,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 {}.", @@ -478,22 +509,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 + TypePath + Eq + Hash, V: FromReflect + TypePath, @@ -503,40 +534,37 @@ macro_rules! impl_reflect_for_hashmap { 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) { map_apply(self, value); } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - fn reflect_kind(&self) -> ReflectKind { ReflectKind::Map } @@ -553,15 +581,52 @@ 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) } } + impl Reflect for $ty + where + K: FromReflect + TypePath + Eq + Hash, + V: FromReflect + TypePath, + S: TypePath + BuildHasher + Send + Sync, + { + 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 { + 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 $ty where K: FromReflect + TypePath + Eq + Hash, @@ -593,7 +658,7 @@ macro_rules! impl_reflect_for_hashmap { V: FromReflect + TypePath, 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() { @@ -620,13 +685,13 @@ impl_type_path!(::bevy_utils::hashbrown::HashMap); 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] @@ -640,59 +705,48 @@ impl Array for [T; N] { } #[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 { + 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 apply(&mut self, value: &dyn Reflect) { + fn apply(&mut self, value: &dyn PartialReflect) { crate::array_apply(self, value); } - #[inline] - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - #[inline] fn reflect_kind(&self) -> ReflectKind { ReflectKind::Array @@ -714,7 +768,7 @@ impl Reflect for [T; N] { } #[inline] - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone_dynamic()) } @@ -724,13 +778,51 @@ impl Reflect for [T; N] { } #[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) } } +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() { @@ -818,49 +910,44 @@ 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 { + #[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) { - let value = value.as_any(); - if let Some(value) = value.downcast_ref::() { + fn apply(&mut self, value: &dyn PartialReflect) { + if let Some(value) = value.try_downcast_ref::() { *self = value.clone(); } else { panic!("Value is not a {}.", Self::type_path()); } } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - fn reflect_kind(&self) -> ReflectKind { ReflectKind::Value } @@ -877,7 +964,7 @@ impl Reflect for Cow<'static, str> { ReflectOwned::Value(self) } - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone()) } @@ -888,9 +975,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) @@ -902,6 +988,37 @@ impl Reflect for Cow<'static, str> { } } +impl Reflect for Cow<'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 Cow<'static, str> { fn type_info() -> &'static TypeInfo { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); @@ -920,13 +1037,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()) } } @@ -946,31 +1058,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 {}.", @@ -980,10 +1092,10 @@ impl List for Cow<'static, [T]> { 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 { @@ -994,7 +1106,7 @@ impl List for Cow<'static, [T]> { 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() @@ -1004,44 +1116,40 @@ impl List for Cow<'static, [T]> { } } -impl Reflect for Cow<'static, [T]> { +impl PartialReflect for Cow<'static, [T]> { fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { 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 set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - fn reflect_kind(&self) -> ReflectKind { ReflectKind::List } @@ -1058,7 +1166,7 @@ impl Reflect for Cow<'static, [T]> { ReflectOwned::List(self) } - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(List::clone_dynamic(self)) } @@ -1066,11 +1174,42 @@ impl Reflect for Cow<'static, [T]> { 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) } } +impl Reflect for Cow<'static, [T]> { + 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, [T]> { fn type_info() -> &'static TypeInfo { static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); @@ -1085,7 +1224,7 @@ impl GetTypeRegistration for Cow<'static, [T] } 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() { @@ -1098,49 +1237,44 @@ impl FromReflect for 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 { + #[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) { - let value = value.as_any(); - if let Some(&value) = value.downcast_ref::() { + fn apply(&mut self, value: &dyn PartialReflect) { + if let Some(&value) = value.try_downcast_ref::() { *self = value; } else { panic!("Value is not a {}.", Self::type_path()); } } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - fn reflect_ref(&self) -> ReflectRef { ReflectRef::Value(self) } @@ -1153,7 +1287,7 @@ impl Reflect for &'static str { ReflectOwned::Value(self) } - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(*self) } @@ -1164,9 +1298,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) @@ -1178,6 +1311,37 @@ impl Reflect for &'static str { } } +impl Reflect for &'static str { + fn into_any(self: Box) -> Box { + self + } + + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } + + fn into_reflect(self: Box) -> Box { + self + } + + fn as_reflect(&self) -> &dyn Reflect { + self + } + + fn as_reflect_mut(&mut self) -> &mut dyn Reflect { + self + } + + fn set(&mut self, value: Box) -> Result<(), Box> { + *self = value.take()?; + Ok(()) + } +} + impl Typed for &'static str { fn type_info() -> &'static TypeInfo { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); @@ -1195,54 +1359,49 @@ 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() } } -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 { + #[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) { - let value = value.as_any(); - if let Some(&value) = value.downcast_ref::() { + fn apply(&mut self, value: &dyn PartialReflect) { + if let Some(&value) = value.try_downcast_ref::() { *self = value; } else { panic!("Value is not a {}.", Self::type_path()); } } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - fn reflect_kind(&self) -> ReflectKind { ReflectKind::Value } @@ -1259,7 +1418,7 @@ impl Reflect for &'static Path { ReflectOwned::Value(self) } - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(*self) } @@ -1270,9 +1429,8 @@ 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) @@ -1280,6 +1438,37 @@ impl Reflect for &'static Path { } } +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 { fn type_info() -> &'static TypeInfo { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); @@ -1296,54 +1485,49 @@ 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() } } -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 { + #[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) { - let value = value.as_any(); - if let Some(value) = value.downcast_ref::() { + fn apply(&mut self, value: &dyn PartialReflect) { + if let Some(value) = value.try_downcast_ref::() { *self = value.clone(); } else { panic!("Value is not a {}.", Self::type_path()); } } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - fn reflect_kind(&self) -> ReflectKind { ReflectKind::Value } @@ -1360,7 +1544,7 @@ impl Reflect for Cow<'static, Path> { ReflectOwned::Value(self) } - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone()) } @@ -1371,9 +1555,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) @@ -1385,6 +1568,37 @@ impl Reflect for Cow<'static, Path> { } } +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> { fn type_info() -> &'static TypeInfo { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); @@ -1396,8 +1610,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()) } } @@ -1414,7 +1628,7 @@ impl GetTypeRegistration for 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, @@ -1438,45 +1652,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()); } @@ -1489,17 +1703,17 @@ 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()); } #[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)); } @@ -1522,7 +1736,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; } @@ -1552,28 +1766,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"); } @@ -1615,8 +1829,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 b11bbbf6ac1ab..9ff051f17f7d5 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -633,10 +633,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] @@ -652,16 +661,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] @@ -691,7 +706,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]); } @@ -723,11 +738,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()); } @@ -1056,9 +1071,9 @@ mod tests { let mut deserializer = Deserializer::from_str(&serialized).unwrap(); let reflect_deserializer = UntypedReflectDeserializer::new(®istry); let value = reflect_deserializer.deserialize(&mut deserializer).unwrap(); - let dynamic_struct = value.take::().unwrap(); + let roundtrip_foo = Foo::from_reflect(value.as_ref()).unwrap(); - assert!(foo.reflect_partial_eq(&dynamic_struct).unwrap()); + assert!(foo.reflect_partial_eq(&roundtrip_foo).unwrap()); } #[test] @@ -1825,7 +1840,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)); @@ -1846,7 +1861,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)); @@ -2062,7 +2077,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], @@ -2071,8 +2086,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(); @@ -2271,13 +2285,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 bc423132c02ea..27a2640d3fd6b 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, FromReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, - TypeInfo, TypePath, TypePathTable, + self as bevy_reflect, FromReflect, PartialReflect, Reflect, ReflectKind, ReflectMut, + ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable, }; /// A trait used to power [list-like] operations via [reflection]. @@ -47,34 +47,34 @@ use crate::{ /// [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,7 +94,7 @@ 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 { @@ -190,7 +190,7 @@ impl ListInfo { #[derive(Default)] pub struct DynamicList { represented_type: Option<&'static TypeInfo>, - values: Vec>, + values: Vec>, } impl DynamicList { @@ -213,38 +213,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() } @@ -256,7 +256,7 @@ impl List for DynamicList { ListIter::new(self) } - fn drain(self: Box) -> Vec> { + fn drain(self: Box) -> Vec> { self.values } @@ -272,52 +272,43 @@ 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); } - #[inline] - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - #[inline] fn reflect_kind(&self) -> ReflectKind { ReflectKind::List @@ -339,7 +330,7 @@ impl Reflect for DynamicList { } #[inline] - fn clone_value(&self) -> Box { + fn clone_value(&self) -> Box { Box::new(self.clone_dynamic()) } @@ -348,7 +339,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) } @@ -373,7 +364,7 @@ impl Debug for DynamicList { } impl IntoIterator for DynamicList { - type Item = Box; + type Item = Box; type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { @@ -396,7 +387,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 { @@ -435,7 +426,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 ReflectRef::List(list_value) = b.reflect_ref() { for (i, value) in list_value.iter().enumerate() { if i < a.len() { @@ -460,7 +451,7 @@ pub fn list_apply(a: &mut L, b: &dyn Reflect) { /// /// 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); }; @@ -518,7 +509,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 5bfb68783788d..77033167d9ff0 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -6,8 +6,8 @@ use bevy_reflect_derive::impl_type_path; use bevy_utils::{Entry, HashMap}; use crate::{ - self as bevy_reflect, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, - TypePath, TypePathTable, + self as bevy_reflect, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned, + ReflectRef, TypeInfo, TypePath, TypePathTable, }; /// A trait used to power [map-like] operations via [reflection]. @@ -41,22 +41,25 @@ use crate::{ /// /// [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; @@ -70,7 +73,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; @@ -81,15 +84,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. @@ -204,7 +207,7 @@ const HASH_ERROR: &str = "the given key does not support hashing"; #[derive(Default)] pub struct DynamicMap { represented_type: Option<&'static TypeInfo>, - values: Vec<(Box, Box)>, + values: Vec<(Box, Box)>, indices: HashMap, } @@ -229,32 +232,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)) .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)) .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)) @@ -268,7 +274,7 @@ impl Map for DynamicMap { MapIter::new(self) } - fn drain(self: Box) -> Vec<(Box, Box)> { + fn drain(self: Box) -> Vec<(Box, Box)> { self.values } @@ -286,9 +292,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)) { Entry::Occupied(entry) => { let (_old_key, old_value) = self.values.get_mut(*entry.get()).unwrap(); @@ -303,7 +309,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))?; @@ -312,46 +318,41 @@ 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 { - self - } - - fn as_any(&self) -> &dyn Any { + #[inline] + fn into_partial_reflect(self: Box) -> Box { self } - fn as_any_mut(&mut self) -> &mut dyn Any { + #[inline] + 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> { + Err(self) } - #[inline] - fn as_reflect_mut(&mut self) -> &mut dyn Reflect { - self + fn try_as_reflect(&self) -> Option<&dyn Reflect> { + None } - fn apply(&mut self, value: &dyn Reflect) { - map_apply(self, value); + fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { + None } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) + fn apply(&mut self, value: &dyn PartialReflect) { + map_apply(self, value); } fn reflect_kind(&self) -> ReflectKind { @@ -370,11 +371,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) } @@ -413,7 +414,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); @@ -428,7 +429,7 @@ impl<'a> Iterator for MapIter<'a> { } impl IntoIterator for DynamicMap { - type Item = (Box, Box); + type Item = (Box, Box); type IntoIter = std::vec::IntoIter; fn into_iter(self) -> Self::IntoIter { @@ -438,17 +439,17 @@ impl IntoIterator for 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); }; @@ -505,7 +506,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 ReflectRef::Map(map_value) = b.reflect_ref() { for (key, b_value) in map_value.iter() { if let Some(a_value) = a.get_mut(key) { @@ -523,7 +524,6 @@ pub fn map_apply(a: &mut M, b: &dyn Reflect) { mod tests { use super::DynamicMap; use super::Map; - use crate::reflect::Reflect; #[test] fn test_into_iter() { @@ -535,10 +535,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); @@ -555,16 +558,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()); } @@ -578,10 +581,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()); @@ -589,9 +592,9 @@ mod tests { *value = 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 5bb4b5b099261..98ec1b587b67b 100644 --- a/crates/bevy_reflect/src/path/access.rs +++ b/crates/bevy_reflect/src/path/access.rs @@ -3,7 +3,7 @@ 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; @@ -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 6fbb88998647d..1e0309799b7f0 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))?; } @@ -230,13 +236,13 @@ impl<'a> ReflectPath<'a> for &'a str { /// [`List`]: crate::List /// [`Array`]: crate::Array /// [`Enum`]: crate::Enum -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`. @@ -246,8 +252,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`. @@ -258,7 +264,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`. @@ -269,7 +275,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()) } } @@ -423,13 +429,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 9a50decb7240b..3c98d433983a9 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -59,7 +59,7 @@ pub enum ReflectRef<'a> { Array(&'a dyn Array), Map(&'a dyn Map), Enum(&'a dyn Enum), - Value(&'a dyn Reflect), + Value(&'a dyn PartialReflect), } impl_reflect_enum!(ReflectRef<'_>); @@ -77,7 +77,7 @@ pub enum ReflectMut<'a> { Array(&'a mut dyn Array), Map(&'a mut dyn Map), Enum(&'a mut dyn Enum), - Value(&'a mut dyn Reflect), + Value(&'a mut dyn PartialReflect), } impl_reflect_enum!(ReflectMut<'_>); @@ -95,7 +95,7 @@ pub enum ReflectOwned { Array(Box), Map(Box), Enum(Box), - Value(Box), + Value(Box), } impl_reflect_enum!(ReflectOwned); @@ -141,7 +141,11 @@ impl std::fmt::Display for ReflectKind { /// [`bevy_reflect`]: crate /// [derive macro]: bevy_reflect_derive::Reflect /// [crate-level documentation]: crate -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`. @@ -159,23 +163,29 @@ 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; - - /// 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 reflected value. - fn into_reflect(self: Box) -> Box; + fn into_partial_reflect(self: Box) -> Box; /// Casts this type to a reflected value. - fn as_reflect(&self) -> &dyn Reflect; + fn as_partial_reflect(&self) -> &dyn PartialReflect; /// Casts this type to a mutable reflected value. - fn as_reflect_mut(&mut self) -> &mut dyn Reflect; + fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect; + + /// Attempts to cast this type to a boxed, [fully-reflected] value. + /// + /// [fully-reflected]: Reflect + fn try_into_reflect(self: Box) -> Result, Box>; + + /// Attempts to cast this type to a [fully-reflected] value. + /// + /// [fully-reflected]: Reflect + fn try_as_reflect(&self) -> Option<&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. /// @@ -217,13 +227,7 @@ 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); - - /// 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 apply(&mut self, value: &dyn PartialReflect); /// Returns a zero-sized enumeration of "kinds" of type. /// @@ -254,7 +258,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). /// @@ -266,7 +270,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 } @@ -314,25 +318,94 @@ 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) +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 { @@ -360,17 +433,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. /// @@ -402,3 +464,28 @@ 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" + } +} diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 6212a74d787b0..fc6eb2494037b 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -1,9 +1,10 @@ use crate::serde::SerializationData; use crate::{ ArrayInfo, DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicStruct, DynamicTuple, - DynamicTupleStruct, DynamicVariant, EnumInfo, ListInfo, Map, MapInfo, NamedField, Reflect, - ReflectDeserialize, StructInfo, StructVariantInfo, TupleInfo, TupleStructInfo, - TupleVariantInfo, TypeInfo, TypeRegistration, TypeRegistry, UnnamedField, VariantInfo, + DynamicTupleStruct, DynamicVariant, EnumInfo, ListInfo, Map, MapInfo, NamedField, + PartialReflect, Reflect, ReflectDeserialize, StructInfo, StructVariantInfo, TupleInfo, + TupleStructInfo, TupleVariantInfo, TypeInfo, TypeRegistration, TypeRegistry, UnnamedField, + VariantInfo, }; use erased_serde::Deserializer; use serde::de::{ @@ -325,7 +326,7 @@ impl<'a> UntypedReflectDeserializer<'a> { } impl<'a, 'de> DeserializeSeed<'de> for UntypedReflectDeserializer<'a> { - type Value = Box; + type Value = Box; fn deserialize(self, deserializer: D) -> Result where @@ -390,7 +391,7 @@ struct UntypedReflectDeserializerVisitor<'a> { } impl<'a, 'de> Visitor<'de> for UntypedReflectDeserializerVisitor<'a> { - type Value = Box; + type Value = Box; fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { formatter.write_str("map containing `type` and `value` entries for the reflected value") @@ -447,7 +448,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 @@ -458,7 +459,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() { @@ -995,7 +996,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(), + ); } } @@ -1025,7 +1029,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; } @@ -1070,7 +1074,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; } @@ -1109,8 +1113,8 @@ mod tests { use bevy_utils::HashMap; - use crate as bevy_reflect; use crate::serde::{TypedReflectDeserializer, UntypedReflectDeserializer}; + use crate::{self as bevy_reflect, PartialReflect}; use crate::{DynamicEnum, FromReflect, Reflect, ReflectDeserialize, TypeRegistry}; #[derive(Reflect, Debug, PartialEq)] @@ -1319,7 +1323,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); } @@ -1346,7 +1350,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); } diff --git a/crates/bevy_reflect/src/serde/mod.rs b/crates/bevy_reflect/src/serde/mod.rs index c444279fa928a..10ae640f1dbae 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::{ReflectSerializer, UntypedReflectDeserializer}, type_registry::TypeRegistry, @@ -53,8 +53,7 @@ mod tests { let mut deserializer = ron::de::Deserializer::from_str(&serialized).unwrap(); let reflect_deserializer = UntypedReflectDeserializer::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 = UntypedReflectDeserializer::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 = UntypedReflectDeserializer::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 35c5107cf5082..0f6d116bb3ad7 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, Struct, Tuple, TupleStruct, - TypeInfo, TypeRegistry, VariantInfo, VariantType, + Array, Enum, List, Map, PartialReflect, ReflectRef, ReflectSerialize, 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 reflect_serialize = type_registry .get_type_data::(reflect_value.type_id()) .ok_or_else(|| { @@ -51,12 +57,12 @@ fn get_serializable<'a, E: Error>( /// /// [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 } } } @@ -93,12 +99,12 @@ impl<'a> Serialize for ReflectSerializer<'a> { /// A serializer for reflected types whose type is known and does not require /// serialization to include other metadata about it. 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 } } } @@ -157,7 +163,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> { @@ -464,7 +470,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; use ron::extensions::Extensions; @@ -894,7 +900,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/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index d26ea6adb5f42..78554a53189d1 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -1,6 +1,6 @@ use crate::{ - self as bevy_reflect, NamedField, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, - TypeInfo, TypePath, TypePathTable, + self as bevy_reflect, NamedField, PartialReflect, Reflect, ReflectKind, ReflectMut, + ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable, }; use bevy_reflect_derive::impl_type_path; use bevy_utils::HashMap; @@ -43,22 +43,22 @@ use std::{ /// [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>; @@ -200,7 +200,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); @@ -248,23 +248,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::()) } } @@ -272,7 +274,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>, } @@ -300,7 +302,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; @@ -315,7 +321,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)); } @@ -327,14 +333,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 { @@ -343,12 +349,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) } @@ -384,43 +390,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 apply(&mut self, value: &dyn Reflect) { + fn apply(&mut self, value: &dyn PartialReflect) { 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(); @@ -433,11 +434,6 @@ impl Reflect for DynamicStruct { } } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - #[inline] fn reflect_kind(&self) -> ReflectKind { ReflectKind::Struct @@ -459,11 +455,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) } @@ -487,17 +483,17 @@ impl Debug for 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 78d78e1a42ea2..d82ae7d556c2b 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -6,7 +6,7 @@ use crate::{ ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, TypeRegistration, 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; @@ -33,14 +33,14 @@ use std::slice::Iter; /// /// [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,11 +355,11 @@ impl Reflect for DynamicTuple { } #[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 { tuple_partial_eq(self, value) } @@ -393,7 +383,7 @@ impl_type_path!((in bevy_reflect) 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 ReflectRef::Tuple(tuple) = b.reflect_ref() { for (i, value) in tuple.iter_fields().enumerate() { if let Some(v) = a.field_mut(i) { @@ -405,16 +395,16 @@ pub fn tuple_apply(a: &mut T, b: &dyn Reflect) { } } -/// 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); }; @@ -463,17 +453,17 @@ macro_rules! impl_reflect_tuple { {$($index:tt : $name:tt),*} => { impl<$($name: Reflect + TypePath),*> 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, } } @@ -493,7 +483,7 @@ macro_rules! impl_reflect_tuple { } #[inline] - fn drain(self: Box) -> Vec> { + fn drain(self: Box) -> Vec> { vec![ $(Box::new(self.$index),)* ] @@ -512,44 +502,40 @@ macro_rules! impl_reflect_tuple { } } - impl<$($name: Reflect + TypePath),*> Reflect for ($($name,)*) { + impl<$($name: Reflect + TypePath),*> PartialReflect for ($($name,)*) { fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { 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::tuple_apply(self, value); } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - fn reflect_kind(&self) -> ReflectKind { ReflectKind::Tuple } @@ -566,15 +552,46 @@ 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) } } + impl<$($name: Reflect + TypePath),*> 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 + TypePath),*> Typed for ($($name,)*) { fn type_info() -> &'static TypeInfo { static CELL: $crate::utility::GenericTypeInfoCell = $crate::utility::GenericTypeInfoCell::new(); @@ -597,7 +614,7 @@ macro_rules! impl_reflect_tuple { impl<$($name: FromReflect + TypePath),*> 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 c8699b506e040..bb6dddf8533fa 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -1,8 +1,8 @@ use bevy_reflect_derive::impl_type_path; use crate::{ - self as bevy_reflect, DynamicTuple, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, - Tuple, TypeInfo, TypePath, TypePathTable, UnnamedField, + self as bevy_reflect, DynamicTuple, PartialReflect, Reflect, ReflectKind, ReflectMut, + ReflectOwned, ReflectRef, Tuple, TypeInfo, TypePath, TypePathTable, UnnamedField, }; use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; @@ -34,14 +34,14 @@ use std::slice::Iter; /// /// [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; @@ -151,7 +151,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); @@ -198,24 +198,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::()) } } @@ -223,7 +223,7 @@ impl GetTupleStructField for dyn TupleStruct { #[derive(Default)] pub struct DynamicTupleStruct { represented_type: Option<&'static TypeInfo>, - fields: Vec>, + fields: Vec>, } impl DynamicTupleStruct { @@ -247,24 +247,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) } @@ -293,43 +293,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 apply(&mut self, value: &dyn Reflect) { + fn apply(&mut self, value: &dyn PartialReflect) { 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) { @@ -341,11 +338,6 @@ impl Reflect for DynamicTupleStruct { } } - fn set(&mut self, value: Box) -> Result<(), Box> { - *self = value.take()?; - Ok(()) - } - #[inline] fn reflect_kind(&self) -> ReflectKind { ReflectKind::TupleStruct @@ -367,11 +359,11 @@ impl Reflect for DynamicTupleStruct { } #[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 { tuple_struct_partial_eq(self, value) } @@ -404,16 +396,19 @@ impl From for 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_registry.rs b/crates/bevy_reflect/src/type_registry.rs index 8118a7824ee72..d9bd05e4c9311 100644 --- a/crates/bevy_reflect/src/type_registry.rs +++ b/crates/bevy_reflect/src/type_registry.rs @@ -637,7 +637,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"), From 4d92903fcc560a76c39ab0d739c5552891553a55 Mon Sep 17 00:00:00 2001 From: soqb Date: Wed, 21 Feb 2024 15:54:23 +0000 Subject: [PATCH 04/16] some of downstream --- crates/bevy_asset/src/reflect.rs | 10 ++-- crates/bevy_ecs/src/reflect/bundle.rs | 56 ++++++++++--------- crates/bevy_ecs/src/reflect/component.rs | 24 ++++---- .../bevy_ecs/src/reflect/entity_commands.rs | 4 +- crates/bevy_ecs/src/reflect/resource.rs | 14 ++--- 5 files changed, 60 insertions(+), 48 deletions(-) diff --git a/crates/bevy_asset/src/reflect.rs b/crates/bevy_asset/src/reflect.rs index dd95df8525bd6..406d40cac37cb 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, 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>, @@ -92,11 +92,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 22905f53b8212..a370c916a4ddd 100644 --- a/crates/bevy_ecs/src/reflect/bundle.rs +++ b/crates/bevy_ecs/src/reflect/bundle.rs @@ -7,7 +7,7 @@ use std::any::TypeId; use crate::{prelude::Bundle, world::EntityWorldMut}; -use bevy_reflect::{FromReflect, FromType, Reflect, ReflectRef, TypeRegistry}; +use bevy_reflect::{FromReflect, FromType, PartialReflect, Reflect, ReflectRef, TypeRegistry}; use super::ReflectComponent; @@ -24,11 +24,11 @@ pub struct ReflectBundle(ReflectBundleFns); #[derive(Clone)] pub struct ReflectBundleFns { /// Function pointer implementing [`ReflectBundle::insert()`]. - pub insert: fn(&mut EntityWorldMut, &dyn Reflect), + pub insert: fn(&mut EntityWorldMut, &dyn PartialReflect), /// Function pointer implementing [`ReflectBundle::apply()`]. - pub apply: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry), + pub apply: fn(&mut EntityWorldMut, &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), } @@ -46,7 +46,7 @@ impl ReflectBundleFns { impl ReflectBundle { /// Insert a reflected [`Bundle`] into the entity like [`insert()`](EntityWorldMut::insert). - pub fn insert(&self, entity: &mut EntityWorldMut, bundle: &dyn Reflect) { + pub fn insert(&self, entity: &mut EntityWorldMut, bundle: &dyn PartialReflect) { (self.0.insert)(entity, bundle); } @@ -58,7 +58,7 @@ impl ReflectBundle { pub fn apply( &self, entity: &mut EntityWorldMut, - bundle: &dyn Reflect, + bundle: &dyn PartialReflect, registry: &TypeRegistry, ) { (self.0.apply)(entity, bundle, registry); @@ -68,7 +68,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); @@ -170,17 +170,20 @@ impl FromType for ReflectBundle { } } -fn insert_field(entity: &mut EntityWorldMut, field: &dyn Reflect, registry: &TypeRegistry) { - if let Some(reflect_component) = registry.get_type_data::(field.type_id()) { - reflect_component.apply(entity, field); - } else if let Some(reflect_bundle) = registry.get_type_data::(field.type_id()) { - reflect_bundle.apply(entity, field, registry); +fn insert_field(entity: &mut EntityWorldMut, field: &dyn PartialReflect, registry: &TypeRegistry) { + let Some(type_id) = field.try_as_reflect().map(|field| field.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, field.as_partial_reflect()); + } else if let Some(reflect_bundle) = registry.get_type_data::(type_id) { + reflect_bundle.apply(entity, field.as_partial_reflect(), 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!( @@ -198,19 +201,22 @@ fn insert_field(entity: &mut EntityWorldMut, field: &dyn Reflect, registry: &Typ 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(|field| field.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 2a17c8aff0634..290db42ccfa08 100644 --- a/crates/bevy_ecs/src/reflect/component.rs +++ b/crates/bevy_ecs/src/reflect/component.rs @@ -66,7 +66,7 @@ use crate::{ entity::Entity, world::{unsafe_world_cell::UnsafeEntityCell, EntityRef, EntityWorldMut, World}, }; -use bevy_reflect::{FromReflect, FromType, Reflect, TypeRegistry}; +use bevy_reflect::{FromReflect, FromType, PartialReflect, Reflect, TypeRegistry}; /// A struct used to operate on reflected [`Component`] trait of a type. /// @@ -98,11 +98,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(&mut EntityWorldMut, &dyn Reflect), + pub apply: fn(&mut EntityWorldMut, &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()`]. @@ -136,7 +136,7 @@ impl ReflectComponent { pub fn insert( &self, entity: &mut EntityWorldMut, - component: &dyn Reflect, + component: &dyn PartialReflect, registry: &TypeRegistry, ) { (self.0.insert)(entity, component, registry); @@ -147,7 +147,7 @@ impl ReflectComponent { /// # Panics /// /// Panics if there is no [`Component`] of the given type. - pub fn apply(&self, entity: &mut EntityWorldMut, component: &dyn Reflect) { + pub fn apply(&self, entity: &mut EntityWorldMut, component: &dyn PartialReflect) { (self.0.apply)(entity, component); } @@ -155,7 +155,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); @@ -260,7 +260,11 @@ impl FromType for ReflectComponent { ReflectComponent(ReflectComponentFns { insert: |entity, reflected_component, registry| { let component = entity.world_scope(|world| { - from_reflect_or_world::(reflected_component, world, registry) + from_reflect_or_world::( + reflected_component.as_partial_reflect(), + world, + registry, + ) }); entity.insert(component); }, @@ -270,7 +274,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_or_world::(reflected_component, world, registry) @@ -320,7 +324,7 @@ impl FromType for ReflectComponent { /// /// Panics if both approaches fail. fn from_reflect_or_world( - reflected: &dyn Reflect, + reflected: &dyn PartialReflect, world: &mut World, registry: &TypeRegistry, ) -> T { diff --git a/crates/bevy_ecs/src/reflect/entity_commands.rs b/crates/bevy_ecs/src/reflect/entity_commands.rs index ae59cd1e33f66..ee1343a66a294 100644 --- a/crates/bevy_ecs/src/reflect/entity_commands.rs +++ b/crates/bevy_ecs/src/reflect/entity_commands.rs @@ -13,6 +13,8 @@ pub trait ReflectCommandExt { /// /// This will overwrite any previous component of the same type. /// + /// Note that `insert_reflect` accepts a `Box`, rather than a + /// /// # Panics /// /// - If the entity doesn't exist. @@ -202,7 +204,7 @@ fn insert_reflect( 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 diff --git a/crates/bevy_ecs/src/reflect/resource.rs b/crates/bevy_ecs/src/reflect/resource.rs index 924eb54b09c8e..2fce1f2709e1a 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, FromWorld, World}, }; -use bevy_reflect::{FromType, Reflect}; +use bevy_reflect::{FromType, PartialReflect, Reflect}; /// A struct used to operate on reflected [`Resource`] of a type. /// @@ -41,11 +41,11 @@ pub struct ReflectResource(ReflectResourceFns); #[derive(Clone)] pub struct ReflectResourceFns { /// Function pointer implementing [`ReflectResource::insert()`]. - pub insert: fn(&mut World, &dyn Reflect), + pub insert: fn(&mut World, &dyn PartialReflect), /// 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), + pub apply_or_insert: fn(&mut World, &dyn PartialReflect), /// Function pointer implementing [`ReflectResource::remove()`]. pub remove: fn(&mut World), /// Function pointer implementing [`ReflectResource::reflect()`]. @@ -72,7 +72,7 @@ impl ReflectResourceFns { impl ReflectResource { /// Insert a reflected [`Resource`] into the world like [`insert()`](World::insert_resource). - pub fn insert(&self, world: &mut World, resource: &dyn Reflect) { + pub fn insert(&self, world: &mut World, resource: &dyn PartialReflect) { (self.0.insert)(world, resource); } @@ -81,12 +81,12 @@ 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); } /// Uses reflection to set the value of this [`Resource`] type in the world to the given value or insert a new one if it does not exist. - pub fn apply_or_insert(&self, world: &mut World, resource: &dyn Reflect) { + pub fn apply_or_insert(&self, world: &mut World, resource: &dyn PartialReflect) { (self.0.apply_or_insert)(world, resource); } From 2ec9148a88dbc58692e1f41f2e1e111c59e63ccc Mon Sep 17 00:00:00 2001 From: soqb Date: Wed, 21 Feb 2024 17:35:00 +0000 Subject: [PATCH 05/16] mostly compiling --- crates/bevy_scene/src/dynamic_scene.rs | 16 ++++++---- .../bevy_scene/src/dynamic_scene_builder.rs | 4 +-- crates/bevy_scene/src/serde.rs | 11 +++---- examples/reflection/reflection.rs | 29 +++++++++++++------ examples/reflection/reflection_types.rs | 1 + 5 files changed, 39 insertions(+), 22 deletions(-) diff --git a/crates/bevy_scene/src/dynamic_scene.rs b/crates/bevy_scene/src/dynamic_scene.rs index 91254836570a2..c64bbddda4905 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, TypeRegistryArc}; +use bevy_reflect::{PartialReflect, TypePath, TypeRegistryArc}; 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 { @@ -90,7 +90,7 @@ impl DynamicScene { // If the world already contains an instance of the given resource // just apply the (possibly) new value, otherwise insert the resource - reflect_resource.apply_or_insert(world, &**resource); + reflect_resource.apply_or_insert(world, resource.as_partial_reflect()); } // For each component types that reference other entities, we keep track @@ -139,7 +139,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..21ab6fbec2219 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; @@ -53,7 +53,7 @@ use std::collections::BTreeMap; /// let dynamic_scene = DynamicSceneBuilder::from_world(&world).extract_entity(entity).build(); /// ``` 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 0904502f2d4e4..1d3c482e80805 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::{TypeRegistrationDeserializer, UntypedReflectDeserializer}, - Reflect, TypeRegistry, TypeRegistryArc, + TypeRegistry, TypeRegistryArc, }; use bevy_utils::HashSet; use serde::ser::SerializeMap; @@ -168,7 +169,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 TypeRegistryArc, } @@ -182,7 +183,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.read()), + &TypedReflectSerializer::new(reflect.as_partial_reflect(), &self.registry.read()), )?; } state.end() @@ -432,7 +433,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 @@ -449,7 +450,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/examples/reflection/reflection.rs b/examples/reflection/reflection.rs index 6033b41396f08..cde248a14eab4 100644 --- a/examples/reflection/reflection.rs +++ b/examples/reflection/reflection.rs @@ -8,7 +8,7 @@ use bevy::{ prelude::*, reflect::{ serde::{ReflectSerializer, UntypedReflectDeserializer}, - 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 contianing 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 3271b5a5d38b4..0d985bb51c1da 100644 --- a/examples/reflection/reflection_types.rs +++ b/examples/reflection/reflection_types.rs @@ -7,6 +7,7 @@ use bevy::{ reflect::{DynamicList, ReflectRef}, utils::HashMap, }; +use bevy_internal::reflect::PartialReflect; use serde::{Deserialize, Serialize}; fn main() { From b4b35b2fdc8e2b39b1f14158a5e754438c27cdf4 Mon Sep 17 00:00:00 2001 From: soqb Date: Sat, 24 Feb 2024 09:00:24 +0000 Subject: [PATCH 06/16] dynamic ecs? --- .../bevy_ecs/src/reflect/entity_commands.rs | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/crates/bevy_ecs/src/reflect/entity_commands.rs b/crates/bevy_ecs/src/reflect/entity_commands.rs index ee1343a66a294..e532919b2d915 100644 --- a/crates/bevy_ecs/src/reflect/entity_commands.rs +++ b/crates/bevy_ecs/src/reflect/entity_commands.rs @@ -2,7 +2,7 @@ use crate::prelude::Mut; use crate::reflect::AppTypeRegistry; use crate::system::{Command, EntityCommands, Resource}; 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; @@ -13,8 +13,6 @@ pub trait ReflectCommandExt { /// /// This will overwrite any previous component of the same type. /// - /// Note that `insert_reflect` accepts a `Box`, rather than a - /// /// # Panics /// /// - If the entity doesn't exist. @@ -55,8 +53,8 @@ pub trait ReflectCommandExt { /// mut prefab: ResMut /// ) { /// // Create a set of new boxed reflect components to use - /// let boxed_reflect_component_a: Box = Box::new(ComponentA(916)); - /// let boxed_reflect_component_b: Box = Box::new(ComponentB("NineSixteen".to_string())); + /// let boxed_reflect_component_a: Box = Box::new(ComponentA(916)); + /// let boxed_reflect_component_b: Box = Box::new(ComponentB("NineSixteen".to_string())); /// /// // You can overwrite the component in the resource with either ComponentA or ComponentB /// prefab.component = boxed_reflect_component_a; @@ -70,7 +68,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`. @@ -84,7 +82,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`]. @@ -143,7 +141,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, @@ -153,7 +151,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, @@ -189,7 +187,7 @@ fn insert_reflect( world: &mut World, entity: Entity, type_registry: &TypeRegistry, - component: Box, + component: Box, ) { let type_info = component .get_represented_type_info() @@ -198,7 +196,7 @@ 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."); }; - 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 { @@ -215,7 +213,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 { @@ -234,7 +232,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 { @@ -318,7 +316,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 { @@ -353,7 +351,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 From 0875441405219705d456b0fd597ed34ce2cacf9f Mon Sep 17 00:00:00 2001 From: soqb Date: Sat, 24 Feb 2024 14:32:02 +0000 Subject: [PATCH 07/16] doctest pass --- crates/bevy_reflect/src/array.rs | 6 +-- crates/bevy_reflect/src/enums/dynamic_enum.rs | 4 +- crates/bevy_reflect/src/lib.rs | 48 +++++++++---------- crates/bevy_reflect/src/list.rs | 6 +-- crates/bevy_reflect/src/map.rs | 6 +-- crates/bevy_reflect/src/struct_trait.rs | 6 +-- crates/bevy_reflect/src/tuple.rs | 6 +-- crates/bevy_reflect/src/tuple_struct.rs | 6 +-- crates/bevy_reflect/src/type_info.rs | 36 ++++++++------ crates/bevy_reflect/src/utility.rs | 44 +++++++++++------ 10 files changed, 96 insertions(+), 72 deletions(-) diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index 80b2b83328119..b451a11ba4c4b 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -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 diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index 234349e8b9a24..a2639c1cd747f 100644 --- a/crates/bevy_reflect/src/enums/dynamic_enum.rs +++ b/crates/bevy_reflect/src/enums/dynamic_enum.rs @@ -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); diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 9ff051f17f7d5..6e912ace7535c 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -78,7 +78,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 @@ -86,14 +86,15 @@ //! 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. //! -//! [`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. @@ -106,8 +107,8 @@ //! ``` //! //! 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. +//! we can just use the matching [`PartialReflect::as_reflect`], [`PartialReflect::as_reflect_mut`], +//! or [`PartialReflect::into_reflect`] methods. //! //! ## Value Types //! @@ -115,7 +116,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. //! @@ -138,18 +139,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 @@ -159,18 +160,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`] method. +//! This is known as "patching" and is done using the [`PartialReflect::apply`] method. //! //! ``` -//! # use bevy_reflect::{DynamicEnum, Reflect}; +//! # use bevy_reflect::{DynamicEnum, PartialReflect, Reflect}; //! let mut value = Some(123_i32); //! let patch = DynamicEnum::new("None", ()); //! value.apply(&patch); @@ -184,7 +184,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 @@ -193,8 +193,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. @@ -209,7 +209,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 @@ -218,7 +218,7 @@ //! foo: 123 //! }); //! -//! let cloned: Box = original.clone_value(); +//! let cloned: Box = original.clone_value(); //! let value = ::from_reflect(&*cloned).unwrap(); // OK! //! ``` //! @@ -353,7 +353,7 @@ //! # use serde::de::DeserializeSeed; //! # use bevy_reflect::{ //! # serde::{ReflectSerializer, UntypedReflectDeserializer}, -//! # Reflect, FromReflect, TypeRegistry +//! # FromReflect, PartialReflect, Reflect, TypeRegistry, //! # }; //! #[derive(Reflect, PartialEq, Debug)] //! struct MyStruct { @@ -369,12 +369,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 = UntypedReflectDeserializer::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(); //! diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index 27a2640d3fd6b..5a0b5c8a04218 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -35,13 +35,13 @@ 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 diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index 77033167d9ff0..343da91a898c5 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -27,7 +27,7 @@ use crate::{ /// # Example /// /// ``` -/// use bevy_reflect::{Reflect, Map}; +/// use bevy_reflect::{PartialReflect, Reflect, Map}; /// use bevy_utils::HashMap; /// /// @@ -35,8 +35,8 @@ 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 diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index 78554a53189d1..aef16c56f3fc6 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -23,7 +23,7 @@ use std::{ /// # Example /// /// ``` -/// use bevy_reflect::{Reflect, Struct}; +/// use bevy_reflect::{PartialReflect, Reflect, Struct}; /// /// #[derive(Reflect)] /// struct Foo { @@ -35,8 +35,8 @@ 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 diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index d82ae7d556c2b..e269aea2dfe5f 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -22,13 +22,13 @@ 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 diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index bb6dddf8533fa..e2e47c3651071 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -19,7 +19,7 @@ use std::slice::Iter; /// # Example /// /// ``` -/// use bevy_reflect::{Reflect, TupleStruct}; +/// use bevy_reflect::{PartialReflect, Reflect, TupleStruct}; /// /// #[derive(Reflect)] /// struct Foo(u32); @@ -28,8 +28,8 @@ use std::slice::Iter; /// /// 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 diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index c5bcd34c714e6..2036096954e22 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -25,7 +25,7 @@ use std::fmt::Debug; /// /// ``` /// # use std::any::Any; -/// # use bevy_reflect::{DynamicTypePath, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, TypeInfo, TypePath, ValueInfo}; +/// # use bevy_reflect::{DynamicTypePath, NamedField, PartialReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, TypeInfo, TypePath, ValueInfo}; /// # use bevy_reflect::utility::NonGenericTypeInfoCell; /// use bevy_reflect::Typed; /// @@ -52,20 +52,28 @@ use std::fmt::Debug; /// # 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 apply(&mut self, value: &dyn PartialReflect) { 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 apply(&mut self, value: &dyn Reflect) { 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!() } /// # } /// ``` /// diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index c658fa64c8c50..1b1a01907ca0a 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}; +/// # use bevy_reflect::{DynamicTypePath, NamedField, PartialReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, Typed, TypeInfo, TypePath}; /// 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 apply(&mut self, value: &dyn PartialReflect) { 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 apply(&mut self, value: &dyn Reflect) { 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!() } /// # } /// ``` /// @@ -124,7 +132,7 @@ impl NonGenericTypeCell { /// /// ``` /// # use std::any::Any; -/// # use bevy_reflect::{DynamicTypePath, Reflect, ReflectMut, ReflectOwned, ReflectRef, TupleStructInfo, Typed, TypeInfo, TypePath, UnnamedField}; +/// # use bevy_reflect::{DynamicTypePath, PartialReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TupleStructInfo, Typed, TypeInfo, TypePath, UnnamedField}; /// use bevy_reflect::utility::GenericTypeInfoCell; /// /// struct Foo(T); @@ -143,20 +151,28 @@ impl 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 apply(&mut self, value: &dyn PartialReflect) { 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 apply(&mut self, value: &dyn Reflect) { 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!() } /// # } /// ``` /// From 1fc1c4591c8e6b0e03339fea34585ea8c6e63026 Mon Sep 17 00:00:00 2001 From: soqb Date: Mon, 26 Feb 2024 08:56:12 +0000 Subject: [PATCH 08/16] use `PartialReflect` bounds in derive to reduce breaking changes --- crates/bevy_ecs/src/reflect/entity_commands.rs | 2 +- crates/bevy_reflect/bevy_reflect_derive/src/utility.rs | 6 +++--- crates/bevy_reflect/src/type_info.rs | 5 ++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/crates/bevy_ecs/src/reflect/entity_commands.rs b/crates/bevy_ecs/src/reflect/entity_commands.rs index e532919b2d915..a96932da8df69 100644 --- a/crates/bevy_ecs/src/reflect/entity_commands.rs +++ b/crates/bevy_ecs/src/reflect/entity_commands.rs @@ -387,7 +387,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_reflect/bevy_reflect_derive/src/utility.rs b/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs index 1a5e01bff5d6d..08dd197e0723f 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs +++ b/crates/bevy_reflect/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. @@ -225,14 +225,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/type_info.rs b/crates/bevy_reflect/src/type_info.rs index 2036096954e22..f046c718b4f2e 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -90,12 +90,12 @@ pub trait Typed: Reflect + TypePath { /// 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`]. /// @@ -103,7 +103,6 @@ pub trait Typed: Reflect + TypePath { /// 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 /// [type path]: TypePath::type_path #[derive(Debug, Clone)] From beb782b27c6fe5915ec3afebc22405e3db7b0d55 Mon Sep 17 00:00:00 2001 From: soqb Date: Sat, 30 Mar 2024 13:27:36 +0000 Subject: [PATCH 09/16] `type_info` doc fix --- crates/bevy_reflect/src/type_info.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index f046c718b4f2e..6a7699fa44ac0 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -104,6 +104,7 @@ pub trait Typed: Reflect + TypePath { /// the static [`TypeInfo`], while the registry simply checks a map. /// /// [`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 { From fe4741ac3caaba7cf6ecaa9eb9cdbe33bdb202e3 Mon Sep 17 00:00:00 2001 From: soqb Date: Sat, 30 Mar 2024 20:10:15 +0000 Subject: [PATCH 10/16] post-merge compilation --- crates/bevy_ecs/src/reflect/mod.rs | 6 ++-- crates/bevy_reflect/src/fields.rs | 6 ++-- crates/bevy_reflect/src/lib.rs | 12 +++---- crates/bevy_reflect/src/serde/de.rs | 41 +++++++++++++----------- crates/bevy_reflect/src/type_registry.rs | 2 +- crates/bevy_render/src/render_asset.rs | 2 +- crates/bevy_scene/src/dynamic_scene.rs | 12 ++----- crates/bevy_scene/src/serde.rs | 2 +- 8 files changed, 39 insertions(+), 44 deletions(-) diff --git a/crates/bevy_ecs/src/reflect/mod.rs b/crates/bevy_ecs/src/reflect/mod.rs index f51c6960f5954..7c1561c5a51ec 100644 --- a/crates/bevy_ecs/src/reflect/mod.rs +++ b/crates/bevy_ecs/src/reflect/mod.rs @@ -5,7 +5,7 @@ use std::ops::{Deref, DerefMut}; use crate as bevy_ecs; use crate::{system::Resource, world::World}; -use bevy_reflect::{FromReflect, Reflect, TypeRegistry, TypeRegistryArc}; +use bevy_reflect::{FromReflect, PartialReflect, TypeRegistry, TypeRegistryArc}; mod bundle; mod component; @@ -42,7 +42,7 @@ impl DerefMut for AppTypeRegistry { } } -/// Creates a `T` from a `&dyn Reflect`. +/// Creates a `T` from a `&dyn PartialReflect`. /// /// The first approach uses `T`'s implementation of `FromReflect`. /// If this fails, it falls back to default-initializing a new instance of `T` using its @@ -51,7 +51,7 @@ impl DerefMut for AppTypeRegistry { /// /// Panics if both approaches fail. fn from_reflect_or_world( - reflected: &dyn Reflect, + reflected: &dyn PartialReflect, world: &mut World, registry: &TypeRegistry, ) -> T { diff --git a/crates/bevy_reflect/src/fields.rs b/crates/bevy_reflect/src/fields.rs index 763d04ab2b7e6..b86e56adcd46f 100644 --- a/crates/bevy_reflect/src/fields.rs +++ b/crates/bevy_reflect/src/fields.rs @@ -1,4 +1,4 @@ -use crate::{Reflect, TypePath, TypePathTable}; +use crate::{PartialReflect, TypePath, TypePathTable}; use std::any::{Any, TypeId}; /// The named field of a reflected struct. @@ -13,7 +13,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_path: TypePathTable::of::(), @@ -79,7 +79,7 @@ pub struct UnnamedField { } impl UnnamedField { - pub fn new(index: usize) -> Self { + pub fn new(index: usize) -> Self { Self { index, type_path: TypePathTable::of::(), diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 19b0ac8446cf2..911069f6f3fab 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -520,9 +520,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, }; } @@ -1240,7 +1240,7 @@ 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 roundtrip_foo = Foo::from_reflect(value.as_ref()).unwrap(); + let roundtrip_foo = Foo::from_reflect(value.as_partial_reflect()).unwrap(); assert!(foo.reflect_partial_eq(&roundtrip_foo).unwrap()); } @@ -2408,7 +2408,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)); } @@ -2465,7 +2465,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)); } diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 5d23c7fe8fa82..44b4813a95a33 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -3,8 +3,7 @@ use crate::{ ArrayInfo, DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicStruct, DynamicTuple, DynamicTupleStruct, DynamicVariant, EnumInfo, ListInfo, Map, MapInfo, NamedField, PartialReflect, Reflect, ReflectDeserialize, StructInfo, StructVariantInfo, TupleInfo, - TupleStructInfo, TupleVariantInfo, TypeInfo, TypeRegistration, TypeRegistry, UnnamedField, - VariantInfo, + TupleStructInfo, TupleVariantInfo, TypeInfo, TypeRegistration, TypeRegistry, VariantInfo, }; use erased_serde::Deserializer; use serde::de::{ @@ -340,21 +339,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 }); /// ``` @@ -379,7 +378,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 @@ -390,7 +389,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 @@ -473,21 +472,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 }); /// ``` @@ -1542,7 +1541,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#"{ @@ -1557,7 +1558,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 @@ -1573,7 +1576,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/type_registry.rs b/crates/bevy_reflect/src/type_registry.rs index 153a1e764cda4..a2de8501a82e9 100644 --- a/crates/bevy_reflect/src/type_registry.rs +++ b/crates/bevy_reflect/src/type_registry.rs @@ -572,7 +572,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:?}", diff --git a/crates/bevy_render/src/render_asset.rs b/crates/bevy_render/src/render_asset.rs index a7c9c97353158..6bf5ce9a6ea11 100644 --- a/crates/bevy_render/src/render_asset.rs +++ b/crates/bevy_render/src/render_asset.rs @@ -8,7 +8,7 @@ use bevy_ecs::{ world::{FromWorld, Mut}, }; use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize}; -use bevy_utils::{thiserror::Error, HashMap, HashSet}; +use bevy_utils::{HashMap, HashSet}; use serde::{Deserialize, Serialize}; use std::marker::PhantomData; use thiserror::Error; diff --git a/crates/bevy_scene/src/dynamic_scene.rs b/crates/bevy_scene/src/dynamic_scene.rs index 6119bea1312ab..9177314511542 100644 --- a/crates/bevy_scene/src/dynamic_scene.rs +++ b/crates/bevy_scene/src/dynamic_scene.rs @@ -5,11 +5,7 @@ use bevy_ecs::{ reflect::{AppTypeRegistry, ReflectComponent, ReflectMapEntities}, world::World, }; -<<<<<<< HEAD -use bevy_reflect::{PartialReflect, TypePath, TypeRegistryArc}; -======= -use bevy_reflect::{Reflect, TypePath, TypeRegistry}; ->>>>>>> 286bc8cce52add44e6f6f9c8cd778d26eaa1a761 +use bevy_reflect::{PartialReflect, TypePath, TypeRegistry}; use bevy_utils::TypeIdMap; #[cfg(feature = "serialize")] @@ -94,11 +90,7 @@ impl DynamicScene { // If the world already contains an instance of the given resource // just apply the (possibly) new value, otherwise insert the resource -<<<<<<< HEAD - reflect_resource.apply_or_insert(world, resource.as_partial_reflect()); -======= - reflect_resource.apply_or_insert(world, &**resource, &type_registry); ->>>>>>> 286bc8cce52add44e6f6f9c8cd778d26eaa1a761 + reflect_resource.apply_or_insert(world, resource.as_partial_reflect(), &type_registry); } // For each component types that reference other entities, we keep track diff --git a/crates/bevy_scene/src/serde.rs b/crates/bevy_scene/src/serde.rs index 02bb515c26390..497c4c4afcf50 100644 --- a/crates/bevy_scene/src/serde.rs +++ b/crates/bevy_scene/src/serde.rs @@ -6,7 +6,7 @@ use bevy_reflect::serde::{TypedReflectDeserializer, TypedReflectSerializer}; use bevy_reflect::PartialReflect; use bevy_reflect::{ serde::{ReflectDeserializer, TypeRegistrationDeserializer}, - Reflect, TypeRegistry, TypeRegistryArc, + TypeRegistry, }; use bevy_utils::HashSet; use serde::ser::SerializeMap; From a0dd2e3667512ff81900fc1237dc80dfdef2d43a Mon Sep 17 00:00:00 2001 From: soqb Date: Sat, 30 Mar 2024 20:13:07 +0000 Subject: [PATCH 11/16] typos --- examples/reflection/reflection.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/reflection/reflection.rs b/examples/reflection/reflection.rs index c4b1be9efb8ca..283c1c6d18257 100644 --- a/examples/reflection/reflection.rs +++ b/examples/reflection/reflection.rs @@ -69,7 +69,7 @@ fn setup(type_registry: Res) { let field = value.field("a").unwrap(); // But values introspected via `PartialReflect` will not return `dyn Reflect` trait objects - // (even if the contianing type does implement `Reflect`), so we need to convert them: + // (even if the containing type does implement `Reflect`), so we need to convert them: let fully_reflected_field = field.try_as_reflect().unwrap(); // Now, you can downcast your `Reflect` value like this: From adc0b564aa973ff765eddc8844788663479ce274 Mon Sep 17 00:00:00 2001 From: soqb Date: Sat, 30 Mar 2024 20:24:26 +0000 Subject: [PATCH 12/16] ci checks --- crates/bevy_ecs/src/reflect/entity_commands.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/reflect/entity_commands.rs b/crates/bevy_ecs/src/reflect/entity_commands.rs index c65d7d4ce0456..0b8c37dafbca3 100644 --- a/crates/bevy_ecs/src/reflect/entity_commands.rs +++ b/crates/bevy_ecs/src/reflect/entity_commands.rs @@ -54,8 +54,8 @@ pub trait ReflectCommandExt { /// mut prefab: ResMut /// ) { /// // Create a set of new boxed reflect components to use - /// let boxed_reflect_component_a: Box = Box::new(ComponentA(916)); - /// let boxed_reflect_component_b: Box = Box::new(ComponentB("NineSixteen".to_string())); + /// let boxed_reflect_component_a: Box = Box::new(ComponentA(916)); + /// let boxed_reflect_component_b: Box = Box::new(ComponentB("NineSixteen".to_string())); /// /// // You can overwrite the component in the resource with either ComponentA or ComponentB /// prefab.component = boxed_reflect_component_a; From 15c40a62c30a68a40bbbdb7bf571d41852df1dd9 Mon Sep 17 00:00:00 2001 From: soqb Date: Sat, 30 Mar 2024 20:28:24 +0000 Subject: [PATCH 13/16] missed example --- examples/reflection/reflection_types.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/reflection/reflection_types.rs b/examples/reflection/reflection_types.rs index 0d985bb51c1da..ebd1aa85b7900 100644 --- a/examples/reflection/reflection_types.rs +++ b/examples/reflection/reflection_types.rs @@ -4,10 +4,9 @@ use bevy::{ prelude::*, - reflect::{DynamicList, ReflectRef}, + reflect::{DynamicList, PartialReflect, ReflectRef}, utils::HashMap, }; -use bevy_internal::reflect::PartialReflect; use serde::{Deserialize, Serialize}; fn main() { From 08673991457b850108aa1ef5b528f9d5a211882a Mon Sep 17 00:00:00 2001 From: soqb Date: Sat, 30 Mar 2024 20:41:49 +0000 Subject: [PATCH 14/16] bless new compile fail --- .../missing_deref.fail.stderr | 6 ++++ .../tests/reflect_derive/generics.fail.stderr | 29 ++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/crates/bevy_macros_compile_fail_tests/tests/deref_mut_derive/missing_deref.fail.stderr b/crates/bevy_macros_compile_fail_tests/tests/deref_mut_derive/missing_deref.fail.stderr index c969892c67ee8..720b6f1217b83 100644 --- a/crates/bevy_macros_compile_fail_tests/tests/deref_mut_derive/missing_deref.fail.stderr +++ b/crates/bevy_macros_compile_fail_tests/tests/deref_mut_derive/missing_deref.fail.stderr @@ -6,6 +6,9 @@ error[E0277]: the trait bound `TupleStruct: Deref` is not satisfied | note: required by a bound in `DerefMut` --> $RUST/core/src/ops/deref.rs + | + | pub trait DerefMut: Deref { + | ^^^^^ required by this bound in `DerefMut` error[E0277]: the trait bound `TupleStruct: Deref` is not satisfied --> tests/deref_mut_derive/missing_deref.fail.rs:3:10 @@ -23,6 +26,9 @@ error[E0277]: the trait bound `Struct: Deref` is not satisfied | note: required by a bound in `DerefMut` --> $RUST/core/src/ops/deref.rs + | + | pub trait DerefMut: Deref { + | ^^^^^ required by this bound in `DerefMut` error[E0277]: the trait bound `Struct: Deref` is not satisfied --> tests/deref_mut_derive/missing_deref.fail.rs:6:10 diff --git a/crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/generics.fail.stderr b/crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/generics.fail.stderr index 3f1dca9e6a20f..8206f823a5d9e 100644 --- a/crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/generics.fail.stderr +++ b/crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/generics.fail.stderr @@ -17,11 +17,38 @@ error[E0277]: the trait bound `NoReflect: Reflect` is not satisfied i128 and $N others note: required by a bound in `bevy_reflect::GetField::get_field` - --> /home/runner/work/bevy/bevy/crates/bevy_reflect/src/struct_trait.rs:242:21 + --> /home/seth/projects/rust/bevy/crates/bevy_reflect/src/struct_trait.rs:242:21 | 242 | fn get_field(&self, name: &str) -> Option<&T>; | ^^^^^^^ required by this bound in `GetField::get_field` +error[E0277]: the trait bound `NoReflect: PartialReflect` is not satisfied + --> tests/reflect_derive/generics.fail.rs:14:36 + | +14 | let mut foo: Box = Box::new(Foo:: { a: NoReflect(42.0) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `PartialReflect` is not implemented for `NoReflect`, which is required by `Foo: bevy_reflect::Struct` + | + = help: the following other types implement trait `PartialReflect`: + bool + char + isize + i8 + i16 + i32 + i64 + i128 + and $N others +note: required for `Foo` to implement `bevy_reflect::Struct` + --> tests/reflect_derive/generics.fail.rs:3:10 + | +3 | #[derive(Reflect)] + | ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro +4 | #[reflect(from_reflect = false)] +5 | struct Foo { + | ^^^^^^ + = note: required for the cast from `Box>` to `Box<(dyn bevy_reflect::Struct + 'static)>` + = note: this error originates in the derive macro `Reflect` (in Nightly builds, run with -Z macro-backtrace for more info) + error[E0277]: the trait bound `NoReflect: GetTypeRegistration` is not satisfied --> tests/reflect_derive/generics.fail.rs:14:36 | From dfcbe3e73b4c6eef5555817a1d9210a220fa4ecb Mon Sep 17 00:00:00 2001 From: soqb Date: Sat, 30 Mar 2024 20:50:43 +0000 Subject: [PATCH 15/16] docs --- crates/bevy_ecs/src/reflect/entity_commands.rs | 2 +- .../bevy_reflect_derive/src/container_attributes.rs | 6 +++--- crates/bevy_reflect/src/lib.rs | 10 +++++----- crates/bevy_reflect/src/list.rs | 2 +- crates/bevy_reflect/src/map.rs | 2 +- crates/bevy_reflect/src/path/access.rs | 2 +- crates/bevy_reflect/src/reflect.rs | 8 ++++---- crates/bevy_scene/src/dynamic_scene_builder.rs | 2 ++ examples/reflection/reflection_types.rs | 5 +++-- 9 files changed, 21 insertions(+), 18 deletions(-) diff --git a/crates/bevy_ecs/src/reflect/entity_commands.rs b/crates/bevy_ecs/src/reflect/entity_commands.rs index 0b8c37dafbca3..0c089923f5b89 100644 --- a/crates/bevy_ecs/src/reflect/entity_commands.rs +++ b/crates/bevy_ecs/src/reflect/entity_commands.rs @@ -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 diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/container_attributes.rs b/crates/bevy_reflect/bevy_reflect_derive/src/container_attributes.rs index 23cb5799f3cde..6e9e47dd7cbb8 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/container_attributes.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/container_attributes.rs @@ -452,7 +452,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 { @@ -475,7 +475,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( @@ -502,7 +502,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/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 911069f6f3fab..b5ad0b8d196b1 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -105,15 +105,15 @@ //! 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 [`PartialReflect::as_reflect`], [`PartialReflect::as_reflect_mut`], -//! or [`PartialReflect::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 //! diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index 5a0b5c8a04218..7f99881339327 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -447,7 +447,7 @@ pub fn list_apply(a: &mut L, b: &dyn PartialReflect) { /// 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] diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index f2e35a4d5e87e..933b604973908 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -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, diff --git a/crates/bevy_reflect/src/path/access.rs b/crates/bevy_reflect/src/path/access.rs index 98ec1b587b67b..a62e243adde7b 100644 --- a/crates/bevy_reflect/src/path/access.rs +++ b/crates/bevy_reflect/src/path/access.rs @@ -10,7 +10,7 @@ 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. diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index 3c98d433983a9..173e048df69bf 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -50,7 +50,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), @@ -68,7 +68,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), @@ -86,7 +86,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), @@ -101,7 +101,7 @@ impl_reflect_enum!(ReflectOwned); /// 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 { diff --git a/crates/bevy_scene/src/dynamic_scene_builder.rs b/crates/bevy_scene/src/dynamic_scene_builder.rs index 21ab6fbec2219..26084c1a3e27f 100644 --- a/crates/bevy_scene/src/dynamic_scene_builder.rs +++ b/crates/bevy_scene/src/dynamic_scene_builder.rs @@ -52,6 +52,8 @@ 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_scene: BTreeMap, diff --git a/examples/reflection/reflection_types.rs b/examples/reflection/reflection_types.rs index ebd1aa85b7900..2c5caf826b580 100644 --- a/examples/reflection/reflection_types.rs +++ b/examples/reflection/reflection_types.rs @@ -41,8 +41,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)] From f22b222b26b402fee9a916f2097095ea571fd25a Mon Sep 17 00:00:00 2001 From: soqb Date: Sat, 30 Mar 2024 20:58:10 +0000 Subject: [PATCH 16/16] compile fail had my name in it? --- .../tests/reflect_derive/generics.fail.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/generics.fail.stderr b/crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/generics.fail.stderr index 8206f823a5d9e..9099a73fbabb2 100644 --- a/crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/generics.fail.stderr +++ b/crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/generics.fail.stderr @@ -17,7 +17,7 @@ error[E0277]: the trait bound `NoReflect: Reflect` is not satisfied i128 and $N others note: required by a bound in `bevy_reflect::GetField::get_field` - --> /home/seth/projects/rust/bevy/crates/bevy_reflect/src/struct_trait.rs:242:21 + --> /home/runner/work/bevy/bevy/crates/bevy_reflect/src/struct_trait.rs:242:21 | 242 | fn get_field(&self, name: &str) -> Option<&T>; | ^^^^^^^ required by this bound in `GetField::get_field`