From 10bd53ec964a53fe40d3c4d75df735e9fafa1cf7 Mon Sep 17 00:00:00 2001 From: radiish Date: Tue, 6 Jun 2023 16:30:19 +0100 Subject: [PATCH 01/27] removed all reflect-scoped std::any::type_name usages --- crates/bevy_asset/src/asset_server.rs | 2 +- crates/bevy_asset/src/assets.rs | 15 +--- .../asset_count_diagnostics_plugin.rs | 2 +- crates/bevy_asset/src/handle.rs | 9 +- .../bevy_reflect_derive/src/derive_data.rs | 2 +- .../bevy_reflect_derive/src/from_reflect.rs | 2 +- .../bevy_reflect_derive/src/impls/enums.rs | 20 +---- .../bevy_reflect_derive/src/impls/structs.rs | 16 +--- .../src/impls/tuple_structs.rs | 16 +--- .../bevy_reflect_derive/src/impls/values.rs | 12 +-- crates/bevy_reflect/src/array.rs | 52 ++++++----- crates/bevy_reflect/src/enums/dynamic_enum.rs | 18 +--- crates/bevy_reflect/src/enums/enum_trait.rs | 35 ++++---- crates/bevy_reflect/src/enums/mod.rs | 10 ++- crates/bevy_reflect/src/fields.rs | 50 +++++++---- crates/bevy_reflect/src/impls/smallvec.rs | 29 +++---- crates/bevy_reflect/src/impls/std.rs | 86 +++---------------- crates/bevy_reflect/src/lib.rs | 85 +++++++----------- crates/bevy_reflect/src/list.rs | 52 ++++++----- crates/bevy_reflect/src/map.rs | 66 +++++++------- crates/bevy_reflect/src/reflect.rs | 50 +++++++---- crates/bevy_reflect/src/serde/de.rs | 56 ++++++------ crates/bevy_reflect/src/serde/ser.rs | 24 +++--- crates/bevy_reflect/src/struct_trait.rs | 47 ++++------ crates/bevy_reflect/src/tuple.rs | 56 +++++------- crates/bevy_reflect/src/tuple_struct.rs | 47 ++++------ crates/bevy_reflect/src/type_info.rs | 59 +++++++++---- crates/bevy_reflect/src/type_path.rs | 62 +++++++++++-- crates/bevy_reflect/src/type_registry.rs | 15 ++-- crates/bevy_reflect/src/utility.rs | 6 +- crates/bevy_scene/src/dynamic_scene.rs | 12 +-- crates/bevy_scene/src/serde.rs | 11 ++- 32 files changed, 465 insertions(+), 559 deletions(-) diff --git a/crates/bevy_asset/src/asset_server.rs b/crates/bevy_asset/src/asset_server.rs index e7e830cd1d90a..1402419e18baa 100644 --- a/crates/bevy_asset/src/asset_server.rs +++ b/crates/bevy_asset/src/asset_server.rs @@ -152,7 +152,7 @@ impl AssetServer { .is_some() { panic!("Error while registering new asset type: {:?} with UUID: {:?}. Another type with the same UUID is already registered. Can not register new asset type with the same UUID", - std::any::type_name::(), T::TYPE_UUID); + T::type_path(), T::TYPE_UUID); } Assets::new(self.server.asset_ref_counter.channel.sender.clone()) } diff --git a/crates/bevy_asset/src/assets.rs b/crates/bevy_asset/src/assets.rs index 7b4d488ca98a3..075e677c28a4f 100644 --- a/crates/bevy_asset/src/assets.rs +++ b/crates/bevy_asset/src/assets.rs @@ -26,24 +26,15 @@ impl Debug for AssetEvent { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { AssetEvent::Created { handle } => f - .debug_struct(&format!( - "AssetEvent<{}>::Created", - std::any::type_name::() - )) + .debug_struct(&format!("AssetEvent<{}>::Created", T::type_path())) .field("handle", &handle.id()) .finish(), AssetEvent::Modified { handle } => f - .debug_struct(&format!( - "AssetEvent<{}>::Modified", - std::any::type_name::() - )) + .debug_struct(&format!("AssetEvent<{}>::Modified", T::type_path())) .field("handle", &handle.id()) .finish(), AssetEvent::Removed { handle } => f - .debug_struct(&format!( - "AssetEvent<{}>::Removed", - std::any::type_name::() - )) + .debug_struct(&format!("AssetEvent<{}>::Removed", T::type_path())) .field("handle", &handle.id()) .finish(), } diff --git a/crates/bevy_asset/src/diagnostic/asset_count_diagnostics_plugin.rs b/crates/bevy_asset/src/diagnostic/asset_count_diagnostics_plugin.rs index a5ce2546db60c..99e0e73452bbc 100644 --- a/crates/bevy_asset/src/diagnostic/asset_count_diagnostics_plugin.rs +++ b/crates/bevy_asset/src/diagnostic/asset_count_diagnostics_plugin.rs @@ -33,7 +33,7 @@ impl AssetCountDiagnosticsPlugin { /// Registers the asset count diagnostic for the current application. pub fn setup_system(mut diagnostics: ResMut) { - let asset_type_name = std::any::type_name::(); + let asset_type_name = T::type_path(); let max_length = MAX_DIAGNOSTIC_NAME_WIDTH - "asset_count ".len(); diagnostics.add(Diagnostic::new( Self::diagnostic_id(), diff --git a/crates/bevy_asset/src/handle.rs b/crates/bevy_asset/src/handle.rs index 4921e97e4481e..2124361bf3d9c 100644 --- a/crates/bevy_asset/src/handle.rs +++ b/crates/bevy_asset/src/handle.rs @@ -297,8 +297,13 @@ impl Default for Handle { impl Debug for Handle { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { - let name = std::any::type_name::().split("::").last().unwrap(); - write!(f, "{:?}Handle<{name}>({:?})", self.handle_type, self.id) + write!( + f, + "{:?}Handle<{}>({:?})", + self.handle_type, + T::short_type_path(), + self.id + ) } } diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs b/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs index 3dc9db462d707..ae7369abefd9a 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs @@ -35,7 +35,7 @@ pub(crate) enum ReflectDerive<'a> { /// // traits /// // |----------------------------------------| /// #[reflect(PartialEq, Serialize, Deserialize, Default)] -/// // type_name generics +/// // type_path generics /// // |-------------------||----------| /// struct ThingThatImReflecting {/* ... */} /// ``` 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 2473dd356f7a6..daadc784377f4 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs @@ -67,7 +67,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { if let #bevy_reflect_path::ReflectRef::Enum(#ref_value) = #bevy_reflect_path::Reflect::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, ::core::any::type_name::()), + name => panic!("variant with name `{}` does not exist on enum `{}`", name, ::type_path()), } } else { #FQOption::None 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 365061df4f2ff..2b01c11a571a0 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs @@ -59,20 +59,18 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { } }); - let string_name = enum_path.get_ident().unwrap().to_string(); - #[cfg(feature = "documentation")] let info_generator = { let doc = reflect_enum.meta().doc(); quote! { - #bevy_reflect_path::EnumInfo::new::(#string_name, &variants).with_docs(#doc) + #bevy_reflect_path::EnumInfo::new::(&variants).with_docs(#doc) } }; #[cfg(not(feature = "documentation"))] let info_generator = { quote! { - #bevy_reflect_path::EnumInfo::new::(#string_name, &variants) + #bevy_reflect_path::EnumInfo::new::(&variants) } }; @@ -189,21 +187,11 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { } impl #impl_generics #bevy_reflect_path::Reflect for #enum_path #ty_generics #where_reflect_clause { - #[inline] - fn type_name(&self) -> &str { - ::core::any::type_name::() - } - #[inline] fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { #FQOption::Some(::type_info()) } - #[inline] - fn get_type_path(&self) -> &dyn #bevy_reflect_path::DynamicTypePath { - self - } - #[inline] fn into_any(self: #FQBox) -> #FQBox { self @@ -270,11 +258,11 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { #(#variant_names => { *self = #variant_constructors })* - name => panic!("variant with name `{}` does not exist on enum `{}`", name, ::core::any::type_name::()), + name => panic!("variant with name `{}` does not exist on enum `{}`", name, ::type_path()), } } } else { - panic!("`{}` is not an enum", #bevy_reflect_path::Reflect::type_name(#ref_value)); + panic!("`{}` is not an enum", #bevy_reflect_path::DynamicTypePath::reflect_type_path(#ref_value)); } } 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 9c5d30ebad8d3..82afb9b0f9576 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs @@ -64,20 +64,18 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { } }; - let string_name = struct_path.get_ident().unwrap().to_string(); - #[cfg(feature = "documentation")] let info_generator = { let doc = reflect_struct.meta().doc(); quote! { - #bevy_reflect_path::StructInfo::new::(#string_name, &fields).with_docs(#doc) + #bevy_reflect_path::StructInfo::new::(&fields).with_docs(#doc) } }; #[cfg(not(feature = "documentation"))] let info_generator = { quote! { - #bevy_reflect_path::StructInfo::new::(#string_name, &fields) + #bevy_reflect_path::StructInfo::new::(&fields) } }; @@ -164,21 +162,11 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { } impl #impl_generics #bevy_reflect_path::Reflect for #struct_path #ty_generics #where_reflect_clause { - #[inline] - fn type_name(&self) -> &str { - ::core::any::type_name::() - } - #[inline] fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { #FQOption::Some(::type_info()) } - #[inline] - fn get_type_path(&self) -> &dyn #bevy_reflect_path::DynamicTypePath { - self - } - #[inline] fn into_any(self: #FQBox) -> #FQBox { self 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 db4b839baa49e..9c2a1e1c9ff97 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 @@ -58,20 +58,18 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { } }; - let string_name = struct_path.get_ident().unwrap().to_string(); - #[cfg(feature = "documentation")] let info_generator = { let doc = reflect_struct.meta().doc(); quote! { - #bevy_reflect_path::TupleStructInfo::new::(#string_name, &fields).with_docs(#doc) + #bevy_reflect_path::TupleStructInfo::new::(&fields).with_docs(#doc) } }; #[cfg(not(feature = "documentation"))] let info_generator = { quote! { - #bevy_reflect_path::TupleStructInfo::new::(#string_name, &fields) + #bevy_reflect_path::TupleStructInfo::new::(&fields) } }; @@ -134,21 +132,11 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { } impl #impl_generics #bevy_reflect_path::Reflect for #struct_path #ty_generics #where_reflect_clause { - #[inline] - fn type_name(&self) -> &str { - ::core::any::type_name::() - } - #[inline] fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { #FQOption::Some(::type_info()) } - #[inline] - fn get_type_path(&self) -> &dyn #bevy_reflect_path::DynamicTypePath { - self - } - #[inline] fn into_any(self: #FQBox) -> #FQBox { self 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 b61b1ca9baf0b..d0c0ddc9a894c 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs @@ -46,21 +46,11 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { #typed_impl impl #impl_generics #bevy_reflect_path::Reflect for #type_path #ty_generics #where_reflect_clause { - #[inline] - fn type_name(&self) -> &str { - ::core::any::type_name::() - } - #[inline] fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> { #FQOption::Some(::type_info()) } - #[inline] - fn get_type_path(&self) -> &dyn #bevy_reflect_path::DynamicTypePath { - self - } - #[inline] fn into_any(self: #FQBox) -> #FQBox { self @@ -102,7 +92,7 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { if let #FQOption::Some(value) = ::downcast_ref::(value) { *self = #FQClone::clone(value); } else { - panic!("Value is not {}.", ::core::any::type_name::()); + panic!("Value is not {}.", ::type_path()); } } diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index 7a4375f83a6a0..4a8af9067b964 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -1,8 +1,8 @@ use bevy_reflect_derive::impl_type_path; use crate::{ - self as bevy_reflect, utility::reflect_hasher, DynamicTypePath, Reflect, ReflectMut, - ReflectOwned, ReflectRef, TypeInfo, + self as bevy_reflect, utility::reflect_hasher, Reflect, ReflectMut, ReflectOwned, ReflectRef, + TypeInfo, TypePath, TypePathVtable, }; use std::{ any::{Any, TypeId}, @@ -78,9 +78,9 @@ pub trait Array: Reflect { /// A container for compile-time array info. #[derive(Clone, Debug)] pub struct ArrayInfo { - type_name: &'static str, + type_path: TypePathVtable, type_id: TypeId, - item_type_name: &'static str, + item_type_path: TypePathVtable, item_type_id: TypeId, capacity: usize, #[cfg(feature = "documentation")] @@ -94,11 +94,11 @@ impl ArrayInfo { /// /// * `capacity`: The maximum capacity of the underlying array. /// - pub fn new(capacity: usize) -> Self { + pub fn new(capacity: usize) -> Self { Self { - type_name: std::any::type_name::(), + type_path: TypePathVtable::of::(), type_id: TypeId::of::(), - item_type_name: std::any::type_name::(), + item_type_path: TypePathVtable::of::(), item_type_id: TypeId::of::(), capacity, #[cfg(feature = "documentation")] @@ -117,11 +117,21 @@ impl ArrayInfo { self.capacity } - /// The [type name] of the array. + /// A representation of the type path of the array. /// - /// [type name]: std::any::type_name - pub fn type_name(&self) -> &'static str { - self.type_name + /// Provides dynamic access to all methods on [`TypePath`]. + pub fn type_path_vtable(&self) -> &TypePathVtable { + &self.type_path + } + + /// The [stable, full type path] of the array. + /// + /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. + /// + /// [stable, full type path]: TypePath + /// [`type_path_vtable`]: Self::type_path_vtable + pub fn type_path(&self) -> &'static str { + self.type_path_vtable().path() } /// The [`TypeId`] of the array. @@ -134,11 +144,9 @@ impl ArrayInfo { TypeId::of::() == self.type_id } - /// The [type name] of the array item. - /// - /// [type name]: std::any::type_name - pub fn item_type_name(&self) -> &'static str { - self.item_type_name + /// The stable type name of the array. + pub fn item_type_path_vtable(&self) -> &TypePathVtable { + &self.item_type_path } /// The [`TypeId`] of the array item. @@ -214,23 +222,11 @@ impl DynamicArray { } impl Reflect for DynamicArray { - #[inline] - fn type_name(&self) -> &str { - self.represented_type - .map(|info| info.type_name()) - .unwrap_or_else(|| std::any::type_name::()) - } - #[inline] fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } - #[inline] - fn get_type_path(&self) -> &dyn DynamicTypePath { - self - } - #[inline] fn into_any(self: Box) -> Box { self diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index 6edc256c68439..2895d3c9a8522 100644 --- a/crates/bevy_reflect/src/enums/dynamic_enum.rs +++ b/crates/bevy_reflect/src/enums/dynamic_enum.rs @@ -2,8 +2,8 @@ use bevy_reflect_derive::impl_type_path; use crate::{ self as bevy_reflect, enum_debug, enum_hash, enum_partial_eq, DynamicStruct, DynamicTuple, - DynamicTypePath, Enum, Reflect, ReflectMut, ReflectOwned, ReflectRef, Struct, Tuple, TypeInfo, - VariantFieldIter, VariantType, + Enum, Reflect, ReflectMut, ReflectOwned, ReflectRef, Struct, Tuple, TypeInfo, VariantFieldIter, + VariantType, }; use std::any::Any; use std::fmt::Formatter; @@ -288,23 +288,11 @@ impl Enum for DynamicEnum { } impl Reflect for DynamicEnum { - #[inline] - fn type_name(&self) -> &str { - self.represented_type - .map(|info| info.type_name()) - .unwrap_or_default() - } - #[inline] fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } - #[inline] - fn get_type_path(&self) -> &dyn DynamicTypePath { - self - } - #[inline] fn into_any(self: Box) -> Box { self @@ -381,7 +369,7 @@ impl Reflect for DynamicEnum { self.set_variant(value.variant_name(), dyn_variant); } } else { - panic!("`{}` is not an enum", value.type_name()); + panic!("`{}` is not an enum", value.reflect_type_path()); } } diff --git a/crates/bevy_reflect/src/enums/enum_trait.rs b/crates/bevy_reflect/src/enums/enum_trait.rs index a4b9bec2a4512..0c821dd92e6d1 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, VariantInfo, VariantType}; +use crate::{DynamicEnum, Reflect, TypePath, TypePathVtable, VariantInfo, VariantType}; use bevy_utils::HashMap; use std::any::{Any, TypeId}; use std::slice::Iter; @@ -126,15 +126,14 @@ pub trait Enum: Reflect { } /// Returns the full path to the current variant. fn variant_path(&self) -> String { - format!("{}::{}", self.type_name(), self.variant_name()) + format!("{}::{}", self.reflect_type_path(), self.variant_name()) } } /// A container for compile-time enum info, used by [`TypeInfo`](crate::TypeInfo). #[derive(Clone, Debug)] pub struct EnumInfo { - name: &'static str, - type_name: &'static str, + type_path: TypePathVtable, type_id: TypeId, variants: Box<[VariantInfo]>, variant_names: Box<[&'static str]>, @@ -151,7 +150,7 @@ impl EnumInfo { /// * `name`: The name of this enum (_without_ generics or lifetimes) /// * `variants`: The variants of this enum in the order they are defined /// - pub fn new(name: &'static str, variants: &[VariantInfo]) -> Self { + pub fn new(variants: &[VariantInfo]) -> Self { let variant_indices = variants .iter() .enumerate() @@ -161,8 +160,7 @@ impl EnumInfo { let variant_names = variants.iter().map(|variant| variant.name()).collect(); Self { - name, - type_name: std::any::type_name::(), + type_path: TypePathVtable::of::(), type_id: TypeId::of::(), variants: variants.to_vec().into_boxed_slice(), variant_names, @@ -204,7 +202,7 @@ impl EnumInfo { /// /// This does _not_ check if the given variant exists. pub fn variant_path(&self, name: &str) -> String { - format!("{}::{name}", self.type_name()) + format!("{}::{name}", self.type_path()) } /// Checks if a variant with the given name exists within this enum. @@ -222,20 +220,21 @@ impl EnumInfo { self.variants.len() } - /// The name of the enum. + /// A representation of the type path of the value. /// - /// This does _not_ include any generics or lifetimes. - /// - /// For example, `foo::bar::Baz<'a, T>` would simply be `Baz`. - pub fn name(&self) -> &'static str { - self.name + /// Provides dynamic access to all methods on [`TypePath`]. + pub fn type_path_vtable(&self) -> &TypePathVtable { + &self.type_path } - /// The [type name] of the enum. + /// The [stable, full type path] of the value. + /// + /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. /// - /// [type name]: std::any::type_name - pub fn type_name(&self) -> &'static str { - self.type_name + /// [stable, full type path]: TypePath + /// [`type_path_vtable`]: Self::type_path_vtable + pub fn type_path(&self) -> &'static str { + self.type_path_vtable().path() } /// The [`TypeId`] of the enum. diff --git a/crates/bevy_reflect/src/enums/mod.rs b/crates/bevy_reflect/src/enums/mod.rs index 7693bf9794acc..ef2f0ae087592 100644 --- a/crates/bevy_reflect/src/enums/mod.rs +++ b/crates/bevy_reflect/src/enums/mod.rs @@ -25,7 +25,15 @@ mod tests { let info = MyEnum::type_info(); if let TypeInfo::Enum(info) = info { assert!(info.is::(), "expected type to be `MyEnum`"); - assert_eq!(std::any::type_name::(), info.type_name()); + assert_eq!(MyEnum::type_path(), info.type_path()); + assert_eq!(MyEnum::type_path(), info.type_path_vtable().path()); + assert_eq!(MyEnum::type_ident(), info.type_path_vtable().ident()); + assert_eq!(MyEnum::module_path(), info.type_path_vtable().module_path()); + assert_eq!(MyEnum::crate_name(), info.type_path_vtable().crate_name()); + assert_eq!( + MyEnum::short_type_path(), + info.type_path_vtable().short_path() + ); // === MyEnum::A === // assert_eq!("A", info.variant_at(0).unwrap().name()); diff --git a/crates/bevy_reflect/src/fields.rs b/crates/bevy_reflect/src/fields.rs index 62c5c332adecc..99f13dc68393f 100644 --- a/crates/bevy_reflect/src/fields.rs +++ b/crates/bevy_reflect/src/fields.rs @@ -1,11 +1,11 @@ -use crate::Reflect; +use crate::{Reflect, TypePath, TypePathVtable}; use std::any::{Any, TypeId}; /// The named field of a reflected struct. #[derive(Clone, Debug)] pub struct NamedField { name: &'static str, - type_name: &'static str, + type_path: TypePathVtable, type_id: TypeId, #[cfg(feature = "documentation")] docs: Option<&'static str>, @@ -13,10 +13,10 @@ 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_name: std::any::type_name::(), + type_path: TypePathVtable::of::(), type_id: TypeId::of::(), #[cfg(feature = "documentation")] docs: None, @@ -34,11 +34,21 @@ impl NamedField { self.name } - /// The [type name] of the field. + /// A representation of the type path of the field. /// - /// [type name]: std::any::type_name - pub fn type_name(&self) -> &'static str { - self.type_name + /// Provides dynamic access to all methods on [`TypePath`]. + pub fn type_path_vtable(&self) -> &TypePathVtable { + &self.type_path + } + + /// The [stable, full type path] of the field. + /// + /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. + /// + /// [stable, full type path]: TypePath + /// [`type_path_vtable`]: Self::type_path_vtable + pub fn type_path(&self) -> &'static str { + self.type_path_vtable().path() } /// The [`TypeId`] of the field. @@ -62,17 +72,17 @@ impl NamedField { #[derive(Clone, Debug)] pub struct UnnamedField { index: usize, - type_name: &'static str, + type_path: TypePathVtable, type_id: TypeId, #[cfg(feature = "documentation")] docs: Option<&'static str>, } impl UnnamedField { - pub fn new(index: usize) -> Self { + pub fn new(index: usize) -> Self { Self { index, - type_name: std::any::type_name::(), + type_path: TypePathVtable::of::(), type_id: TypeId::of::(), #[cfg(feature = "documentation")] docs: None, @@ -90,11 +100,21 @@ impl UnnamedField { self.index } - /// The [type name] of the field. + /// A representation of the type path of the field. + /// + /// Provides dynamic access to all methods on [`TypePath`]. + pub fn type_path_vtable(&self) -> &TypePathVtable { + &self.type_path + } + + /// The [stable, full type path] of the field. + /// + /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. /// - /// [type name]: std::any::type_name - pub fn type_name(&self) -> &'static str { - self.type_name + /// [stable, full type path]: TypePath + /// [`type_path_vtable`]: Self::type_path_vtable + pub fn type_path(&self) -> &'static str { + self.type_path_vtable().path() } /// The [`TypeId`] of the field. diff --git a/crates/bevy_reflect/src/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index eb6a4b1c025ad..a0b8777566393 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -4,14 +4,14 @@ use std::any::Any; use crate::utility::GenericTypeInfoCell; use crate::{ - self as bevy_reflect, DynamicTypePath, FromReflect, FromType, GetTypeRegistration, List, - ListInfo, ListIter, Reflect, ReflectFromPtr, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, - TypePath, TypeRegistration, Typed, + self as bevy_reflect, FromReflect, FromType, GetTypeRegistration, List, ListInfo, ListIter, + Reflect, ReflectFromPtr, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, + TypeRegistration, Typed, }; impl List for SmallVec where - T::Item: FromReflect, + T::Item: FromReflect + TypePath, { fn get(&self, index: usize) -> Option<&dyn Reflect> { if index < SmallVec::len(self) { @@ -34,7 +34,7 @@ where ::Item::from_reflect(&*value).unwrap_or_else(|| { panic!( "Attempted to insert invalid value of type {}.", - value.type_name() + value.reflect_type_path() ) }) }); @@ -50,7 +50,7 @@ where ::Item::from_reflect(&*value).unwrap_or_else(|| { panic!( "Attempted to push invalid value of type {}.", - value.type_name() + value.reflect_type_path() ) }) }); @@ -78,21 +78,12 @@ where impl Reflect for SmallVec where - T::Item: FromReflect, + T::Item: FromReflect + TypePath, { - fn type_name(&self) -> &str { - std::any::type_name::() - } - fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } - #[inline] - fn get_type_path(&self) -> &dyn DynamicTypePath { - self - } - fn into_any(self: Box) -> Box { self } @@ -149,7 +140,7 @@ where impl Typed for SmallVec where - T::Item: FromReflect, + T::Item: FromReflect + TypePath, { fn type_info() -> &'static TypeInfo { static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); @@ -161,7 +152,7 @@ impl_type_path!(::smallvec::SmallVec FromReflect for SmallVec where - T::Item: FromReflect, + T::Item: FromReflect + TypePath, { fn from_reflect(reflect: &dyn Reflect) -> Option { if let ReflectRef::List(ref_list) = reflect.reflect_ref() { @@ -178,7 +169,7 @@ where impl GetTypeRegistration for SmallVec where - T::Item: FromReflect, + T::Item: FromReflect + TypePath, { fn get_type_registration() -> TypeRegistration { let mut registration = TypeRegistration::of::>(); diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 806aff9fa8af0..2051022f81468 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -2,8 +2,8 @@ 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, DynamicTypePath, Enum, EnumInfo, FromReflect, FromType, GetTypeRegistration, List, - ListInfo, ListIter, Map, MapInfo, MapIter, Reflect, ReflectDeserialize, ReflectMut, ReflectRef, + DynamicMap, Enum, EnumInfo, FromReflect, FromType, GetTypeRegistration, List, ListInfo, + ListIter, Map, MapInfo, MapIter, Reflect, ReflectDeserialize, ReflectMut, ReflectRef, ReflectSerialize, TupleVariantInfo, TypeInfo, TypePath, TypeRegistration, Typed, UnitVariantInfo, UnnamedField, ValueInfo, VariantFieldIter, VariantInfo, VariantType, }; @@ -280,7 +280,7 @@ macro_rules! impl_reflect_for_veclike { T::from_reflect(&*value).unwrap_or_else(|| { panic!( "Attempted to insert invalid value of type {}.", - value.type_name() + value.reflect_type_path() ) }) }); @@ -295,7 +295,7 @@ macro_rules! impl_reflect_for_veclike { let value = T::take_from_reflect(value).unwrap_or_else(|value| { panic!( "Attempted to push invalid value of type {}.", - value.type_name() + value.reflect_type_path() ) }); $push(self, value); @@ -324,19 +324,10 @@ macro_rules! impl_reflect_for_veclike { } impl Reflect for $ty { - fn type_name(&self) -> &str { - std::any::type_name::() - } - fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } - #[inline] - fn get_type_path(&self) -> &dyn DynamicTypePath { - self - } - fn into_any(self: Box) -> Box { self } @@ -501,7 +492,10 @@ macro_rules! impl_reflect_for_hashmap { dynamic_map.set_represented_type(self.get_represented_type_info()); for (k, v) in self { let key = K::from_reflect(k).unwrap_or_else(|| { - panic!("Attempted to clone invalid key of type {}.", k.type_name()) + panic!( + "Attempted to clone invalid key of type {}.", + k.reflect_type_path() + ) }); dynamic_map.insert_boxed(Box::new(key), v.clone_value()); } @@ -516,13 +510,13 @@ macro_rules! impl_reflect_for_hashmap { let key = K::take_from_reflect(key).unwrap_or_else(|key| { panic!( "Attempted to insert invalid key of type {}.", - key.type_name() + key.reflect_type_path() ) }); let value = V::take_from_reflect(value).unwrap_or_else(|value| { panic!( "Attempted to insert invalid value of type {}.", - value.type_name() + value.reflect_type_path() ) }); self.insert(key, value) @@ -547,18 +541,10 @@ macro_rules! impl_reflect_for_hashmap { V: FromReflect + TypePath, S: TypePath + BuildHasher + Send + Sync, { - fn type_name(&self) -> &str { - std::any::type_name::() - } - fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } - fn get_type_path(&self) -> &dyn DynamicTypePath { - self - } - fn into_any(self: Box) -> Box { self } @@ -712,20 +698,10 @@ impl Array for [T; N] { } impl Reflect for [T; N] { - #[inline] - fn type_name(&self) -> &str { - std::any::type_name::() - } - fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } - #[inline] - fn get_type_path(&self) -> &dyn DynamicTypePath { - self - } - #[inline] fn into_any(self: Box) -> Box { self @@ -933,21 +909,11 @@ impl Enum for Option { } impl Reflect for Option { - #[inline] - fn type_name(&self) -> &str { - std::any::type_name::() - } - #[inline] fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } - #[inline] - fn get_type_path(&self) -> &dyn DynamicTypePath { - self - } - #[inline] fn into_any(self: Box) -> Box { self @@ -1096,10 +1062,7 @@ impl Typed for Option { let none_variant = VariantInfo::Unit(UnitVariantInfo::new("None")); let some_variant = VariantInfo::Tuple(TupleVariantInfo::new("Some", &[UnnamedField::new::(0)])); - TypeInfo::Enum(EnumInfo::new::( - "Option", - &[none_variant, some_variant], - )) + TypeInfo::Enum(EnumInfo::new::(&[none_variant, some_variant])) }) } } @@ -1107,19 +1070,10 @@ impl Typed for Option { impl_type_path!(::core::option::Option); impl Reflect for Cow<'static, str> { - fn type_name(&self) -> &str { - std::any::type_name::() - } - fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } - #[inline] - fn get_type_path(&self) -> &dyn DynamicTypePath { - self - } - fn into_any(self: Box) -> Box { self } @@ -1244,19 +1198,10 @@ impl FromReflect for Cow<'static, str> { } impl Reflect for &'static Path { - fn type_name(&self) -> &str { - std::any::type_name::() - } - fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } - #[inline] - fn get_type_path(&self) -> &dyn DynamicTypePath { - self - } - fn into_any(self: Box) -> Box { self } @@ -1362,15 +1307,6 @@ impl FromReflect for &'static Path { } impl Reflect for Cow<'static, Path> { - fn type_name(&self) -> &str { - std::any::type_name::() - } - - #[inline] - fn get_type_path(&self) -> &dyn DynamicTypePath { - self - } - fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index c00b91e626ff1..268b2e04c31c4 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -307,7 +307,7 @@ //! The general entry point are the "untyped" versions of these structs. //! These will automatically extract the type information and pass them into their respective "typed" version. //! -//! The output of the `ReflectSerializer` will be a map, where the key is the [type name] +//! The output of the `ReflectSerializer` will be a map, where the key is the [type path] //! and the value is the serialized data. //! The `TypedReflectSerializer` will simply output the serialized data. //! @@ -427,7 +427,7 @@ //! [`TypedReflectDeserializer`]: serde::TypedReflectDeserializer //! [registry]: TypeRegistry //! [type information]: TypeInfo -//! [type name]: Reflect::type_name +//! [type path]: TypePath //! [type registry]: TypeRegistry //! [`bevy_math`]: https://docs.rs/bevy_math/latest/bevy_math/ //! [`glam`]: https://docs.rs/glam/latest/glam/ @@ -1083,25 +1083,25 @@ mod tests { fn dynamic_names() { let list = Vec::::new(); let dyn_list = list.clone_dynamic(); - assert_eq!(dyn_list.type_name(), std::any::type_name::>()); + assert_eq!(dyn_list.reflect_type_path(), Vec::::type_path()); let array = [b'0'; 4]; let dyn_array = array.clone_dynamic(); - assert_eq!(dyn_array.type_name(), std::any::type_name::<[u8; 4]>()); + assert_eq!(dyn_array.reflect_type_path(), <[u8; 4]>::type_path()); let map = HashMap::::default(); let dyn_map = map.clone_dynamic(); assert_eq!( - dyn_map.type_name(), - std::any::type_name::>() + dyn_map.reflect_type_path(), + HashMap::::type_path() ); let tuple = (0usize, "1".to_string(), 2.0f32); let mut dyn_tuple = tuple.clone_dynamic(); dyn_tuple.insert::(3); assert_eq!( - dyn_tuple.type_name(), - std::any::type_name::<(usize, String, f32, usize)>() + dyn_tuple.reflect_type_path(), + <(usize, String, f32, usize)>::type_path() ); #[derive(Reflect)] @@ -1110,15 +1110,15 @@ mod tests { } let struct_ = TestStruct { a: 0 }; let dyn_struct = struct_.clone_dynamic(); - assert_eq!(dyn_struct.type_name(), std::any::type_name::()); + assert_eq!(dyn_struct.reflect_type_path(), TestStruct::type_path()); #[derive(Reflect)] struct TestTupleStruct(usize); let tuple_struct = TestTupleStruct(0); let dyn_tuple_struct = tuple_struct.clone_dynamic(); assert_eq!( - dyn_tuple_struct.type_name(), - std::any::type_name::() + dyn_tuple_struct.reflect_type_path(), + TestTupleStruct::type_path() ); } @@ -1218,7 +1218,7 @@ mod tests { fn reflect_type_info() { // TypeInfo let info = i32::type_info(); - assert_eq!(std::any::type_name::(), info.type_name()); + assert_eq!(i32::type_path(), info.type_path()); assert_eq!(std::any::TypeId::of::(), info.type_id()); // TypeInfo (unsized) @@ -1242,21 +1242,15 @@ mod tests { let info = MyStruct::type_info(); if let TypeInfo::Struct(info) = info { assert!(info.is::()); - assert_eq!(std::any::type_name::(), info.type_name()); - assert_eq!( - std::any::type_name::(), - info.field("foo").unwrap().type_name() - ); + assert_eq!(MyStruct::type_path(), info.type_path()); + assert_eq!(i32::type_path(), info.field("foo").unwrap().type_path()); assert_eq!( std::any::TypeId::of::(), info.field("foo").unwrap().type_id() ); assert!(info.field("foo").unwrap().is::()); assert_eq!("foo", info.field("foo").unwrap().name()); - assert_eq!( - std::any::type_name::(), - info.field_at(1).unwrap().type_name() - ); + assert_eq!(usize::type_path(), info.field_at(1).unwrap().type_path()); } else { panic!("Expected `TypeInfo::Struct`"); } @@ -1275,19 +1269,10 @@ mod tests { let info = >::type_info(); if let TypeInfo::Struct(info) = info { assert!(info.is::>()); - assert_eq!( - std::any::type_name::>(), - info.type_name() - ); - assert_eq!( - std::any::type_name::(), - info.field("foo").unwrap().type_name() - ); + assert_eq!(MyGenericStruct::::type_path(), info.type_path()); + assert_eq!(i32::type_path(), info.field("foo").unwrap().type_path()); assert_eq!("foo", info.field("foo").unwrap().name()); - assert_eq!( - std::any::type_name::(), - info.field_at(1).unwrap().type_name() - ); + assert_eq!(usize::type_path(), info.field_at(1).unwrap().type_path()); } else { panic!("Expected `TypeInfo::Struct`"); } @@ -1306,11 +1291,8 @@ mod tests { let info = MyTupleStruct::type_info(); if let TypeInfo::TupleStruct(info) = info { assert!(info.is::()); - assert_eq!(std::any::type_name::(), info.type_name()); - assert_eq!( - std::any::type_name::(), - info.field_at(1).unwrap().type_name() - ); + assert_eq!(MyTupleStruct::type_path(), info.type_path()); + assert_eq!(i32::type_path(), info.field_at(1).unwrap().type_path()); assert!(info.field_at(1).unwrap().is::()); } else { panic!("Expected `TypeInfo::TupleStruct`"); @@ -1322,11 +1304,8 @@ mod tests { let info = MyTuple::type_info(); if let TypeInfo::Tuple(info) = info { assert!(info.is::()); - assert_eq!(std::any::type_name::(), info.type_name()); - assert_eq!( - std::any::type_name::(), - info.field_at(1).unwrap().type_name() - ); + assert_eq!(MyTuple::type_path(), info.type_path()); + assert_eq!(f32::type_path(), info.field_at(1).unwrap().type_path()); } else { panic!("Expected `TypeInfo::Tuple`"); } @@ -1342,8 +1321,8 @@ mod tests { if let TypeInfo::List(info) = info { assert!(info.is::()); assert!(info.item_is::()); - assert_eq!(std::any::type_name::(), info.type_name()); - assert_eq!(std::any::type_name::(), info.item_type_name()); + assert_eq!(MyList::type_path(), info.type_path()); + assert_eq!(usize::type_path(), info.item_type_path_vtable().path()); } else { panic!("Expected `TypeInfo::List`"); } @@ -1361,8 +1340,8 @@ mod tests { if let TypeInfo::List(info) = info { assert!(info.is::()); assert!(info.item_is::()); - assert_eq!(std::any::type_name::(), info.type_name()); - assert_eq!(std::any::type_name::(), info.item_type_name()); + assert_eq!(MySmallVec::type_path(), info.type_path()); + assert_eq!(String::type_path(), info.item_type_path_vtable().path()); } else { panic!("Expected `TypeInfo::List`"); } @@ -1380,8 +1359,8 @@ mod tests { if let TypeInfo::Array(info) = info { assert!(info.is::()); assert!(info.item_is::()); - assert_eq!(std::any::type_name::(), info.type_name()); - assert_eq!(std::any::type_name::(), info.item_type_name()); + assert_eq!(MyArray::type_path(), info.type_path()); + assert_eq!(usize::type_path(), info.item_type_path_vtable().path()); assert_eq!(3, info.capacity()); } else { panic!("Expected `TypeInfo::Array`"); @@ -1399,9 +1378,9 @@ mod tests { assert!(info.is::()); assert!(info.key_is::()); assert!(info.value_is::()); - assert_eq!(std::any::type_name::(), info.type_name()); - assert_eq!(std::any::type_name::(), info.key_type_name()); - assert_eq!(std::any::type_name::(), info.value_type_name()); + assert_eq!(MyMap::type_path(), info.type_path()); + assert_eq!(usize::type_path(), info.key_type_path_vtable().path()); + assert_eq!(f32::type_path(), info.value_type_path_vtable().path()); } else { panic!("Expected `TypeInfo::Map`"); } @@ -1416,7 +1395,7 @@ mod tests { let info = MyValue::type_info(); if let TypeInfo::Value(info) = info { assert!(info.is::()); - assert_eq!(std::any::type_name::(), info.type_name()); + assert_eq!(MyValue::type_path(), info.type_path()); } else { panic!("Expected `TypeInfo::Value`"); } diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index b040464ec33fa..47aed0df22299 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, DynamicTypePath, FromReflect, Reflect, ReflectMut, ReflectOwned, - ReflectRef, TypeInfo, + self as bevy_reflect, FromReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, + TypePath, TypePathVtable, }; /// A trait used to power [list-like] operations via [reflection]. @@ -109,9 +109,9 @@ pub trait List: Reflect { /// A container for compile-time list info. #[derive(Clone, Debug)] pub struct ListInfo { - type_name: &'static str, + type_path: TypePathVtable, type_id: TypeId, - item_type_name: &'static str, + item_type_path: TypePathVtable, item_type_id: TypeId, #[cfg(feature = "documentation")] docs: Option<&'static str>, @@ -119,11 +119,11 @@ pub struct ListInfo { impl ListInfo { /// Create a new [`ListInfo`]. - pub fn new() -> Self { + pub fn new() -> Self { Self { - type_name: std::any::type_name::(), + type_path: TypePathVtable::of::(), type_id: TypeId::of::(), - item_type_name: std::any::type_name::(), + item_type_path: TypePathVtable::of::(), item_type_id: TypeId::of::(), #[cfg(feature = "documentation")] docs: None, @@ -136,11 +136,21 @@ impl ListInfo { Self { docs, ..self } } - /// The [type name] of the list. + /// A representation of the type path of the list. /// - /// [type name]: std::any::type_name - pub fn type_name(&self) -> &'static str { - self.type_name + /// Provides dynamic access to all methods on [`TypePath`]. + pub fn type_path_vtable(&self) -> &TypePathVtable { + &self.type_path + } + + /// The [stable, full type path] of the list. + /// + /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. + /// + /// [stable, full type path]: TypePath + /// [`type_path_vtable`]: Self::type_path_vtable + pub fn type_path(&self) -> &'static str { + self.type_path_vtable().path() } /// The [`TypeId`] of the list. @@ -153,11 +163,11 @@ impl ListInfo { TypeId::of::() == self.type_id } - /// The [type name] of the list item. + /// A representation of the type path of the list item. /// - /// [type name]: std::any::type_name - pub fn item_type_name(&self) -> &'static str { - self.item_type_name + /// Provides dynamic access to all methods on [`TypePath`]. + pub fn item_type_path_vtable(&self) -> &TypePathVtable { + &self.item_type_path } /// The [`TypeId`] of the list item. @@ -264,23 +274,11 @@ impl List for DynamicList { } impl Reflect for DynamicList { - #[inline] - fn type_name(&self) -> &str { - self.represented_type - .map(|info| info.type_name()) - .unwrap_or_else(|| std::any::type_name::()) - } - #[inline] fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } - #[inline] - fn get_type_path(&self) -> &dyn DynamicTypePath { - self - } - #[inline] fn into_any(self: Box) -> Box { self diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index 3b9c0c751bc27..755c72d605156 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -6,7 +6,8 @@ use bevy_reflect_derive::impl_type_path; use bevy_utils::{Entry, HashMap}; use crate::{ - self as bevy_reflect, DynamicTypePath, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, + self as bevy_reflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, + TypePathVtable, }; /// A trait used to power [map-like] operations via [reflection]. @@ -95,11 +96,11 @@ pub trait Map: Reflect { /// A container for compile-time map info. #[derive(Clone, Debug)] pub struct MapInfo { - type_name: &'static str, + type_path: TypePathVtable, type_id: TypeId, - key_type_name: &'static str, + key_type_path: TypePathVtable, key_type_id: TypeId, - value_type_name: &'static str, + value_type_path: TypePathVtable, value_type_id: TypeId, #[cfg(feature = "documentation")] docs: Option<&'static str>, @@ -107,13 +108,17 @@ pub struct MapInfo { impl MapInfo { /// Create a new [`MapInfo`]. - pub fn new() -> Self { + pub fn new< + TMap: Map + TypePath, + TKey: Hash + Reflect + TypePath, + TValue: Reflect + TypePath, + >() -> Self { Self { - type_name: std::any::type_name::(), + type_path: TypePathVtable::of::(), type_id: TypeId::of::(), - key_type_name: std::any::type_name::(), + key_type_path: TypePathVtable::of::(), key_type_id: TypeId::of::(), - value_type_name: std::any::type_name::(), + value_type_path: TypePathVtable::of::(), value_type_id: TypeId::of::(), #[cfg(feature = "documentation")] docs: None, @@ -126,11 +131,21 @@ impl MapInfo { Self { docs, ..self } } - /// The [type name] of the map. + /// A representation of the type path of the map. /// - /// [type name]: std::any::type_name - pub fn type_name(&self) -> &'static str { - self.type_name + /// Provides dynamic access to all methods on [`TypePath`]. + pub fn type_path_vtable(&self) -> &TypePathVtable { + &self.type_path + } + + /// The [stable, full type path] of the map. + /// + /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. + /// + /// [stable, full type path]: TypePath + /// [`type_path_vtable`]: Self::type_path_vtable + pub fn type_path(&self) -> &'static str { + self.type_path_vtable().path() } /// The [`TypeId`] of the map. @@ -143,11 +158,11 @@ impl MapInfo { TypeId::of::() == self.type_id } - /// The [type name] of the key. + /// A representation of the type path of the keys. /// - /// [type name]: std::any::type_name - pub fn key_type_name(&self) -> &'static str { - self.key_type_name + /// Provides dynamic access to all methods on [`TypePath`]. + pub fn key_type_path_vtable(&self) -> &TypePathVtable { + &self.key_type_path } /// The [`TypeId`] of the key. @@ -160,11 +175,11 @@ impl MapInfo { TypeId::of::() == self.key_type_id } - /// The [type name] of the value. + /// A representation of the type path of the values. /// - /// [type name]: std::any::type_name - pub fn value_type_name(&self) -> &'static str { - self.value_type_name + /// Provides dynamic access to all methods on [`TypePath`]. + pub fn value_type_path_vtable(&self) -> &TypePathVtable { + &self.value_type_path } /// The [`TypeId`] of the value. @@ -299,22 +314,11 @@ impl Map for DynamicMap { } impl Reflect for DynamicMap { - fn type_name(&self) -> &str { - self.represented_type - .map(|info| info.type_name()) - .unwrap_or_else(|| std::any::type_name::()) - } - #[inline] fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } - #[inline] - fn get_type_path(&self) -> &dyn DynamicTypePath { - self - } - fn into_any(self: Box) -> Box { self } diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index 53bf3aca1a0e5..440e99ea7521d 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -1,10 +1,10 @@ use crate::{ array_debug, enum_debug, list_debug, map_debug, serde::Serializable, struct_debug, tuple_debug, tuple_struct_debug, Array, DynamicTypePath, Enum, List, Map, Struct, Tuple, TupleStruct, - TypeInfo, Typed, ValueInfo, + TypeInfo, TypePath, TypePathId, Typed, ValueInfo, }; use std::{ - any::{self, Any, TypeId}, + any::{Any, TypeId}, fmt::Debug, }; @@ -72,10 +72,7 @@ pub enum ReflectOwned { /// [`bevy_reflect`]: crate /// [derive macro]: bevy_reflect_derive::Reflect /// [crate-level documentation]: crate -pub trait Reflect: Any + Send + Sync { - /// Returns the [type name][std::any::type_name] of the underlying type. - fn type_name(&self) -> &str; - +pub trait Reflect: DynamicTypePath + Any + Send + Sync { /// Returns the [`TypeInfo`] of the type _represented_ by this value. /// /// For most types, this will simply return their own `TypeInfo`. @@ -93,13 +90,13 @@ pub trait Reflect: Any + Send + Sync { /// [`TypeRegistry::get_type_info`]: crate::TypeRegistry::get_type_info fn get_represented_type_info(&self) -> Option<&'static TypeInfo>; - /// Returns the [`TypePath`] implementation for the underlying type. - /// - /// Methods on [`DynamicTypePath`] suffer the same performance concerns as [`get_represented_type_info`]. - /// - /// [`TypePath`]: crate::TypePath - /// [`get_represented_type_info`]: Reflect::get_represented_type_info - fn get_type_path(&self) -> &dyn DynamicTypePath; + // /// Returns the [`TypePath`] implementation for the underlying type. + // /// + // /// Methods on [`DynamicTypePath`] suffer the same performance concerns as [`get_represented_type_info`]. + // /// + // /// [`TypePath`]: crate::TypePath + // /// [`get_represented_type_info`]: Reflect::get_represented_type_info + // fn type_path(&self) -> &dyn DynamicTypePath; /// Returns the value as a [`Box`][std::any::Any]. fn into_any(self: Box) -> Box; @@ -208,10 +205,10 @@ pub trait Reflect: Any + Send + Sync { /// Debug formatter for the value. /// /// Any value that is not an implementor of other `Reflect` subtraits - /// (e.g. [`List`], [`Map`]), will default to the format: `"Reflect(type_name)"`, - /// where `type_name` is the [type name] of the underlying type. + /// (e.g. [`List`], [`Map`]), will default to the format: `"Reflect(type_path)"`, + /// where `type_path` is the [type path] of the underlying type. /// - /// [type name]: Self::type_name + /// [type path]: TypePath::type_path fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self.reflect_ref() { ReflectRef::Struct(dyn_struct) => struct_debug(dyn_struct, f), @@ -221,7 +218,7 @@ pub trait Reflect: Any + Send + Sync { ReflectRef::Array(dyn_array) => array_debug(dyn_array, f), ReflectRef::Map(dyn_map) => map_debug(dyn_map, f), ReflectRef::Enum(dyn_enum) => enum_debug(dyn_enum, f), - _ => write!(f, "Reflect({})", self.type_name()), + _ => write!(f, "Reflect({})", self.reflect_type_path()), } } @@ -262,6 +259,21 @@ impl Typed for dyn Reflect { } } +// 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" + } + + const TYPE_PATH_ID: TypePathId = TypePathId::from_base("dyn bevy_reflect::Reflect"); +} + #[deny(rustdoc::broken_intra_doc_links)] impl dyn Reflect { /// Downcasts the value to type `T`, consuming the trait object. @@ -287,8 +299,8 @@ impl dyn Reflect { /// /// Read `is` for more information on underlying values and represented types. #[inline] - pub fn represents(&self) -> bool { - self.type_name() == any::type_name::() + pub fn represents(&self) -> bool { + self.reflect_type_path() == T::type_path() } /// Returns `true` if the underlying value is of type `T`, or `false` diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index de7c47438104c..3524d94336a9f 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -24,13 +24,13 @@ pub trait DeserializeValue { } trait StructLikeInfo { - fn get_name(&self) -> &str; + fn get_path(&self) -> &str; fn get_field(&self, name: &str) -> Option<&NamedField>; fn iter_fields(&self) -> Iter<'_, NamedField>; } trait TupleLikeInfo { - fn get_name(&self) -> &str; + fn get_path(&self) -> &str; fn get_field(&self, index: usize) -> Option<&UnnamedField>; fn get_field_len(&self) -> usize; } @@ -44,8 +44,8 @@ trait Container { } impl StructLikeInfo for StructInfo { - fn get_name(&self) -> &str { - self.type_name() + fn get_path(&self) -> &str { + self.type_path() } fn get_field(&self, name: &str) -> Option<&NamedField> { @@ -67,15 +67,15 @@ impl Container for StructInfo { de::Error::custom(format_args!( "no field at index {} on struct {}", index, - self.type_name(), + self.type_path(), )) })?; - get_registration(field.type_id(), field.type_name(), registry) + get_registration(field.type_id(), field.type_path(), registry) } } impl StructLikeInfo for StructVariantInfo { - fn get_name(&self) -> &str { + fn get_path(&self) -> &str { self.name() } @@ -101,13 +101,13 @@ impl Container for StructVariantInfo { self.name(), )) })?; - get_registration(field.type_id(), field.type_name(), registry) + get_registration(field.type_id(), field.type_path(), registry) } } impl TupleLikeInfo for TupleInfo { - fn get_name(&self) -> &str { - self.type_name() + fn get_path(&self) -> &str { + self.type_path() } fn get_field(&self, index: usize) -> Option<&UnnamedField> { @@ -120,7 +120,7 @@ impl TupleLikeInfo for TupleInfo { } impl TupleLikeInfo for TupleVariantInfo { - fn get_name(&self) -> &str { + fn get_path(&self) -> &str { self.name() } @@ -370,7 +370,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { where D: serde::Deserializer<'de>, { - let type_name = self.registration.type_name(); + let type_name = self.registration.type_info().type_path(); // Handle both Value case and types that have a custom `ReflectDeserialize` if let Some(deserialize_reflect) = self.registration.data::() { @@ -381,7 +381,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { match self.registration.type_info() { TypeInfo::Struct(struct_info) => { let mut dynamic_struct = deserializer.deserialize_struct( - struct_info.name(), + struct_info.type_path_vtable().ident().unwrap(), struct_info.field_names(), StructVisitor { struct_info, @@ -394,7 +394,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { } TypeInfo::TupleStruct(tuple_struct_info) => { let mut dynamic_tuple_struct = deserializer.deserialize_tuple_struct( - tuple_struct_info.name(), + tuple_struct_info.type_path_vtable().ident().unwrap(), tuple_struct_info.field_len(), TupleStructVisitor { tuple_struct_info, @@ -444,7 +444,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { Ok(Box::new(dynamic_tuple)) } TypeInfo::Enum(enum_info) => { - let type_name = enum_info.type_name(); + let type_name = enum_info.type_path(); let mut dynamic_enum = if type_name.starts_with("core::option::Option") { deserializer.deserialize_option(OptionVisitor { enum_info, @@ -452,7 +452,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { })? } else { deserializer.deserialize_enum( - enum_info.name(), + enum_info.type_path_vtable().ident().unwrap(), enum_info.variant_names(), EnumVisitor { enum_info, @@ -571,10 +571,10 @@ impl<'a, 'de> Visitor<'de> for TupleStructVisitor<'a> { de::Error::custom(format_args!( "no field at index {} on tuple {}", index, - self.tuple_struct_info.type_name(), + self.tuple_struct_info.type_path(), )) })?; - get_registration(field.type_id(), field.type_name(), self.registry) + get_registration(field.type_id(), field.type_path(), self.registry) }; while let Some(value) = seq.next_element_seed(TypedReflectDeserializer { @@ -643,7 +643,7 @@ impl<'a, 'de> Visitor<'de> for ArrayVisitor<'a> { let mut vec = Vec::with_capacity(seq.size_hint().unwrap_or_default()); let registration = get_registration( self.array_info.item_type_id(), - self.array_info.item_type_name(), + self.array_info.item_type_path_vtable().path(), self.registry, )?; while let Some(value) = seq.next_element_seed(TypedReflectDeserializer { @@ -683,7 +683,7 @@ impl<'a, 'de> Visitor<'de> for ListVisitor<'a> { let mut list = DynamicList::default(); let registration = get_registration( self.list_info.item_type_id(), - self.list_info.item_type_name(), + self.list_info.item_type_path_vtable().path(), self.registry, )?; while let Some(value) = seq.next_element_seed(TypedReflectDeserializer { @@ -715,12 +715,12 @@ impl<'a, 'de> Visitor<'de> for MapVisitor<'a> { let mut dynamic_map = DynamicMap::default(); let key_registration = get_registration( self.map_info.key_type_id(), - self.map_info.key_type_name(), + self.map_info.key_type_path_vtable().path(), self.registry, )?; let value_registration = get_registration( self.map_info.value_type_id(), - self.map_info.value_type_name(), + self.map_info.value_type_path_vtable().path(), self.registry, )?; while let Some(key) = map.next_key_seed(TypedReflectDeserializer { @@ -775,7 +775,7 @@ impl<'a, 'de> Visitor<'de> for EnumVisitor<'a> { VariantInfo::Tuple(tuple_info) if tuple_info.field_len() == 1 => { let field = tuple_info.field_at(0).unwrap(); let registration = - get_registration(field.type_id(), field.type_name(), self.registry)?; + get_registration(field.type_id(), field.type_path(), self.registry)?; let value = variant.newtype_variant_seed(TypedReflectDeserializer { registration, registry: self.registry, @@ -843,7 +843,7 @@ impl<'de> DeserializeSeed<'de> for VariantDeserializer { Error::custom(format_args!( "no variant found at index `{}` on enum `{}`", variant_index, - self.0.name() + self.0.type_path() )) }) } @@ -953,7 +953,7 @@ impl<'a, 'de> Visitor<'de> for OptionVisitor<'a> { fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { formatter.write_str("reflected option value of type ")?; - formatter.write_str(self.enum_info.type_name()) + formatter.write_str(self.enum_info.type_path()) } fn visit_some(self, deserializer: D) -> Result @@ -965,7 +965,7 @@ impl<'a, 'de> Visitor<'de> for OptionVisitor<'a> { VariantInfo::Tuple(tuple_info) if tuple_info.field_len() == 1 => { let field = tuple_info.field_at(0).unwrap(); let registration = - get_registration(field.type_id(), field.type_name(), self.registry)?; + get_registration(field.type_id(), field.type_path(), self.registry)?; let de = TypedReflectDeserializer { registration, registry: self.registry, @@ -1012,7 +1012,7 @@ where ExpectedValues(fields.collect()) )) })?; - let registration = get_registration(field.type_id(), field.type_name(), registry)?; + let registration = get_registration(field.type_id(), field.type_path(), registry)?; let value = map.next_value_seed(TypedReflectDeserializer { registration, registry, @@ -1039,7 +1039,7 @@ where let field = info.get_field(index).ok_or_else(|| { Error::invalid_length(index, &info.get_field_len().to_string().as_str()) })?; - get_registration(field.type_id(), field.type_name(), registry) + get_registration(field.type_id(), field.type_path(), registry) }; while let Some(value) = seq.next_element_seed(TypedReflectDeserializer { diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index 38d4529a3a40b..d1c48030bc87c 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -37,7 +37,7 @@ fn get_serializable<'a, E: serde::ser::Error>( .ok_or_else(|| { serde::ser::Error::custom(format_args!( "Type '{}' did not register ReflectSerialize", - reflect_value.type_name() + reflect_value.reflect_type_path() )) })?; Ok(reflect_serialize.get_serializable(reflect_value)) @@ -68,7 +68,7 @@ impl<'a> Serialize for ReflectSerializer<'a> { { let mut state = serializer.serialize_map(Some(1))?; state.serialize_entry( - self.value.type_name(), + self.value.reflect_type_path(), &TypedReflectSerializer::new(self.value, self.registry), )?; state.end() @@ -172,7 +172,7 @@ impl<'a> Serialize for StructSerializer<'a> { .ok_or_else(|| { Error::custom(format_args!( "cannot get type info for {}", - self.struct_value.type_name() + self.struct_value.reflect_type_path() )) })?; @@ -191,7 +191,7 @@ impl<'a> Serialize for StructSerializer<'a> { .and_then(|registration| registration.data::()); let ignored_len = serialization_data.map(|data| data.len()).unwrap_or(0); let mut state = serializer.serialize_struct( - struct_info.name(), + struct_info.type_path_vtable().ident().unwrap(), self.struct_value.field_len() - ignored_len, )?; @@ -225,7 +225,7 @@ impl<'a> Serialize for TupleStructSerializer<'a> { .ok_or_else(|| { Error::custom(format_args!( "cannot get type info for {}", - self.tuple_struct.type_name() + self.tuple_struct.reflect_type_path() )) })?; @@ -244,7 +244,7 @@ impl<'a> Serialize for TupleStructSerializer<'a> { .and_then(|registration| registration.data::()); let ignored_len = serialization_data.map(|data| data.len()).unwrap_or(0); let mut state = serializer.serialize_tuple_struct( - tuple_struct_info.name(), + tuple_struct_info.type_path_vtable().ident().unwrap(), self.tuple_struct.field_len() - ignored_len, )?; @@ -274,7 +274,7 @@ impl<'a> Serialize for EnumSerializer<'a> { let type_info = self.enum_value.get_represented_type_info().ok_or_else(|| { Error::custom(format_args!( "cannot get type info for {}", - self.enum_value.type_name() + self.enum_value.reflect_type_path() )) })?; @@ -287,7 +287,7 @@ impl<'a> Serialize for EnumSerializer<'a> { } }; - let enum_name = enum_info.name(); + let enum_name = enum_info.type_path_vtable().ident().unwrap(); let variant_index = self.enum_value.variant_index() as u32; let variant_info = enum_info .variant_at(variant_index as usize) @@ -302,10 +302,8 @@ impl<'a> Serialize for EnumSerializer<'a> { match variant_type { VariantType::Unit => { - if self - .enum_value - .type_name() - .starts_with("core::option::Option") + if self.enum_value.reflect_module_path() == Some("core::option") + && self.enum_value.reflect_type_ident() == Some("Option") { serializer.serialize_none() } else { @@ -341,7 +339,7 @@ impl<'a> Serialize for EnumSerializer<'a> { let field = self.enum_value.field_at(0).unwrap(); if self .enum_value - .type_name() + .reflect_type_path() .starts_with("core::option::Option") { serializer.serialize_some(&TypedReflectSerializer::new(field, self.registry)) diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index fce88b78dd47c..a9730331d7efa 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, DynamicTypePath, NamedField, Reflect, ReflectMut, ReflectOwned, - ReflectRef, TypeInfo, + self as bevy_reflect, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, + TypePath, TypePathVtable, }; use bevy_reflect_derive::impl_type_path; use bevy_utils::{Entry, HashMap}; @@ -76,8 +76,7 @@ pub trait Struct: Reflect { /// A container for compile-time named struct info. #[derive(Clone, Debug)] pub struct StructInfo { - name: &'static str, - type_name: &'static str, + type_path: TypePathVtable, type_id: TypeId, fields: Box<[NamedField]>, field_names: Box<[&'static str]>, @@ -94,7 +93,7 @@ impl StructInfo { /// * `name`: The name of this struct (_without_ generics or lifetimes) /// * `fields`: The fields of this struct in the order they are defined /// - pub fn new(name: &'static str, fields: &[NamedField]) -> Self { + pub fn new(fields: &[NamedField]) -> Self { let field_indices = fields .iter() .enumerate() @@ -104,8 +103,7 @@ impl StructInfo { let field_names = fields.iter().map(|field| field.name()).collect(); Self { - name, - type_name: std::any::type_name::(), + type_path: TypePathVtable::of::(), type_id: TypeId::of::(), fields: fields.to_vec().into_boxed_slice(), field_names, @@ -153,20 +151,21 @@ impl StructInfo { self.fields.len() } - /// The name of the struct. + /// A representation of the type path of the struct. /// - /// This does _not_ include any generics or lifetimes. - /// - /// For example, `foo::bar::Baz<'a, T>` would simply be `Baz`. - pub fn name(&self) -> &'static str { - self.name + /// Provides dynamic access to all methods on [`TypePath`]. + pub fn type_path_vtable(&self) -> &TypePathVtable { + &self.type_path } - /// The [type name] of the struct. + /// The [stable, full type path] of the struct. + /// + /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. /// - /// [type name]: std::any::type_name - pub fn type_name(&self) -> &'static str { - self.type_name + /// [stable, full type path]: TypePath + /// [`type_path_vtable`]: Self::type_path_vtable + pub fn type_path(&self) -> &'static str { + self.type_path_vtable().path() } /// The [`TypeId`] of the struct. @@ -393,23 +392,11 @@ impl Struct for DynamicStruct { } impl Reflect for DynamicStruct { - #[inline] - fn type_name(&self) -> &str { - self.represented_type - .map(|info| info.type_name()) - .unwrap_or_else(|| std::any::type_name::()) - } - #[inline] fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } - #[inline] - fn get_type_path(&self) -> &dyn DynamicTypePath { - self - } - #[inline] fn into_any(self: Box) -> Box { self @@ -557,7 +544,7 @@ pub fn struct_partial_eq(a: &S, b: &dyn Reflect) -> Option { /// ``` #[inline] pub fn struct_debug(dyn_struct: &dyn Struct, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let mut debug = f.debug_struct(dyn_struct.type_name()); + let mut debug = f.debug_struct(dyn_struct.reflect_type_path()); for field_index in 0..dyn_struct.field_len() { let field = dyn_struct.field_at(field_index).unwrap(); debug.field( diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index 2c7c6afaaa685..48d11e2547b7e 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -1,10 +1,11 @@ use bevy_reflect_derive::impl_type_path; use crate::{ - self as bevy_reflect, utility::GenericTypePathCell, DynamicTypePath, FromReflect, - GetTypeRegistration, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, - TypeRegistration, Typed, UnnamedField, + self as bevy_reflect, utility::GenericTypePathCell, FromReflect, GetTypeRegistration, Reflect, + ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, TypeRegistration, Typed, + UnnamedField, }; +use crate::{TypePathId, TypePathVtable}; use std::any::{Any, TypeId}; use std::borrow::Cow; use std::fmt::{Debug, Formatter}; @@ -138,7 +139,7 @@ impl GetTupleField for dyn Tuple { /// A container for compile-time tuple info. #[derive(Clone, Debug)] pub struct TupleInfo { - type_name: &'static str, + type_path: TypePathVtable, type_id: TypeId, fields: Box<[UnnamedField]>, #[cfg(feature = "documentation")] @@ -152,9 +153,9 @@ impl TupleInfo { /// /// * `fields`: The fields of this tuple in the order they are defined /// - pub fn new(fields: &[UnnamedField]) -> Self { + pub fn new(fields: &[UnnamedField]) -> Self { Self { - type_name: std::any::type_name::(), + type_path: TypePathVtable::of::(), type_id: TypeId::of::(), fields: fields.to_vec().into_boxed_slice(), #[cfg(feature = "documentation")] @@ -183,11 +184,21 @@ impl TupleInfo { self.fields.len() } - /// The [type name] of the tuple. + /// A representation of the type path of the tuple. /// - /// [type name]: std::any::type_name - pub fn type_name(&self) -> &'static str { - self.type_name + /// Provides dynamic access to all methods on [`TypePath`]. + pub fn type_path_vtable(&self) -> &TypePathVtable { + &self.type_path + } + + /// The [stable, full type path] of the tuple. + /// + /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. + /// + /// [stable, full type path]: TypePath + /// [`type_path_vtable`]: Self::type_path_vtable + pub fn type_path(&self) -> &'static str { + self.type_path_vtable().path() } /// The [`TypeId`] of the tuple. @@ -231,7 +242,7 @@ impl DynamicTuple { represented_type ); - self.name = Cow::Borrowed(represented_type.type_name()); + self.name = Cow::Borrowed(represented_type.type_path()); } self.represented_type = represented_type; } @@ -258,7 +269,7 @@ impl DynamicTuple { if i > 0 { name.push_str(", "); } - name.push_str(field.type_name()); + name.push_str(field.reflect_type_path()); } name.push(')'); self.name = Cow::Owned(name); @@ -309,23 +320,11 @@ impl Tuple for DynamicTuple { } impl Reflect for DynamicTuple { - #[inline] - fn type_name(&self) -> &str { - self.represented_type - .map(|info| info.type_name()) - .unwrap_or_else(|| &self.name) - } - #[inline] fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } - #[inline] - fn get_type_path(&self) -> &dyn DynamicTypePath { - self - } - #[inline] fn into_any(self: Box) -> Box { self @@ -530,19 +529,10 @@ macro_rules! impl_reflect_tuple { } impl<$($name: Reflect + TypePath),*> Reflect for ($($name,)*) { - fn type_name(&self) -> &str { - std::any::type_name::() - } - fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } - #[inline] - fn get_type_path(&self) -> &dyn DynamicTypePath { - self - } - fn into_any(self: Box) -> Box { self } diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index b2703b65aa7b5..353ae7863ed47 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, DynamicTypePath, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, - UnnamedField, + self as bevy_reflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, + TypePathVtable, UnnamedField, }; use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; @@ -56,8 +56,7 @@ pub trait TupleStruct: Reflect { /// A container for compile-time tuple struct info. #[derive(Clone, Debug)] pub struct TupleStructInfo { - name: &'static str, - type_name: &'static str, + type_path: TypePathVtable, type_id: TypeId, fields: Box<[UnnamedField]>, #[cfg(feature = "documentation")] @@ -72,10 +71,9 @@ impl TupleStructInfo { /// * `name`: The name of this struct (_without_ generics or lifetimes) /// * `fields`: The fields of this struct in the order they are defined /// - pub fn new(name: &'static str, fields: &[UnnamedField]) -> Self { + pub fn new(fields: &[UnnamedField]) -> Self { Self { - name, - type_name: std::any::type_name::(), + type_path: TypePathVtable::of::(), type_id: TypeId::of::(), fields: fields.to_vec().into_boxed_slice(), #[cfg(feature = "documentation")] @@ -104,20 +102,21 @@ impl TupleStructInfo { self.fields.len() } - /// The name of the struct. + /// A representation of the type path of the struct. /// - /// This does _not_ include any generics or lifetimes. - /// - /// For example, `foo::bar::Baz<'a, T>` would simply be `Baz`. - pub fn name(&self) -> &'static str { - self.name + /// Provides dynamic access to all methods on [`TypePath`]. + pub fn type_path_vtable(&self) -> &TypePathVtable { + &self.type_path } - /// The [type name] of the tuple struct. + /// The [stable, full type path] of the struct. + /// + /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. /// - /// [type name]: std::any::type_name - pub fn type_name(&self) -> &'static str { - self.type_name + /// [stable, full type path]: TypePath + /// [`type_path_vtable`]: Self::type_path_vtable + pub fn type_path(&self) -> &'static str { + self.type_path_vtable().path() } /// The [`TypeId`] of the tuple struct. @@ -296,23 +295,11 @@ impl TupleStruct for DynamicTupleStruct { } impl Reflect for DynamicTupleStruct { - #[inline] - fn type_name(&self) -> &str { - self.represented_type - .map(|info| info.type_name()) - .unwrap_or_else(|| std::any::type_name::()) - } - #[inline] fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { self.represented_type } - #[inline] - fn get_type_path(&self) -> &dyn DynamicTypePath { - self - } - #[inline] fn into_any(self: Box) -> Box { self @@ -458,7 +445,7 @@ pub fn tuple_struct_debug( dyn_tuple_struct: &dyn TupleStruct, f: &mut std::fmt::Formatter<'_>, ) -> std::fmt::Result { - let mut debug = f.debug_tuple(dyn_tuple_struct.type_name()); + let mut debug = f.debug_tuple(dyn_tuple_struct.reflect_type_path()); for field in dyn_tuple_struct.iter_fields() { debug.field(&field as &dyn Debug); } diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index 7a4099815ab5f..aace5bea121a3 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -1,5 +1,6 @@ use crate::{ ArrayInfo, EnumInfo, ListInfo, MapInfo, Reflect, StructInfo, TupleInfo, TupleStructInfo, + TypePath, TypePathVtable, }; use std::any::{Any, TypeId}; use std::fmt::Debug; @@ -51,7 +52,7 @@ use std::fmt::Debug; /// # impl Reflect for MyStruct { /// # fn type_name(&self) -> &str { todo!() } /// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } -/// # fn get_type_path(&self) -> &dyn DynamicTypePath { todo!() } +/// # fn type_path(&self) -> &dyn DynamicTypePath { 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!() } @@ -124,22 +125,32 @@ impl TypeInfo { } } - /// The [name] of the underlying type. + /// A representation of the type path of the underlying type. /// - /// [name]: std::any::type_name - pub fn type_name(&self) -> &'static str { + /// Provides dynamic access to all methods on [`TypePath`]. + pub fn type_path_vtable(&self) -> &TypePathVtable { match self { - Self::Struct(info) => info.type_name(), - Self::TupleStruct(info) => info.type_name(), - Self::Tuple(info) => info.type_name(), - Self::List(info) => info.type_name(), - Self::Array(info) => info.type_name(), - Self::Map(info) => info.type_name(), - Self::Enum(info) => info.type_name(), - Self::Value(info) => info.type_name(), + Self::Struct(info) => info.type_path_vtable(), + Self::TupleStruct(info) => info.type_path_vtable(), + Self::Tuple(info) => info.type_path_vtable(), + Self::List(info) => info.type_path_vtable(), + Self::Array(info) => info.type_path_vtable(), + Self::Map(info) => info.type_path_vtable(), + Self::Enum(info) => info.type_path_vtable(), + Self::Value(info) => info.type_path_vtable(), } } + /// The [stable, full type path] of the underlying type. + /// + /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. + /// + /// [stable, full type path]: TypePath + /// [`type_path_vtable`]: Self::type_path_vtable + pub fn type_path(&self) -> &'static str { + self.type_path_vtable().path() + } + /// Check if the given type matches the underlying type. pub fn is(&self) -> bool { TypeId::of::() == self.type_id() @@ -171,16 +182,16 @@ impl TypeInfo { /// it _as_ a struct. It therefore makes more sense to represent it as a [`ValueInfo`]. #[derive(Debug, Clone)] pub struct ValueInfo { - type_name: &'static str, + type_path: TypePathVtable, type_id: TypeId, #[cfg(feature = "documentation")] docs: Option<&'static str>, } impl ValueInfo { - pub fn new() -> Self { + pub fn new() -> Self { Self { - type_name: std::any::type_name::(), + type_path: TypePathVtable::of::(), type_id: TypeId::of::(), #[cfg(feature = "documentation")] docs: None, @@ -193,11 +204,21 @@ impl ValueInfo { Self { docs: doc, ..self } } - /// The [type name] of the value. + /// A representation of the type path of the value. + /// + /// Provides dynamic access to all methods on [`TypePath`]. + pub fn type_path_vtable(&self) -> &TypePathVtable { + &self.type_path + } + + /// The [stable, full type path] of the value. + /// + /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. /// - /// [type name]: std::any::type_name - pub fn type_name(&self) -> &'static str { - self.type_name + /// [stable, full type path]: TypePath + /// [`type_path_vtable`]: Self::type_path_vtable + pub fn type_path(&self) -> &'static str { + self.type_path_vtable().path() } /// The [`TypeId`] of the value. diff --git a/crates/bevy_reflect/src/type_path.rs b/crates/bevy_reflect/src/type_path.rs index 387fb11930d9c..edff71e31312f 100644 --- a/crates/bevy_reflect/src/type_path.rs +++ b/crates/bevy_reflect/src/type_path.rs @@ -82,21 +82,21 @@ pub trait TypePath: 'static { /// /// Generic parameter types are also fully expanded. /// - /// For `Option`, this is `"core::option::Option"`. + /// For `Option>`, this is `"core::option::Option>"`. fn type_path() -> &'static str; /// Returns a short, pretty-print enabled path to the type. /// /// Generic parameter types are also shortened. /// - /// For `Option`, this is `"Option"`. + /// For `Option>`, this is `"Option>"`. fn short_type_path() -> &'static str; /// Returns the name of the type, or [`None`] if it is [anonymous]. /// /// Primitive types will return [`Some`]. /// - /// For `Option`, this is `"Option"`. + /// For `Option>`, this is `"Option"`. /// /// [anonymous]: TypePath#anonymity fn type_ident() -> Option<&'static str> { @@ -105,7 +105,7 @@ pub trait TypePath: 'static { /// Returns the name of the crate the type is in, or [`None`] if it is [anonymous]. /// - /// For `Option`, this is `"core"`. + /// For `Option>`, this is `"core"`. /// /// [anonymous]: TypePath#anonymity fn crate_name() -> Option<&'static str> { @@ -114,7 +114,7 @@ pub trait TypePath: 'static { /// Returns the path to the moudle the type is in, or [`None`] if it is [anonymous]. /// - /// For `Option`, this is `"core::option"`. + /// For `Option>`, this is `"core::option"`. /// /// [anonymous]: TypePath#anonymity fn module_path() -> Option<&'static str> { @@ -124,9 +124,9 @@ pub trait TypePath: 'static { /// Dynamic dispatch for [`TypePath`]. /// -/// Retrieved using [`Reflect::get_type_path`]. +/// Since this is a supertrait of [`Reflect`] its methods can be called on a `dyn Reflect`. /// -/// [`Reflect::get_type_path`]: crate::Reflect::get_type_path +/// [`Reflect`]: crate::Reflect pub trait DynamicTypePath { /// See [`TypePath::type_path`]. fn reflect_type_path(&self) -> &str; @@ -165,3 +165,51 @@ impl DynamicTypePath for T { Self::module_path() } } + +#[derive(Debug, Clone, Copy)] +pub struct TypePathVtable { + // Cache the type path as it is likely the only one that will be used. + type_path: &'static str, + short_type_path: fn() -> &'static str, + type_ident: fn() -> Option<&'static str>, + crate_name: fn() -> Option<&'static str>, + module_path: fn() -> Option<&'static str>, + type_path_id: TypePathId, +} + +impl TypePathVtable { + pub fn of() -> Self { + Self { + type_path: T::type_path(), + short_type_path: T::short_type_path, + type_ident: T::type_ident, + crate_name: T::crate_name, + module_path: T::module_path, + type_path_id: T::TYPE_PATH_ID, + } + } + + pub fn path(&self) -> &'static str { + self.type_path + } + + pub fn short_path(&self) -> &'static str { + (self.short_type_path)() + } + + pub fn ident(&self) -> Option<&'static str> { + (self.type_ident)() + } + + pub fn crate_name(&self) -> Option<&'static str> { + (self.crate_name)() + } + + pub fn module_path(&self) -> Option<&'static str> { + (self.module_path)() + } + + pub fn type_path_id(&self) -> TypePathId { + self.type_path_id + } +} diff --git a/crates/bevy_reflect/src/type_registry.rs b/crates/bevy_reflect/src/type_registry.rs index aeaba79a2f6d5..054cb07d3f799 100644 --- a/crates/bevy_reflect/src/type_registry.rs +++ b/crates/bevy_reflect/src/type_registry.rs @@ -121,8 +121,10 @@ impl TypeRegistry { self.short_name_to_id .insert(short_name, registration.type_id()); } - self.full_name_to_id - .insert(registration.type_name().to_string(), registration.type_id()); + self.full_name_to_id.insert( + registration.type_info().type_path().to_string(), + registration.type_id(), + ); self.registrations .insert(registration.type_id(), registration); } @@ -374,13 +376,6 @@ impl TypeRegistration { pub fn short_name(&self) -> &str { &self.short_name } - - /// Returns the [name] of the type. - /// - /// [name]: std::any::type_name - pub fn type_name(&self) -> &'static str { - self.type_info.type_name() - } } impl Clone for TypeRegistration { @@ -445,7 +440,7 @@ impl FromType for ReflectSerialize { ReflectSerialize { get_serializable: |value| { let value = value.downcast_ref::().unwrap_or_else(|| { - panic!("ReflectSerialize::get_serialize called with type `{}`, even though it was created for `{}`", value.type_name(), std::any::type_name::()) + panic!("ReflectSerialize::get_serialize called with type `{}`, even though it was created for `{}`", value.reflect_type_path(), std::any::type_name::()) }); Serializable::Borrowed(value) }, diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index 6344072b08215..1b4960bba55ff 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -70,7 +70,7 @@ mod sealed { /// # /// # impl Reflect for Foo { /// # fn type_name(&self) -> &str { todo!() } -/// # fn get_type_path(&self) -> &dyn DynamicTypePath { todo!() } +/// # fn type_path(&self) -> &dyn DynamicTypePath { todo!() } /// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } /// # fn into_any(self: Box) -> Box { todo!() } /// # fn as_any(&self) -> &dyn Any { todo!() } @@ -141,8 +141,6 @@ impl NonGenericTypeCell { /// } /// # /// # impl Reflect for Foo { -/// # fn type_name(&self) -> &str { todo!() } -/// # fn get_type_path(&self) -> &dyn DynamicTypePath { todo!() } /// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } /// # fn into_any(self: Box) -> Box { todo!() } /// # fn as_any(&self) -> &dyn Any { todo!() } @@ -181,8 +179,6 @@ impl NonGenericTypeCell { /// } /// # /// # impl Reflect for Foo { -/// # fn type_name(&self) -> &str { todo!() } -/// # fn get_type_path(&self) -> &dyn DynamicTypePath { todo!() } /// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } /// # fn into_any(self: Box) -> Box { todo!() } /// # fn as_any(&self) -> &dyn Any { todo!() } diff --git a/crates/bevy_scene/src/dynamic_scene.rs b/crates/bevy_scene/src/dynamic_scene.rs index 3b4b681716a34..daf70192ce5cd 100644 --- a/crates/bevy_scene/src/dynamic_scene.rs +++ b/crates/bevy_scene/src/dynamic_scene.rs @@ -76,13 +76,13 @@ impl DynamicScene { for resource in &self.resources { let registration = type_registry - .get_with_name(resource.type_name()) + .get_with_name(resource.reflect_type_path()) .ok_or_else(|| SceneSpawnError::UnregisteredType { - type_name: resource.type_name().to_string(), + type_name: resource.reflect_type_path().to_string(), })?; let reflect_resource = registration.data::().ok_or_else(|| { SceneSpawnError::UnregisteredResource { - type_name: resource.type_name().to_string(), + type_name: resource.reflect_type_path().to_string(), } })?; @@ -109,14 +109,14 @@ impl DynamicScene { // Apply/ add each component to the given entity. for component in &scene_entity.components { let registration = type_registry - .get_with_name(component.type_name()) + .get_with_name(component.reflect_type_path()) .ok_or_else(|| SceneSpawnError::UnregisteredType { - type_name: component.type_name().to_string(), + type_name: component.reflect_type_path().to_string(), })?; let reflect_component = registration.data::().ok_or_else(|| { SceneSpawnError::UnregisteredComponent { - type_name: component.type_name().to_string(), + type_name: component.reflect_type_path().to_string(), } })?; diff --git a/crates/bevy_scene/src/serde.rs b/crates/bevy_scene/src/serde.rs index 635feee649230..1397ddeee5ef8 100644 --- a/crates/bevy_scene/src/serde.rs +++ b/crates/bevy_scene/src/serde.rs @@ -116,7 +116,7 @@ impl<'a> Serialize for SceneMapSerializer<'a> { let mut state = serializer.serialize_map(Some(self.entries.len()))?; for reflect in self.entries { state.serialize_entry( - reflect.type_name(), + reflect.reflect_type_path(), &TypedReflectSerializer::new(&**reflect, &self.registry.read()), )?; } @@ -393,7 +393,7 @@ impl<'a, 'de> Visitor<'de> for SceneMapVisitor<'a> { if !added.insert(registration.type_id()) { return Err(Error::custom(format_args!( "duplicate reflect type: `{}`", - registration.type_name() + registration.type_info().type_path(), ))); } @@ -813,9 +813,12 @@ mod tests { let received = received .components .iter() - .find(|component| component.type_name() == expected.type_name()) + .find(|component| component.reflect_type_path() == expected.reflect_type_path()) .unwrap_or_else(|| { - panic!("missing component (expected: `{}`)", expected.type_name()) + panic!( + "missing component (expected: `{}`)", + expected.reflect_type_path() + ) }); assert!( From 5a9a5ff2678962c758e249ed2c6e3605c5545241 Mon Sep 17 00:00:00 2001 From: radiish Date: Tue, 6 Jun 2023 17:53:00 +0100 Subject: [PATCH 02/27] regular tests --- crates/bevy_app/src/app.rs | 2 +- crates/bevy_reflect/Cargo.toml | 1 + crates/bevy_reflect/src/enums/mod.rs | 2 +- crates/bevy_reflect/src/from_reflect.rs | 2 +- crates/bevy_reflect/src/impls/std.rs | 22 ++--- crates/bevy_reflect/src/lib.rs | 20 ++--- crates/bevy_reflect/src/serde/de.rs | 40 ++++----- crates/bevy_reflect/src/serde/mod.rs | 2 +- crates/bevy_reflect/src/serde/ser.rs | 16 ++-- crates/bevy_reflect/src/tuple.rs | 2 +- crates/bevy_reflect/src/type_info.rs | 4 +- crates/bevy_reflect/src/type_path.rs | 27 ++++++ crates/bevy_reflect/src/type_registry.rs | 104 ++++++----------------- crates/bevy_reflect/src/utility.rs | 47 +++++----- crates/bevy_scene/src/dynamic_scene.rs | 4 +- 15 files changed, 138 insertions(+), 157 deletions(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 613c5063df803..48a82f0651feb 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -833,7 +833,7 @@ impl App { /// See [`bevy_reflect::TypeRegistry::register_type_data`]. #[cfg(feature = "bevy_reflect")] pub fn register_type_data< - T: bevy_reflect::Reflect + 'static, + T: bevy_reflect::Reflect + bevy_reflect::TypePath, D: bevy_reflect::TypeData + bevy_reflect::FromType, >( &mut self, diff --git a/crates/bevy_reflect/Cargo.toml b/crates/bevy_reflect/Cargo.toml index 2736045723d83..b7a8cca9fe258 100644 --- a/crates/bevy_reflect/Cargo.toml +++ b/crates/bevy_reflect/Cargo.toml @@ -37,6 +37,7 @@ glam = { version = "0.24", features = ["serde"], optional = true } ron = "0.8.0" rmp-serde = "1.1" bincode = "1.3" +sha2 = "0.10.6" [[example]] name = "reflect_docs" diff --git a/crates/bevy_reflect/src/enums/mod.rs b/crates/bevy_reflect/src/enums/mod.rs index ef2f0ae087592..4bcac6ef80307 100644 --- a/crates/bevy_reflect/src/enums/mod.rs +++ b/crates/bevy_reflect/src/enums/mod.rs @@ -283,7 +283,7 @@ mod tests { } #[test] - #[should_panic(expected = "`((usize, i32))` is not an enum")] + #[should_panic(expected = "`bevy_reflect::DynamicTuple` is not an enum")] fn applying_non_enum_should_panic() { let mut value = MyEnum::B(0, 0); let mut dyn_tuple = DynamicTuple::default(); diff --git a/crates/bevy_reflect/src/from_reflect.rs b/crates/bevy_reflect/src/from_reflect.rs index f4abb65d7e0f6..72af559037f7e 100644 --- a/crates/bevy_reflect/src/from_reflect.rs +++ b/crates/bevy_reflect/src/from_reflect.rs @@ -86,7 +86,7 @@ pub trait FromReflect: Reflect + Sized { /// let mut reflected = DynamicTupleStruct::default(); /// reflected.set_represented_type(Some(::type_info())); /// -/// let registration = registry.get_with_name(reflected.type_name()).unwrap(); +/// let registration = registry.get_with_name(reflected.reflect_type_path()).unwrap(); /// let rfr = registration.data::().unwrap(); /// /// let concrete: Box = rfr.from_reflect(&reflected).unwrap(); diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 2051022f81468..c351981e5107e 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -962,7 +962,7 @@ impl Reflect for Option { .unwrap_or_else(|| { panic!( "Field in `Some` variant of {} should exist", - std::any::type_name::>() + Self::type_path() ) }) .clone_value(), @@ -970,8 +970,8 @@ impl Reflect for Option { .unwrap_or_else(|_| { panic!( "Field in `Some` variant of {} should be of type {}", - std::any::type_name::>(), - std::any::type_name::() + Self::type_path(), + T::type_path() ) }); *self = Some(field); @@ -979,7 +979,7 @@ impl Reflect for Option { "None" => { *self = None; } - _ => panic!("Enum is not a {}.", std::any::type_name::()), + _ => panic!("Enum is not a {}.", Self::type_path()), } } } @@ -1028,7 +1028,7 @@ impl FromReflect for Option { .unwrap_or_else(|| { panic!( "Field in `Some` variant of {} should exist", - std::any::type_name::>() + Option::::type_path() ) }) .clone_value(), @@ -1036,8 +1036,8 @@ impl FromReflect for Option { .unwrap_or_else(|_| { panic!( "Field in `Some` variant of {} should be of type {}", - std::any::type_name::>(), - std::any::type_name::() + Option::::type_path(), + T::type_path() ) }); Some(Some(field)) @@ -1046,7 +1046,7 @@ impl FromReflect for Option { name => panic!( "variant with name `{}` does not exist on enum `{}`", name, - std::any::type_name::() + Self::type_path() ), } } else { @@ -1103,7 +1103,7 @@ impl Reflect for Cow<'static, str> { if let Some(value) = value.downcast_ref::() { *self = value.clone(); } else { - panic!("Value is not a {}.", std::any::type_name::()); + panic!("Value is not a {}.", Self::type_path()); } } @@ -1231,7 +1231,7 @@ impl Reflect for &'static Path { if let Some(&value) = value.downcast_ref::() { *self = value; } else { - panic!("Value is not a {}.", std::any::type_name::()); + panic!("Value is not a {}.", Self::type_path()); } } @@ -1340,7 +1340,7 @@ impl Reflect for Cow<'static, Path> { if let Some(value) = value.downcast_ref::() { *self = value.clone(); } else { - panic!("Value is not a {}.", std::any::type_name::()); + panic!("Value is not a {}.", Self::type_path()); } } diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 268b2e04c31c4..a4175c23a5b1f 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1080,18 +1080,18 @@ mod tests { } #[test] - fn dynamic_names() { + fn not_dynamic_names() { let list = Vec::::new(); let dyn_list = list.clone_dynamic(); - assert_eq!(dyn_list.reflect_type_path(), Vec::::type_path()); + assert_ne!(dyn_list.reflect_type_path(), Vec::::type_path()); let array = [b'0'; 4]; let dyn_array = array.clone_dynamic(); - assert_eq!(dyn_array.reflect_type_path(), <[u8; 4]>::type_path()); + assert_ne!(dyn_array.reflect_type_path(), <[u8; 4]>::type_path()); let map = HashMap::::default(); let dyn_map = map.clone_dynamic(); - assert_eq!( + assert_ne!( dyn_map.reflect_type_path(), HashMap::::type_path() ); @@ -1099,7 +1099,7 @@ mod tests { let tuple = (0usize, "1".to_string(), 2.0f32); let mut dyn_tuple = tuple.clone_dynamic(); dyn_tuple.insert::(3); - assert_eq!( + assert_ne!( dyn_tuple.reflect_type_path(), <(usize, String, f32, usize)>::type_path() ); @@ -1110,13 +1110,13 @@ mod tests { } let struct_ = TestStruct { a: 0 }; let dyn_struct = struct_.clone_dynamic(); - assert_eq!(dyn_struct.reflect_type_path(), TestStruct::type_path()); + assert_ne!(dyn_struct.reflect_type_path(), TestStruct::type_path()); #[derive(Reflect)] struct TestTupleStruct(usize); let tuple_struct = TestTupleStruct(0); let dyn_tuple_struct = tuple_struct.clone_dynamic(); - assert_eq!( + assert_ne!( dyn_tuple_struct.reflect_type_path(), TestTupleStruct::type_path() ); @@ -1668,7 +1668,7 @@ mod tests { let reflected: &dyn Reflect = &test; let expected = r#" -bevy_reflect::tests::should_reflect_debug::Test { +bevy_reflect::tests::Test { value: 123, list: [ "A", @@ -1683,10 +1683,10 @@ bevy_reflect::tests::should_reflect_debug::Test { map: { 123: 1.23, }, - a_struct: bevy_reflect::tests::should_reflect_debug::SomeStruct { + a_struct: bevy_reflect::tests::SomeStruct { foo: "A Struct!", }, - a_tuple_struct: bevy_reflect::tests::should_reflect_debug::SomeTupleStruct( + a_tuple_struct: bevy_reflect::tests::SomeTupleStruct( "A Tuple Struct!", ), enum_unit: A, diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 3524d94336a9f..56a0f44742797 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -223,7 +223,7 @@ impl<'de> Visitor<'de> for U32Visitor { /// /// Because the type isn't known ahead of time, the serialized data must take the form of /// a map containing the following entries (in order): -/// 1. `type`: The _full_ [type name] +/// 1. `type`: The _full_ [type path] /// 2. `value`: The serialized value of the reflected type /// /// If the type is already known and the [`TypeInfo`] for it can be retrieved, @@ -233,7 +233,7 @@ impl<'de> Visitor<'de> for U32Visitor { /// [`DynamicStruct`]: crate::DynamicStruct /// [`DynamicList`]: crate::DynamicList /// [`FromReflect`]: crate::FromReflect -/// [type name]: std::any::type_name +/// [type path]: TypePath::type_path pub struct UntypedReflectDeserializer<'a> { registry: &'a TypeRegistry, } @@ -260,11 +260,11 @@ impl<'a, 'de> DeserializeSeed<'de> for UntypedReflectDeserializer<'a> { /// A deserializer for type registrations. /// /// This will return a [`&TypeRegistration`] corresponding to the given type. -/// This deserializer expects a string containing the _full_ [type name] of the +/// This deserializer expects a string containing the _full_ [type path] of the /// type to find the `TypeRegistration` of. /// /// [`&TypeRegistration`]: crate::TypeRegistration -/// [type name]: std::any::type_name +/// [type path]: TypePath::type_path pub struct TypeRegistrationDeserializer<'a> { registry: &'a TypeRegistry, } @@ -291,12 +291,12 @@ impl<'a, 'de> DeserializeSeed<'de> for TypeRegistrationDeserializer<'a> { formatter.write_str("string containing `type` entry for the reflected value") } - fn visit_str(self, type_name: &str) -> Result + fn visit_str(self, type_path: &str) -> Result where E: Error, { - self.0.get_with_name(type_name).ok_or_else(|| { - Error::custom(format_args!("No registration found for `{type_name}`")) + self.0.get_with_type_path(type_path).ok_or_else(|| { + Error::custom(format_args!("No registration found for `{type_path}`")) }) } } @@ -370,7 +370,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { where D: serde::Deserializer<'de>, { - let type_name = self.registration.type_info().type_path(); + let type_path = self.registration.type_info().type_path(); // Handle both Value case and types that have a custom `ReflectDeserialize` if let Some(deserialize_reflect) = self.registration.data::() { @@ -444,8 +444,10 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { Ok(Box::new(dynamic_tuple)) } TypeInfo::Enum(enum_info) => { - let type_name = enum_info.type_path(); - let mut dynamic_enum = if type_name.starts_with("core::option::Option") { + let mut dynamic_enum = if enum_info.type_path_vtable().module_path() + == Some("core::option") + && enum_info.type_path_vtable().ident() == Some("Option") + { deserializer.deserialize_option(OptionVisitor { enum_info, registry: self.registry, @@ -467,7 +469,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { TypeInfo::Value(_) => { // This case should already be handled Err(de::Error::custom(format_args!( - "the TypeRegistration for {type_name} doesn't have ReflectDeserialize", + "the TypeRegistration for {type_path} doesn't have ReflectDeserialize", ))) } } @@ -1067,11 +1069,11 @@ where fn get_registration<'a, E: Error>( type_id: TypeId, - type_name: &str, + type_path: &str, registry: &'a TypeRegistry, ) -> Result<&'a TypeRegistration, E> { let registration = registry.get(type_id).ok_or_else(|| { - Error::custom(format_args!("no registration found for type `{type_name}`",)) + Error::custom(format_args!("no registration found for type `{type_path}`",)) })?; Ok(registration) } @@ -1349,7 +1351,7 @@ mod tests { // === Normal === // let input = r#"{ - "bevy_reflect::serde::de::tests::should_deserialize_option::OptionTest": ( + "bevy_reflect::serde::de::tests::OptionTest": ( none: None, simple: Some("Hello world!"), complex: Some(( @@ -1371,7 +1373,7 @@ mod tests { let input = r#" #![enable(implicit_some)] { - "bevy_reflect::serde::de::tests::should_deserialize_option::OptionTest": ( + "bevy_reflect::serde::de::tests::OptionTest": ( none: None, simple: "Hello world!", complex: ( @@ -1408,7 +1410,7 @@ mod tests { // === Unit Variant === // let input = r#"{ - "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": Unit, + "bevy_reflect::serde::de::tests::MyEnum": Unit, }"#; let reflect_deserializer = UntypedReflectDeserializer::new(®istry); let mut deserializer = ron::de::Deserializer::from_str(input).unwrap(); @@ -1419,7 +1421,7 @@ mod tests { // === NewType Variant === // let input = r#"{ - "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": NewType(123), + "bevy_reflect::serde::de::tests::MyEnum": NewType(123), }"#; let reflect_deserializer = UntypedReflectDeserializer::new(®istry); let mut deserializer = ron::de::Deserializer::from_str(input).unwrap(); @@ -1430,7 +1432,7 @@ mod tests { // === Tuple Variant === // let input = r#"{ - "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": Tuple(1.23, 3.21), + "bevy_reflect::serde::de::tests::MyEnum": Tuple(1.23, 3.21), }"#; let reflect_deserializer = UntypedReflectDeserializer::new(®istry); let mut deserializer = ron::de::Deserializer::from_str(input).unwrap(); @@ -1441,7 +1443,7 @@ mod tests { // === Struct Variant === // let input = r#"{ - "bevy_reflect::serde::de::tests::enum_should_deserialize::MyEnum": Struct( + "bevy_reflect::serde::de::tests::MyEnum": Struct( value: "I <3 Enums", ), }"#; diff --git a/crates/bevy_reflect/src/serde/mod.rs b/crates/bevy_reflect/src/serde/mod.rs index 58231b2654ac2..b675b5dcb2395 100644 --- a/crates/bevy_reflect/src/serde/mod.rs +++ b/crates/bevy_reflect/src/serde/mod.rs @@ -94,7 +94,7 @@ mod tests { } #[test] - #[should_panic(expected = "cannot get type info for bevy_reflect::struct_trait::DynamicStruct")] + #[should_panic(expected = "cannot get type info for bevy_reflect::DynamicStruct")] fn unproxied_dynamic_should_not_serialize() { let registry = TypeRegistry::default(); diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index d1c48030bc87c..846ea99a88b03 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -46,10 +46,10 @@ fn get_serializable<'a, E: serde::ser::Error>( /// A general purpose serializer for reflected types. /// /// The serialized data will take the form of a map containing the following entries: -/// 1. `type`: The _full_ [type name] +/// 1. `type`: The _full_ [type path] /// 2. `value`: The serialized value of the reflected type /// -/// [type name]: std::any::type_name +/// [type path]: TypePath::type_path pub struct ReflectSerializer<'a> { pub value: &'a dyn Reflect, pub registry: &'a TypeRegistry, @@ -665,7 +665,7 @@ mod tests { let output = ron::ser::to_string_pretty(&serializer, config).unwrap(); let expected = r#"{ - "bevy_reflect::serde::ser::tests::should_serialize_option::OptionTest": ( + "bevy_reflect::serde::ser::tests::OptionTest": ( none: None, simple: Some("Hello world!"), complex: Some(( @@ -685,7 +685,7 @@ mod tests { let output = ron::ser::to_string_pretty(&serializer, config).unwrap(); let expected = r#"#![enable(implicit_some)] { - "bevy_reflect::serde::ser::tests::should_serialize_option::OptionTest": ( + "bevy_reflect::serde::ser::tests::OptionTest": ( none: None, simple: "Hello world!", complex: ( @@ -717,7 +717,7 @@ mod tests { let serializer = ReflectSerializer::new(&value, ®istry); let output = ron::ser::to_string_pretty(&serializer, config.clone()).unwrap(); let expected = r#"{ - "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": Unit, + "bevy_reflect::serde::ser::tests::MyEnum": Unit, }"#; assert_eq!(expected, output); @@ -726,7 +726,7 @@ mod tests { let serializer = ReflectSerializer::new(&value, ®istry); let output = ron::ser::to_string_pretty(&serializer, config.clone()).unwrap(); let expected = r#"{ - "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": NewType(123), + "bevy_reflect::serde::ser::tests::MyEnum": NewType(123), }"#; assert_eq!(expected, output); @@ -735,7 +735,7 @@ mod tests { let serializer = ReflectSerializer::new(&value, ®istry); let output = ron::ser::to_string_pretty(&serializer, config.clone()).unwrap(); let expected = r#"{ - "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": Tuple(1.23, 3.21), + "bevy_reflect::serde::ser::tests::MyEnum": Tuple(1.23, 3.21), }"#; assert_eq!(expected, output); @@ -746,7 +746,7 @@ mod tests { let serializer = ReflectSerializer::new(&value, ®istry); let output = ron::ser::to_string_pretty(&serializer, config).unwrap(); let expected = r#"{ - "bevy_reflect::serde::ser::tests::enum_should_serialize::MyEnum": Struct( + "bevy_reflect::serde::ser::tests::MyEnum": Struct( value: "I <3 Enums", ), }"#; diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index 48d11e2547b7e..16fb2d0f95335 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -518,7 +518,7 @@ macro_rules! impl_reflect_tuple { fn clone_dynamic(&self) -> DynamicTuple { let info = self.get_represented_type_info(); DynamicTuple { - name: Cow::Borrowed(::core::any::type_name::()), + name: Cow::Borrowed(Self::type_path()), represented_type: info, fields: self .iter_fields() diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index aace5bea121a3..d0e6548312420 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -87,7 +87,7 @@ pub trait Typed: Reflect { /// 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`]. -/// Lastly, if all you have is a [`TypeId`] or [type name], you will need to go through +/// Lastly, if all you have is a [`TypeId`] or [type path], you will need to go through /// [`TypeRegistry::get_type_info`]. /// /// You may also opt to use [`TypeRegistry::get_type_info`] in place of the other methods simply because @@ -97,7 +97,7 @@ pub trait Typed: Reflect { /// [`Reflect::get_represented_type_info`]: crate::Reflect::get_represented_type_info /// [`TypeRegistry::get_type_info`]: crate::TypeRegistry::get_type_info /// [`TypeId`]: std::any::TypeId -/// [type name]: std::any::type_name +/// [type path]: TypePath::type_path #[derive(Debug, Clone)] pub enum TypeInfo { Struct(StructInfo), diff --git a/crates/bevy_reflect/src/type_path.rs b/crates/bevy_reflect/src/type_path.rs index edff71e31312f..935a415ea170d 100644 --- a/crates/bevy_reflect/src/type_path.rs +++ b/crates/bevy_reflect/src/type_path.rs @@ -213,3 +213,30 @@ impl TypePathVtable { self.type_path_id } } + +#[cfg(test)] +mod tests { + use super::*; + use sha2::Digest; + + fn verify(text: &'static str) { + let real_hash = { + let mut sha_hasher = sha2::Sha256::new(); + sha_hasher.update(text.as_bytes()); + sha_hasher.finalize() + }; + println!("{:2x?}", real_hash); + let short_hash: [u8; 16] = real_hash[..16].try_into().unwrap(); + let real = TypePathId::new_raw(short_hash); + let ours = TypePathId::from_base(text); + assert_eq!(real, ours); + } + + #[test] + fn test_uuid_sha() { + verify("one, two, buckle my shoe!"); + verify("my_crate::foo::bar::baz::Qux"); + verify("()"); + verify(""); + } +} diff --git a/crates/bevy_reflect/src/type_registry.rs b/crates/bevy_reflect/src/type_registry.rs index 054cb07d3f799..4ce39dfea900f 100644 --- a/crates/bevy_reflect/src/type_registry.rs +++ b/crates/bevy_reflect/src/type_registry.rs @@ -1,4 +1,4 @@ -use crate::{serde::Serializable, Reflect, TypeInfo, Typed}; +use crate::{serde::Serializable, Reflect, TypeInfo, TypePath, Typed}; use bevy_ptr::{Ptr, PtrMut}; use bevy_utils::{HashMap, HashSet}; use downcast_rs::{impl_downcast, Downcast}; @@ -20,9 +20,9 @@ use std::{any::TypeId, fmt::Debug, sync::Arc}; /// [crate-level documentation]: crate pub struct TypeRegistry { registrations: HashMap, - short_name_to_id: HashMap, - full_name_to_id: HashMap, - ambiguous_names: HashSet, + short_path_to_id: HashMap<&'static str, TypeId>, + full_name_to_id: HashMap<&'static str, TypeId>, + ambiguous_names: HashSet<&'static str>, } // TODO: remove this wrapper once we migrate to Atelier Assets and the Scene AssetLoader doesn't @@ -63,7 +63,7 @@ impl TypeRegistry { pub fn empty() -> Self { Self { registrations: Default::default(), - short_name_to_id: Default::default(), + short_path_to_id: Default::default(), full_name_to_id: Default::default(), ambiguous_names: Default::default(), } @@ -110,21 +110,19 @@ impl TypeRegistry { return; } - let short_name = registration.short_name.to_string(); - if self.short_name_to_id.contains_key(&short_name) - || self.ambiguous_names.contains(&short_name) + let short_name = registration.type_info().type_path_vtable().short_path(); + if self.short_path_to_id.contains_key(short_name) + || self.ambiguous_names.contains(short_name) { // name is ambiguous. fall back to long names for all ambiguous types - self.short_name_to_id.remove(&short_name); + self.short_path_to_id.remove(short_name); self.ambiguous_names.insert(short_name); } else { - self.short_name_to_id + self.short_path_to_id .insert(short_name, registration.type_id()); } - self.full_name_to_id.insert( - registration.type_info().type_path().to_string(), - registration.type_id(), - ); + self.full_name_to_id + .insert(registration.type_info().type_path(), registration.type_id()); self.registrations .insert(registration.type_id(), registration); } @@ -145,11 +143,11 @@ impl TypeRegistry { /// type_registry.register_type_data::, ReflectSerialize>(); /// type_registry.register_type_data::, ReflectDeserialize>(); /// ``` - pub fn register_type_data>(&mut self) { + pub fn register_type_data>(&mut self) { let data = self.get_mut(TypeId::of::()).unwrap_or_else(|| { panic!( "attempted to call `TypeRegistry::register_type_data` for type `{T}` with data `{D}` without registering `{T}` first", - T = std::any::type_name::(), + T = T::type_path(), D = std::any::type_name::(), ) }); @@ -180,9 +178,9 @@ impl TypeRegistry { /// given name. /// /// If no type with the given name has been registered, returns `None`. - pub fn get_with_name(&self, type_name: &str) -> Option<&TypeRegistration> { + pub fn get_with_type_path(&self, type_path: &str) -> Option<&TypeRegistration> { self.full_name_to_id - .get(type_name) + .get(type_path) .and_then(|id| self.get(*id)) } @@ -190,9 +188,9 @@ impl TypeRegistry { /// the given name. /// /// If no type with the given name has been registered, returns `None`. - pub fn get_with_name_mut(&mut self, type_name: &str) -> Option<&mut TypeRegistration> { + pub fn get_with_type_path_mut(&mut self, type_path: &str) -> Option<&mut TypeRegistration> { self.full_name_to_id - .get(type_name) + .get(type_path) .cloned() .and_then(move |id| self.get_mut(id)) } @@ -202,9 +200,9 @@ impl TypeRegistry { /// /// If the short name is ambiguous, or if no type with the given short name /// has been registered, returns `None`. - pub fn get_with_short_name(&self, short_type_name: &str) -> Option<&TypeRegistration> { - self.short_name_to_id - .get(short_type_name) + pub fn get_with_short_type_path(&self, short_type_path: &str) -> Option<&TypeRegistration> { + self.short_path_to_id + .get(short_type_path) .and_then(|id| self.registrations.get(id)) } @@ -213,12 +211,12 @@ impl TypeRegistry { /// /// If the short name is ambiguous, or if no type with the given short name /// has been registered, returns `None`. - pub fn get_with_short_name_mut( + pub fn get_with_short_type_path_mut( &mut self, - short_type_name: &str, + short_type_path: &str, ) -> Option<&mut TypeRegistration> { - self.short_name_to_id - .get(short_type_name) + self.short_path_to_id + .get(short_type_path) .and_then(|id| self.registrations.get_mut(id)) } @@ -295,7 +293,7 @@ impl TypeRegistryArc { /// # use bevy_reflect::{TypeRegistration, std_traits::ReflectDefault, FromType}; /// let mut registration = TypeRegistration::of::>(); /// -/// assert_eq!("core::option::Option", registration.type_name()); +/// assert_eq!("core::option::Option", registration.type_info().type_path()); /// assert_eq!("Option", registration.short_name()); /// /// registration.insert::(FromType::>::from_type()); @@ -305,7 +303,6 @@ impl TypeRegistryArc { /// [short name]: bevy_utils::get_short_name /// [crate-level documentation]: crate pub struct TypeRegistration { - short_name: String, data: HashMap>, type_info: &'static TypeInfo, } @@ -313,7 +310,6 @@ pub struct TypeRegistration { impl Debug for TypeRegistration { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("TypeRegistration") - .field("short_name", &self.short_name) .field("type_info", &self.type_info) .finish() } @@ -361,21 +357,12 @@ impl TypeRegistration { } /// Creates type registration information for `T`. - pub fn of() -> Self { - let type_name = std::any::type_name::(); + pub fn of() -> Self { Self { data: HashMap::default(), - short_name: bevy_utils::get_short_name(type_name), type_info: T::type_info(), } } - - /// Returns the [short name] of the type. - /// - /// [short name]: bevy_utils::get_short_name - pub fn short_name(&self) -> &str { - &self.short_name - } } impl Clone for TypeRegistration { @@ -387,7 +374,6 @@ impl Clone for TypeRegistration { TypeRegistration { data, - short_name: self.short_name.clone(), type_info: self.type_info, } } @@ -570,9 +556,8 @@ impl FromType for ReflectFromPtr { #[cfg(test)] mod test { - use crate::{GetTypeRegistration, ReflectFromPtr, TypeRegistration}; + use crate::{GetTypeRegistration, ReflectFromPtr}; use bevy_ptr::{Ptr, PtrMut}; - use bevy_utils::HashMap; use crate as bevy_reflect; use crate::Reflect; @@ -617,37 +602,4 @@ mod test { } } } - - #[test] - fn test_property_type_registration() { - assert_eq!( - TypeRegistration::of::>().short_name, - "Option" - ); - assert_eq!( - TypeRegistration::of::>().short_name, - "HashMap" - ); - assert_eq!( - TypeRegistration::of::>>().short_name, - "Option>" - ); - assert_eq!( - TypeRegistration::of::>>>().short_name, - "Option>>" - ); - assert_eq!( - TypeRegistration::of::>>>().short_name, - "Option>>" - ); - assert_eq!( - TypeRegistration::of::, Option>>>().short_name, - "Option, Option>>" - ); - assert_eq!( - TypeRegistration::of::, (String, Option)>>>() - .short_name, - "Option, (String, Option)>>" - ); - } } diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index 1b4960bba55ff..2ef4dadabadc5 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -50,7 +50,7 @@ mod sealed { /// /// ``` /// # use std::any::Any; -/// # use bevy_reflect::{DynamicTypePath, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, Typed, TypeInfo}; +/// # use bevy_reflect::{DynamicTypePath, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, Typed, TypeInfo, TypePath}; /// use bevy_reflect::utility::NonGenericTypeInfoCell; /// /// struct Foo { @@ -62,15 +62,16 @@ mod sealed { /// static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); /// CELL.get_or_set(|| { /// let fields = [NamedField::new::("bar")]; -/// let info = StructInfo::new::("Foo", &fields); +/// let info = StructInfo::new::(&fields); /// TypeInfo::Struct(info) /// }) /// } /// } -/// # +/// # impl TypePath for Foo { +/// # fn type_path() -> &'static str { todo!() } +/// # fn short_type_path() -> &'static str { todo!() } +/// # } /// # impl Reflect for Foo { -/// # fn type_name(&self) -> &str { todo!() } -/// # fn type_path(&self) -> &dyn DynamicTypePath { todo!() } /// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } /// # fn into_any(self: Box) -> Box { todo!() } /// # fn as_any(&self) -> &dyn Any { todo!() } @@ -139,7 +140,10 @@ impl NonGenericTypeCell { /// }) /// } /// } -/// # +/// # impl TypePath for Foo { +/// # fn type_path() -> &'static str { todo!() } +/// # fn short_type_path() -> &'static str { todo!() } +/// # } /// # impl Reflect for Foo { /// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } /// # fn into_any(self: Box) -> Box { todo!() } @@ -161,12 +165,11 @@ impl NonGenericTypeCell { /// /// ``` /// # use std::any::Any; -/// # use bevy_reflect::{DynamicTypePath, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath}; /// use bevy_reflect::utility::GenericTypePathCell; /// /// struct Foo(T); /// -/// impl TypePath for Foo { +/// impl TypePath for Foo { /// fn type_path() -> &'static str { /// static CELL: GenericTypePathCell = GenericTypePathCell::new(); /// CELL.get_or_insert::(|| format!("my_crate::foo::Foo<{}>", T::type_path())) @@ -176,23 +179,19 @@ impl NonGenericTypeCell { /// static CELL: GenericTypePathCell = GenericTypePathCell::new(); /// CELL.get_or_insert::(|| format!("Foo<{}>", T::short_type_path())) /// } +/// +/// fn type_ident() -> Option<&'static str> { +/// Some("Foo") +/// } +/// +/// fn module_path() -> Option<&'static str> { +/// Some("my_crate::foo") +/// } +/// +/// fn crate_name() -> Option<&'static str> { +/// Some("my_crate") +/// } /// } -/// # -/// # impl Reflect for Foo { -/// # 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!() } -/// # } /// ``` /// [`impl_type_path`]: crate::impl_type_path /// [`TypePath`]: crate::TypePath diff --git a/crates/bevy_scene/src/dynamic_scene.rs b/crates/bevy_scene/src/dynamic_scene.rs index daf70192ce5cd..8b3a188b2aeb4 100644 --- a/crates/bevy_scene/src/dynamic_scene.rs +++ b/crates/bevy_scene/src/dynamic_scene.rs @@ -76,7 +76,7 @@ impl DynamicScene { for resource in &self.resources { let registration = type_registry - .get_with_name(resource.reflect_type_path()) + .get_with_type_path(resource.reflect_type_path()) .ok_or_else(|| SceneSpawnError::UnregisteredType { type_name: resource.reflect_type_path().to_string(), })?; @@ -109,7 +109,7 @@ impl DynamicScene { // Apply/ add each component to the given entity. for component in &scene_entity.components { let registration = type_registry - .get_with_name(component.reflect_type_path()) + .get_with_type_path(component.reflect_type_path()) .ok_or_else(|| SceneSpawnError::UnregisteredType { type_name: component.reflect_type_path().to_string(), })?; From 0fd5e3642466955fe2e6203b8f2778faa785542a Mon Sep 17 00:00:00 2001 From: radiish Date: Tue, 6 Jun 2023 18:30:26 +0100 Subject: [PATCH 03/27] doctests! --- crates/bevy_reflect/src/from_reflect.rs | 4 ++-- crates/bevy_reflect/src/impls/std.rs | 2 +- crates/bevy_reflect/src/reflect.rs | 4 +++- crates/bevy_reflect/src/type_info.rs | 12 +++++++----- crates/bevy_reflect/src/type_registry.rs | 14 +++++++------- crates/bevy_reflect/src/utility.rs | 17 +++++++++++------ 6 files changed, 31 insertions(+), 22 deletions(-) diff --git a/crates/bevy_reflect/src/from_reflect.rs b/crates/bevy_reflect/src/from_reflect.rs index 72af559037f7e..9169b7de65fe4 100644 --- a/crates/bevy_reflect/src/from_reflect.rs +++ b/crates/bevy_reflect/src/from_reflect.rs @@ -75,7 +75,7 @@ pub trait FromReflect: Reflect + Sized { /// # Example /// /// ``` -/// # use bevy_reflect::{DynamicTupleStruct, FromReflect, Reflect, ReflectFromReflect, Typed, TypeRegistry}; +/// # use bevy_reflect::{DynamicTupleStruct, FromReflect, Reflect, ReflectFromReflect, Typed, TypeRegistry, TypePath}; /// # #[derive(Reflect, FromReflect, PartialEq, Eq, Debug)] /// # #[reflect(FromReflect)] /// # struct Foo(#[reflect(default = "default_value")] usize); @@ -86,7 +86,7 @@ pub trait FromReflect: Reflect + Sized { /// let mut reflected = DynamicTupleStruct::default(); /// reflected.set_represented_type(Some(::type_info())); /// -/// let registration = registry.get_with_name(reflected.reflect_type_path()).unwrap(); +/// let registration = registry.get_with_type_path(::type_path()).unwrap(); /// let rfr = registration.data::().unwrap(); /// /// let concrete: Box = rfr.from_reflect(&reflected).unwrap(); diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index c351981e5107e..839b89cdebbd7 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -87,7 +87,7 @@ impl_reflect_value!(isize( )); impl_reflect_value!(f32(Debug, PartialEq, Serialize, Deserialize, Default)); impl_reflect_value!(f64(Debug, PartialEq, Serialize, Deserialize, Default)); -impl_reflect_value!(String( +impl_reflect_value!(::alloc::string::String( Debug, Hash, PartialEq, diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index 440e99ea7521d..43bf5b010cf1e 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -300,7 +300,9 @@ impl dyn Reflect { /// Read `is` for more information on underlying values and represented types. #[inline] pub fn represents(&self) -> bool { - self.reflect_type_path() == T::type_path() + 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` diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index d0e6548312420..4eeb79519f287 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, ValueInfo}; +/// # use bevy_reflect::{DynamicTypePath, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, TypeInfo, TypePath, TypePathId, ValueInfo}; /// # use bevy_reflect::utility::NonGenericTypeInfoCell; /// use bevy_reflect::Typed; /// @@ -42,17 +42,19 @@ use std::fmt::Debug; /// NamedField::new::("foo"), /// NamedField::new::<(f32, f32) >("bar"), /// ]; -/// let info = StructInfo::new::("MyStruct", &fields); +/// let info = StructInfo::new::(&fields); /// TypeInfo::Struct(info) /// }) /// } /// } /// -/// # +/// # impl TypePath for MyStruct { +/// # fn type_path() -> &'static str { todo!() } +/// # fn short_type_path() -> &'static str { todo!() } +/// # const TYPE_PATH_ID: TypePathId = todo!(); +/// # } /// # impl Reflect for MyStruct { -/// # fn type_name(&self) -> &str { todo!() } /// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } -/// # fn type_path(&self) -> &dyn DynamicTypePath { 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!() } diff --git a/crates/bevy_reflect/src/type_registry.rs b/crates/bevy_reflect/src/type_registry.rs index 4ce39dfea900f..cee8d60ba1f50 100644 --- a/crates/bevy_reflect/src/type_registry.rs +++ b/crates/bevy_reflect/src/type_registry.rs @@ -21,7 +21,7 @@ use std::{any::TypeId, fmt::Debug, sync::Arc}; pub struct TypeRegistry { registrations: HashMap, short_path_to_id: HashMap<&'static str, TypeId>, - full_name_to_id: HashMap<&'static str, TypeId>, + type_path_to_id: HashMap<&'static str, TypeId>, ambiguous_names: HashSet<&'static str>, } @@ -35,7 +35,7 @@ pub struct TypeRegistryArc { impl Debug for TypeRegistryArc { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.internal.read().full_name_to_id.keys().fmt(f) + self.internal.read().type_path_to_id.keys().fmt(f) } } @@ -64,7 +64,7 @@ impl TypeRegistry { Self { registrations: Default::default(), short_path_to_id: Default::default(), - full_name_to_id: Default::default(), + type_path_to_id: Default::default(), ambiguous_names: Default::default(), } } @@ -121,7 +121,7 @@ impl TypeRegistry { self.short_path_to_id .insert(short_name, registration.type_id()); } - self.full_name_to_id + self.type_path_to_id .insert(registration.type_info().type_path(), registration.type_id()); self.registrations .insert(registration.type_id(), registration); @@ -179,7 +179,7 @@ impl TypeRegistry { /// /// If no type with the given name has been registered, returns `None`. pub fn get_with_type_path(&self, type_path: &str) -> Option<&TypeRegistration> { - self.full_name_to_id + self.type_path_to_id .get(type_path) .and_then(|id| self.get(*id)) } @@ -189,7 +189,7 @@ impl TypeRegistry { /// /// If no type with the given name has been registered, returns `None`. pub fn get_with_type_path_mut(&mut self, type_path: &str) -> Option<&mut TypeRegistration> { - self.full_name_to_id + self.type_path_to_id .get(type_path) .cloned() .and_then(move |id| self.get_mut(id)) @@ -294,7 +294,7 @@ impl TypeRegistryArc { /// let mut registration = TypeRegistration::of::>(); /// /// assert_eq!("core::option::Option", registration.type_info().type_path()); -/// assert_eq!("Option", registration.short_name()); +/// assert_eq!("Option", registration.type_info().type_path_vtable().short_path()); /// /// registration.insert::(FromType::>::from_type()); /// assert!(registration.data::().is_some()) diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index 2ef4dadabadc5..58e816f0f197c 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -50,7 +50,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, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, Typed, TypeInfo, TypePath, TypePathId}; /// use bevy_reflect::utility::NonGenericTypeInfoCell; /// /// struct Foo { @@ -70,6 +70,7 @@ mod sealed { /// # impl TypePath for Foo { /// # fn type_path() -> &'static str { todo!() } /// # fn short_type_path() -> &'static str { todo!() } +/// # const TYPE_PATH_ID: TypePathId = todo!(); /// # } /// # impl Reflect for Foo { /// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } @@ -125,26 +126,27 @@ impl NonGenericTypeCell { /// /// ``` /// # use std::any::Any; -/// # use bevy_reflect::{DynamicTypePath, Reflect, ReflectMut, ReflectOwned, ReflectRef, TupleStructInfo, Typed, TypeInfo, UnnamedField}; +/// # use bevy_reflect::{DynamicTypePath, Reflect, ReflectMut, ReflectOwned, ReflectRef, TupleStructInfo, Typed, TypeInfo, TypePath, TypePathId, UnnamedField}; /// use bevy_reflect::utility::GenericTypeInfoCell; /// /// struct Foo(T); /// -/// impl Typed for Foo { +/// impl Typed for Foo { /// fn type_info() -> &'static TypeInfo { /// static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); /// CELL.get_or_insert::(|| { /// let fields = [UnnamedField::new::(0)]; -/// let info = TupleStructInfo::new::("Foo", &fields); +/// let info = TupleStructInfo::new::(&fields); /// TypeInfo::TupleStruct(info) /// }) /// } /// } -/// # impl TypePath for Foo { +/// # impl TypePath for Foo { /// # fn type_path() -> &'static str { todo!() } /// # fn short_type_path() -> &'static str { todo!() } +/// # const TYPE_PATH_ID: TypePathId = todo!(); /// # } -/// # impl Reflect for Foo { +/// # impl Reflect for Foo { /// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() } /// # fn into_any(self: Box) -> Box { todo!() } /// # fn as_any(&self) -> &dyn Any { todo!() } @@ -165,6 +167,7 @@ impl NonGenericTypeCell { /// /// ``` /// # use std::any::Any; +/// # use bevy_reflect::{TypePath, TypePathId}; /// use bevy_reflect::utility::GenericTypePathCell; /// /// struct Foo(T); @@ -191,6 +194,8 @@ impl NonGenericTypeCell { /// fn crate_name() -> Option<&'static str> { /// Some("my_crate") /// } +/// +/// const TYPE_PATH_ID: TypePathId = todo!(); /// } /// ``` /// [`impl_type_path`]: crate::impl_type_path From 6792bb174824c70925ff0c5c7d2479c0c34675f5 Mon Sep 17 00:00:00 2001 From: radiish Date: Tue, 6 Jun 2023 18:53:54 +0100 Subject: [PATCH 04/27] docs and collision resistance --- crates/bevy_reflect/Cargo.toml | 1 - crates/bevy_reflect/src/type_path.rs | 39 +++++----------------------- 2 files changed, 7 insertions(+), 33 deletions(-) diff --git a/crates/bevy_reflect/Cargo.toml b/crates/bevy_reflect/Cargo.toml index b7a8cca9fe258..2736045723d83 100644 --- a/crates/bevy_reflect/Cargo.toml +++ b/crates/bevy_reflect/Cargo.toml @@ -37,7 +37,6 @@ glam = { version = "0.24", features = ["serde"], optional = true } ron = "0.8.0" rmp-serde = "1.1" bincode = "1.3" -sha2 = "0.10.6" [[example]] name = "reflect_docs" diff --git a/crates/bevy_reflect/src/type_path.rs b/crates/bevy_reflect/src/type_path.rs index 935a415ea170d..0554e6ccd7922 100644 --- a/crates/bevy_reflect/src/type_path.rs +++ b/crates/bevy_reflect/src/type_path.rs @@ -166,6 +166,7 @@ impl DynamicTypePath for T { } } +/// Provides dynamic access to all methods on [`TypePath`]. #[derive(Debug, Clone, Copy)] pub struct TypePathVtable { // Cache the type path as it is likely the only one that will be used. @@ -174,10 +175,10 @@ pub struct TypePathVtable { type_ident: fn() -> Option<&'static str>, crate_name: fn() -> Option<&'static str>, module_path: fn() -> Option<&'static str>, - type_path_id: TypePathId, } impl TypePathVtable { + /// Creates a new vtable from a type. pub fn of() -> Self { Self { type_path: T::type_path(), @@ -189,54 +190,28 @@ impl TypePathVtable { } } + /// See [`TypePath::type_path`]. pub fn path(&self) -> &'static str { self.type_path } + /// See [`TypePath::short_type_path`]. pub fn short_path(&self) -> &'static str { (self.short_type_path)() } + /// See [`TypePath::type_ident`]. pub fn ident(&self) -> Option<&'static str> { (self.type_ident)() } + /// See [`TypePath::crate_name`]. pub fn crate_name(&self) -> Option<&'static str> { (self.crate_name)() } + /// See [`TypePath::module_path`]. pub fn module_path(&self) -> Option<&'static str> { (self.module_path)() } - - pub fn type_path_id(&self) -> TypePathId { - self.type_path_id - } -} - -#[cfg(test)] -mod tests { - use super::*; - use sha2::Digest; - - fn verify(text: &'static str) { - let real_hash = { - let mut sha_hasher = sha2::Sha256::new(); - sha_hasher.update(text.as_bytes()); - sha_hasher.finalize() - }; - println!("{:2x?}", real_hash); - let short_hash: [u8; 16] = real_hash[..16].try_into().unwrap(); - let real = TypePathId::new_raw(short_hash); - let ours = TypePathId::from_base(text); - assert_eq!(real, ours); - } - - #[test] - fn test_uuid_sha() { - verify("one, two, buckle my shoe!"); - verify("my_crate::foo::bar::baz::Qux"); - verify("()"); - verify(""); - } } From fa544afa06afd519d8b4c015549ab24f29efb72a Mon Sep 17 00:00:00 2001 From: radiish Date: Tue, 6 Jun 2023 19:51:51 +0100 Subject: [PATCH 05/27] merge fixes --- .../asset_count_diagnostics_plugin.rs | 2 +- crates/bevy_reflect/src/impls/std.rs | 24 --------------- crates/bevy_reflect/src/type_info.rs | 5 ---- crates/bevy_reflect/src/type_path.rs | 30 +++++++++++++++++++ examples/reflection/generic_reflection.rs | 5 +++- 5 files changed, 35 insertions(+), 31 deletions(-) diff --git a/crates/bevy_asset/src/diagnostic/asset_count_diagnostics_plugin.rs b/crates/bevy_asset/src/diagnostic/asset_count_diagnostics_plugin.rs index ddba39cd7a751..40feff8c4204a 100644 --- a/crates/bevy_asset/src/diagnostic/asset_count_diagnostics_plugin.rs +++ b/crates/bevy_asset/src/diagnostic/asset_count_diagnostics_plugin.rs @@ -34,7 +34,7 @@ impl AssetCountDiagnosticsPlugin { } /// Registers the asset count diagnostic for the current application. - pub fn setup_system(mut diagnostics: ResMut) { + pub fn setup_system(mut diagnostics: ResMut) { let asset_type_name = T::type_path(); let max_length = MAX_DIAGNOSTIC_NAME_WIDTH - "asset_count ".len(); diagnostics.add(Diagnostic::new( diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 5af2114683686..25c2febd3c9fd 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -1152,30 +1152,6 @@ impl Typed for Cow<'static, str> { } } -impl TypePath for Cow<'static, str> { - fn type_path() -> &'static str { - static CELL: GenericTypePathCell = GenericTypePathCell::new(); - CELL.get_or_insert::(|| "std::borrow::Cow::".to_owned()) - } - - fn short_type_path() -> &'static str { - static CELL: GenericTypePathCell = GenericTypePathCell::new(); - CELL.get_or_insert::(|| "Cow".to_owned()) - } - - fn type_ident() -> Option<&'static str> { - Some("Cow") - } - - fn crate_name() -> Option<&'static str> { - Some("std") - } - - fn module_path() -> Option<&'static str> { - Some("std::borrow") - } -} - impl GetTypeRegistration for Cow<'static, str> { fn get_type_registration() -> TypeRegistration { let mut registration = TypeRegistration::of::>(); diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index 7eb92d93439bf..d30b327821730 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -67,11 +67,6 @@ use std::fmt::Debug; /// # fn reflect_owned(self: Box) -> ReflectOwned { todo!() } /// # fn clone_value(&self) -> Box { todo!() } /// # } -/// # -/// # impl TypePath for MyStruct { -/// # fn type_path() -> &'static str { todo!() } -/// # fn short_type_path() -> &'static str { todo!() } -/// # } /// ``` /// /// [utility]: crate::utility diff --git a/crates/bevy_reflect/src/type_path.rs b/crates/bevy_reflect/src/type_path.rs index 0c2c57371d4e1..3ba009b3b6e90 100644 --- a/crates/bevy_reflect/src/type_path.rs +++ b/crates/bevy_reflect/src/type_path.rs @@ -214,3 +214,33 @@ impl TypePathVtable { (self.module_path)() } } +<<<<<<< HEAD +======= + +#[cfg(test)] +mod tests { + use super::*; + use sha2::Digest; + + fn verify(text: &'static str) { + let real_hash = { + let mut sha_hasher = sha2::Sha256::new(); + sha_hasher.update(text.as_bytes()); + sha_hasher.finalize() + }; + println!("{:2x?}", real_hash); + let short_hash: [u8; 16] = real_hash[..16].try_into().unwrap(); + let real = TypePathId::new_raw(short_hash); + let ours = TypePathId::from_base(text); + assert_eq!(real, ours); + } + + #[test] + fn test_uuid_sha() { + verify("one, two, buckle my shoe!"); + verify("my_crate::foo::bar::baz::Qux"); + verify("()"); + verify(""); + } +} +>>>>>>> aea4a155f (most horrific merge of all time) diff --git a/examples/reflection/generic_reflection.rs b/examples/reflection/generic_reflection.rs index 854bbb5ca18fd..409d814c327d0 100644 --- a/examples/reflection/generic_reflection.rs +++ b/examples/reflection/generic_reflection.rs @@ -21,7 +21,10 @@ fn setup(type_registry: Res) { let type_registry = type_registry.read(); let registration = type_registry.get(TypeId::of::>()).unwrap(); - info!("Registration for {} exists", registration.short_name()); + info!( + "Registration for {} exists", + registration.type_info().type_path(), + ); // MyType was not manually registered, so it does not exist assert!(type_registry.get(TypeId::of::>()).is_none()); From 0e94e7e9cc01aed8297ca177f3647e4d50aa1596 Mon Sep 17 00:00:00 2001 From: radiish Date: Tue, 6 Jun 2023 20:18:43 +0100 Subject: [PATCH 06/27] remove extra println --- crates/bevy_reflect/src/type_path.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/bevy_reflect/src/type_path.rs b/crates/bevy_reflect/src/type_path.rs index 3ba009b3b6e90..d24f287f2920f 100644 --- a/crates/bevy_reflect/src/type_path.rs +++ b/crates/bevy_reflect/src/type_path.rs @@ -228,7 +228,6 @@ mod tests { sha_hasher.update(text.as_bytes()); sha_hasher.finalize() }; - println!("{:2x?}", real_hash); let short_hash: [u8; 16] = real_hash[..16].try_into().unwrap(); let real = TypePathId::new_raw(short_hash); let ours = TypePathId::from_base(text); From 8cb80eafaa66691368bd47b86fe4e4e0d8152b0b Mon Sep 17 00:00:00 2001 From: radiish Date: Tue, 6 Jun 2023 20:52:14 +0100 Subject: [PATCH 07/27] docs and tests --- crates/bevy_reflect/src/lib.rs | 4 ++-- crates/bevy_reflect/src/serde/de.rs | 4 ++-- crates/bevy_reflect/src/serde/ser.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index adca4103c2976..3e01ecd44deab 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1847,7 +1847,7 @@ bevy_reflect::tests::Test { let output = to_string_pretty(&ser, config).unwrap(); let expected = r#" { - "glam::f32::vec3::Vec3": ( + "glam::Vec3": ( x: 12.0, y: 3.0, z: -6.9, @@ -1861,7 +1861,7 @@ bevy_reflect::tests::Test { fn vec3_deserialization() { let data = r#" { - "glam::f32::vec3::Vec3": ( + "glam::Vec3": ( x: 12.0, y: 3.0, z: -6.9, diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index 56a0f44742797..49d603b197297 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -233,7 +233,7 @@ impl<'de> Visitor<'de> for U32Visitor { /// [`DynamicStruct`]: crate::DynamicStruct /// [`DynamicList`]: crate::DynamicList /// [`FromReflect`]: crate::FromReflect -/// [type path]: TypePath::type_path +/// [type path]: crate::TypePath::type_path pub struct UntypedReflectDeserializer<'a> { registry: &'a TypeRegistry, } @@ -264,7 +264,7 @@ impl<'a, 'de> DeserializeSeed<'de> for UntypedReflectDeserializer<'a> { /// type to find the `TypeRegistration` of. /// /// [`&TypeRegistration`]: crate::TypeRegistration -/// [type path]: TypePath::type_path +/// [type path]: crate::TypePath::type_path pub struct TypeRegistrationDeserializer<'a> { registry: &'a TypeRegistry, } diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index 846ea99a88b03..4ea6daddb4c6e 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -49,7 +49,7 @@ fn get_serializable<'a, E: serde::ser::Error>( /// 1. `type`: The _full_ [type path] /// 2. `value`: The serialized value of the reflected type /// -/// [type path]: TypePath::type_path +/// [type path]: crate::TypePath::type_path pub struct ReflectSerializer<'a> { pub value: &'a dyn Reflect, pub registry: &'a TypeRegistry, From 6768e050a9b23e23fc4078e4d6da15ec00d6d988 Mon Sep 17 00:00:00 2001 From: radiish Date: Tue, 6 Jun 2023 21:25:20 +0100 Subject: [PATCH 08/27] maximally relax bounds for all TypePath impls --- .../bevy_reflect_derive/src/impls/enums.rs | 2 +- .../bevy_reflect_derive/src/impls/structs.rs | 2 +- .../src/impls/tuple_structs.rs | 2 +- .../bevy_reflect_derive/src/impls/typed.rs | 8 ++-- .../bevy_reflect_derive/src/impls/values.rs | 2 +- .../bevy_reflect_derive/src/lib.rs | 9 +---- crates/bevy_reflect/src/impls/smallvec.rs | 2 +- crates/bevy_reflect/src/impls/std.rs | 40 +++++++++---------- crates/bevy_reflect/src/type_path.rs | 29 -------------- 9 files changed, 28 insertions(+), 68 deletions(-) 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 2b01c11a571a0..feccabe12105a 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs @@ -84,7 +84,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { }, ); - let type_path_impl = impl_type_path(reflect_enum.meta(), &where_clause_options); + let type_path_impl = impl_type_path(reflect_enum.meta()); let get_type_registration_impl = reflect_enum .meta() 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 82afb9b0f9576..74461835d3c76 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs @@ -90,7 +90,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { }, ); - let type_path_impl = impl_type_path(reflect_struct.meta(), &where_clause_options); + let type_path_impl = impl_type_path(reflect_struct.meta()); let get_type_registration_impl = reflect_struct.get_type_registration(&where_clause_options); 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 9c2a1e1c9ff97..fad6c5f19f81f 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 @@ -83,7 +83,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { }, ); - let type_path_impl = impl_type_path(reflect_struct.meta(), &where_clause_options); + let type_path_impl = impl_type_path(reflect_struct.meta()); let (impl_generics, ty_generics, where_clause) = reflect_struct .meta() diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs index 290154692c496..7b6e76d7c3aeb 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -48,12 +48,10 @@ pub(crate) enum TypedProperty { TypePath, } -pub(crate) fn impl_type_path( - meta: &ReflectMeta, - where_clause_options: &WhereClauseOptions, -) -> proc_macro2::TokenStream { +pub(crate) fn impl_type_path(meta: &ReflectMeta) -> proc_macro2::TokenStream { let type_path = meta.type_path(); let bevy_reflect_path = meta.bevy_reflect_path(); + let where_clause_options = WhereClauseOptions::type_path_bounds(meta); let (long_type_path, short_type_path) = if type_path.impl_is_generic() { let long_path_cell = static_type_cell( @@ -97,7 +95,7 @@ pub(crate) fn impl_type_path( let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl(); // Add Typed bound for each active field - let where_reflect_clause = extend_where_clause(where_clause, where_clause_options); + let where_reflect_clause = extend_where_clause(where_clause, &where_clause_options); quote! { #primitive_assert 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 d0c0ddc9a894c..0edda17218939 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs @@ -32,7 +32,7 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { }, ); - let type_path_impl = impl_type_path(meta, &where_clause_options); + let type_path_impl = impl_type_path(meta); let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl(); let where_reflect_clause = extend_where_clause(where_clause, &where_clause_options); diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs index 0956fe785ecaf..46cfa1031672f 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs @@ -41,7 +41,6 @@ use syn::spanned::Spanned; use syn::{parse_macro_input, DeriveInput}; use type_path::NamedTypePathDef; use type_uuid::TypeUuidDef; -use utility::WhereClauseOptions; pub(crate) static REFLECT_ATTRIBUTE_NAME: &str = "reflect"; pub(crate) static REFLECT_VALUE_ATTRIBUTE_NAME: &str = "reflect_value"; @@ -220,11 +219,7 @@ pub fn derive_type_path(input: TokenStream) -> TokenStream { Err(err) => return err.into_compile_error().into(), }; - impls::impl_type_path( - derive_data.meta(), - &WhereClauseOptions::type_path_bounds(derive_data.meta()), - ) - .into() + impls::impl_type_path(derive_data.meta()).into() } // From https://github.com/randomPoison/type-uuid @@ -516,7 +511,7 @@ pub fn impl_type_path(input: TokenStream) -> TokenStream { let meta = ReflectMeta::new(type_path, ReflectTraits::default()); - impls::impl_type_path(&meta, &WhereClauseOptions::type_path_bounds(&meta)).into() + impls::impl_type_path(&meta).into() } /// Derives `TypeUuid` for the given type. This is used internally to implement `TypeUuid` on foreign types, such as those in the std. This macro should be used in the format of `<[Generic Params]> [Type (Path)], [Uuid (String Literal)]`. diff --git a/crates/bevy_reflect/src/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index a0b8777566393..6ff89469afcff 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -148,7 +148,7 @@ where } } -impl_type_path!(::smallvec::SmallVec); +impl_type_path!(::smallvec::SmallVec); impl FromReflect for SmallVec where diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 25c2febd3c9fd..de0f9d595f67a 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -393,7 +393,7 @@ macro_rules! impl_reflect_for_veclike { } } - impl_type_path!($ty where T: FromReflect); + impl_type_path!($ty); impl GetTypeRegistration for $ty { fn get_type_registration() -> TypeRegistration { @@ -652,20 +652,12 @@ impl_reflect_for_hashmap!(::std::collections::HashMap); impl_type_path!(::std::collections::hash_map::RandomState); impl_type_path!( ::std::collections::HashMap - where - K: FromReflect + Eq + Hash + ?Sized, - V: FromReflect + ?Sized, - S: BuildHasher + Send + Sync + 'static, ); impl_reflect_for_hashmap!(bevy_utils::hashbrown::HashMap); impl_type_path!(::bevy_utils::hashbrown::hash_map::DefaultHashBuilder); impl_type_path!( ::bevy_utils::hashbrown::HashMap - where - K: FromReflect + Eq + Hash + ?Sized, - V: FromReflect + ?Sized, - S: BuildHasher + Send + Sync + 'static, ); impl Array for [T; N] { @@ -795,7 +787,7 @@ impl Typed for [T; N] { } } -impl TypePath for [T; N] { +impl TypePath for [T; N] { fn type_path() -> &'static str { static CELL: GenericTypePathCell = GenericTypePathCell::new(); CELL.get_or_insert::(|| format!("[{t}; {N}]", t = T::type_path())) @@ -1067,7 +1059,21 @@ impl Typed for Option { } } -impl_type_path!(::core::option::Option); +impl_type_path!(::core::option::Option); + +impl TypePath for &'static T { + fn type_path() -> &'static str { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| format!("&{}", T::type_path())) + } + + fn short_type_path() -> &'static str { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| format!("&{}", T::short_type_path())) + } + + const TYPE_PATH_ID: TypePathId = TypePathId::from_base("&").with_generics(&[T::TYPE_PATH_ID]); +} impl Reflect for Cow<'static, str> { fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { @@ -1455,13 +1461,6 @@ impl FromReflect for &'static Path { } impl Reflect for Cow<'static, Path> { -<<<<<<< HEAD -======= - fn type_name(&self) -> &str { - std::any::type_name::() - } - ->>>>>>> bevy/main fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) } @@ -1548,10 +1547,7 @@ impl Typed for Cow<'static, Path> { } } -trait PathOnly: ToOwned {} -impl PathOnly for Path {} -impl_type_path!(::alloc::borrow::Cow<'a: 'static, T: PathOnly + ?Sized>); -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 { diff --git a/crates/bevy_reflect/src/type_path.rs b/crates/bevy_reflect/src/type_path.rs index d24f287f2920f..0c2c57371d4e1 100644 --- a/crates/bevy_reflect/src/type_path.rs +++ b/crates/bevy_reflect/src/type_path.rs @@ -214,32 +214,3 @@ impl TypePathVtable { (self.module_path)() } } -<<<<<<< HEAD -======= - -#[cfg(test)] -mod tests { - use super::*; - use sha2::Digest; - - fn verify(text: &'static str) { - let real_hash = { - let mut sha_hasher = sha2::Sha256::new(); - sha_hasher.update(text.as_bytes()); - sha_hasher.finalize() - }; - let short_hash: [u8; 16] = real_hash[..16].try_into().unwrap(); - let real = TypePathId::new_raw(short_hash); - let ours = TypePathId::from_base(text); - assert_eq!(real, ours); - } - - #[test] - fn test_uuid_sha() { - verify("one, two, buckle my shoe!"); - verify("my_crate::foo::bar::baz::Qux"); - verify("()"); - verify(""); - } -} ->>>>>>> aea4a155f (most horrific merge of all time) From 4a9e9028f12c518534ed4c5de2d15deaf0c6dba8 Mon Sep 17 00:00:00 2001 From: radiish Date: Tue, 6 Jun 2023 21:44:45 +0100 Subject: [PATCH 09/27] `Typed: TypePath` and where clause lifetime bounds --- .../bevy_reflect_derive/src/utility.rs | 24 +++++++++++++++++-- crates/bevy_reflect/src/type_info.rs | 2 +- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs b/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs index 32549bd4af8e3..6e04a8d826d1a 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs @@ -5,7 +5,7 @@ use bevy_macro_utils::BevyManifest; use bit_set::BitSet; use proc_macro2::{Ident, Span}; use quote::{quote, ToTokens}; -use syn::{spanned::Spanned, LitStr, Member, Path, Type, WhereClause}; +use syn::{spanned::Spanned, Lifetime, LitStr, Member, Path, Type, WhereClause}; /// Returns the correct path for `bevy_reflect`. pub(crate) fn get_bevy_reflect_path() -> Path { @@ -60,6 +60,10 @@ pub(crate) fn ident_or_index(ident: Option<&Ident>, index: usize) -> Member { /// Options defining how to extend the `where` clause in reflection with any additional bounds needed. pub(crate) struct WhereClauseOptions { + /// Lifetime parameters that need extra trait bounds. + pub(crate) parameter_lifetimes: Box<[Lifetime]>, + /// Bounds to add to the lifetime parameters. + pub(crate) parameter_lifetime_bounds: proc_macro2::TokenStream, /// Type parameters that need extra trait bounds. pub(crate) parameter_types: Box<[Ident]>, /// Trait bounds to add to the type parameters. @@ -79,6 +83,13 @@ impl WhereClauseOptions { pub fn type_path_bounds(meta: &ReflectMeta) -> Self { let bevy_reflect_path = meta.bevy_reflect_path(); Self { + parameter_lifetimes: meta + .type_path() + .generics() + .lifetimes() + .map(|param| param.lifetime.clone()) + .collect(), + parameter_lifetime_bounds: quote! { 'static }, parameter_types: meta .type_path() .generics() @@ -95,10 +106,12 @@ impl Default for WhereClauseOptions { /// By default, don't add any additional bounds to the `where` clause fn default() -> Self { Self { + parameter_lifetimes: Box::new([]), parameter_types: Box::new([]), active_types: Box::new([]), ignored_types: Box::new([]), parameter_trait_bounds: quote! {}, + parameter_lifetime_bounds: quote! {}, active_trait_bounds: quote! {}, ignored_trait_bounds: quote! {}, } @@ -140,9 +153,11 @@ pub(crate) fn extend_where_clause( where_clause: Option<&WhereClause>, where_clause_options: &WhereClauseOptions, ) -> proc_macro2::TokenStream { + let parameter_lifetimes = &where_clause_options.parameter_lifetimes; let parameter_types = &where_clause_options.parameter_types; let active_types = &where_clause_options.active_types; let ignored_types = &where_clause_options.ignored_types; + let parameter_lifetime_bounds = &where_clause_options.parameter_lifetime_bounds; let parameter_trait_bounds = &where_clause_options.parameter_trait_bounds; let active_trait_bounds = &where_clause_options.active_trait_bounds; let ignored_trait_bounds = &where_clause_options.ignored_trait_bounds; @@ -150,7 +165,11 @@ pub(crate) fn extend_where_clause( let mut generic_where_clause = if let Some(where_clause) = where_clause { let predicates = where_clause.predicates.iter(); quote! {where #(#predicates,)*} - } else if !(parameter_types.is_empty() && active_types.is_empty() && ignored_types.is_empty()) { + } else if !(parameter_lifetimes.is_empty() + && parameter_types.is_empty() + && active_types.is_empty() + && ignored_types.is_empty()) + { quote! {where} } else { quote!() @@ -161,6 +180,7 @@ pub(crate) fn extend_where_clause( // the whole bound by default, resulting in a failure to prove trait // adherence. generic_where_clause.extend(quote! { + #(#parameter_lifetimes: #parameter_lifetime_bounds,)* #((#active_types): #active_trait_bounds,)* #((#ignored_types): #ignored_trait_bounds,)* // Leave parameter bounds to the end for more sane error messages. diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index d30b327821730..d2f8811b74431 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -70,7 +70,7 @@ use std::fmt::Debug; /// ``` /// /// [utility]: crate::utility -pub trait Typed: Reflect { +pub trait Typed: Reflect + TypePath { /// Returns the compile-time [info] for the underlying type. /// /// [info]: TypeInfo From 4e8dfa7abb2023a64eb60e7e2ac11df09914c6a2 Mon Sep 17 00:00:00 2001 From: radiish Date: Fri, 23 Jun 2023 13:11:47 +0100 Subject: [PATCH 10/27] various correctness fixes --- crates/bevy_reflect/src/type_path.rs | 8 +++++- crates/bevy_scene/src/dynamic_scene.rs | 34 +++++++++++++++++--------- crates/bevy_scene/src/scene.rs | 8 +++--- crates/bevy_scene/src/scene_spawner.rs | 14 ++++++----- crates/bevy_scene/src/serde.rs | 9 ++++--- 5 files changed, 47 insertions(+), 26 deletions(-) diff --git a/crates/bevy_reflect/src/type_path.rs b/crates/bevy_reflect/src/type_path.rs index 0c2c57371d4e1..d396ab8b2b460 100644 --- a/crates/bevy_reflect/src/type_path.rs +++ b/crates/bevy_reflect/src/type_path.rs @@ -167,7 +167,7 @@ impl DynamicTypePath for T { } /// Provides dynamic access to all methods on [`TypePath`]. -#[derive(Debug, Clone, Copy)] +#[derive(Clone, Copy)] pub struct TypePathVtable { // Cache the type path as it is likely the only one that will be used. type_path: &'static str, @@ -177,6 +177,12 @@ pub struct TypePathVtable { module_path: fn() -> Option<&'static str>, } +impl fmt::Debug for TypePathVtable { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(self.type_path, f) + } +} + impl TypePathVtable { /// Creates a new vtable from a type. pub fn of() -> Self { diff --git a/crates/bevy_scene/src/dynamic_scene.rs b/crates/bevy_scene/src/dynamic_scene.rs index 382c0214fc3cd..bc29616a65376 100644 --- a/crates/bevy_scene/src/dynamic_scene.rs +++ b/crates/bevy_scene/src/dynamic_scene.rs @@ -74,14 +74,19 @@ impl DynamicScene { let type_registry = type_registry.read(); for resource in &self.resources { - let registration = type_registry - .get_with_type_path(resource.reflect_type_path()) - .ok_or_else(|| SceneSpawnError::UnregisteredType { - type_name: resource.reflect_type_path().to_string(), - })?; + let type_info = resource.get_represented_type_info().ok_or_else(|| { + SceneSpawnError::NoRepresentedType { + type_path: resource.reflect_type_path().to_string(), + } + })?; + let registration = type_registry.get(type_info.type_id()).ok_or_else(|| { + SceneSpawnError::UnregisteredType { + type_path: type_info.type_path().to_string(), + } + })?; let reflect_resource = registration.data::().ok_or_else(|| { SceneSpawnError::UnregisteredResource { - type_name: resource.reflect_type_path().to_string(), + type_path: type_info.type_path().to_string(), } })?; @@ -107,15 +112,20 @@ impl DynamicScene { // Apply/ add each component to the given entity. for component in &scene_entity.components { - let registration = type_registry - .get_with_type_path(component.reflect_type_path()) - .ok_or_else(|| SceneSpawnError::UnregisteredType { - type_name: component.reflect_type_path().to_string(), - })?; + let type_info = component.get_represented_type_info().ok_or_else(|| { + SceneSpawnError::NoRepresentedType { + type_path: component.reflect_type_path().to_string(), + } + })?; + let registration = type_registry.get(type_info.type_id()).ok_or_else(|| { + SceneSpawnError::UnregisteredType { + type_path: type_info.type_path().to_string(), + } + })?; let reflect_component = registration.data::().ok_or_else(|| { SceneSpawnError::UnregisteredComponent { - type_name: component.reflect_type_path().to_string(), + type_path: type_info.type_path().to_string(), } })?; diff --git a/crates/bevy_scene/src/scene.rs b/crates/bevy_scene/src/scene.rs index e49b3fc8bcb00..9317e4c08133c 100644 --- a/crates/bevy_scene/src/scene.rs +++ b/crates/bevy_scene/src/scene.rs @@ -77,11 +77,11 @@ impl Scene { type_registry .get(type_id) .ok_or_else(|| SceneSpawnError::UnregisteredType { - type_name: component_info.name().to_string(), + type_path: component_info.name().to_string(), })?; let reflect_resource = registration.data::().ok_or_else(|| { SceneSpawnError::UnregisteredResource { - type_name: component_info.name().to_string(), + type_path: component_info.name().to_string(), } })?; reflect_resource.copy(&self.world, world); @@ -103,12 +103,12 @@ impl Scene { let reflect_component = type_registry .get(component_info.type_id().unwrap()) .ok_or_else(|| SceneSpawnError::UnregisteredType { - type_name: component_info.name().to_string(), + type_path: component_info.name().to_string(), }) .and_then(|registration| { registration.data::().ok_or_else(|| { SceneSpawnError::UnregisteredComponent { - type_name: component_info.name().to_string(), + type_path: registration.type_info().type_path().to_string(), } }) })?; diff --git a/crates/bevy_scene/src/scene_spawner.rs b/crates/bevy_scene/src/scene_spawner.rs index 732b8593f1a21..5b7bc1099acbe 100644 --- a/crates/bevy_scene/src/scene_spawner.rs +++ b/crates/bevy_scene/src/scene_spawner.rs @@ -43,12 +43,14 @@ pub struct SceneSpawner { #[derive(Error, Debug)] pub enum SceneSpawnError { - #[error("scene contains the unregistered component `{type_name}`. consider adding `#[reflect(Component)]` to your type")] - UnregisteredComponent { type_name: String }, - #[error("scene contains the unregistered resource `{type_name}`. consider adding `#[reflect(Resource)]` to your type")] - UnregisteredResource { type_name: String }, - #[error("scene contains the unregistered type `{type_name}`. consider registering the type using `app.register_type::()`")] - UnregisteredType { type_name: String }, + #[error("scene contains the unregistered component `{type_path}`. consider adding `#[reflect(Component)]` to your type")] + UnregisteredComponent { type_path: String }, + #[error("scene contains the unregistered resource `{type_path}`. consider adding `#[reflect(Resource)]` to your type")] + UnregisteredResource { type_path: String }, + #[error("scene contains the unregistered type `{type_path}`. consider registering the type using `app.register_type::()`")] + UnregisteredType { type_path: String }, + #[error("scene contains dynamic type `{type_path}` without a represented type. consider changing this using `set_represented_type`.")] + NoRepresentedType { type_path: String }, #[error("scene does not exist")] NonExistentScene { handle: Handle }, #[error("scene does not exist")] diff --git a/crates/bevy_scene/src/serde.rs b/crates/bevy_scene/src/serde.rs index d20b26ee0dcac..a0b503122af82 100644 --- a/crates/bevy_scene/src/serde.rs +++ b/crates/bevy_scene/src/serde.rs @@ -116,7 +116,7 @@ impl<'a> Serialize for SceneMapSerializer<'a> { let mut state = serializer.serialize_map(Some(self.entries.len()))?; for reflect in self.entries { state.serialize_entry( - reflect.reflect_type_path(), + reflect.get_represented_type_info().unwrap().type_path(), &TypedReflectSerializer::new(&**reflect, &self.registry.read()), )?; } @@ -812,11 +812,14 @@ mod tests { let received = received .components .iter() - .find(|component| component.reflect_type_path() == expected.reflect_type_path()) + .find(|component| { + component.get_represented_type_info().unwrap().type_path() + == expected.get_represented_type_info().unwrap().type_path() + }) .unwrap_or_else(|| { panic!( "missing component (expected: `{}`)", - expected.reflect_type_path() + expected.get_represented_type_info().unwrap().type_path() ) }); From bd0b4076a688a04831d8104db6a8f305fb9ffb4d Mon Sep 17 00:00:00 2001 From: radiish Date: Fri, 23 Jun 2023 15:39:51 +0100 Subject: [PATCH 11/27] merge fixes --- crates/bevy_reflect/src/impls/std.rs | 28 ++++------------------------ crates/bevy_reflect/src/lib.rs | 9 ++++++--- crates/bevy_reflect/src/type_path.rs | 2 ++ 3 files changed, 12 insertions(+), 27 deletions(-) diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index de0f9d595f67a..879f3ec2ac117 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -87,6 +87,7 @@ impl_reflect_value!(isize( )); impl_reflect_value!(f32(Debug, PartialEq, Serialize, Deserialize, Default)); impl_reflect_value!(f64(Debug, PartialEq, Serialize, Deserialize, Default)); +impl_type_path!(str); impl_reflect_value!(::alloc::string::String( Debug, Hash, @@ -1071,8 +1072,6 @@ impl TypePath for &'static T { static CELL: GenericTypePathCell = GenericTypePathCell::new(); CELL.get_or_insert::(|| format!("&{}", T::short_type_path())) } - - const TYPE_PATH_ID: TypePathId = TypePathId::from_base("&").with_generics(&[T::TYPE_PATH_ID]); } impl Reflect for Cow<'static, str> { @@ -1179,8 +1178,6 @@ impl FromReflect for Cow<'static, str> { } } -impl PathOnly for [T] where [T]: ToOwned {} - impl TypePath for [T] where [T]: ToOwned, @@ -1196,8 +1193,6 @@ where } } -impl PathOnly for T {} - 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) @@ -1229,7 +1224,7 @@ impl List for Cow<'static, [T]> { T::from_reflect(&*value).unwrap_or_else(|| { panic!( "Attempted to insert invalid value of type {}.", - value.type_name() + value.reflect_type_path() ) }) }); @@ -1244,7 +1239,7 @@ impl List for Cow<'static, [T]> { let value = T::take_from_reflect(value).unwrap_or_else(|value| { panic!( "Attempted to push invalid value of type {}.", - value.type_name() + value.reflect_type_path() ) }); self.to_mut().push(value); @@ -1258,10 +1253,6 @@ impl List for Cow<'static, [T]> { } impl Reflect for Cow<'static, [T]> { - fn type_name(&self) -> &str { - std::any::type_name::() - } - fn into_any(self: Box) -> Box { self } @@ -1434,18 +1425,6 @@ impl Typed for &'static Path { } } -impl TypePath for &'static Path { - fn type_path() -> &'static str { - static CELL: GenericTypePathCell = GenericTypePathCell::new(); - CELL.get_or_insert::(|| "&std::path::Path".to_owned()) - } - - fn short_type_path() -> &'static str { - static CELL: GenericTypePathCell = GenericTypePathCell::new(); - CELL.get_or_insert::(|| "&Path".to_owned()) - } -} - impl GetTypeRegistration for &'static Path { fn get_type_registration() -> TypeRegistration { let mut registration = TypeRegistration::of::(); @@ -1547,6 +1526,7 @@ impl Typed for Cow<'static, Path> { } } +impl_type_path!(::std::path::Path); impl_type_path!(::alloc::borrow::Cow<'a: 'static, T: ToOwned + ?Sized>); impl FromReflect for Cow<'static, Path> { diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 3e01ecd44deab..6ad86bd7d0e65 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1389,7 +1389,7 @@ mod tests { let info = MyCowStr::type_info(); if let TypeInfo::Value(info) = info { assert!(info.is::()); - assert_eq!(std::any::type_name::(), info.type_name()); + assert_eq!(std::any::type_name::(), info.type_path()); } else { panic!("Expected `TypeInfo::Value`"); } @@ -1405,8 +1405,11 @@ mod tests { if let TypeInfo::List(info) = info { assert!(info.is::()); assert!(info.item_is::()); - assert_eq!(std::any::type_name::(), info.type_name()); - assert_eq!(std::any::type_name::(), info.item_type_name()); + assert_eq!(std::any::type_name::(), info.type_path()); + assert_eq!( + std::any::type_name::(), + info.item_type_path_vtable().path() + ); } else { panic!("Expected `TypeInfo::List`"); } diff --git a/crates/bevy_reflect/src/type_path.rs b/crates/bevy_reflect/src/type_path.rs index d396ab8b2b460..21ce25b946cf2 100644 --- a/crates/bevy_reflect/src/type_path.rs +++ b/crates/bevy_reflect/src/type_path.rs @@ -1,3 +1,5 @@ +use std::fmt; + /// A static accessor to type paths and names. /// /// The engine uses this trait over [`std::any::type_name`] for stability and flexibility. From edc0d43f9464c4931ca830c4a133d832e4ac6f91 Mon Sep 17 00:00:00 2001 From: radiish Date: Fri, 23 Jun 2023 16:42:08 +0100 Subject: [PATCH 12/27] documentation fixes --- crates/bevy_reflect/src/array.rs | 4 +++- crates/bevy_reflect/src/map.rs | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index 5e6084cbbaf1a..3fb0f834a9a13 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -143,7 +143,9 @@ impl ArrayInfo { TypeId::of::() == self.type_id } - /// The stable type name of the array. + /// A representation of the type path of the array item. + /// + /// Provides dynamic access to all methods on [`TypePath`]. pub fn item_type_path_vtable(&self) -> &TypePathVtable { &self.item_type_path } diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index 755c72d605156..f9a65a750c0e5 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -158,7 +158,7 @@ impl MapInfo { TypeId::of::() == self.type_id } - /// A representation of the type path of the keys. + /// A representation of the type path of the key type. /// /// Provides dynamic access to all methods on [`TypePath`]. pub fn key_type_path_vtable(&self) -> &TypePathVtable { @@ -175,7 +175,7 @@ impl MapInfo { TypeId::of::() == self.key_type_id } - /// A representation of the type path of the values. + /// A representation of the type path of the value type. /// /// Provides dynamic access to all methods on [`TypePath`]. pub fn value_type_path_vtable(&self) -> &TypePathVtable { From a6b3b1c7c23ce36512babd0b872bbd09721faef8 Mon Sep 17 00:00:00 2001 From: radiish Date: Fri, 23 Jun 2023 16:42:28 +0100 Subject: [PATCH 13/27] `cargo fmt --all` --- crates/bevy_reflect/src/tuple.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index 13b14f6aab7ae..4da3de50656ec 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -1,11 +1,11 @@ use bevy_reflect_derive::impl_type_path; +use crate::TypePathVtable; use crate::{ self as bevy_reflect, utility::GenericTypePathCell, FromReflect, GetTypeRegistration, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, TypeRegistration, Typed, UnnamedField, }; -use crate::TypePathVtable; use std::any::{Any, TypeId}; use std::borrow::Cow; use std::fmt::{Debug, Formatter}; From 6a5ed3547ea1491443941385a8d8065af4fc4dd5 Mon Sep 17 00:00:00 2001 From: radiish Date: Fri, 23 Jun 2023 16:44:33 +0100 Subject: [PATCH 14/27] fix doc test --- crates/bevy_reflect/src/utility.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index 1ce317e1740b4..cac33c1262fc0 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -86,11 +86,6 @@ mod sealed { /// # fn reflect_owned(self: Box) -> ReflectOwned { todo!() } /// # fn clone_value(&self) -> Box { todo!() } /// # } - -/// # impl TypePath for Foo { -/// # fn type_path() -> &'static str { todo!() } -/// # fn short_type_path() -> &'static str { todo!() } -/// # } /// ``` /// /// [`TypePath`]: crate::TypePath @@ -164,10 +159,6 @@ impl NonGenericTypeCell { /// # fn reflect_owned(self: Box) -> ReflectOwned { todo!() } /// # fn clone_value(&self) -> Box { todo!() } /// # } -/// # impl TypePath for Foo { -/// # fn type_path() -> &'static str { todo!() } -/// # fn short_type_path() -> &'static str { todo!() } -/// # } /// ``` /// /// Implementing [`TypePath`] with generics. From 5e2ac167a8ccf9d85743831f5f0a3aadab5775d9 Mon Sep 17 00:00:00 2001 From: radiish Date: Mon, 26 Jun 2023 10:38:21 +0100 Subject: [PATCH 15/27] fix doc slips --- crates/bevy_reflect/src/impls/std.rs | 8 ++------ crates/bevy_reflect/src/type_path.rs | 4 +++- crates/bevy_reflect/src/type_registry.rs | 25 +++++++++++++++--------- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 879f3ec2ac117..384b6e5798b73 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -651,15 +651,11 @@ macro_rules! impl_reflect_for_hashmap { impl_reflect_for_hashmap!(::std::collections::HashMap); impl_type_path!(::std::collections::hash_map::RandomState); -impl_type_path!( - ::std::collections::HashMap -); +impl_type_path!(::std::collections::HashMap); impl_reflect_for_hashmap!(bevy_utils::hashbrown::HashMap); impl_type_path!(::bevy_utils::hashbrown::hash_map::DefaultHashBuilder); -impl_type_path!( - ::bevy_utils::hashbrown::HashMap -); +impl_type_path!(::bevy_utils::hashbrown::HashMap); impl Array for [T; N] { #[inline] diff --git a/crates/bevy_reflect/src/type_path.rs b/crates/bevy_reflect/src/type_path.rs index 21ce25b946cf2..467542dac6565 100644 --- a/crates/bevy_reflect/src/type_path.rs +++ b/crates/bevy_reflect/src/type_path.rs @@ -181,7 +181,9 @@ pub struct TypePathVtable { impl fmt::Debug for TypePathVtable { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(self.type_path, f) + f.debug_struct("TypePathVtable") + .field("type_path", &self.type_path) + .finish() } } diff --git a/crates/bevy_reflect/src/type_registry.rs b/crates/bevy_reflect/src/type_registry.rs index cee8d60ba1f50..0c67893c3383a 100644 --- a/crates/bevy_reflect/src/type_registry.rs +++ b/crates/bevy_reflect/src/type_registry.rs @@ -175,9 +175,11 @@ impl TypeRegistry { } /// Returns a reference to the [`TypeRegistration`] of the type with the - /// given name. + /// given [type path]. /// /// If no type with the given name has been registered, returns `None`. + /// + /// [type path]: TypePath::type_path pub fn get_with_type_path(&self, type_path: &str) -> Option<&TypeRegistration> { self.type_path_to_id .get(type_path) @@ -185,9 +187,11 @@ impl TypeRegistry { } /// Returns a mutable reference to the [`TypeRegistration`] of the type with - /// the given name. + /// the given [type path]. /// - /// If no type with the given name has been registered, returns `None`. + /// If no type with the given type path has been registered, returns `None`. + /// + /// [type path]: TypePath::type_path pub fn get_with_type_path_mut(&mut self, type_path: &str) -> Option<&mut TypeRegistration> { self.type_path_to_id .get(type_path) @@ -196,10 +200,12 @@ impl TypeRegistry { } /// Returns a reference to the [`TypeRegistration`] of the type with - /// the given short name. + /// the given [short type path]. /// - /// If the short name is ambiguous, or if no type with the given short name + /// If the short type path is ambiguous, or if no type with the given path /// has been registered, returns `None`. + /// + /// [type path]: TypePath::short_type_path pub fn get_with_short_type_path(&self, short_type_path: &str) -> Option<&TypeRegistration> { self.short_path_to_id .get(short_type_path) @@ -207,10 +213,12 @@ impl TypeRegistry { } /// Returns a mutable reference to the [`TypeRegistration`] of the type with - /// the given short name. + /// the given [short type path]. /// - /// If the short name is ambiguous, or if no type with the given short name + /// If the short type path is ambiguous, or if no type with the given path /// has been registered, returns `None`. + /// + /// [type path]: TypePath::short_type_path pub fn get_with_short_type_path_mut( &mut self, short_type_path: &str, @@ -282,7 +290,7 @@ impl TypeRegistryArc { /// but is more often automatically generated using [`#[derive(Reflect)]`](derive@crate::Reflect) which itself generates /// an implementation of the [`GetTypeRegistration`] trait. /// -/// Along with the type's [`TypeInfo`] and [short name], +/// Along with the type's [`TypeInfo`], /// this struct also contains a type's registered [`TypeData`]. /// /// See the [crate-level documentation] for more information on type registration. @@ -300,7 +308,6 @@ impl TypeRegistryArc { /// assert!(registration.data::().is_some()) /// ``` /// -/// [short name]: bevy_utils::get_short_name /// [crate-level documentation]: crate pub struct TypeRegistration { data: HashMap>, From 074d7691c88c2c42a3ad857de5c7d72661ba1a8e Mon Sep 17 00:00:00 2001 From: radiish Date: Mon, 26 Jun 2023 10:43:35 +0100 Subject: [PATCH 16/27] remove `DynamicTuple::name` that was never used --- crates/bevy_reflect/src/tuple.rs | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index 4da3de50656ec..698210fc7dc51 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -7,7 +7,6 @@ use crate::{ UnnamedField, }; use std::any::{Any, TypeId}; -use std::borrow::Cow; use std::fmt::{Debug, Formatter}; use std::slice::Iter; @@ -221,7 +220,6 @@ impl TupleInfo { /// A tuple which allows fields to be added at runtime. #[derive(Default, Debug)] pub struct DynamicTuple { - name: Cow<'static, str>, represented_type: Option<&'static TypeInfo>, fields: Vec>, } @@ -241,8 +239,6 @@ impl DynamicTuple { "expected TypeInfo::Tuple but received: {:?}", represented_type ); - - self.name = Cow::Borrowed(represented_type.type_path()); } self.represented_type = represented_type; } @@ -251,28 +247,12 @@ impl DynamicTuple { pub fn insert_boxed(&mut self, value: Box) { self.represented_type = None; self.fields.push(value); - self.generate_name(); } /// Appends a typed element with value `value` to the tuple. pub fn insert(&mut self, value: T) { self.represented_type = None; self.insert_boxed(Box::new(value)); - self.generate_name(); - } - - fn generate_name(&mut self) { - let mut name = self.name.to_string(); - name.clear(); - name.push('('); - for (i, field) in self.fields.iter().enumerate() { - if i > 0 { - name.push_str(", "); - } - name.push_str(field.reflect_type_path()); - } - name.push(')'); - self.name = Cow::Owned(name); } } @@ -308,7 +288,6 @@ impl Tuple for DynamicTuple { #[inline] fn clone_dynamic(&self) -> DynamicTuple { DynamicTuple { - name: self.name.clone(), represented_type: self.represented_type, fields: self .fields @@ -518,7 +497,6 @@ macro_rules! impl_reflect_tuple { fn clone_dynamic(&self) -> DynamicTuple { let info = self.get_represented_type_info(); DynamicTuple { - name: Cow::Borrowed(Self::type_path()), represented_type: info, fields: self .iter_fields() From 4c682532fd723dd00942750aa95a8edb0fdfd1ac Mon Sep 17 00:00:00 2001 From: radiish Date: Mon, 26 Jun 2023 11:50:23 +0100 Subject: [PATCH 17/27] change more docs --- crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs | 4 ++-- crates/bevy_reflect/src/enums/enum_trait.rs | 1 - crates/bevy_reflect/src/struct_trait.rs | 1 - crates/bevy_reflect/src/tuple_struct.rs | 1 - crates/bevy_reflect/src/type_registry.rs | 2 +- 5 files changed, 3 insertions(+), 6 deletions(-) diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs b/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs index ae7369abefd9a..8fd96fe2904e1 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs @@ -42,7 +42,7 @@ pub(crate) enum ReflectDerive<'a> { pub(crate) struct ReflectMeta<'a> { /// The registered traits for this type. traits: ReflectTraits, - /// The name of this type. + /// The path to this type. type_path: ReflectTypePath<'a>, /// A cached instance of the path to the `bevy_reflect` crate. bevy_reflect_path: Path, @@ -376,7 +376,7 @@ impl<'a> ReflectMeta<'a> { &self.traits } - /// The name of this struct. + /// The path to this type. pub fn type_path(&self) -> &ReflectTypePath<'a> { &self.type_path } diff --git a/crates/bevy_reflect/src/enums/enum_trait.rs b/crates/bevy_reflect/src/enums/enum_trait.rs index 0c821dd92e6d1..46e8957fb9ec0 100644 --- a/crates/bevy_reflect/src/enums/enum_trait.rs +++ b/crates/bevy_reflect/src/enums/enum_trait.rs @@ -147,7 +147,6 @@ impl EnumInfo { /// /// # Arguments /// - /// * `name`: The name of this enum (_without_ generics or lifetimes) /// * `variants`: The variants of this enum in the order they are defined /// pub fn new(variants: &[VariantInfo]) -> Self { diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index a9730331d7efa..ad2cb1910caa9 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -90,7 +90,6 @@ impl StructInfo { /// /// # Arguments /// - /// * `name`: The name of this struct (_without_ generics or lifetimes) /// * `fields`: The fields of this struct in the order they are defined /// pub fn new(fields: &[NamedField]) -> Self { diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index 353ae7863ed47..da3f3eef8c5ec 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -68,7 +68,6 @@ impl TupleStructInfo { /// /// # Arguments /// - /// * `name`: The name of this struct (_without_ generics or lifetimes) /// * `fields`: The fields of this struct in the order they are defined /// pub fn new(fields: &[UnnamedField]) -> Self { diff --git a/crates/bevy_reflect/src/type_registry.rs b/crates/bevy_reflect/src/type_registry.rs index 0c67893c3383a..d15ac69650eb6 100644 --- a/crates/bevy_reflect/src/type_registry.rs +++ b/crates/bevy_reflect/src/type_registry.rs @@ -177,7 +177,7 @@ impl TypeRegistry { /// Returns a reference to the [`TypeRegistration`] of the type with the /// given [type path]. /// - /// If no type with the given name has been registered, returns `None`. + /// If no type with the given path has been registered, returns `None`. /// /// [type path]: TypePath::type_path pub fn get_with_type_path(&self, type_path: &str) -> Option<&TypeRegistration> { From 71ad523c36924cd22b8f9b7144b8740c5c9032d3 Mon Sep 17 00:00:00 2001 From: radiish Date: Mon, 26 Jun 2023 12:55:15 +0100 Subject: [PATCH 18/27] fix tuple `TypePath` impl --- crates/bevy_reflect/src/lib.rs | 94 ++++++++++++++++---------------- crates/bevy_reflect/src/tuple.rs | 70 ++++++++++++++++++------ 2 files changed, 102 insertions(+), 62 deletions(-) diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 6ad86bd7d0e65..95f9e93a40101 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1135,6 +1135,15 @@ mod tests { ); } + macro_rules! assert_type_paths { + ($($ty:ty => $long:literal, $short:literal,)*) => { + $( + assert_eq!(<$ty as TypePath>::type_path(), $long); + assert_eq!(<$ty as TypePath>::short_type_path(), $short); + )* + }; + } + #[test] fn reflect_type_path() { #[derive(TypePath)] @@ -1176,55 +1185,48 @@ mod tests { struct MacroNameG(PhantomData); impl_type_path!((in my_alias as MyMacroNameG) MacroNameG); - assert_eq!(Derive::type_path(), "bevy_reflect::tests::Derive"); - assert_eq!(DerivePath::type_path(), "my_alias::DerivePath"); - assert_eq!(DerivePathName::type_path(), "my_alias::MyDerivePathName"); - - assert_eq!( - DeriveG::::type_path(), - "bevy_reflect::tests::DeriveG" - ); - assert_eq!( - DerivePathG::::type_path(), - "my_alias::DerivePathG" - ); - assert_eq!( - DerivePathNameG::::type_path(), - "my_alias::MyDerivePathNameG" - ); - - assert_eq!(Macro::type_path(), "my_alias::Macro"); - assert_eq!(MacroName::type_path(), "my_alias::MyMacroName"); - assert_eq!( - MacroG::::type_path(), - "my_alias::MacroG" - ); - assert_eq!( - MacroNameG::::type_path(), - "my_alias::MyMacroNameG" - ); + assert_type_paths! { + Derive => "bevy_reflect::tests::Derive", "Derive", + DerivePath => "my_alias::DerivePath", "DerivePath", + DerivePathName => "my_alias::MyDerivePathName", "MyDerivePathName", + DeriveG => "bevy_reflect::tests::DeriveG", "DeriveG", + DerivePathG => "my_alias::DerivePathG", "DerivePathG", + DerivePathNameG => "my_alias::MyDerivePathNameG", "MyDerivePathNameG", + Macro => "my_alias::Macro", "Macro", + MacroName => "my_alias::MyMacroName", "MyMacroName", + MacroG => "my_alias::MacroG", "MacroG", + MacroNameG => "my_alias::MyMacroNameG", "MyMacroNameG", + } + } - assert_eq!(Derive::short_type_path(), "Derive"); - assert_eq!(DerivePath::short_type_path(), "DerivePath"); - assert_eq!(DerivePathName::short_type_path(), "MyDerivePathName"); + #[test] + fn std_type_paths() { + #[derive(Clone)] + struct Type; + + impl TypePath for Type { + fn type_path() -> &'static str { + // for brevity in tests + "Long" + } - assert_eq!(DeriveG::::short_type_path(), "DeriveG"); - assert_eq!( - DerivePathG::::short_type_path(), - "DerivePathG" - ); - assert_eq!( - DerivePathNameG::::short_type_path(), - "MyDerivePathNameG" - ); + fn short_type_path() -> &'static str { + "Short" + } + } - assert_eq!(Macro::short_type_path(), "Macro"); - assert_eq!(MacroName::short_type_path(), "MyMacroName"); - assert_eq!(MacroG::::short_type_path(), "MacroG"); - assert_eq!( - MacroNameG::::short_type_path(), - "MyMacroNameG" - ); + assert_type_paths! { + u8 => "u8", "u8", + Type => "Long", "Short", + &Type => "&Long", "&Short", + [Type; 0] => "[Long; 0]", "[Short; 0]", + [Type; 100] => "[Long; 100]", "[Short; 100]", + () => "()", "()", + (Type,) => "(Long,)", "(Short,)", + (Type, Type) => "(Long, Long)", "(Short, Short)", + (Type, Type, Type) => "(Long, Long, Long)", "(Short, Short, Short)", + Cow<'static, Type> => "alloc::borrow::Cow", "Cow", + } } #[test] diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index 698210fc7dc51..c98e48613c0f3 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -1,4 +1,5 @@ use bevy_reflect_derive::impl_type_path; +use bevy_utils::all_tuples; use crate::TypePathVtable; use crate::{ @@ -578,22 +579,6 @@ macro_rules! impl_reflect_tuple { } } - impl <$($name: Reflect + TypePath),*> TypePath for ($($name,)*) { - fn type_path() -> &'static str { - static CELL: GenericTypePathCell = GenericTypePathCell::new(); - CELL.get_or_insert::(|| { - "(".to_owned() $(+ <$name as TypePath>::type_path())* + ")" - }) - } - - fn short_type_path() -> &'static str { - static CELL: GenericTypePathCell = GenericTypePathCell::new(); - CELL.get_or_insert::(|| { - "(".to_owned() $(+ <$name as TypePath>::short_type_path())* + ")" - }) - } - } - impl<$($name: Reflect + TypePath),*> GetTypeRegistration for ($($name,)*) { fn get_type_registration() -> TypeRegistration { @@ -633,3 +618,56 @@ impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I} impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J} impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J, 10: K} impl_reflect_tuple! {0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H, 8: I, 9: J, 10: K, 11: L} + +macro_rules! impl_type_path_tuple { + () => { + impl TypePath for () { + fn type_path() -> &'static str { + "()" + } + + fn short_type_path() -> &'static str { + "()" + } + } + }; + + ($param:ident) => { + impl <$param: TypePath> TypePath for ($param,) { + fn type_path() -> &'static str { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| { + "(".to_owned() + $param::type_path() + ",)" + }) + } + + fn short_type_path() -> &'static str { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| { + "(".to_owned() + $param::short_type_path() + ",)" + }) + } + } + }; + + ($last:ident $(,$param:ident)*) => { + + impl <$($param: TypePath,)* $last: TypePath> TypePath for ($($param,)* $last) { + fn type_path() -> &'static str { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| { + "(".to_owned() $(+ $param::type_path() + ", ")* + $last::type_path() + ")" + }) + } + + fn short_type_path() -> &'static str { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| { + "(".to_owned() $(+ $param::short_type_path() + ", ")* + $last::short_type_path() + ")" + }) + } + } + }; +} + +all_tuples!(impl_type_path_tuple, 0, 12, P); From e42152f48bd464f4cbb1f3f2ba8ed6f45f472fa8 Mon Sep 17 00:00:00 2001 From: radiish Date: Mon, 26 Jun 2023 12:57:19 +0100 Subject: [PATCH 19/27] add slices to new test --- crates/bevy_reflect/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 95f9e93a40101..2affd1dbd6fbb 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1219,6 +1219,8 @@ mod tests { u8 => "u8", "u8", Type => "Long", "Short", &Type => "&Long", "&Short", + [Type] => "[Long]", "[Short]", + &[Type] => "&[Long]", "&[Short]", [Type; 0] => "[Long; 0]", "[Short; 0]", [Type; 100] => "[Long; 100]", "[Short; 100]", () => "()", "()", From 6057a4f3c03015065479e4344132dc8d37c6673c Mon Sep 17 00:00:00 2001 From: radiish Date: Tue, 15 Aug 2023 22:48:14 +0100 Subject: [PATCH 20/27] vtable -> table --- crates/bevy_reflect/src/array.rs | 20 +++++------ crates/bevy_reflect/src/enums/enum_trait.rs | 14 ++++---- crates/bevy_reflect/src/enums/mod.rs | 10 +++--- crates/bevy_reflect/src/fields.rs | 26 +++++++------- crates/bevy_reflect/src/lib.rs | 14 ++++---- crates/bevy_reflect/src/list.rs | 20 +++++------ crates/bevy_reflect/src/map.rs | 26 +++++++------- crates/bevy_reflect/src/serde/de.rs | 18 +++++----- crates/bevy_reflect/src/serde/ser.rs | 6 ++-- crates/bevy_reflect/src/struct_trait.rs | 14 ++++---- crates/bevy_reflect/src/tuple.rs | 14 ++++---- crates/bevy_reflect/src/tuple_struct.rs | 14 ++++---- crates/bevy_reflect/src/type_info.rs | 38 ++++++++++----------- crates/bevy_reflect/src/type_path.rs | 8 ++--- crates/bevy_reflect/src/type_registry.rs | 4 +-- 15 files changed, 123 insertions(+), 123 deletions(-) diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index f9db390fd319c..befb87c6d78e2 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, ReflectMut, ReflectOwned, ReflectRef, - TypeInfo, TypePath, TypePathVtable, + TypeInfo, TypePath, TypePathTable, }; use bevy_reflect_derive::impl_type_path; use std::{ @@ -77,9 +77,9 @@ pub trait Array: Reflect { /// A container for compile-time array info. #[derive(Clone, Debug)] pub struct ArrayInfo { - type_path: TypePathVtable, + type_path: TypePathTable, type_id: TypeId, - item_type_path: TypePathVtable, + item_type_path: TypePathTable, item_type_id: TypeId, capacity: usize, #[cfg(feature = "documentation")] @@ -95,9 +95,9 @@ impl ArrayInfo { /// pub fn new(capacity: usize) -> Self { Self { - type_path: TypePathVtable::of::(), + type_path: TypePathTable::of::(), type_id: TypeId::of::(), - item_type_path: TypePathVtable::of::(), + item_type_path: TypePathTable::of::(), item_type_id: TypeId::of::(), capacity, #[cfg(feature = "documentation")] @@ -119,18 +119,18 @@ impl ArrayInfo { /// A representation of the type path of the array. /// /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_vtable(&self) -> &TypePathVtable { + pub fn type_path_table(&self) -> &TypePathTable { &self.type_path } /// The [stable, full type path] of the array. /// - /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. + /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. /// /// [stable, full type path]: TypePath - /// [`type_path_vtable`]: Self::type_path_vtable + /// [`type_path_table`]: Self::type_path_table pub fn type_path(&self) -> &'static str { - self.type_path_vtable().path() + self.type_path_table().path() } /// The [`TypeId`] of the array. @@ -146,7 +146,7 @@ impl ArrayInfo { /// A representation of the type path of the array item. /// /// Provides dynamic access to all methods on [`TypePath`]. - pub fn item_type_path_vtable(&self) -> &TypePathVtable { + pub fn item_type_path_table(&self) -> &TypePathTable { &self.item_type_path } diff --git a/crates/bevy_reflect/src/enums/enum_trait.rs b/crates/bevy_reflect/src/enums/enum_trait.rs index 46e8957fb9ec0..09158754ae029 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, TypePathVtable, VariantInfo, VariantType}; +use crate::{DynamicEnum, Reflect, TypePath, TypePathTable, VariantInfo, VariantType}; use bevy_utils::HashMap; use std::any::{Any, TypeId}; use std::slice::Iter; @@ -133,7 +133,7 @@ pub trait Enum: Reflect { /// A container for compile-time enum info, used by [`TypeInfo`](crate::TypeInfo). #[derive(Clone, Debug)] pub struct EnumInfo { - type_path: TypePathVtable, + type_path: TypePathTable, type_id: TypeId, variants: Box<[VariantInfo]>, variant_names: Box<[&'static str]>, @@ -159,7 +159,7 @@ impl EnumInfo { let variant_names = variants.iter().map(|variant| variant.name()).collect(); Self { - type_path: TypePathVtable::of::(), + type_path: TypePathTable::of::(), type_id: TypeId::of::(), variants: variants.to_vec().into_boxed_slice(), variant_names, @@ -222,18 +222,18 @@ impl EnumInfo { /// A representation of the type path of the value. /// /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_vtable(&self) -> &TypePathVtable { + pub fn type_path_table(&self) -> &TypePathTable { &self.type_path } /// The [stable, full type path] of the value. /// - /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. + /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. /// /// [stable, full type path]: TypePath - /// [`type_path_vtable`]: Self::type_path_vtable + /// [`type_path_table`]: Self::type_path_table pub fn type_path(&self) -> &'static str { - self.type_path_vtable().path() + self.type_path_table().path() } /// The [`TypeId`] of the enum. diff --git a/crates/bevy_reflect/src/enums/mod.rs b/crates/bevy_reflect/src/enums/mod.rs index 81d51535ad831..b78af06f86729 100644 --- a/crates/bevy_reflect/src/enums/mod.rs +++ b/crates/bevy_reflect/src/enums/mod.rs @@ -26,13 +26,13 @@ mod tests { if let TypeInfo::Enum(info) = info { assert!(info.is::(), "expected type to be `MyEnum`"); assert_eq!(MyEnum::type_path(), info.type_path()); - assert_eq!(MyEnum::type_path(), info.type_path_vtable().path()); - assert_eq!(MyEnum::type_ident(), info.type_path_vtable().ident()); - assert_eq!(MyEnum::module_path(), info.type_path_vtable().module_path()); - assert_eq!(MyEnum::crate_name(), info.type_path_vtable().crate_name()); + assert_eq!(MyEnum::type_path(), info.type_path_table().path()); + assert_eq!(MyEnum::type_ident(), info.type_path_table().ident()); + assert_eq!(MyEnum::module_path(), info.type_path_table().module_path()); + assert_eq!(MyEnum::crate_name(), info.type_path_table().crate_name()); assert_eq!( MyEnum::short_type_path(), - info.type_path_vtable().short_path() + info.type_path_table().short_path() ); // === MyEnum::A === // diff --git a/crates/bevy_reflect/src/fields.rs b/crates/bevy_reflect/src/fields.rs index 99f13dc68393f..763d04ab2b7e6 100644 --- a/crates/bevy_reflect/src/fields.rs +++ b/crates/bevy_reflect/src/fields.rs @@ -1,11 +1,11 @@ -use crate::{Reflect, TypePath, TypePathVtable}; +use crate::{Reflect, TypePath, TypePathTable}; use std::any::{Any, TypeId}; /// The named field of a reflected struct. #[derive(Clone, Debug)] pub struct NamedField { name: &'static str, - type_path: TypePathVtable, + type_path: TypePathTable, type_id: TypeId, #[cfg(feature = "documentation")] docs: Option<&'static str>, @@ -16,7 +16,7 @@ impl NamedField { pub fn new(name: &'static str) -> Self { Self { name, - type_path: TypePathVtable::of::(), + type_path: TypePathTable::of::(), type_id: TypeId::of::(), #[cfg(feature = "documentation")] docs: None, @@ -37,18 +37,18 @@ impl NamedField { /// A representation of the type path of the field. /// /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_vtable(&self) -> &TypePathVtable { + pub fn type_path_table(&self) -> &TypePathTable { &self.type_path } /// The [stable, full type path] of the field. /// - /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. + /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. /// /// [stable, full type path]: TypePath - /// [`type_path_vtable`]: Self::type_path_vtable + /// [`type_path_table`]: Self::type_path_table pub fn type_path(&self) -> &'static str { - self.type_path_vtable().path() + self.type_path_table().path() } /// The [`TypeId`] of the field. @@ -72,7 +72,7 @@ impl NamedField { #[derive(Clone, Debug)] pub struct UnnamedField { index: usize, - type_path: TypePathVtable, + type_path: TypePathTable, type_id: TypeId, #[cfg(feature = "documentation")] docs: Option<&'static str>, @@ -82,7 +82,7 @@ impl UnnamedField { pub fn new(index: usize) -> Self { Self { index, - type_path: TypePathVtable::of::(), + type_path: TypePathTable::of::(), type_id: TypeId::of::(), #[cfg(feature = "documentation")] docs: None, @@ -103,18 +103,18 @@ impl UnnamedField { /// A representation of the type path of the field. /// /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_vtable(&self) -> &TypePathVtable { + pub fn type_path_table(&self) -> &TypePathTable { &self.type_path } /// The [stable, full type path] of the field. /// - /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. + /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. /// /// [stable, full type path]: TypePath - /// [`type_path_vtable`]: Self::type_path_vtable + /// [`type_path_table`]: Self::type_path_table pub fn type_path(&self) -> &'static str { - self.type_path_vtable().path() + self.type_path_table().path() } /// The [`TypeId`] of the field. diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 21c9b02886663..1f379e4416720 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1376,7 +1376,7 @@ mod tests { assert!(info.is::()); assert!(info.item_is::()); assert_eq!(MyList::type_path(), info.type_path()); - assert_eq!(usize::type_path(), info.item_type_path_vtable().path()); + assert_eq!(usize::type_path(), info.item_type_path_table().path()); } else { panic!("Expected `TypeInfo::List`"); } @@ -1395,7 +1395,7 @@ mod tests { assert!(info.is::()); assert!(info.item_is::()); assert_eq!(MySmallVec::type_path(), info.type_path()); - assert_eq!(String::type_path(), info.item_type_path_vtable().path()); + assert_eq!(String::type_path(), info.item_type_path_table().path()); } else { panic!("Expected `TypeInfo::List`"); } @@ -1414,7 +1414,7 @@ mod tests { assert!(info.is::()); assert!(info.item_is::()); assert_eq!(MyArray::type_path(), info.type_path()); - assert_eq!(usize::type_path(), info.item_type_path_vtable().path()); + assert_eq!(usize::type_path(), info.item_type_path_table().path()); assert_eq!(3, info.capacity()); } else { panic!("Expected `TypeInfo::Array`"); @@ -1449,7 +1449,7 @@ mod tests { assert_eq!(std::any::type_name::(), info.type_path()); assert_eq!( std::any::type_name::(), - info.item_type_path_vtable().path() + info.item_type_path_table().path() ); } else { panic!("Expected `TypeInfo::List`"); @@ -1468,8 +1468,8 @@ mod tests { assert!(info.key_is::()); assert!(info.value_is::()); assert_eq!(MyMap::type_path(), info.type_path()); - assert_eq!(usize::type_path(), info.key_type_path_vtable().path()); - assert_eq!(f32::type_path(), info.value_type_path_vtable().path()); + assert_eq!(usize::type_path(), info.key_type_path_table().path()); + assert_eq!(f32::type_path(), info.value_type_path_table().path()); } else { panic!("Expected `TypeInfo::Map`"); } @@ -1928,7 +1928,7 @@ bevy_reflect::tests::Test { let registration = registry.get(TypeId::of::>()).unwrap(); assert_eq!( "Foo", - registration.type_info().type_path_vtable().short_path() + registration.type_info().type_path_table().short_path() ); } diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index 64a7a2a03d58e..ed129b803be3b 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -7,7 +7,7 @@ use bevy_reflect_derive::impl_type_path; use crate::utility::reflect_hasher; use crate::{ self as bevy_reflect, FromReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, - TypePath, TypePathVtable, + TypePath, TypePathTable, }; /// A trait used to power [list-like] operations via [reflection]. @@ -109,9 +109,9 @@ pub trait List: Reflect { /// A container for compile-time list info. #[derive(Clone, Debug)] pub struct ListInfo { - type_path: TypePathVtable, + type_path: TypePathTable, type_id: TypeId, - item_type_path: TypePathVtable, + item_type_path: TypePathTable, item_type_id: TypeId, #[cfg(feature = "documentation")] docs: Option<&'static str>, @@ -121,9 +121,9 @@ impl ListInfo { /// Create a new [`ListInfo`]. pub fn new() -> Self { Self { - type_path: TypePathVtable::of::(), + type_path: TypePathTable::of::(), type_id: TypeId::of::(), - item_type_path: TypePathVtable::of::(), + item_type_path: TypePathTable::of::(), item_type_id: TypeId::of::(), #[cfg(feature = "documentation")] docs: None, @@ -139,18 +139,18 @@ impl ListInfo { /// A representation of the type path of the list. /// /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_vtable(&self) -> &TypePathVtable { + pub fn type_path_table(&self) -> &TypePathTable { &self.type_path } /// The [stable, full type path] of the list. /// - /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. + /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. /// /// [stable, full type path]: TypePath - /// [`type_path_vtable`]: Self::type_path_vtable + /// [`type_path_table`]: Self::type_path_table pub fn type_path(&self) -> &'static str { - self.type_path_vtable().path() + self.type_path_table().path() } /// The [`TypeId`] of the list. @@ -166,7 +166,7 @@ impl ListInfo { /// A representation of the type path of the list item. /// /// Provides dynamic access to all methods on [`TypePath`]. - pub fn item_type_path_vtable(&self) -> &TypePathVtable { + pub fn item_type_path_table(&self) -> &TypePathTable { &self.item_type_path } diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index f9a65a750c0e5..70a14a13bad96 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -7,7 +7,7 @@ use bevy_utils::{Entry, HashMap}; use crate::{ self as bevy_reflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, - TypePathVtable, + TypePathTable, }; /// A trait used to power [map-like] operations via [reflection]. @@ -96,11 +96,11 @@ pub trait Map: Reflect { /// A container for compile-time map info. #[derive(Clone, Debug)] pub struct MapInfo { - type_path: TypePathVtable, + type_path: TypePathTable, type_id: TypeId, - key_type_path: TypePathVtable, + key_type_path: TypePathTable, key_type_id: TypeId, - value_type_path: TypePathVtable, + value_type_path: TypePathTable, value_type_id: TypeId, #[cfg(feature = "documentation")] docs: Option<&'static str>, @@ -114,11 +114,11 @@ impl MapInfo { TValue: Reflect + TypePath, >() -> Self { Self { - type_path: TypePathVtable::of::(), + type_path: TypePathTable::of::(), type_id: TypeId::of::(), - key_type_path: TypePathVtable::of::(), + key_type_path: TypePathTable::of::(), key_type_id: TypeId::of::(), - value_type_path: TypePathVtable::of::(), + value_type_path: TypePathTable::of::(), value_type_id: TypeId::of::(), #[cfg(feature = "documentation")] docs: None, @@ -134,18 +134,18 @@ impl MapInfo { /// A representation of the type path of the map. /// /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_vtable(&self) -> &TypePathVtable { + pub fn type_path_table(&self) -> &TypePathTable { &self.type_path } /// The [stable, full type path] of the map. /// - /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. + /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. /// /// [stable, full type path]: TypePath - /// [`type_path_vtable`]: Self::type_path_vtable + /// [`type_path_table`]: Self::type_path_table pub fn type_path(&self) -> &'static str { - self.type_path_vtable().path() + self.type_path_table().path() } /// The [`TypeId`] of the map. @@ -161,7 +161,7 @@ impl MapInfo { /// A representation of the type path of the key type. /// /// Provides dynamic access to all methods on [`TypePath`]. - pub fn key_type_path_vtable(&self) -> &TypePathVtable { + pub fn key_type_path_table(&self) -> &TypePathTable { &self.key_type_path } @@ -178,7 +178,7 @@ impl MapInfo { /// A representation of the type path of the value type. /// /// Provides dynamic access to all methods on [`TypePath`]. - pub fn value_type_path_vtable(&self) -> &TypePathVtable { + pub fn value_type_path_table(&self) -> &TypePathTable { &self.value_type_path } diff --git a/crates/bevy_reflect/src/serde/de.rs b/crates/bevy_reflect/src/serde/de.rs index eec7d788fefe2..7435340b418b7 100644 --- a/crates/bevy_reflect/src/serde/de.rs +++ b/crates/bevy_reflect/src/serde/de.rs @@ -388,7 +388,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { match self.registration.type_info() { TypeInfo::Struct(struct_info) => { let mut dynamic_struct = deserializer.deserialize_struct( - struct_info.type_path_vtable().ident().unwrap(), + struct_info.type_path_table().ident().unwrap(), struct_info.field_names(), StructVisitor { struct_info, @@ -401,7 +401,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { } TypeInfo::TupleStruct(tuple_struct_info) => { let mut dynamic_tuple_struct = deserializer.deserialize_tuple_struct( - tuple_struct_info.type_path_vtable().ident().unwrap(), + tuple_struct_info.type_path_table().ident().unwrap(), tuple_struct_info.field_len(), TupleStructVisitor { tuple_struct_info, @@ -451,9 +451,9 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { Ok(Box::new(dynamic_tuple)) } TypeInfo::Enum(enum_info) => { - let mut dynamic_enum = if enum_info.type_path_vtable().module_path() + let mut dynamic_enum = if enum_info.type_path_table().module_path() == Some("core::option") - && enum_info.type_path_vtable().ident() == Some("Option") + && enum_info.type_path_table().ident() == Some("Option") { deserializer.deserialize_option(OptionVisitor { enum_info, @@ -461,7 +461,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { })? } else { deserializer.deserialize_enum( - enum_info.type_path_vtable().ident().unwrap(), + enum_info.type_path_table().ident().unwrap(), enum_info.variant_names(), EnumVisitor { enum_info, @@ -652,7 +652,7 @@ impl<'a, 'de> Visitor<'de> for ArrayVisitor<'a> { let mut vec = Vec::with_capacity(seq.size_hint().unwrap_or_default()); let registration = get_registration( self.array_info.item_type_id(), - self.array_info.item_type_path_vtable().path(), + self.array_info.item_type_path_table().path(), self.registry, )?; while let Some(value) = seq.next_element_seed(TypedReflectDeserializer { @@ -692,7 +692,7 @@ impl<'a, 'de> Visitor<'de> for ListVisitor<'a> { let mut list = DynamicList::default(); let registration = get_registration( self.list_info.item_type_id(), - self.list_info.item_type_path_vtable().path(), + self.list_info.item_type_path_table().path(), self.registry, )?; while let Some(value) = seq.next_element_seed(TypedReflectDeserializer { @@ -724,12 +724,12 @@ impl<'a, 'de> Visitor<'de> for MapVisitor<'a> { let mut dynamic_map = DynamicMap::default(); let key_registration = get_registration( self.map_info.key_type_id(), - self.map_info.key_type_path_vtable().path(), + self.map_info.key_type_path_table().path(), self.registry, )?; let value_registration = get_registration( self.map_info.value_type_id(), - self.map_info.value_type_path_vtable().path(), + self.map_info.value_type_path_table().path(), self.registry, )?; while let Some(key) = map.next_key_seed(TypedReflectDeserializer { diff --git a/crates/bevy_reflect/src/serde/ser.rs b/crates/bevy_reflect/src/serde/ser.rs index 7292ed73f4069..da0b464893dcf 100644 --- a/crates/bevy_reflect/src/serde/ser.rs +++ b/crates/bevy_reflect/src/serde/ser.rs @@ -191,7 +191,7 @@ impl<'a> Serialize for StructSerializer<'a> { .and_then(|registration| registration.data::()); let ignored_len = serialization_data.map(|data| data.len()).unwrap_or(0); let mut state = serializer.serialize_struct( - struct_info.type_path_vtable().ident().unwrap(), + struct_info.type_path_table().ident().unwrap(), self.struct_value.field_len() - ignored_len, )?; @@ -244,7 +244,7 @@ impl<'a> Serialize for TupleStructSerializer<'a> { .and_then(|registration| registration.data::()); let ignored_len = serialization_data.map(|data| data.len()).unwrap_or(0); let mut state = serializer.serialize_tuple_struct( - tuple_struct_info.type_path_vtable().ident().unwrap(), + tuple_struct_info.type_path_table().ident().unwrap(), self.tuple_struct.field_len() - ignored_len, )?; @@ -287,7 +287,7 @@ impl<'a> Serialize for EnumSerializer<'a> { } }; - let enum_name = enum_info.type_path_vtable().ident().unwrap(); + let enum_name = enum_info.type_path_table().ident().unwrap(); let variant_index = self.enum_value.variant_index() as u32; let variant_info = enum_info .variant_at(variant_index as usize) diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index ad2cb1910caa9..16abb795b39a8 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, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, - TypePath, TypePathVtable, + TypePath, TypePathTable, }; use bevy_reflect_derive::impl_type_path; use bevy_utils::{Entry, HashMap}; @@ -76,7 +76,7 @@ pub trait Struct: Reflect { /// A container for compile-time named struct info. #[derive(Clone, Debug)] pub struct StructInfo { - type_path: TypePathVtable, + type_path: TypePathTable, type_id: TypeId, fields: Box<[NamedField]>, field_names: Box<[&'static str]>, @@ -102,7 +102,7 @@ impl StructInfo { let field_names = fields.iter().map(|field| field.name()).collect(); Self { - type_path: TypePathVtable::of::(), + type_path: TypePathTable::of::(), type_id: TypeId::of::(), fields: fields.to_vec().into_boxed_slice(), field_names, @@ -153,18 +153,18 @@ impl StructInfo { /// A representation of the type path of the struct. /// /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_vtable(&self) -> &TypePathVtable { + pub fn type_path_table(&self) -> &TypePathTable { &self.type_path } /// The [stable, full type path] of the struct. /// - /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. + /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. /// /// [stable, full type path]: TypePath - /// [`type_path_vtable`]: Self::type_path_vtable + /// [`type_path_table`]: Self::type_path_table pub fn type_path(&self) -> &'static str { - self.type_path_vtable().path() + self.type_path_table().path() } /// The [`TypeId`] of the struct. diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index c98e48613c0f3..87ad68c59f0ff 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -1,7 +1,7 @@ use bevy_reflect_derive::impl_type_path; use bevy_utils::all_tuples; -use crate::TypePathVtable; +use crate::TypePathTable; use crate::{ self as bevy_reflect, utility::GenericTypePathCell, FromReflect, GetTypeRegistration, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, TypeRegistration, Typed, @@ -139,7 +139,7 @@ impl GetTupleField for dyn Tuple { /// A container for compile-time tuple info. #[derive(Clone, Debug)] pub struct TupleInfo { - type_path: TypePathVtable, + type_path: TypePathTable, type_id: TypeId, fields: Box<[UnnamedField]>, #[cfg(feature = "documentation")] @@ -155,7 +155,7 @@ impl TupleInfo { /// pub fn new(fields: &[UnnamedField]) -> Self { Self { - type_path: TypePathVtable::of::(), + type_path: TypePathTable::of::(), type_id: TypeId::of::(), fields: fields.to_vec().into_boxed_slice(), #[cfg(feature = "documentation")] @@ -187,18 +187,18 @@ impl TupleInfo { /// A representation of the type path of the tuple. /// /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_vtable(&self) -> &TypePathVtable { + pub fn type_path_table(&self) -> &TypePathTable { &self.type_path } /// The [stable, full type path] of the tuple. /// - /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. + /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. /// /// [stable, full type path]: TypePath - /// [`type_path_vtable`]: Self::type_path_vtable + /// [`type_path_table`]: Self::type_path_table pub fn type_path(&self) -> &'static str { - self.type_path_vtable().path() + self.type_path_table().path() } /// The [`TypeId`] of the tuple. diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index da3f3eef8c5ec..9d12490871980 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -2,7 +2,7 @@ use bevy_reflect_derive::impl_type_path; use crate::{ self as bevy_reflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, - TypePathVtable, UnnamedField, + TypePathTable, UnnamedField, }; use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; @@ -56,7 +56,7 @@ pub trait TupleStruct: Reflect { /// A container for compile-time tuple struct info. #[derive(Clone, Debug)] pub struct TupleStructInfo { - type_path: TypePathVtable, + type_path: TypePathTable, type_id: TypeId, fields: Box<[UnnamedField]>, #[cfg(feature = "documentation")] @@ -72,7 +72,7 @@ impl TupleStructInfo { /// pub fn new(fields: &[UnnamedField]) -> Self { Self { - type_path: TypePathVtable::of::(), + type_path: TypePathTable::of::(), type_id: TypeId::of::(), fields: fields.to_vec().into_boxed_slice(), #[cfg(feature = "documentation")] @@ -104,18 +104,18 @@ impl TupleStructInfo { /// A representation of the type path of the struct. /// /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_vtable(&self) -> &TypePathVtable { + pub fn type_path_table(&self) -> &TypePathTable { &self.type_path } /// The [stable, full type path] of the struct. /// - /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. + /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. /// /// [stable, full type path]: TypePath - /// [`type_path_vtable`]: Self::type_path_vtable + /// [`type_path_table`]: Self::type_path_table pub fn type_path(&self) -> &'static str { - self.type_path_vtable().path() + self.type_path_table().path() } /// The [`TypeId`] of the tuple struct. diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index d2f8811b74431..8d677c908c9a8 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -1,6 +1,6 @@ use crate::{ ArrayInfo, EnumInfo, ListInfo, MapInfo, Reflect, StructInfo, TupleInfo, TupleStructInfo, - TypePath, TypePathVtable, + TypePath, TypePathTable, }; use std::any::{Any, TypeId}; use std::fmt::Debug; @@ -129,27 +129,27 @@ impl TypeInfo { /// A representation of the type path of the underlying type. /// /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_vtable(&self) -> &TypePathVtable { + pub fn type_path_table(&self) -> &TypePathTable { match self { - Self::Struct(info) => info.type_path_vtable(), - Self::TupleStruct(info) => info.type_path_vtable(), - Self::Tuple(info) => info.type_path_vtable(), - Self::List(info) => info.type_path_vtable(), - Self::Array(info) => info.type_path_vtable(), - Self::Map(info) => info.type_path_vtable(), - Self::Enum(info) => info.type_path_vtable(), - Self::Value(info) => info.type_path_vtable(), + Self::Struct(info) => info.type_path_table(), + Self::TupleStruct(info) => info.type_path_table(), + Self::Tuple(info) => info.type_path_table(), + Self::List(info) => info.type_path_table(), + Self::Array(info) => info.type_path_table(), + Self::Map(info) => info.type_path_table(), + Self::Enum(info) => info.type_path_table(), + Self::Value(info) => info.type_path_table(), } } /// The [stable, full type path] of the underlying type. /// - /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. + /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. /// /// [stable, full type path]: TypePath - /// [`type_path_vtable`]: Self::type_path_vtable + /// [`type_path_table`]: Self::type_path_table pub fn type_path(&self) -> &'static str { - self.type_path_vtable().path() + self.type_path_table().path() } /// Check if the given type matches the underlying type. @@ -183,7 +183,7 @@ impl TypeInfo { /// it _as_ a struct. It therefore makes more sense to represent it as a [`ValueInfo`]. #[derive(Debug, Clone)] pub struct ValueInfo { - type_path: TypePathVtable, + type_path: TypePathTable, type_id: TypeId, #[cfg(feature = "documentation")] docs: Option<&'static str>, @@ -192,7 +192,7 @@ pub struct ValueInfo { impl ValueInfo { pub fn new() -> Self { Self { - type_path: TypePathVtable::of::(), + type_path: TypePathTable::of::(), type_id: TypeId::of::(), #[cfg(feature = "documentation")] docs: None, @@ -208,18 +208,18 @@ impl ValueInfo { /// A representation of the type path of the value. /// /// Provides dynamic access to all methods on [`TypePath`]. - pub fn type_path_vtable(&self) -> &TypePathVtable { + pub fn type_path_table(&self) -> &TypePathTable { &self.type_path } /// The [stable, full type path] of the value. /// - /// Use [`type_path_vtable`] if you need access to the other methods on [`TypePath`]. + /// Use [`type_path_table`] if you need access to the other methods on [`TypePath`]. /// /// [stable, full type path]: TypePath - /// [`type_path_vtable`]: Self::type_path_vtable + /// [`type_path_table`]: Self::type_path_table pub fn type_path(&self) -> &'static str { - self.type_path_vtable().path() + self.type_path_table().path() } /// The [`TypeId`] of the value. diff --git a/crates/bevy_reflect/src/type_path.rs b/crates/bevy_reflect/src/type_path.rs index 8e5fe32e57e57..9861f76289b66 100644 --- a/crates/bevy_reflect/src/type_path.rs +++ b/crates/bevy_reflect/src/type_path.rs @@ -170,7 +170,7 @@ impl DynamicTypePath for T { /// Provides dynamic access to all methods on [`TypePath`]. #[derive(Clone, Copy)] -pub struct TypePathVtable { +pub struct TypePathTable { // Cache the type path as it is likely the only one that will be used. type_path: &'static str, short_type_path: fn() -> &'static str, @@ -179,7 +179,7 @@ pub struct TypePathVtable { module_path: fn() -> Option<&'static str>, } -impl fmt::Debug for TypePathVtable { +impl fmt::Debug for TypePathTable { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("TypePathVtable") .field("type_path", &self.type_path) @@ -187,8 +187,8 @@ impl fmt::Debug for TypePathVtable { } } -impl TypePathVtable { - /// Creates a new vtable from a type. +impl TypePathTable { + /// Creates a new table from a type. pub fn of() -> Self { Self { type_path: T::type_path(), diff --git a/crates/bevy_reflect/src/type_registry.rs b/crates/bevy_reflect/src/type_registry.rs index d15ac69650eb6..ca8dba4257fef 100644 --- a/crates/bevy_reflect/src/type_registry.rs +++ b/crates/bevy_reflect/src/type_registry.rs @@ -110,7 +110,7 @@ impl TypeRegistry { return; } - let short_name = registration.type_info().type_path_vtable().short_path(); + let short_name = registration.type_info().type_path_table().short_path(); if self.short_path_to_id.contains_key(short_name) || self.ambiguous_names.contains(short_name) { @@ -302,7 +302,7 @@ impl TypeRegistryArc { /// let mut registration = TypeRegistration::of::>(); /// /// assert_eq!("core::option::Option", registration.type_info().type_path()); -/// assert_eq!("Option", registration.type_info().type_path_vtable().short_path()); +/// assert_eq!("Option", registration.type_info().type_path_table().short_path()); /// /// registration.insert::(FromType::>::from_type()); /// assert!(registration.data::().is_some()) From bce5c9d8091f40d58ac00d6f549ca6e0087b46f0 Mon Sep 17 00:00:00 2001 From: radiish Date: Sat, 19 Aug 2023 15:05:34 +0100 Subject: [PATCH 21/27] address feedback --- crates/bevy_scene/src/dynamic_scene.rs | 4 ++-- crates/bevy_scene/src/scene.rs | 6 +++--- crates/bevy_scene/src/scene_spawner.rs | 13 +++++++++++-- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/crates/bevy_scene/src/dynamic_scene.rs b/crates/bevy_scene/src/dynamic_scene.rs index 43b0ae333ddc6..2491a572c7a6b 100644 --- a/crates/bevy_scene/src/dynamic_scene.rs +++ b/crates/bevy_scene/src/dynamic_scene.rs @@ -79,7 +79,7 @@ impl DynamicScene { } })?; let registration = type_registry.get(type_info.type_id()).ok_or_else(|| { - SceneSpawnError::UnregisteredType { + SceneSpawnError::UnregisteredButReflectedType { type_path: type_info.type_path().to_string(), } })?; @@ -117,7 +117,7 @@ impl DynamicScene { } })?; let registration = type_registry.get(type_info.type_id()).ok_or_else(|| { - SceneSpawnError::UnregisteredType { + SceneSpawnError::UnregisteredButReflectedType { type_path: type_info.type_path().to_string(), } })?; diff --git a/crates/bevy_scene/src/scene.rs b/crates/bevy_scene/src/scene.rs index 9317e4c08133c..b695101a922e3 100644 --- a/crates/bevy_scene/src/scene.rs +++ b/crates/bevy_scene/src/scene.rs @@ -77,11 +77,11 @@ impl Scene { type_registry .get(type_id) .ok_or_else(|| SceneSpawnError::UnregisteredType { - type_path: component_info.name().to_string(), + std_type_name: component_info.name().to_string(), })?; let reflect_resource = registration.data::().ok_or_else(|| { SceneSpawnError::UnregisteredResource { - type_path: component_info.name().to_string(), + type_path: registration.type_info().type_path().to_string(), } })?; reflect_resource.copy(&self.world, world); @@ -103,7 +103,7 @@ impl Scene { let reflect_component = type_registry .get(component_info.type_id().unwrap()) .ok_or_else(|| SceneSpawnError::UnregisteredType { - type_path: component_info.name().to_string(), + std_type_name: component_info.name().to_string(), }) .and_then(|registration| { registration.data::().ok_or_else(|| { diff --git a/crates/bevy_scene/src/scene_spawner.rs b/crates/bevy_scene/src/scene_spawner.rs index 5b7bc1099acbe..6e3aef65af3ed 100644 --- a/crates/bevy_scene/src/scene_spawner.rs +++ b/crates/bevy_scene/src/scene_spawner.rs @@ -47,8 +47,17 @@ pub enum SceneSpawnError { UnregisteredComponent { type_path: String }, #[error("scene contains the unregistered resource `{type_path}`. consider adding `#[reflect(Resource)]` to your type")] UnregisteredResource { type_path: String }, - #[error("scene contains the unregistered type `{type_path}`. consider registering the type using `app.register_type::()`")] - UnregisteredType { type_path: String }, + #[error( + "scene contains the unregistered type `{std_type_name}`. \ + consider reflecting it with `#[derive(Reflect)]` \ + and registering the type using `app.register_type::()`" + )] + UnregisteredType { std_type_name: String }, + #[error( + "scene contains the reflected type `{type_path}` but it was not found in the type registry. \ + consider registering the type using `app.register_type::()``" + )] + UnregisteredButReflectedType { type_path: String }, #[error("scene contains dynamic type `{type_path}` without a represented type. consider changing this using `set_represented_type`.")] NoRepresentedType { type_path: String }, #[error("scene does not exist")] From 2a4442f9f8ad9a48ed818512fec82eee72394c2b Mon Sep 17 00:00:00 2001 From: radiish Date: Sat, 19 Aug 2023 15:35:43 +0100 Subject: [PATCH 22/27] remove unused import --- crates/bevy_reflect/bevy_reflect_derive/src/utility.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs b/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs index 9bed1d3b8b882..925e678f2956d 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs @@ -7,7 +7,7 @@ use bevy_macro_utils::BevyManifest; use bit_set::BitSet; use proc_macro2::{Ident, Span}; use quote::{quote, ToTokens}; -use syn::{spanned::Spanned, Lifetime, LitStr, Member, Path, Type, WhereClause}; +use syn::{spanned::Spanned, LitStr, Member, Path, Type, WhereClause}; /// Returns the correct path for `bevy_reflect`. pub(crate) fn get_bevy_reflect_path() -> Path { From c1bc5cc8e66f84af908a56ad8691a0177f18df1c Mon Sep 17 00:00:00 2001 From: radiish Date: Sat, 19 Aug 2023 16:15:44 +0100 Subject: [PATCH 23/27] appease clippy --- crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs index 3cdfdad7257c8..5894ef82e5540 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -101,7 +101,7 @@ pub(crate) fn impl_type_path( let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl(); // Add Typed bound for each active field - let where_reflect_clause = extend_where_clause(where_clause, &where_clause_options); + let where_reflect_clause = extend_where_clause(where_clause, where_clause_options); quote! { #primitive_assert From a3dbbd54c491d936820bc84c25b2c8c7a4eb55de Mon Sep 17 00:00:00 2001 From: soqb Date: Fri, 22 Sep 2023 19:36:30 +0100 Subject: [PATCH 24/27] readded via deprecation `Reflect::type_name` --- crates/bevy_reflect/src/reflect.rs | 16 ++++++++++++++++ crates/bevy_scene/src/dynamic_scene.rs | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index 458022566baa5..223d0f5ebf378 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -73,6 +73,22 @@ pub enum ReflectOwned { /// [derive macro]: bevy_reflect_derive::Reflect /// [crate-level documentation]: crate pub trait Reflect: DynamicTypePath + Any + Send + Sync { + /// Returns the type path of the underlying type. + /// + /// This type path will either be found through [`get_represented_type_info`] + /// or taken from a [`TypePath`] implementation if the former isn't available. + /// + /// This method is deprecated; please consider migrating to one of the above methods. + #[deprecated( + since = "0.12.0", + note = "view the method documentation to find alternatives to this method." + )] + fn type_name(&self) -> &str { + self.get_represented_type_info() + .map(|info| info.type_path()) + .unwrap_or_else(|| self.reflect_type_path()) + } + /// Returns the [`TypeInfo`] of the type _represented_ by this value. /// /// For most types, this will simply return their own `TypeInfo`. diff --git a/crates/bevy_scene/src/dynamic_scene.rs b/crates/bevy_scene/src/dynamic_scene.rs index 2491a572c7a6b..34ea1e6998ccb 100644 --- a/crates/bevy_scene/src/dynamic_scene.rs +++ b/crates/bevy_scene/src/dynamic_scene.rs @@ -10,6 +10,10 @@ use bevy_ecs::{ use bevy_reflect::{Reflect, TypePath, TypeRegistryArc, TypeUuid}; use bevy_utils::HashMap; +fn a(b: impl Reflect) { + b.type_name(); +} + #[cfg(feature = "serialize")] use crate::serde::SceneSerializer; use bevy_ecs::reflect::ReflectResource; From b6b9af8cf7b4f45dc445b91ca2ab432219a58895 Mon Sep 17 00:00:00 2001 From: soqb Date: Fri, 22 Sep 2023 19:37:05 +0100 Subject: [PATCH 25/27] aaagh! --- crates/bevy_scene/src/dynamic_scene.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/bevy_scene/src/dynamic_scene.rs b/crates/bevy_scene/src/dynamic_scene.rs index 34ea1e6998ccb..2491a572c7a6b 100644 --- a/crates/bevy_scene/src/dynamic_scene.rs +++ b/crates/bevy_scene/src/dynamic_scene.rs @@ -10,10 +10,6 @@ use bevy_ecs::{ use bevy_reflect::{Reflect, TypePath, TypeRegistryArc, TypeUuid}; use bevy_utils::HashMap; -fn a(b: impl Reflect) { - b.type_name(); -} - #[cfg(feature = "serialize")] use crate::serde::SceneSerializer; use bevy_ecs::reflect::ReflectResource; From 9d49b3ab53b5fb9b728bc72c989351671ad71228 Mon Sep 17 00:00:00 2001 From: soqb Date: Fri, 22 Sep 2023 20:33:58 +0100 Subject: [PATCH 26/27] `TypePath` for &mut --- crates/bevy_reflect/src/impls/std.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index a554f0f89eee1..55506a8e77823 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -1021,6 +1021,18 @@ impl TypePath for &'static T { } } +impl TypePath for &'static mut T { + fn type_path() -> &'static str { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| format!("&mut {}", T::type_path())) + } + + fn short_type_path() -> &'static str { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| format!("&mut {}", T::short_type_path())) + } +} + impl Reflect for Cow<'static, str> { fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { Some(::type_info()) From aae3ca30f7794a09c65b2245f5b86ab7d744a596 Mon Sep 17 00:00:00 2001 From: soqb Date: Fri, 22 Sep 2023 21:16:47 +0100 Subject: [PATCH 27/27] add missing doc link --- crates/bevy_reflect/src/reflect.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index 223d0f5ebf378..d36fd5db94f21 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -79,6 +79,8 @@ pub trait Reflect: DynamicTypePath + Any + Send + Sync { /// or taken from a [`TypePath`] implementation if the former isn't available. /// /// This method is deprecated; please consider migrating to one of the above methods. + /// + /// [`get_represented_type_info`]: Reflect::get_represented_type_info #[deprecated( since = "0.12.0", note = "view the method documentation to find alternatives to this method."