From 91cafebffec185302c6e15fbf5f14c0def6a8c91 Mon Sep 17 00:00:00 2001 From: radiish Date: Tue, 10 Jan 2023 19:19:46 +0000 Subject: [PATCH 01/52] a lot. --- crates/bevy_input/src/input.rs | 8 +- .../bevy_reflect_derive/src/derive_data.rs | 318 ++++++++++++++++-- .../bevy_reflect_derive/src/from_reflect.rs | 20 +- .../bevy_reflect_derive/src/impls/enums.rs | 14 +- .../bevy_reflect_derive/src/impls/mod.rs | 3 +- .../bevy_reflect_derive/src/impls/structs.rs | 14 +- .../src/impls/tuple_structs.rs | 14 +- .../bevy_reflect_derive/src/impls/typed.rs | 79 ++++- .../bevy_reflect_derive/src/impls/values.rs | 8 +- .../bevy_reflect_derive/src/lib.rs | 67 +++- .../bevy_reflect_derive/src/reflect_value.rs | 33 +- .../bevy_reflect_derive/src/registration.rs | 20 +- .../bevy_reflect_derive/src/with_path.rs | 197 +++++++++++ crates/bevy_reflect/src/array.rs | 9 +- crates/bevy_reflect/src/enums/dynamic_enum.rs | 9 +- crates/bevy_reflect/src/enums/mod.rs | 2 +- crates/bevy_reflect/src/impls/smallvec.rs | 21 +- crates/bevy_reflect/src/impls/std.rs | 134 +++++--- crates/bevy_reflect/src/lib.rs | 44 ++- crates/bevy_reflect/src/list.rs | 14 +- crates/bevy_reflect/src/map.rs | 13 +- crates/bevy_reflect/src/reflect.rs | 7 +- crates/bevy_reflect/src/struct_trait.rs | 13 +- crates/bevy_reflect/src/tuple.rs | 37 +- crates/bevy_reflect/src/tuple_struct.rs | 11 +- crates/bevy_reflect/src/type_info.rs | 6 +- crates/bevy_reflect/src/type_path.rs | 72 ++++ crates/bevy_reflect/src/utility.rs | 181 ++++++---- 28 files changed, 1109 insertions(+), 259 deletions(-) create mode 100644 crates/bevy_reflect/bevy_reflect_derive/src/with_path.rs create mode 100644 crates/bevy_reflect/src/type_path.rs diff --git a/crates/bevy_input/src/input.rs b/crates/bevy_input/src/input.rs index a22145ea64f5d..8c4273bfc9f41 100644 --- a/crates/bevy_input/src/input.rs +++ b/crates/bevy_input/src/input.rs @@ -1,5 +1,5 @@ use bevy_ecs::system::Resource; -use bevy_reflect::{std_traits::ReflectDefault, Reflect}; +use bevy_reflect::{std_traits::ReflectDefault, Reflect, Typed}; use bevy_utils::HashSet; use std::hash::Hash; @@ -43,7 +43,7 @@ use bevy_ecs::schedule::State; ///[`DetectChangesMut::bypass_change_detection`]: bevy_ecs::change_detection::DetectChangesMut::bypass_change_detection #[derive(Debug, Clone, Resource, Reflect)] #[reflect(Default)] -pub struct Input { +pub struct Input { /// A collection of every button that is currently being pressed. pressed: HashSet, /// A collection of every button that has just been pressed. @@ -52,7 +52,7 @@ pub struct Input { just_released: HashSet, } -impl Default for Input { +impl Default for Input { fn default() -> Self { Self { pressed: Default::default(), @@ -64,7 +64,7 @@ impl Default for Input { impl Input where - T: Copy + Eq + Hash + Send + Sync + 'static, + T: Typed + Copy + Eq + Hash + Send + Sync + 'static, { /// Registers a press for the given `input`. pub fn press(&mut self, input: T) { 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 1b47092dbd872..ddbdbe8c426e5 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs @@ -2,13 +2,20 @@ use crate::container_attributes::ReflectTraits; use crate::field_attributes::{parse_field_attrs, ReflectFieldAttr}; use crate::fq_std::{FQAny, FQDefault, FQSend, FQSync}; use crate::utility::{members_to_serialization_denylist, WhereClauseOptions}; +use crate::utility::members_to_serialization_denylist; +use crate::with_path::parse_path_no_leading_colon; use bit_set::BitSet; -use quote::quote; +use quote::{quote, ToTokens}; -use crate::{utility, REFLECT_ATTRIBUTE_NAME, REFLECT_VALUE_ATTRIBUTE_NAME}; +use crate::{ + utility, REFLECT_ATTRIBUTE_NAME, REFLECT_VALUE_ATTRIBUTE_NAME, TYPE_PATH_ATTRIBUTE_NAME, +}; use syn::punctuated::Punctuated; use syn::spanned::Spanned; -use syn::{Data, DeriveInput, Field, Fields, Generics, Ident, Meta, Path, Token, Variant}; +use syn::{ + parse_str, Data, DeriveInput, Field, Fields, GenericParam, Generics, Ident, Lit, LitStr, Meta, + Path, Token, Type, TypePath, Variant, ImplGenerics, TypeGenerics, WhereClause, +}; pub(crate) enum ReflectDerive<'a> { Struct(ReflectStruct<'a>), @@ -35,7 +42,7 @@ pub(crate) struct ReflectMeta<'a> { /// The registered traits for this type. traits: ReflectTraits, /// The name of this type. - type_name: &'a Ident, + path_to_type: PathToType<'a>, /// The generics defined on this type. generics: &'a Generics, /// A cached instance of the path to the `bevy_reflect` crate. @@ -130,8 +137,10 @@ enum ReflectMode { impl<'a> ReflectDerive<'a> { pub fn from_input(input: &'a DeriveInput) -> Result { let mut traits = ReflectTraits::default(); - // Should indicate whether `#[reflect_value]` was used + // Should indicate whether `#[reflect_value]` was used. let mut reflect_mode = None; + // Should indicate whether `#[type_path = "..."]` was used. + let mut type_path_alias: Option = None; #[cfg(feature = "documentation")] let mut doc = crate::documentation::Documentation::default(); @@ -172,9 +181,31 @@ impl<'a> ReflectDerive<'a> { reflect_mode = Some(ReflectMode::Value); } + Meta::NameValue(pair) if pair.path.is_ident(TYPE_PATH_ATTRIBUTE_NAME) => { + if type_path_alias.is_some() { + return Err(syn::Error::new( + pair.span(), + format_args!( + "cannot use multuple `#[{TYPE_PATH_ATTRIBUTE_NAME} = \"...\"]`" + ), + )); + } + + let Lit::Str(lit) = pair.lit else { + return Err(syn::Error::new( + pair.span(), + format_args!("`#[{TYPE_PATH_ATTRIBUTE_NAME} = \"...\"]` must be a string literal"), + )); + }; + + type_path_alias = Some(syn::parse::Parser::parse_str( + parse_path_no_leading_colon, + &lit.value(), + )?); + } #[cfg(feature = "documentation")] Meta::NameValue(pair) if pair.path.is_ident("doc") => { - if let syn::Lit::Str(lit) = pair.lit { + if let Lit::Str(lit) = pair.lit { doc.push(lit.value()); } } @@ -182,7 +213,19 @@ impl<'a> ReflectDerive<'a> { } } - let meta = ReflectMeta::new(&input.ident, &input.generics, traits); + let path_to_type = if let Some(alias) = type_path_alias { + PathToType::AliasedNamed { + alias, + ty: Type::Path(TypePath { + qself: None, + path: Path::from(input.ident.clone()), + }), + } + } else { + PathToType::Internal(&input.ident) + }; + + let meta = ReflectMeta::new(path_to_type, &input.generics, traits); #[cfg(feature = "documentation")] let meta = meta.with_docs(doc); @@ -224,6 +267,16 @@ impl<'a> ReflectDerive<'a> { }; } + pub fn meta(&self) -> &ReflectMeta<'a> { + match self { + ReflectDerive::Struct(data) => data.meta(), + ReflectDerive::TupleStruct(data) => data.meta(), + ReflectDerive::UnitStruct(data) => data.meta(), + ReflectDerive::Enum(data) => data.meta(), + ReflectDerive::Value(meta) => meta, + } + } + fn collect_struct_fields(fields: &'a Fields) -> Result>, syn::Error> { let sifter: utility::ResultSifter> = fields .iter() @@ -279,10 +332,14 @@ impl<'a> ReflectDerive<'a> { } impl<'a> ReflectMeta<'a> { - pub fn new(type_name: &'a Ident, generics: &'a Generics, traits: ReflectTraits) -> Self { + pub fn new( + path_to_type: PathToType<'a>, + generics: &'a Generics, + traits: ReflectTraits, + ) -> Self { Self { traits, - type_name, + path_to_type, generics, bevy_reflect_path: utility::get_bevy_reflect_path(), #[cfg(feature = "documentation")] @@ -302,8 +359,8 @@ impl<'a> ReflectMeta<'a> { } /// The name of this struct. - pub fn type_name(&self) -> &'a Ident { - self.type_name + pub fn path_to_type(&self) -> &'a PathToType { + &self.path_to_type } /// The generics associated with this struct. @@ -315,6 +372,27 @@ impl<'a> ReflectMeta<'a> { pub fn bevy_reflect_path(&self) -> &Path { &self.bevy_reflect_path } + + /// Use this over [`Generics::split_for_impl`]. + pub fn split_generics_for_impl(&self) -> (ImplGenerics, Option, Option<&WhereClause>) { + let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl(); + if let PathToType::AliasedNamed { .. } = self.path_to_type { + (impl_generics, None, where_clause) + } else { + (impl_generics, Some(ty_generics), where_clause) + } + } + + /// Whether an impl using this [`ReflectMeta`] should be generic. + pub fn impl_is_generic(&self) -> bool { + // Whether to use `GenericTypedCell` is not dependent on lifetimes + // (which all have to be 'static anyway). + !self + .generics + .params + .iter() + .all(|param| matches!(param, GenericParam::Lifetime(_))) + } /// Returns the `GetTypeRegistration` impl as a `TokenStream`. pub fn get_type_registration( @@ -322,10 +400,7 @@ impl<'a> ReflectMeta<'a> { where_clause_options: &WhereClauseOptions, ) -> proc_macro2::TokenStream { crate::registration::impl_get_type_registration( - self.type_name, - &self.bevy_reflect_path, - self.traits.idents(), - self.generics, + self.meta(), where_clause_options, None, ) @@ -359,13 +434,8 @@ impl<'a> ReflectStruct<'a> { &self, where_clause_options: &WhereClauseOptions, ) -> proc_macro2::TokenStream { - let reflect_path = self.meta.bevy_reflect_path(); - crate::registration::impl_get_type_registration( - self.meta.type_name(), - reflect_path, - self.meta.traits().idents(), - self.meta.generics(), + self.meta(), where_clause_options, Some(&self.serialization_denylist), ) @@ -424,7 +494,7 @@ impl<'a> ReflectEnum<'a> { /// Returns the given ident as a qualified unit variant of this enum. pub fn get_unit(&self, variant: &Ident) -> proc_macro2::TokenStream { - let name = self.meta.type_name; + let name = self.meta.path_to_type(); quote! { #name::#variant } @@ -500,3 +570,207 @@ impl<'a> EnumVariant<'a> { } } } + +pub(crate) enum PathToType<'a> { + /// The name of a type relative to itself. + /// + /// Module and crate are found with [`module_path!()`](core::module_path). + Internal(&'a Ident), + /// Using `::my_crate::foo::Bar` syntax. + External(&'a Path), + /// Types without a crate/module (e.g. `bool`). + Primtive(&'a Ident), + /// [`PathToType::External`] but with a seperately defined qualified path. + AliasedNamed { ty: Type, alias: Path }, + /// Types without a crate/module and with a seperately defined qualified path. + AliasedAnonymous { ty: Type, alias: LitStr }, +} + +impl<'a> PathToType<'a> { + /// Returns whether [`crate_name`](PathToType::crate_name) + /// and [`module_path`](PathToType::module_path) return [`Some`]. + /// + /// This is true for primitives and anonymous paths. + pub fn has_module(&self) -> bool { + match self { + Self::Primtive(_) | Self::AliasedAnonymous { .. } => false, + _ => true, + } + } + + /// Returns an expression for a [`&str`](str). + pub fn crate_name(&self) -> Option { + match self { + Self::Internal { .. } => Some(quote! { + ::core::module_path!() + .split(':') + .next() + .unwrap() + }), + &Self::External(&ref path) | Self::AliasedNamed { alias: ref path, .. } => { + let crate_name = path.segments.first().unwrap().ident.to_string(); + let crate_name = LitStr::new(&crate_name, path.span()); + Some(quote!(#crate_name)) + } + Self::Primtive(_) => None, + } + } + + /// Returns an expression representing a [`String`]. + pub fn fully_qualified_path(&self) -> proc_macro2::TokenStream { + match self { + Self::Internal(ident) => { + let module_path = self.module_path().unwrap(); + let ident = LitStr::new(&ident.to_string(), ident.span()); + quote! { + #module_path.to_owned() + ::core::concat!("::", #ident) + } + } + Self::External(&ref path) | Self::AliasedNamed { alias: ref path, .. } => { + let module_path = self.module_path().unwrap(); + let ident = &path.segments.last().unwrap().ident; + let ident = LitStr::new(&ident.to_string(), ident.span()); + quote! { + #module_path.to_owned() + ::core::concat!("::", #ident) + } + } + Self::Primtive(ident) => { + let ident = LitStr::new(&ident.to_string(), ident.span()); + quote! { + #ident.to_owned() + } + } + } + } + + /// Returns an expression for a [`&str`](str). + pub fn module_path(&self) -> Option { + match self { + Self::Internal { .. } => Some(quote! { + ::core::module_path!() + }), + Self::External(&ref path) | Self::AliasedNamed { alias: ref path, .. } => { + let path = path + .segments + .pairs() + .take(path.segments.len() - 1) + .map(|pair| pair.value().ident.to_string()) + .reduce(|path, ident| path + "::" + &ident) + .unwrap(); + + let path = LitStr::new(&path, path.span()); + Some(quote! { + #path + }) + } + Self::Primtive(_) => None, + } + } + + /// Returns the name of the type. This is not necessarily a valid qualified path to the type. + pub fn name(&self) -> &Ident { + match self { + Self::Internal(ident) | Self::Primtive(ident) => ident, + Self::External(&ref path) | Self::AliasedNamed { alias: ref path, .. } => { + &path.segments.last().unwrap().ident + } + } + } +} + +impl<'a> ToTokens for PathToType<'a> { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + match self { + Self::Internal(ident) | Self::Primtive(ident) => ident.to_tokens(tokens), + Self::External(path) => path.to_tokens(tokens), + Self::AliasedNamed { + ty, + .. + } | Self::AliasedAnonymous { ty, .. } => ty.to_tokens(tokens), + } + } +} + +pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStream { + let path_to_type = meta.path_to_type(); + let generics = meta.generics(); + let bevy_reflect_path = meta.bevy_reflect_path(); + // Whether to use `GenericTypedCell` is not dependent on lifetimes + // (which all have to be 'static anyway). + let is_generic = !generics + .params + .iter() + .all(|param| matches!(param, GenericParam::Lifetime(_))); + let generic_type_paths: Vec = generics + .type_params() + .map(|param| { + let ident = ¶m.ident; + quote! { + <#ident as #bevy_reflect_path::WithPath>::type_path() + } + }) + .collect(); + + let ident = path_to_type.name().to_string(); + let ident = LitStr::new(&ident, path_to_type.span()); + + let path = { + let path = path_to_type.fully_qualified_path(); + + if is_generic { + let generics = generic_type_paths.iter().map(|type_path| { + quote! { + #type_path.path() + } + }); + + quote! { + #path + "::<" #(+ #generics)* + ">" + } + } else { + quote! { + #path + } + } + }; + + let short_path = { + if is_generic { + let generics = generic_type_paths.iter().map(|type_path| { + quote! { + #type_path.short_path() + } + }); + + quote! { + ::core::concat!(#ident, "<").to_owned() #(+ #generics)* + ">" + } + } else { + quote! { + #ident.to_owned() + } + } + }; + + if path_to_type.has_module() { + quote! { + #bevy_reflect_path::TypePath::new_anonymous( + #path, + #short_path, + ) + } + } else { + let crate_name = path_to_type.crate_name(); + let module_path = path_to_type.module_path(); + + quote! { + #bevy_reflect_path::TypePath::new_named( + #path, + #short_path, + #ident.to_owned(), + #crate_name.to_owned(), + #module_path.to_owned(), + ) + } + } +} 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 aab2545b54989..4147445a57962 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs @@ -21,13 +21,13 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { /// Implements `FromReflect` for the given value type pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { - let type_name = meta.type_name(); + let path_to_type = meta.path_to_type(); let bevy_reflect_path = meta.bevy_reflect_path(); - let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl(); + let (impl_generics, ty_generics, where_clause) = meta.split_generics_for_impl(); TokenStream::from(quote! { - impl #impl_generics #bevy_reflect_path::FromReflect for #type_name #ty_generics #where_clause { + impl #impl_generics #bevy_reflect_path::FromReflect for #path_to_type #ty_generics #where_clause { fn from_reflect(reflect: &dyn #bevy_reflect_path::Reflect) -> #FQOption { - #FQOption::Some(#FQClone::clone(::downcast_ref::<#type_name #ty_generics>(::as_any(reflect))?)) + #FQOption::Some(#FQClone::clone(::downcast_ref::<#path_to_type #ty_generics>(::as_any(reflect))?)) } } }) @@ -37,7 +37,7 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { let fqoption = FQOption.into_token_stream(); - let type_name = reflect_enum.meta().type_name(); + let enum_path = reflect_enum.meta().path_to_type(); let bevy_reflect_path = reflect_enum.meta().bevy_reflect_path(); let ref_value = Ident::new("__param0", Span::call_site()); @@ -47,9 +47,9 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { } = get_variant_constructors(reflect_enum, &ref_value, false); let (impl_generics, ty_generics, where_clause) = - reflect_enum.meta().generics().split_for_impl(); + reflect_enum.meta().split_generics_for_impl(); TokenStream::from(quote! { - impl #impl_generics #bevy_reflect_path::FromReflect for #type_name #ty_generics #where_clause { + impl #impl_generics #bevy_reflect_path::FromReflect for #enum_path #ty_generics #where_clause { fn from_reflect(#ref_value: &dyn #bevy_reflect_path::Reflect) -> #FQOption { if let #bevy_reflect_path::ReflectRef::Enum(#ref_value) = #bevy_reflect_path::Reflect::reflect_ref(#ref_value) { match #bevy_reflect_path::Enum::variant_name(#ref_value) { @@ -77,7 +77,7 @@ impl MemberValuePair { fn impl_struct_internal(reflect_struct: &ReflectStruct, is_tuple: bool) -> TokenStream { let fqoption = FQOption.into_token_stream(); - let struct_name = reflect_struct.meta().type_name(); + let struct_path = reflect_struct.meta().path_to_type(); let generics = reflect_struct.meta().generics(); let bevy_reflect_path = reflect_struct.meta().bevy_reflect_path(); @@ -117,7 +117,7 @@ fn impl_struct_internal(reflect_struct: &ReflectStruct, is_tuple: bool) -> Token ) }; - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + let (impl_generics, ty_generics, where_clause) = reflect_struct.meta().split_generics_for_impl(); // Add FromReflect bound for each active field let mut where_from_reflect_clause = if where_clause.is_some() { @@ -132,7 +132,7 @@ fn impl_struct_internal(reflect_struct: &ReflectStruct, is_tuple: bool) -> Token }); TokenStream::from(quote! { - impl #impl_generics #bevy_reflect_path::FromReflect for #struct_name #ty_generics #where_from_reflect_clause + impl #impl_generics #bevy_reflect_path::FromReflect for #struct_path #ty_generics #where_from_reflect_clause { fn from_reflect(reflect: &dyn #bevy_reflect_path::Reflect) -> #FQOption { if let #bevy_reflect_path::ReflectRef::#ref_struct_type(#ref_struct) = #bevy_reflect_path::Reflect::reflect_ref(reflect) { 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 666283615d985..c845d55ee4db8 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs @@ -10,7 +10,7 @@ use syn::Fields; pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { let bevy_reflect_path = reflect_enum.meta().bevy_reflect_path(); - let enum_name = reflect_enum.meta().type_name(); + let enum_path = reflect_enum.meta().path_to_type(); let ref_name = Ident::new("__name_param", Span::call_site()); let ref_index = Ident::new("__index_param", Span::call_site()); @@ -59,7 +59,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { } }); - let string_name = enum_name.to_string(); + let string_name = enum_path.name().to_string(); #[cfg(feature = "documentation")] let info_generator = { @@ -77,22 +77,20 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { }; let typed_impl = impl_typed( - enum_name, - reflect_enum.meta().generics(), + reflect_enum.meta(), &where_clause_options, quote! { let variants = [#(#variant_info),*]; let info = #info_generator; #bevy_reflect_path::TypeInfo::Enum(info) }, - bevy_reflect_path, ); let get_type_registration_impl = reflect_enum .meta() .get_type_registration(&where_clause_options); let (impl_generics, ty_generics, where_clause) = - reflect_enum.meta().generics().split_for_impl(); + reflect_enum.meta().split_generics_for_impl(); let where_reflect_clause = extend_where_clause(where_clause, &where_clause_options); @@ -101,7 +99,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { #typed_impl - impl #impl_generics #bevy_reflect_path::Enum for #enum_name #ty_generics #where_reflect_clause { + impl #impl_generics #bevy_reflect_path::Enum for #enum_path #ty_generics #where_reflect_clause { fn field(&self, #ref_name: &str) -> #FQOption<&dyn #bevy_reflect_path::Reflect> { match self { #(#enum_field,)* @@ -185,7 +183,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { } } - impl #impl_generics #bevy_reflect_path::Reflect for #enum_name #ty_generics #where_reflect_clause { + 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::() diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/impls/mod.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/mod.rs index 19523fbf806ba..21630f69bad04 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/mod.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/mod.rs @@ -8,4 +8,5 @@ pub(crate) use enums::impl_enum; pub(crate) use structs::impl_struct; pub(crate) use tuple_structs::impl_tuple_struct; pub(crate) use typed::impl_typed; -pub(crate) use values::impl_value; +pub(crate) use typed::impl_with_path; +pub(crate) use values::impl_value; \ No newline at end of file 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 6dd4e983c93c6..472465da85862 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs @@ -11,7 +11,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { let fqoption = FQOption.into_token_stream(); let bevy_reflect_path = reflect_struct.meta().bevy_reflect_path(); - let struct_name = reflect_struct.meta().type_name(); + let struct_path = reflect_struct.meta().path_to_type(); let field_names = reflect_struct .active_fields() @@ -72,7 +72,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { } }; - let string_name = struct_name.to_string(); + let string_name = struct_path.name().to_string(); #[cfg(feature = "documentation")] let info_generator = { @@ -91,20 +91,18 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { let where_clause_options = reflect_struct.where_clause_options(); let typed_impl = impl_typed( - struct_name, - reflect_struct.meta().generics(), + reflect_struct.meta(), &where_clause_options, quote! { let fields = [#field_generator]; let info = #info_generator; #bevy_reflect_path::TypeInfo::Struct(info) }, - bevy_reflect_path, ); let get_type_registration_impl = reflect_struct.get_type_registration(&where_clause_options); let (impl_generics, ty_generics, where_clause) = - reflect_struct.meta().generics().split_for_impl(); + reflect_struct.meta().split_generics_for_impl(); let where_reflect_clause = extend_where_clause(where_clause, &where_clause_options); @@ -113,7 +111,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { #typed_impl - impl #impl_generics #bevy_reflect_path::Struct for #struct_name #ty_generics #where_reflect_clause { + impl #impl_generics #bevy_reflect_path::Struct for #struct_path #ty_generics #where_reflect_clause { fn field(&self, name: &str) -> #FQOption<&dyn #bevy_reflect_path::Reflect> { match name { #(#field_names => #fqoption::Some(&self.#field_idents),)* @@ -165,7 +163,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { } } - impl #impl_generics #bevy_reflect_path::Reflect for #struct_name #ty_generics #where_reflect_clause { + 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::() 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 c41c53b86ef55..5a74c91ce2f9d 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 @@ -11,7 +11,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { let fqoption = FQOption.into_token_stream(); let bevy_reflect_path = reflect_struct.meta().bevy_reflect_path(); - let struct_name = reflect_struct.meta().type_name(); + let struct_path = reflect_struct.meta().path_to_type(); let field_idents = reflect_struct .active_fields() @@ -58,7 +58,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { } }; - let string_name = struct_name.to_string(); + let string_name = struct_path.name().to_string(); #[cfg(feature = "documentation")] let info_generator = { @@ -76,19 +76,17 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { }; let typed_impl = impl_typed( - struct_name, - reflect_struct.meta().generics(), + reflect_struct.meta(), &where_clause_options, quote! { let fields = [#field_generator]; let info = #info_generator; #bevy_reflect_path::TypeInfo::TupleStruct(info) }, - bevy_reflect_path, ); let (impl_generics, ty_generics, where_clause) = - reflect_struct.meta().generics().split_for_impl(); + reflect_struct.meta().split_generics_for_impl(); let where_reflect_clause = extend_where_clause(where_clause, &where_clause_options); @@ -97,7 +95,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { #typed_impl - impl #impl_generics #bevy_reflect_path::TupleStruct for #struct_name #ty_generics #where_reflect_clause { + impl #impl_generics #bevy_reflect_path::TupleStruct for #struct_path #ty_generics #where_reflect_clause { fn field(&self, index: usize) -> #FQOption<&dyn #bevy_reflect_path::Reflect> { match index { #(#field_indices => #fqoption::Some(&self.#field_idents),)* @@ -128,7 +126,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { } } - impl #impl_generics #bevy_reflect_path::Reflect for #struct_name #ty_generics #where_reflect_clause { + 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::() 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 e0b88c92e44d4..60e0eb8426933 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -1,43 +1,92 @@ + use crate::utility::{extend_where_clause, WhereClauseOptions}; +use crate::ReflectMeta; use proc_macro2::Ident; use quote::quote; -use syn::{Generics, Path}; +use syn::spanned::Spanned; -#[allow(clippy::too_many_arguments)] -pub(crate) fn impl_typed( - type_name: &Ident, - generics: &Generics, - where_clause_options: &WhereClauseOptions, +fn static_typed_cell( + meta: &ReflectMeta, + property: TypedProperty, generator: proc_macro2::TokenStream, - bevy_reflect_path: &Path, ) -> proc_macro2::TokenStream { - let is_generic = !generics.params.is_empty(); + let bevy_reflect_path = meta.bevy_reflect_path(); + if meta.impl_is_generic() { + let cell_type = match property { + TypedProperty::TypePath => quote!(GenericTypePathCell), + TypedProperty::TypeInfo => quote!(GenericTypeInfoCell), + }; - let static_generator = if is_generic { quote! { - static CELL: #bevy_reflect_path::utility::GenericTypeInfoCell = #bevy_reflect_path::utility::GenericTypeInfoCell::new(); + static CELL: #bevy_reflect_path::utility::#cell_type = #bevy_reflect_path::utility::#cell_type::new(); CELL.get_or_insert::(|| { #generator }) } } else { + let cell_type = match property { + TypedProperty::TypePath => quote!(NonGenericTypePathCell), + TypedProperty::TypeInfo => quote!(NonGenericTypeInfoCell), + }; + quote! { - static CELL: #bevy_reflect_path::utility::NonGenericTypeInfoCell = #bevy_reflect_path::utility::NonGenericTypeInfoCell::new(); + static CELL: #bevy_reflect_path::utility::#cell_type = #bevy_reflect_path::utility::#cell_type::new(); CELL.get_or_set(|| { #generator }) } - }; + } +} - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); +#[derive(Clone, Copy)] +pub(crate) enum TypedProperty { + TypeInfo, + TypePath, +} + +pub(crate) fn impl_with_path(meta: &ReflectMeta) -> proc_macro2::TokenStream { + let path_to_type = meta.path_to_type(); + let bevy_reflect_path = meta.bevy_reflect_path(); + + let type_path_cell = + static_typed_cell(meta, TypedProperty::TypePath, type_path_generator(meta)); + + let (impl_generics, ty_generics, where_clause) = meta.split_generics_for_impl(); // Add Typed bound for each active field let where_reflect_clause = extend_where_clause(where_clause, where_clause_options); quote! { - impl #impl_generics #bevy_reflect_path::Typed for #type_name #ty_generics #where_reflect_clause { + impl #impl_generics #bevy_reflect_path::WithPath for #path_to_type #ty_generics #where_reflect_clause { + fn type_path() -> &'static #bevy_reflect_path::TypePath { + #type_path_cell + } + } + } +} + +pub(crate) fn impl_typed( + meta: &ReflectMeta, + where_clause_options: &WhereClauseOptions, + type_info_generator: proc_macro2::TokenStream, +) -> proc_macro2::TokenStream { + let path_to_type = meta.path_to_type(); + let bevy_reflect_path = meta.bevy_reflect_path(); + + let with_path_impl = impl_with_path(meta); + + let type_info_cell = static_typed_cell(meta, TypedProperty::TypeInfo, type_info_generator); + + let (impl_generics, ty_generics, where_clause) = meta.split_generics_for_impl(); + + let where_reflect_clause = extend_where_clause(where_clause, where_clause_options); + + quote! { + #with_path_impl + + impl #impl_generics #bevy_reflect_path::Typed for #path_to_type #ty_generics #where_reflect_clause { fn type_info() -> &'static #bevy_reflect_path::TypeInfo { - #static_generator + #type_info_cell } } } 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 4aa3aed418fb6..074c0d9be3e1e 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs @@ -8,7 +8,7 @@ use quote::quote; /// Implements `GetTypeRegistration` and `Reflect` for the given type data. pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { let bevy_reflect_path = meta.bevy_reflect_path(); - let type_name = meta.type_name(); + let path_to_type = meta.path_to_type(); let hash_fn = meta.traits().get_hash_impl(bevy_reflect_path); let partial_eq_fn = meta.traits().get_partial_eq_impl(bevy_reflect_path); @@ -24,14 +24,12 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { let where_clause_options = WhereClauseOptions::default(); let typed_impl = impl_typed( - type_name, - meta.generics(), + meta, &where_clause_options, quote! { let info = #bevy_reflect_path::ValueInfo::new::() #with_docs; #bevy_reflect_path::TypeInfo::Value(info) }, - bevy_reflect_path, ); let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl(); @@ -42,7 +40,7 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { #typed_impl - impl #impl_generics #bevy_reflect_path::Reflect for #type_name #ty_generics #where_clause { + impl #impl_generics #bevy_reflect_path::Reflect for #path_to_type #ty_generics #where_clause { #[inline] fn type_name(&self) -> &str { ::core::any::type_name::() diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs index eb486d86baa31..bfba7d90fcc72 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs @@ -24,22 +24,27 @@ mod fq_std; mod from_reflect; mod impls; mod reflect_value; +mod with_path; mod registration; mod trait_reflection; mod type_uuid; mod utility; use crate::derive_data::{ReflectDerive, ReflectMeta, ReflectStruct}; +use container_attributes::ReflectTraits; +use derive_data::{type_path_generator, PathToType}; use proc_macro::TokenStream; use quote::quote; use reflect_value::ReflectValueDef; use syn::spanned::Spanned; use syn::{parse_macro_input, DeriveInput}; +use with_path::WithPathDef; pub(crate) static REFLECT_ATTRIBUTE_NAME: &str = "reflect"; pub(crate) static REFLECT_VALUE_ATTRIBUTE_NAME: &str = "reflect_value"; +pub(crate) static TYPE_PATH_ATTRIBUTE_NAME: &str = "type_path"; -#[proc_macro_derive(Reflect, attributes(reflect, reflect_value, module))] +#[proc_macro_derive(Reflect, attributes(reflect, reflect_value, type_path, module))] pub fn derive_reflect(input: TokenStream) -> TokenStream { let ast = parse_macro_input!(input as DeriveInput); @@ -84,6 +89,17 @@ pub fn derive_from_reflect(input: TokenStream) -> TokenStream { } } +#[proc_macro_derive(WithPath, attributes(type_path))] +pub fn derive_with_path(input: TokenStream) -> TokenStream { + let ast = parse_macro_input!(input as DeriveInput); + let derive_data = match ReflectDerive::from_input(&ast) { + Ok(data) => data, + Err(err) => return err.into_compile_error().into(), + }; + + impls::impl_with_path(derive_data.meta()).into() +} + // From https://github.com/randomPoison/type-uuid #[proc_macro_derive(TypeUuid, attributes(uuid))] pub fn derive_type_uuid(input: TokenStream) -> TokenStream { @@ -98,11 +114,14 @@ pub fn reflect_trait(args: TokenStream, input: TokenStream) -> TokenStream { #[proc_macro] pub fn impl_reflect_value(input: TokenStream) -> TokenStream { let def = parse_macro_input!(input as ReflectValueDef); - let meta = ReflectMeta::new( - &def.type_name, - &def.generics, - def.traits.unwrap_or_default(), - ); + + let path_to_type = if def.type_path.leading_colon.is_some() { + PathToType::External(&def.type_path) + } else { + PathToType::Primtive(&def.type_path.segments.first().unwrap().ident) + }; + + let meta = ReflectMeta::new(path_to_type, &def.generics, def.traits.unwrap_or_default()); #[cfg(feature = "documentation")] let meta = meta.with_docs(documentation::Documentation::from_attributes(&def.attrs)); @@ -179,9 +198,43 @@ pub fn impl_reflect_struct(input: TokenStream) -> TokenStream { #[proc_macro] pub fn impl_from_reflect_value(input: TokenStream) -> TokenStream { let def = parse_macro_input!(input as ReflectValueDef); + let path_to_type = if def.type_path.leading_colon.is_some() { + PathToType::External(&def.type_path) + } else { + PathToType::Primtive(&def.type_path.segments.first().unwrap().ident) + }; + from_reflect::impl_value(&ReflectMeta::new( - &def.type_name, + path_to_type, &def.generics, def.traits.unwrap_or_default(), )) } + +#[proc_macro] +pub fn impl_with_path(input: TokenStream) -> TokenStream { + let def = parse_macro_input!(input as WithPathDef); + + let (path_to_type, generics) = match def { + WithPathDef::External { ref path, ref generics } => (PathToType::External(path), generics), + WithPathDef::AliasedAnonymous { alias, ty, ref generics } => (PathToType::AliasedAnonymous { ty, alias }, generics), + WithPathDef::AliasedNamed { alias, ty, ref generics } => (PathToType::AliasedNamed { ty, alias }, generics), + }; + + impls::impl_with_path(&ReflectMeta::new( + path_to_type, + generics, + ReflectTraits::default(), + )).into() +} + +// #[proc_macro] +// pub fn type_path_for(input: TokenStream) -> TokenStream { +// let def = parse_macro_input!(input as ReflectValueDef); +// type_path_generator(&ReflectMeta::new( +// PathToType::External(&def.type_path), +// &def.generics, +// def.traits.unwrap_or_default(), +// )) +// .into() +// } diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs b/crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs index 0e71413758dd7..20aafc3bb91a3 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs @@ -1,27 +1,30 @@ use crate::container_attributes::ReflectTraits; use proc_macro2::Ident; use syn::parse::{Parse, ParseStream}; -use syn::token::{Paren, Where}; -use syn::{parenthesized, Attribute, Generics}; +use syn::punctuated::Punctuated; +use syn::token::{Colon2, Paren, Where}; +use syn::{parenthesized, Attribute, Generics, Path, PathSegment}; /// A struct used to define a simple reflected value type (such as primitives). /// +/// +/// /// This takes the form: /// /// ```ignore /// // Standard -/// foo(TraitA, TraitB) +/// ::my_crate::foo::Bar(TraitA, TraitB) /// /// // With generics -/// foo(TraitA, TraitB) +/// ::my_crate::foo::Bar(TraitA, TraitB) /// /// // With generics and where clause -/// foo where T1: Bar (TraitA, TraitB) +/// ::my_crate::foo::Bar where T1: Bar (TraitA, TraitB) /// ``` pub(crate) struct ReflectValueDef { #[allow(dead_code)] pub attrs: Vec, - pub type_name: Ident, + pub type_path: Path, pub generics: Generics, pub traits: Option, } @@ -29,7 +32,21 @@ pub(crate) struct ReflectValueDef { impl Parse for ReflectValueDef { fn parse(input: ParseStream) -> syn::Result { let attrs = input.call(Attribute::parse_outer)?; - let type_ident = input.parse::()?; + let type_path = { + let lookahead = input.lookahead1(); + if lookahead.peek(Colon2) { + // This parses `::foo::Foo` from `::foo::Foo` (leaving the generics). + Path::parse_mod_style(input)? + } else { + let ident = input.parse::()?; + let mut segments = Punctuated::new(); + segments.push(PathSegment::from(ident)); + Path { + leading_colon: None, + segments, + } + } + }; let generics = input.parse::()?; let mut lookahead = input.lookahead1(); let mut where_clause = None; @@ -47,7 +64,7 @@ impl Parse for ReflectValueDef { Ok(ReflectValueDef { attrs, - type_name: type_ident, + type_path, generics: Generics { where_clause, ..generics diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/registration.rs b/crates/bevy_reflect/bevy_reflect_derive/src/registration.rs index 256fd82c55886..62df8e3b5a5a3 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/registration.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/registration.rs @@ -6,17 +6,19 @@ use proc_macro2::Ident; use quote::quote; use syn::{Generics, Path}; +use crate::derive_data::{PathToType, ReflectMeta}; + /// Creates the `GetTypeRegistration` impl for the given type data. #[allow(clippy::too_many_arguments)] pub(crate) fn impl_get_type_registration( - type_name: &Ident, - bevy_reflect_path: &Path, - registration_data: &[Ident], - generics: &Generics, + meta: &ReflectMeta, where_clause_options: &WhereClauseOptions, serialization_denylist: Option<&BitSet>, ) -> proc_macro2::TokenStream { - let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + let path_to_type = meta.path_to_type(); + let bevy_reflect_path = meta.bevy_reflect_path(); + let registration_data = meta.traits().idents(); + let (impl_generics, ty_generics, where_clause) = meta.split_generics_for_impl(); let serialization_data = serialization_denylist.map(|denylist| { let denylist = denylist.into_iter(); quote! { @@ -29,12 +31,12 @@ pub(crate) fn impl_get_type_registration( quote! { #[allow(unused_mut)] - impl #impl_generics #bevy_reflect_path::GetTypeRegistration for #type_name #ty_generics #where_reflect_clause { + impl #impl_generics #bevy_reflect_path::GetTypeRegistration for #path_to_type #ty_generics #where_reflect_clause { fn get_type_registration() -> #bevy_reflect_path::TypeRegistration { - let mut registration = #bevy_reflect_path::TypeRegistration::of::<#type_name #ty_generics>(); - registration.insert::<#bevy_reflect_path::ReflectFromPtr>(#bevy_reflect_path::FromType::<#type_name #ty_generics>::from_type()); + let mut registration = #bevy_reflect_path::TypeRegistration::of::(); + registration.insert::<#bevy_reflect_path::ReflectFromPtr>(#bevy_reflect_path::FromType::::from_type()); #serialization_data - #(registration.insert::<#registration_data>(#bevy_reflect_path::FromType::<#type_name #ty_generics>::from_type());)* + #(registration.insert::<#registration_data>(#bevy_reflect_path::FromType::::from_type());)* registration } } diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/with_path.rs b/crates/bevy_reflect/bevy_reflect_derive/src/with_path.rs new file mode 100644 index 0000000000000..c683d3dbe0ec8 --- /dev/null +++ b/crates/bevy_reflect/bevy_reflect_derive/src/with_path.rs @@ -0,0 +1,197 @@ +use std::path; + +use quote::{quote, ToTokens, TokenStreamExt}; +use syn::{ + parse::{Parse, ParseStream}, + Generics, LitStr, Path, Token, Type, TypeArray, TypeParamBound, TypePath, Expr, +}; + +use crate::derive_data::ReflectMeta; + +pub enum WithPathDef { + External { + path: Path, + generics: Generics, + }, + AliasedNamed { + generics: Generics, + ty: Type, + alias: Path, + }, + AliasedAnonymous { + generics: Generics, + ty: Type, + alias: Type, + }, +} + +pub fn parse_path_leading_colon(input: ParseStream) -> syn::Result { + let leading = input.parse::()?; + + if input.peek(Token![::]) { + return Err(input.error("did not expect two leading double colons (`::::`)")); + } + + let mut path = Path::parse_mod_style(input)?; + path.leading_colon = Some(leading); + Ok(path) +} + +pub fn parse_path_no_leading_colon(input: ParseStream) -> syn::Result { + if input.peek(Token![::]) { + return Err(input.error("did not expect a leading double colon (`::`)")); + } + + Path::parse_mod_style(input) +} + +impl Parse for WithPathDef { + fn parse(input: ParseStream) -> syn::Result { + let (generics, ty) = if input.peek(Token![::]) { + let path = parse_path_leading_colon(input)?; + let mut generics = input.parse::()?; + generics.where_clause = input.parse()?; + + if !input.peek(Token![as]) { + return Ok(WithPathDef::External { path, generics }); + } + + ( + Generics::default(), + Type::Path(TypePath { qself: None, path }), + ) + } else { + let generics = input.parse()?; + let ty = input.parse()?; + (generics, ty) + }; + + let _as_token: Token![as] = input.parse()?; + + let alias = parse_path_no_leading_colon(input)?; + + Ok(WithPathDef::AliasedNamed { + generics, + ty, + alias, + }) + } +} + +macro_rules! format_lit { + ($($arg:tt)*) => {{ + LitStr::new(&format!($($arg)*), proc_macro2::Span::call_site()).to_token_stream() + }} +} + +struct StrExprBuilder<'a> { + meta: &'a ReflectMeta<'a>, + stream: proc_macro2::TokenStream, +} + +impl<'a> StrExprBuilder<'a> { + pub fn new(meta: &'a ReflectMeta<'a>) -> Self { + Self { + meta, + stream: proc_macro2::TokenStream::new(), + } + } + + pub fn append(&mut self, tokens: proc_macro2::TokenStream) { + if self.stream.is_empty() { + quote!((#tokens).to_owned()).to_tokens(&mut self.stream); + } else { + quote!(+ #tokens).to_tokens(&mut self.stream); + } + } + + pub fn append_owned(&mut self, tokens: proc_macro2::TokenStream) { + if self.stream.is_empty() { + quote!(#tokens).to_tokens(&mut self.stream); + } else { + quote!(+ &#tokens).to_tokens(&mut self.stream); + } + } +} + +trait ToAnonymousPath { + fn to_path_str(&self, path: &mut StrExprBuilder) -> syn::Result<()>; + fn to_short_path_str(&self, path: &mut StrExprBuilder) -> syn::Result<()>; +} + +impl ToAnonymousPath for Expr { + fn to_path_str(&self, path: &mut StrExprBuilder) -> syn::Result<()> { + path.append_owned(quote! { + ::std::string::ToString::to_string(#self) + }); + Ok(()) + } + + fn to_short_path_str(&self, path: &mut StrExprBuilder) -> syn::Result<()> { + self.to_path_str(path) + } +} + +impl ToAnonymousPath for Path { + fn to_path_str(&self, path: &mut StrExprBuilder) -> syn::Result<()> { + + path.append_owned(quote! { + ::std::string::ToString::to_string(#self) + }); + Ok(()) + } + + fn to_short_path_str(&self, path: &mut StrExprBuilder) -> syn::Result<()> { + self.to_path_str(path) + } +} + +fn type_to_path_str(ty: &Type, meta: &ReflectMeta) -> syn::Result { + fn path_to_path_str(path: &Path) -> syn::Result { + path.segments. + } + + let bevy_reflect_path = meta.bevy_reflect_path(); + + Ok(match ty { + Type::Array(array) => format_lit!( + "[{elem}; {len}]", + elem = type_to_path_str(&array.elem, meta)?, + len = array.len + ), + Type::BareFn(bare_fn) => type_to_path_str(ty, meta), + Type::Group(group) => type_to_path_str(&group.elem, meta)?, + Type::ImplTrait(_) => todo!(), + Type::Infer(_) => todo!(), + Type::Macro(_) => todo!(), + Type::Never(_) => quote!(!), + Type::Paren(paren) => type_to_path_str(&paren.elem, meta)?, + Type::Path(path) => quote! { + <#path as #bevy_reflect_path::WithPath>::type_path().path() + }, + Type::Ptr(ptr) => format_lit!( + "*{m} {t}", + m = ptr.mutability.map(|_| "mut").unwrap_or_else(|| "const"), + t = type_to_path_str(&ptr.elem, meta)?, + ), + Type::Reference(reference) => format_lit!( + "&{m}{t}", + m = reference.mutability.map(|_| "mut ").unwrap_or_default(), + t = type_to_path_str(&reference.elem, meta)?, + ), + Type::Slice(slice) => format_lit!("[{}]", type_to_path_str(&slice.elem, meta)?), + Type::TraitObject(trait_object) => { + let bounds: syn::Result = trait_object.bounds.iter().filter_map( + |bound| if let TypeParamBound::Trait(t) = bound { + Some(path_to_path_str(&t.path)) + } else { + None + } + ).collect(); + format_lit!("dyn {}", bounds?) + }, + Type::Tuple(_) => todo!(), + Type::Verbatim(_) => todo!(), + _ => todo!(), + }) +} diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index 438a135c040a3..8853026607a83 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -1,6 +1,9 @@ +use bevy_reflect_derive::impl_with_path; + use crate::{ - utility::NonGenericTypeInfoCell, DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, - TypeInfo, Typed, + self as bevy_reflect, + utility::{NonGenericTypeInfoCell, NonGenericTypePathCell}, DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, + TypeInfo, Typed, TypePath, WithPath, }; use std::{ any::{Any, TypeId}, @@ -301,6 +304,8 @@ impl Typed for DynamicArray { } } +impl_with_path!(DynamicArray as bevy_reflect::DynamicArray); + /// An iterator over an [`Array`]. pub struct ArrayIter<'a> { pub(crate) array: &'a dyn Array, diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index fd3a8585b763f..9946fbfe0b31d 100644 --- a/crates/bevy_reflect/src/enums/dynamic_enum.rs +++ b/crates/bevy_reflect/src/enums/dynamic_enum.rs @@ -1,8 +1,11 @@ -use crate::utility::NonGenericTypeInfoCell; +use bevy_reflect_derive::impl_with_path; + +use crate::utility::{NonGenericTypeInfoCell, NonGenericTypePathCell}; use crate::{ + self as bevy_reflect, enum_debug, enum_hash, enum_partial_eq, DynamicInfo, DynamicStruct, DynamicTuple, Enum, Reflect, ReflectMut, ReflectOwned, ReflectRef, Struct, Tuple, TypeInfo, Typed, - VariantFieldIter, VariantType, + VariantFieldIter, VariantType, TypePath, WithPath, }; use std::any::Any; use std::fmt::Formatter; @@ -430,3 +433,5 @@ impl Typed for DynamicEnum { CELL.get_or_set(|| TypeInfo::Dynamic(DynamicInfo::new::())) } } + +impl_with_path!(DynamicEnum as bevy_reflect::DynamicEnum); diff --git a/crates/bevy_reflect/src/enums/mod.rs b/crates/bevy_reflect/src/enums/mod.rs index e8c32e73ef9c5..35716336aebb0 100644 --- a/crates/bevy_reflect/src/enums/mod.rs +++ b/crates/bevy_reflect/src/enums/mod.rs @@ -316,7 +316,7 @@ mod tests { #[test] fn enum_should_allow_generics() { #[derive(Reflect, Debug, PartialEq)] - enum TestEnum { + enum TestEnum { A, B(T), C { value: T }, diff --git a/crates/bevy_reflect/src/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index 4a4c64e4ff9dd..7004284dbad74 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -1,13 +1,16 @@ +use bevy_reflect_derive::impl_with_path; use smallvec::SmallVec; use std::any::Any; -use crate::utility::GenericTypeInfoCell; +use crate::utility::{GenericTypeInfoCell, GenericTypePathCell}; use crate::{ + self as bevy_reflect, Array, ArrayIter, FromReflect, FromType, GetTypeRegistration, List, ListInfo, Reflect, - ReflectFromPtr, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypeRegistration, Typed, + ReflectFromPtr, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypeRegistration, Typed, TypePath, + WithPath }; -impl Array for SmallVec +impl Array for SmallVec where T::Item: FromReflect, { @@ -45,7 +48,7 @@ where } } -impl List for SmallVec +impl List for SmallVec where T::Item: FromReflect, { @@ -82,7 +85,7 @@ where } } -impl Reflect for SmallVec +impl Reflect for SmallVec where T::Item: FromReflect, { @@ -148,7 +151,7 @@ where } } -impl Typed for SmallVec +impl Typed for SmallVec where T::Item: FromReflect, { @@ -158,7 +161,9 @@ where } } -impl FromReflect for SmallVec +impl_with_path!(::smallvec::SmallVec); + +impl FromReflect for SmallVec where T::Item: FromReflect, { @@ -175,7 +180,7 @@ where } } -impl GetTypeRegistration for SmallVec +impl GetTypeRegistration for SmallVec where T::Item: FromReflect, { diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 9b7bbf8ff77fa..79f5af3c90dad 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -1,14 +1,16 @@ use crate::std_traits::ReflectDefault; use crate::{self as bevy_reflect, ReflectFromPtr, ReflectOwned}; use crate::{ - map_apply, map_partial_eq, Array, ArrayInfo, ArrayIter, DynamicEnum, DynamicMap, Enum, - EnumInfo, FromReflect, FromType, GetTypeRegistration, List, ListInfo, Map, MapInfo, MapIter, - Reflect, ReflectDeserialize, ReflectMut, ReflectRef, ReflectSerialize, TupleVariantInfo, - TypeInfo, TypeRegistration, Typed, UnitVariantInfo, UnnamedField, ValueInfo, VariantFieldIter, - VariantInfo, VariantType, + map_apply, map_partial_eq, Array, ArrayInfo, ArrayIter, DynamicEnum, DynamicMap, + Enum, EnumInfo, FromReflect, FromType, GetTypeRegistration, List, ListInfo, Map, MapInfo, + MapIter, Reflect, ReflectDeserialize, ReflectMut, ReflectRef, ReflectSerialize, + TupleVariantInfo, TypeInfo, TypePath, TypeRegistration, Typed, UnitVariantInfo, UnnamedField, + ValueInfo, VariantFieldIter, VariantInfo, VariantType, WithPath, impl_with_path, }; -use crate::utility::{GenericTypeInfoCell, NonGenericTypeInfoCell}; +use crate::utility::{ + GenericTypeInfoCell, GenericTypePathCell, NonGenericTypeInfoCell, NonGenericTypePathCell, +}; use bevy_reflect_derive::{impl_from_reflect_value, impl_reflect_value}; use bevy_utils::{Duration, Instant}; use bevy_utils::{HashMap, HashSet}; @@ -100,13 +102,13 @@ impl_reflect_value!(PathBuf( Deserialize, Default )); -impl_reflect_value!(Result()); -impl_reflect_value!(HashSet()); -impl_reflect_value!(Range()); -impl_reflect_value!(RangeInclusive()); -impl_reflect_value!(RangeFrom()); -impl_reflect_value!(RangeTo()); -impl_reflect_value!(RangeToInclusive()); +impl_reflect_value!(Result()); +impl_reflect_value!(HashSet()); +impl_reflect_value!(Range()); +impl_reflect_value!(RangeInclusive()); +impl_reflect_value!(RangeFrom()); +impl_reflect_value!(RangeTo()); +impl_reflect_value!(RangeToInclusive()); impl_reflect_value!(RangeFull()); impl_reflect_value!(Duration( Debug, @@ -156,12 +158,12 @@ impl_from_reflect_value!(f64); impl_from_reflect_value!(String); impl_from_reflect_value!(PathBuf); impl_from_reflect_value!(OsString); -impl_from_reflect_value!(HashSet); -impl_from_reflect_value!(Range); -impl_from_reflect_value!(RangeInclusive); -impl_from_reflect_value!(RangeFrom); -impl_from_reflect_value!(RangeTo); -impl_from_reflect_value!(RangeToInclusive); +impl_from_reflect_value!(HashSet); +impl_from_reflect_value!(Range); +impl_from_reflect_value!(RangeInclusive); +impl_from_reflect_value!(RangeFrom); +impl_from_reflect_value!(RangeTo); +impl_from_reflect_value!(RangeToInclusive); impl_from_reflect_value!(RangeFull); impl_from_reflect_value!(Duration); impl_from_reflect_value!(Instant); @@ -179,8 +181,8 @@ impl_from_reflect_value!(NonZeroU8); impl_from_reflect_value!(NonZeroI8); macro_rules! impl_reflect_for_veclike { - ($ty:ty, $insert:expr, $remove:expr, $push:expr, $pop:expr, $sub:ty) => { - impl Array for $ty { + ($ty:path, $insert:expr, $remove:expr, $push:expr, $pop:expr, $sub:ty) => { + impl Array for $ty { #[inline] fn get(&self, index: usize) -> Option<&dyn Reflect> { <$sub>::get(self, index).map(|value| value as &dyn Reflect) @@ -212,7 +214,7 @@ macro_rules! impl_reflect_for_veclike { } } - impl List for $ty { + impl List for $ty { fn insert(&mut self, index: usize, value: Box) { let value = value.take::().unwrap_or_else(|value| { T::from_reflect(&*value).unwrap_or_else(|| { @@ -244,7 +246,7 @@ macro_rules! impl_reflect_for_veclike { } } - impl Reflect for $ty { + impl Reflect for $ty { fn type_name(&self) -> &str { std::any::type_name::() } @@ -311,22 +313,24 @@ macro_rules! impl_reflect_for_veclike { } } - impl Typed for $ty { + impl Typed for $ty { fn type_info() -> &'static TypeInfo { static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); CELL.get_or_insert::(|| TypeInfo::List(ListInfo::new::())) - } + } } + + impl_with_path!($ty where T: FromReflect + WithPath); - impl GetTypeRegistration for $ty { + impl GetTypeRegistration for $ty { fn get_type_registration() -> TypeRegistration { - let mut registration = TypeRegistration::of::>(); - registration.insert::(FromType::>::from_type()); + let mut registration = TypeRegistration::of::<$ty>(); + registration.insert::(FromType::<$ty>::from_type()); registration } } - impl FromReflect for $ty { + impl FromReflect for $ty { fn from_reflect(reflect: &dyn Reflect) -> Option { if let ReflectRef::List(ref_list) = reflect.reflect_ref() { let mut new_list = Self::with_capacity(ref_list.len()); @@ -342,9 +346,16 @@ macro_rules! impl_reflect_for_veclike { }; } -impl_reflect_for_veclike!(Vec, Vec::insert, Vec::remove, Vec::push, Vec::pop, [T]); impl_reflect_for_veclike!( - VecDeque, + ::alloc::vec::Vec, + Vec::insert, + Vec::remove, + Vec::push, + Vec::pop, + [T] +); +impl_reflect_for_veclike!( + ::alloc::collections::VecDeque, VecDeque::insert, VecDeque::remove, VecDeque::push_back, @@ -352,7 +363,7 @@ impl_reflect_for_veclike!( VecDeque:: ); -impl Map for HashMap { +impl Map for HashMap { fn get(&self, key: &dyn Reflect) -> Option<&dyn Reflect> { key.downcast_ref::() .and_then(|key| HashMap::get(self, key)) @@ -435,7 +446,7 @@ impl Map for HashMap { } } -impl Reflect for HashMap { +impl Reflect for HashMap { fn type_name(&self) -> &str { std::any::type_name::() } @@ -499,17 +510,19 @@ impl Reflect for HashMap { } } -impl Typed for HashMap { +impl Typed for HashMap { fn type_info() -> &'static TypeInfo { static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); CELL.get_or_insert::(|| TypeInfo::Map(MapInfo::new::())) } } +impl_with_path!( HashMap as hashbrown::HashMap); + impl GetTypeRegistration for HashMap where - K: FromReflect + Eq + Hash, - V: FromReflect, + K: FromReflect + WithPath + Eq + Hash, + V: FromReflect + WithPath, { fn get_type_registration() -> TypeRegistration { let mut registration = TypeRegistration::of::>(); @@ -518,7 +531,7 @@ where } } -impl FromReflect for HashMap { +impl FromReflect for HashMap { fn from_reflect(reflect: &dyn Reflect) -> Option { if let ReflectRef::Map(ref_map) = reflect.reflect_ref() { let mut new_map = Self::with_capacity(ref_map.len()); @@ -534,7 +547,7 @@ impl FromReflect for HashMap { } } -impl Array for [T; N] { +impl Array for [T; N] { #[inline] fn get(&self, index: usize) -> Option<&dyn Reflect> { <[T]>::get(self, index).map(|value| value as &dyn Reflect) @@ -566,7 +579,7 @@ impl Array for [T; N] { } } -impl Reflect for [T; N] { +impl Reflect for [T; N] { #[inline] fn type_name(&self) -> &str { std::any::type_name::() @@ -648,7 +661,7 @@ impl Reflect for [T; N] { } } -impl FromReflect for [T; N] { +impl FromReflect for [T; N] { fn from_reflect(reflect: &dyn Reflect) -> Option { if let ReflectRef::Array(ref_array) = reflect.reflect_ref() { let mut temp_vec = Vec::with_capacity(ref_array.len()); @@ -662,13 +675,25 @@ impl FromReflect for [T; N] { } } -impl Typed for [T; N] { +impl Typed for [T; N] { fn type_info() -> &'static TypeInfo { static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); CELL.get_or_insert::(|| TypeInfo::Array(ArrayInfo::new::(N))) } } +impl WithPath for [T; N] { + fn type_path() -> &'static TypePath { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| { + TypePath::new_anonymous( + format!("[{name}; {N}]", name = T::type_path().path()), + format!("[{name}; {N}]", name = T::type_path().short_path()), + ) + }) + } +} + // TODO: // `FromType::from_type` requires `Deserialize<'de>` to be implemented for `T`. // Currently serde only supports `Deserialize<'de>` for arrays up to size 32. @@ -677,7 +702,7 @@ impl Typed for [T; N] { macro_rules! impl_array_get_type_registration { ($($N:expr)+) => { $( - impl GetTypeRegistration for [T; $N] { + impl GetTypeRegistration for [T; $N] { fn get_type_registration() -> TypeRegistration { TypeRegistration::of::<[T; $N]>() } @@ -693,13 +718,13 @@ impl_array_get_type_registration! { 30 31 32 } -impl GetTypeRegistration for Option { +impl GetTypeRegistration for Option { fn get_type_registration() -> TypeRegistration { TypeRegistration::of::>() } } -impl Enum for Option { +impl Enum for Option { fn field(&self, _name: &str) -> Option<&dyn Reflect> { None } @@ -770,7 +795,7 @@ impl Enum for Option { } } -impl Reflect for Option { +impl Reflect for Option { #[inline] fn type_name(&self) -> &str { std::any::type_name::() @@ -884,7 +909,7 @@ impl Reflect for Option { } } -impl FromReflect for Option { +impl FromReflect for Option { fn from_reflect(reflect: &dyn Reflect) -> Option { if let ReflectRef::Enum(dyn_enum) = reflect.reflect_ref() { match dyn_enum.variant_name() { @@ -922,7 +947,7 @@ impl FromReflect for Option { } } -impl Typed for Option { +impl Typed for Option { fn type_info() -> &'static TypeInfo { static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); CELL.get_or_insert::(|| { @@ -937,6 +962,8 @@ impl Typed for Option { } } +impl_with_path!(::core::option::Option); + impl Reflect for Cow<'static, str> { fn type_name(&self) -> &str { std::any::type_name::() @@ -1024,6 +1051,12 @@ impl Typed for Cow<'static, str> { } } +impl WithPath for Cow<'static, str> { + fn type_path() -> &'static TypePath { + todo!() + } +} + impl GetTypeRegistration for Cow<'static, str> { fn get_type_registration() -> TypeRegistration { let mut registration = TypeRegistration::of::>(); @@ -1132,6 +1165,10 @@ impl Typed for &'static Path { } } +impl_with_path!(&'static ::std::path::Path); + +impl + impl GetTypeRegistration for &'static Path { fn get_type_registration() -> TypeRegistration { let mut registration = TypeRegistration::of::(); @@ -1362,5 +1399,4 @@ mod tests { let path = Path::new("hello_world.rs"); let output = <&'static Path as FromReflect>::from_reflect(&path).unwrap(); assert_eq!(path, output); - } -} + \ No newline at end of file diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index d0bf81058442e..1a6eefb6839d8 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -11,6 +11,7 @@ mod struct_trait; mod tuple; mod tuple_struct; mod type_info; +mod type_path; mod type_registry; mod type_uuid; mod impls { @@ -58,12 +59,15 @@ pub use struct_trait::*; pub use tuple::*; pub use tuple_struct::*; pub use type_info::*; +pub use type_path::*; pub use type_registry::*; pub use type_uuid::*; pub use bevy_reflect_derive::*; pub use erased_serde; +extern crate alloc; + #[doc(hidden)] pub mod __macro_exports { use crate::Uuid; @@ -105,7 +109,7 @@ mod tests { ser::{to_string_pretty, PrettyConfig}, Deserializer, }; - use std::any::TypeId; + use std::{any::TypeId, marker::PhantomData}; use std::fmt::{Debug, Formatter}; use super::prelude::*; @@ -646,6 +650,42 @@ mod tests { std::any::type_name::() ); } + + #[test] + fn reflect_type_path() { + #[derive(WithPath)] + struct A; + + #[derive(WithPath)] + #[type_path = "my_alias::B"] + struct B; + + #[derive(WithPath)] + struct C(PhantomData); + + #[derive(WithPath)] + #[type_path = "my_alias::D"] + struct D(PhantomData); + + struct E; + impl_with_path!(E); + + struct F; + impl_with_path!(F as my_alias::F); + + struct G(PhantomData); + impl_with_path!(G); + + struct H(PhantomData); + impl_with_path!(H as my_alias::H); + + A::type_path(); + B::type_path(); + C::::type_path(); + D::::type_path(); + E::::type_path(); + F::::type_path(); + } #[test] fn reflect_type_info() { @@ -700,7 +740,7 @@ mod tests { // Struct (generic) #[derive(Reflect)] - struct MyGenericStruct { + struct MyGenericStruct { foo: T, bar: usize, } diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index 2d67a62f24140..e86d080c766c1 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -1,10 +1,13 @@ use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; -use crate::utility::NonGenericTypeInfoCell; +use bevy_reflect_derive::type_path_for; + +use crate::utility::{NonGenericTypeInfoCell, NonGenericTypePathCell}; use crate::{ + self as bevy_reflect, Array, ArrayIter, DynamicArray, DynamicInfo, FromReflect, Reflect, ReflectMut, ReflectOwned, - ReflectRef, TypeInfo, Typed, + ReflectRef, TypeInfo, Typed, TypePath, WithPath, }; /// An ordered, mutable list of [Reflect] items. This corresponds to types like [`std::vec::Vec`]. @@ -326,6 +329,13 @@ impl Typed for DynamicList { CELL.get_or_set(|| TypeInfo::Dynamic(DynamicInfo::new::())) } } + +impl WithPath for DynamicList { + fn type_path() -> &'static TypePath { + static CELL: NonGenericTypePathCell = NonGenericTypePathCell::new(); + CELL.get_or_set(|| type_path_for!(::bevy_reflect::DynamicList)) + } +} impl IntoIterator for DynamicList { type Item = Box; diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index f5e4a8695f2a2..512617c7aa206 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -2,10 +2,14 @@ use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; use std::hash::Hash; +use bevy_reflect_derive::type_path_for; use bevy_utils::{Entry, HashMap}; -use crate::utility::NonGenericTypeInfoCell; -use crate::{DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed}; +use crate::utility::{NonGenericTypeInfoCell, NonGenericTypePathCell}; +use crate::{ + self as bevy_reflect, DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, + TypePath, Typed, +}; /// An ordered mapping between [`Reflect`] values. /// @@ -349,6 +353,11 @@ impl Typed for DynamicMap { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); CELL.get_or_set(|| TypeInfo::Dynamic(DynamicInfo::new::())) } + + fn type_path() -> &'static TypePath { + static CELL: NonGenericTypePathCell = NonGenericTypePathCell::new(); + CELL.get_or_set(|| type_path_for!(::bevy_reflect::DynamicMap)) + } } /// An iterator over the key-value pairs of a [`Map`]. diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index 3857d8f3cd84b..1970c921decd2 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -1,7 +1,7 @@ use crate::{ array_debug, enum_debug, list_debug, map_debug, serde::Serializable, struct_debug, tuple_debug, tuple_struct_debug, Array, Enum, List, Map, Struct, Tuple, TupleStruct, TypeInfo, Typed, - ValueInfo, + ValueInfo, TypePath, utility::{NonGenericTypePathCell}, }; use std::{ any::{self, Any, TypeId}, @@ -226,6 +226,11 @@ impl Typed for dyn Reflect { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); CELL.get_or_set(|| TypeInfo::Value(ValueInfo::new::())) } + + fn type_path() -> &'static TypePath { + static CELL: NonGenericTypePathCell = NonGenericTypePathCell::new(); + CELL.get_or_set(|| TypePath::new_anonymous("dyn bevy_reflect::Reflect".to_owned(), "dyn Reflect".to_owned())) + } } #[deny(rustdoc::broken_intra_doc_links)] diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index 4b8485cbb5b3e..e80c324d89121 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -1,7 +1,9 @@ -use crate::utility::NonGenericTypeInfoCell; +use crate::utility::{NonGenericTypeInfoCell, NonGenericTypePathCell}; use crate::{ - DynamicInfo, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, + self as bevy_reflect, + DynamicInfo, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, TypePath, WithPath, }; +use bevy_reflect_derive::{type_path_for, impl_with_path}; use bevy_utils::{Entry, HashMap}; use std::fmt::{Debug, Formatter}; use std::{ @@ -479,8 +481,15 @@ impl Typed for DynamicStruct { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); CELL.get_or_set(|| TypeInfo::Dynamic(DynamicInfo::new::())) } + + fn type_path() -> &'static TypePath { + static CELL: NonGenericTypePathCell = NonGenericTypePathCell::new(); + CELL.get_or_set(|| type_path_for!(::bevy_reflect::DynamicStruct)) + } } +impl_with_path!(::bevy_reflect::DynamicStruct); + /// Compares a [`Struct`] with a [`Reflect`] value. /// /// Returns true if and only if all of the following are true: diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index cebabaf3ffc9d..091c9d137801b 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -1,7 +1,9 @@ -use crate::utility::NonGenericTypeInfoCell; +use bevy_reflect_derive::type_path_for; + +use crate::utility::{GenericTypePathCell, NonGenericTypeInfoCell, NonGenericTypePathCell}; use crate::{ - DynamicInfo, FromReflect, GetTypeRegistration, Reflect, ReflectMut, ReflectOwned, ReflectRef, - TypeInfo, TypeRegistration, Typed, UnnamedField, + self as bevy_reflect, DynamicInfo, FromReflect, GetTypeRegistration, Reflect, ReflectMut, + ReflectOwned, ReflectRef, TypeInfo, TypePath, TypeRegistration, Typed, UnnamedField, WithPath, }; use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; @@ -378,6 +380,13 @@ impl Typed for DynamicTuple { } } +impl WithPath for DynamicTuple { + fn type_path() -> &'static TypePath { + static CELL: NonGenericTypePathCell = NonGenericTypePathCell::new(); + CELL.get_or_set(|| type_path_for!(::bevy_reflect::DynamicTuple)) + } +} + /// Applies the elements of `b` to the corresponding elements of `a`. /// /// # Panics @@ -452,7 +461,7 @@ pub fn tuple_debug(dyn_tuple: &dyn Tuple, f: &mut std::fmt::Formatter<'_>) -> st macro_rules! impl_reflect_tuple { {$($index:tt : $name:tt),*} => { - impl<$($name: Reflect),*> Tuple for ($($name,)*) { + impl<$($name: Reflect + WithPath),*> Tuple for ($($name,)*) { #[inline] fn field(&self, index: usize) -> Option<&dyn Reflect> { match index { @@ -504,7 +513,7 @@ macro_rules! impl_reflect_tuple { } } - impl<$($name: Reflect),*> Reflect for ($($name,)*) { + impl<$($name: Reflect + WithPath),*> Reflect for ($($name,)*) { fn type_name(&self) -> &str { std::any::type_name::() } @@ -567,7 +576,7 @@ macro_rules! impl_reflect_tuple { } } - impl <$($name: Reflect),*> Typed for ($($name,)*) { + impl <$($name: Reflect + WithPath),*> Typed for ($($name,)*) { fn type_info() -> &'static TypeInfo { static CELL: $crate::utility::GenericTypeInfoCell = $crate::utility::GenericTypeInfoCell::new(); CELL.get_or_insert::(|| { @@ -579,14 +588,26 @@ macro_rules! impl_reflect_tuple { }) } } + + impl <$($name: Reflect + WithPath),*> WithPath for ($($name,)*) { + fn type_path() -> &'static TypePath { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| { + TypePath::new_anonymous( + "(".to_owned() $(+ <$name as WithPath>::type_path().path())* + ")", + "(".to_owned() $(+ <$name as WithPath>::type_path().short_path())* + ")", + ) + }) + } + } - impl<$($name: Reflect + Typed),*> GetTypeRegistration for ($($name,)*) { + impl<$($name: Reflect + WithPath),*> GetTypeRegistration for ($($name,)*) { fn get_type_registration() -> TypeRegistration { TypeRegistration::of::<($($name,)*)>() } } - impl<$($name: FromReflect),*> FromReflect for ($($name,)*) + impl<$($name: FromReflect + WithPath),*> FromReflect for ($($name,)*) { fn from_reflect(reflect: &dyn Reflect) -> Option { if let ReflectRef::Tuple(_ref_tuple) = reflect.reflect_ref() { diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index e8c52bdadddbd..cd03812c1742b 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -1,6 +1,9 @@ -use crate::utility::NonGenericTypeInfoCell; +use bevy_reflect_derive::type_path_for; + +use crate::utility::{NonGenericTypeInfoCell, NonGenericTypePathCell}; use crate::{ - DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, UnnamedField, + self as bevy_reflect, + DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, UnnamedField, TypePath, WithPath, }; use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; @@ -380,9 +383,11 @@ impl Typed for DynamicTupleStruct { fn type_info() -> &'static TypeInfo { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); CELL.get_or_set(|| TypeInfo::Dynamic(DynamicInfo::new::())) - } + } } +impl_with_path!(::bevy_reflect::DynamicTupleStruct); + /// Compares a [`TupleStruct`] with a [`Reflect`] value. /// /// Returns true if and only if all of the following are true: diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index 42e011c14915f..28c0e03ba498e 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -1,5 +1,5 @@ use crate::{ - ArrayInfo, EnumInfo, ListInfo, MapInfo, Reflect, StructInfo, TupleInfo, TupleStructInfo, + ArrayInfo, EnumInfo, ListInfo, MapInfo, Reflect, StructInfo, TupleInfo, TupleStructInfo, WithPath, }; use std::any::{Any, TypeId}; @@ -66,7 +66,7 @@ use std::any::{Any, TypeId}; /// ``` /// /// [utility]: crate::utility -pub trait Typed: Reflect { +pub trait Typed: WithPath + Reflect { /// Returns the compile-time [info] for the underlying type. /// /// [info]: TypeInfo @@ -276,4 +276,4 @@ impl DynamicInfo { pub fn docs(&self) -> Option<&'static str> { self.docs } -} +} \ No newline at end of file diff --git a/crates/bevy_reflect/src/type_path.rs b/crates/bevy_reflect/src/type_path.rs new file mode 100644 index 0000000000000..a49d777830013 --- /dev/null +++ b/crates/bevy_reflect/src/type_path.rs @@ -0,0 +1,72 @@ +pub trait WithPath { + /// Returns the [path] of the underlying type. + /// + /// [path]: TypePath + fn type_path() -> &'static TypePath; +} + +pub struct TypePath { + path: String, + short_path: String, + ident: Option, + crate_name: Option, + module_path: Option, +} + +impl TypePath { + pub fn new_primitive(name: String) -> Self { + Self { + path: name.clone(), + short_path: name.clone(), + ident: Some(name), + crate_name: None, + module_path: None, + + } + } + + pub fn new_anonymous(path: String, short_path: String) -> Self { + Self { + path, + short_path, + ident: None, + crate_name: None, + module_path: None, + } + } + + pub fn new_named(path: String, short_path: String, ident: String, crate_name: String, module_path: String) -> Self { + Self { + path, + short_path, + ident: Some(ident), + crate_name: Some(crate_name), + module_path: Some(module_path), + } + } + + #[inline] + pub fn path(&self) -> &str { + &self.path + } + + #[inline] + pub fn short_path(&self) -> &str { + &self.short_path + } + + #[inline] + pub fn ident(&self) -> Option<&str> { + self.ident.as_deref() + } + + #[inline] + pub fn crate_name(&self) -> Option<&str> { + self.crate_name.as_deref() + } + + #[inline] + pub fn module_path(&self) -> Option<&str> { + self.module_path.as_deref() + } +} \ No newline at end of file diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index 8474bcb6e8595..6df9df1eb6eb6 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -1,15 +1,28 @@ //! Helpers for working with Bevy reflection. -use crate::TypeInfo; +use crate::{TypeInfo, TypePath}; use bevy_utils::HashMap; use once_cell::race::OnceBox; use parking_lot::RwLock; use std::any::{Any, TypeId}; -/// A container for [`TypeInfo`] over non-generic types, allowing instances to be stored statically. +mod sealed { + use crate::{TypePath, TypeInfo}; + + trait Sealed {} + impl Sealed for TypeInfo {} + impl Sealed for TypePath {} + + pub trait TypedProperty: 'static {} + impl TypedProperty for T {} +} +pub use sealed::TypedProperty; + + +/// A container for [`TypeInfo`] or [`TypePath`] over non-generic types, allowing instances to be stored statically. /// /// This is specifically meant for use with _non_-generic types. If your type _is_ generic, -/// then use [`GenericTypeInfoCell`] instead. Otherwise, it will not take into account all +/// then use [`GenericTypedCell`] instead. Otherwise, it will not take into account all /// monomorphizations of your type. /// /// ## Example @@ -20,62 +33,76 @@ use std::any::{Any, TypeId}; /// use bevy_reflect::utility::NonGenericTypeInfoCell; /// /// struct Foo { -/// bar: i32 +/// bar: i32 /// } /// /// impl Typed for Foo { -/// fn type_info() -> &'static TypeInfo { -/// static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); -/// CELL.get_or_set(|| { -/// let fields = [NamedField::new::("bar")]; -/// let info = StructInfo::new::("Foo", &fields); -/// TypeInfo::Struct(info) -/// }) -/// } +/// fn type_info() -> &'static TypeInfo { +/// static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); +/// CELL.get_or_set(|| { +/// let fields = [NamedField::new::("bar")]; +/// let info = StructInfo::new::("Foo", &fields); +/// TypeInfo::Struct(info) +/// }) +/// } +/// +/// fn type_path() -> &'static TypePath { +/// static CELL: NonGenericTypePathCell = NonGenericTypePathCell::new(); +/// CELL.get_or_set(|| { +/// TypePath::new_named( +/// "my_crate::Foo".to_owned(), +/// "Foo".to_owned(), +/// "Foo".to_owned(), +/// "my_crate".to_owned(), +/// "my_crate".to_owned(), +/// ) +/// }) +/// } /// } /// # /// # impl Reflect for Foo { -/// # fn type_name(&self) -> &str { todo!() } -/// # fn get_type_info(&self) -> &'static TypeInfo { todo!() } -/// # fn into_any(self: Box) -> Box { todo!() } -/// # fn as_any(&self) -> &dyn Any { todo!() } -/// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() } -/// # fn into_reflect(self: Box) -> Box { todo!() } -/// # fn as_reflect(&self) -> &dyn Reflect { todo!() } -/// # fn as_reflect_mut(&mut self) -> &mut dyn Reflect { todo!() } -/// # fn apply(&mut self, value: &dyn Reflect) { todo!() } -/// # fn set(&mut self, value: Box) -> Result<(), Box> { todo!() } -/// # fn reflect_ref(&self) -> ReflectRef { todo!() } -/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() } -/// # fn reflect_owned(self: Box) -> ReflectOwned { todo!() } -/// # fn clone_value(&self) -> Box { todo!() } +/// # fn type_name(&self) -> &str { todo!() } +/// # fn get_type_info(&self) -> &'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!() } /// # } /// ``` -pub struct NonGenericTypeInfoCell(OnceBox); +pub struct NonGenericTypedCell(OnceBox); + +pub type NonGenericTypeInfoCell = NonGenericTypedCell; +pub type NonGenericTypePathCell = NonGenericTypedCell; -impl NonGenericTypeInfoCell { - /// Initialize a [`NonGenericTypeInfoCell`] for non-generic types. +impl NonGenericTypedCell { + /// Initialize a [`NonGenericTypedCell`] for non-generic types. pub const fn new() -> Self { Self(OnceBox::new()) } - /// Returns a reference to the [`TypeInfo`] stored in the cell. - /// - /// If there is no [`TypeInfo`] found, a new one will be generated from the given function. + /// Returns a reference to the [`TypeInfo`]/[`TypePath`] stored in the cell. /// - /// [`TypeInfos`]: TypeInfo - pub fn get_or_set(&self, f: F) -> &TypeInfo + /// If there is no entry found, a new one will be generated from the given function. + pub fn get_or_set(&self, f: F) -> &T where - F: FnOnce() -> TypeInfo, + F: FnOnce() -> T, { self.0.get_or_init(|| Box::new(f())) } } -/// A container for [`TypeInfo`] over generic types, allowing instances to be stored statically. +/// A container for [`TypeInfo`] or [`TypePath`] over generic types, allowing instances to be stored statically. /// /// This is specifically meant for use with generic types. If your type isn't generic, -/// then use [`NonGenericTypeInfoCell`] instead as it should be much more performant. +/// then use [`NonGenericTypedCell`] instead as it should be much more performant. /// /// ## Example /// @@ -87,51 +114,67 @@ impl NonGenericTypeInfoCell { /// struct Foo(T); /// /// 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); -/// TypeInfo::TupleStruct(info) -/// }) -/// } +/// 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); +/// TypeInfo::TupleStruct(info) +/// }) +/// } +/// +/// fn type_path() -> &'static TypePath { +/// static CELL: GenericTypePathCell = GenericTypePathCell::new(); +/// CELL.get_or_insert::(|| { +/// TypePath::new_named( +/// "my_crate::Foo::<".to_owned() + T::type_path().path() + ">", +/// "Foo<".to_owned() + T::type_path().short_path() + ">", +/// "Foo".to_owned(), +/// "my_crate".to_owned(), +/// "my_crate".to_owned(), +/// ) +/// }) +/// } /// } /// # /// # impl Reflect for Foo { -/// # fn type_name(&self) -> &str { todo!() } -/// # fn get_type_info(&self) -> &'static TypeInfo { todo!() } -/// # fn into_any(self: Box) -> Box { todo!() } -/// # fn as_any(&self) -> &dyn Any { todo!() } -/// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() } -/// # fn into_reflect(self: Box) -> Box { todo!() } -/// # fn as_reflect(&self) -> &dyn Reflect { todo!() } -/// # fn as_reflect_mut(&mut self) -> &mut dyn Reflect { todo!() } -/// # fn apply(&mut self, value: &dyn Reflect) { todo!() } -/// # fn set(&mut self, value: Box) -> Result<(), Box> { todo!() } -/// # fn reflect_ref(&self) -> ReflectRef { todo!() } -/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() } -/// # fn reflect_owned(self: Box) -> ReflectOwned { todo!() } -/// # fn clone_value(&self) -> Box { todo!() } +/// # fn type_name(&self) -> &str { todo!() } +/// # fn get_type_info(&self) -> &'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!() } /// # } /// ``` -pub struct GenericTypeInfoCell(OnceBox>>); +pub struct GenericTypedCell(OnceBox>>); + +pub type GenericTypeInfoCell = GenericTypedCell; +pub type GenericTypePathCell = GenericTypedCell; -impl GenericTypeInfoCell { - /// Initialize a [`GenericTypeInfoCell`] for generic types. +impl GenericTypedCell { + /// Initialize a [`GenericTypedCell`] for generic types. pub const fn new() -> Self { Self(OnceBox::new()) } - /// Returns a reference to the [`TypeInfo`] stored in the cell. + /// Returns a reference to the [`TypeInfo`]/[`TypePath`] stored in the cell. /// - /// This method will then return the correct [`TypeInfo`] reference for the given type `T`. - /// If there is no [`TypeInfo`] found, a new one will be generated from the given function. - pub fn get_or_insert(&self, f: F) -> &TypeInfo + /// This method will then return the correct [`TypeInfo`]/[`TypePath`] reference for the given type `T`. + /// If there is no entry found, a new one will be generated from the given function. + pub fn get_or_insert(&self, f: F) -> &T where - T: Any + ?Sized, - F: FnOnce() -> TypeInfo, + G: Any + ?Sized, + F: FnOnce() -> T, { - let type_id = TypeId::of::(); + let type_id = TypeId::of::(); // let mapping = self.0.get_or_init(|| Box::new(RwLock::default())); let mapping = self.0.get_or_init(Box::default); if let Some(info) = mapping.read().get(&type_id) { From 2beb8dee1880d62506b566ff37d907ee1b1e1660 Mon Sep 17 00:00:00 2001 From: radiish Date: Fri, 13 Jan 2023 17:57:20 +0000 Subject: [PATCH 02/52] compiles! --- crates/bevy_asset/src/asset_server.rs | 4 +- crates/bevy_asset/src/assets.rs | 2 +- crates/bevy_asset/src/loader.rs | 5 +- crates/bevy_audio/src/audio_output.rs | 4 +- crates/bevy_audio/src/audio_source.rs | 4 +- crates/bevy_gltf/src/lib.rs | 10 +- crates/bevy_input/src/input.rs | 12 +- crates/bevy_pbr/src/material.rs | 4 +- .../bevy_reflect_derive/src/derive_data.rs | 218 ++++++++++-------- .../bevy_reflect_derive/src/from_reflect.rs | 6 +- .../bevy_reflect_derive/src/impls/enums.rs | 4 +- .../bevy_reflect_derive/src/impls/mod.rs | 2 +- .../bevy_reflect_derive/src/impls/structs.rs | 4 +- .../src/impls/tuple_structs.rs | 4 +- .../bevy_reflect_derive/src/impls/typed.rs | 60 ++++- .../bevy_reflect_derive/src/impls/values.rs | 7 +- .../bevy_reflect_derive/src/lib.rs | 30 ++- .../bevy_reflect_derive/src/reflect_value.rs | 38 ++- .../bevy_reflect_derive/src/registration.rs | 2 +- .../bevy_reflect_derive/src/type_path.rs | 80 +++++++ .../bevy_reflect_derive/src/with_path.rs | 197 ---------------- crates/bevy_reflect/src/array.rs | 15 +- crates/bevy_reflect/src/enums/dynamic_enum.rs | 6 +- crates/bevy_reflect/src/enums/mod.rs | 2 +- crates/bevy_reflect/src/impls/smallvec.rs | 20 +- crates/bevy_reflect/src/impls/std.rs | 121 +++++----- crates/bevy_reflect/src/lib.rs | 36 +-- crates/bevy_reflect/src/list.rs | 15 +- crates/bevy_reflect/src/map.rs | 16 +- crates/bevy_reflect/src/reflect.rs | 18 +- crates/bevy_reflect/src/struct_trait.rs | 11 +- crates/bevy_reflect/src/tuple.rs | 46 ++-- crates/bevy_reflect/src/tuple_struct.rs | 8 +- crates/bevy_reflect/src/type_info.rs | 4 +- crates/bevy_reflect/src/type_path.rs | 88 ++----- crates/bevy_reflect/src/utility.rs | 169 +++++++++++++- crates/bevy_render/src/mesh/mesh/mod.rs | 4 +- crates/bevy_render/src/mesh/mesh/skinning.rs | 4 +- .../bevy_render/src/render_resource/shader.rs | 4 +- crates/bevy_scene/src/dynamic_scene.rs | 4 +- crates/bevy_scene/src/scene.rs | 4 +- crates/bevy_sprite/src/mesh2d/material.rs | 4 +- crates/bevy_text/src/font.rs | 4 +- crates/bevy_text/src/font_atlas_set.rs | 3 +- examples/3d/lines.rs | 4 +- examples/asset/custom_asset.rs | 4 +- examples/reflection/generic_reflection.rs | 4 +- examples/shader/animate_shader.rs | 4 +- examples/shader/array_texture.rs | 4 +- examples/shader/custom_vertex_attribute.rs | 4 +- examples/shader/post_processing.rs | 4 +- examples/shader/shader_defs.rs | 4 +- examples/shader/shader_material.rs | 4 +- examples/shader/shader_material_glsl.rs | 4 +- .../shader_material_screenspace_texture.rs | 4 +- 55 files changed, 687 insertions(+), 660 deletions(-) create mode 100644 crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs delete mode 100644 crates/bevy_reflect/bevy_reflect_derive/src/with_path.rs diff --git a/crates/bevy_asset/src/asset_server.rs b/crates/bevy_asset/src/asset_server.rs index 41c91fe7c7f4f..b9227ce3734a8 100644 --- a/crates/bevy_asset/src/asset_server.rs +++ b/crates/bevy_asset/src/asset_server.rs @@ -646,10 +646,10 @@ mod test { use crate::{loader::LoadedAsset, update_asset_storage_system}; use bevy_app::App; use bevy_ecs::prelude::*; - use bevy_reflect::TypeUuid; + use bevy_reflect::{TypeUuid, TypePath}; use bevy_utils::BoxedFuture; - #[derive(Debug, TypeUuid)] + #[derive(Debug, TypeUuid, TypePath)] #[uuid = "a5189b72-0572-4290-a2e0-96f73a491c44"] struct PngAsset; diff --git a/crates/bevy_asset/src/assets.rs b/crates/bevy_asset/src/assets.rs index 1a3a300553990..8a5b1a64e507d 100644 --- a/crates/bevy_asset/src/assets.rs +++ b/crates/bevy_asset/src/assets.rs @@ -489,7 +489,7 @@ mod tests { #[test] fn asset_overwriting() { - #[derive(bevy_reflect::TypeUuid)] + #[derive(bevy_reflect::TypeUuid, bevy_reflect::TypePath)] #[uuid = "44115972-f31b-46e5-be5c-2b9aece6a52f"] struct MyAsset; let mut app = App::new(); diff --git a/crates/bevy_asset/src/loader.rs b/crates/bevy_asset/src/loader.rs index 931efacb4c42a..cb8cab8838cba 100644 --- a/crates/bevy_asset/src/loader.rs +++ b/crates/bevy_asset/src/loader.rs @@ -5,6 +5,7 @@ use crate::{ use anyhow::Error; use anyhow::Result; use bevy_ecs::system::{Res, ResMut}; +use bevy_reflect::TypePath; use bevy_reflect::{TypeUuid, TypeUuidDynamic}; use bevy_utils::{BoxedFuture, HashMap}; use crossbeam_channel::{Receiver, Sender}; @@ -47,13 +48,13 @@ pub trait AssetLoader: Send + Sync + 'static { /// /// In order to load assets into your game you must either add them manually to an asset storage /// with [`Assets::add`] or load them from the filesystem with [`AssetServer::load`]. -pub trait Asset: TypeUuid + AssetDynamic {} +pub trait Asset: TypeUuid + TypePath + AssetDynamic {} /// An untyped version of the [`Asset`] trait. pub trait AssetDynamic: Downcast + TypeUuidDynamic + Send + Sync + 'static {} impl_downcast!(AssetDynamic); -impl Asset for T where T: TypeUuid + AssetDynamic + TypeUuidDynamic {} +impl Asset for T where T: TypeUuid + TypePath + AssetDynamic + TypeUuidDynamic {} impl AssetDynamic for T where T: Send + Sync + 'static + TypeUuidDynamic {} diff --git a/crates/bevy_audio/src/audio_output.rs b/crates/bevy_audio/src/audio_output.rs index 31ee5f503adc3..5676a437b5b33 100644 --- a/crates/bevy_audio/src/audio_output.rs +++ b/crates/bevy_audio/src/audio_output.rs @@ -1,7 +1,7 @@ use crate::{Audio, AudioSource, Decodable}; use bevy_asset::{Asset, Assets}; use bevy_ecs::system::{Res, ResMut, Resource}; -use bevy_reflect::TypeUuid; +use bevy_reflect::{TypeUuid, TypePath}; use bevy_utils::tracing::warn; use rodio::{OutputStream, OutputStreamHandle, Sink, Source}; use std::marker::PhantomData; @@ -127,7 +127,7 @@ pub fn play_queued_audio_system( /// } /// ``` /// -#[derive(TypeUuid)] +#[derive(TypeUuid, TypePath)] #[uuid = "8BEE570C-57C2-4FC0-8CFB-983A22F7D981"] pub struct AudioSink { // This field is an Option in order to allow us to have a safe drop that will detach the sink. diff --git a/crates/bevy_audio/src/audio_source.rs b/crates/bevy_audio/src/audio_source.rs index dda555f13a4de..589eafbfd42bd 100644 --- a/crates/bevy_audio/src/audio_source.rs +++ b/crates/bevy_audio/src/audio_source.rs @@ -1,11 +1,11 @@ use anyhow::Result; use bevy_asset::{Asset, AssetLoader, LoadContext, LoadedAsset}; -use bevy_reflect::TypeUuid; +use bevy_reflect::{TypeUuid, TypePath}; use bevy_utils::BoxedFuture; use std::{io::Cursor, sync::Arc}; /// A source of audio data -#[derive(Debug, Clone, TypeUuid)] +#[derive(Debug, Clone, TypeUuid, TypePath)] #[uuid = "7a14806a-672b-443b-8d16-4f18afefa463"] pub struct AudioSource { /// Raw data of the audio source. diff --git a/crates/bevy_gltf/src/lib.rs b/crates/bevy_gltf/src/lib.rs index f86efd9732ffb..77a5b14650eba 100644 --- a/crates/bevy_gltf/src/lib.rs +++ b/crates/bevy_gltf/src/lib.rs @@ -9,7 +9,7 @@ use bevy_app::prelude::*; use bevy_asset::{AddAsset, Handle}; use bevy_ecs::{prelude::Component, reflect::ReflectComponent}; use bevy_pbr::StandardMaterial; -use bevy_reflect::{Reflect, TypeUuid}; +use bevy_reflect::{Reflect, TypeUuid, TypePath}; use bevy_render::mesh::Mesh; use bevy_scene::Scene; @@ -29,7 +29,7 @@ impl Plugin for GltfPlugin { } /// Representation of a loaded glTF file. -#[derive(Debug, TypeUuid)] +#[derive(Debug, TypeUuid, TypePath)] #[uuid = "5c7d5f8a-f7b0-4e45-a09e-406c0372fea2"] pub struct Gltf { pub scenes: Vec>, @@ -49,7 +49,7 @@ pub struct Gltf { /// A glTF node with all of its child nodes, its [`GltfMesh`] and /// [`Transform`](bevy_transform::prelude::Transform). -#[derive(Debug, Clone, TypeUuid)] +#[derive(Debug, Clone, TypeUuid, TypePath)] #[uuid = "dad74750-1fd6-460f-ac51-0a7937563865"] pub struct GltfNode { pub children: Vec, @@ -58,14 +58,14 @@ pub struct GltfNode { } /// A glTF mesh, which may consist of multiple [`GltfPrimitives`](GltfPrimitive). -#[derive(Debug, Clone, TypeUuid)] +#[derive(Debug, Clone, TypeUuid, TypePath)] #[uuid = "8ceaec9a-926a-4f29-8ee3-578a69f42315"] pub struct GltfMesh { pub primitives: Vec, } /// Part of a [`GltfMesh`] that consists of a [`Mesh`] and an optional [`StandardMaterial`]. -#[derive(Debug, Clone, TypeUuid)] +#[derive(Debug, Clone, TypeUuid, TypePath)] #[uuid = "cbfca302-82fd-41cb-af77-cab6b3d50af1"] pub struct GltfPrimitive { pub mesh: Handle, diff --git a/crates/bevy_input/src/input.rs b/crates/bevy_input/src/input.rs index 8c4273bfc9f41..033e9e3bfb246 100644 --- a/crates/bevy_input/src/input.rs +++ b/crates/bevy_input/src/input.rs @@ -1,5 +1,5 @@ use bevy_ecs::system::Resource; -use bevy_reflect::{std_traits::ReflectDefault, Reflect, Typed}; +use bevy_reflect::{std_traits::ReflectDefault, Reflect, Typed, TypePath}; use bevy_utils::HashSet; use std::hash::Hash; @@ -43,7 +43,7 @@ use bevy_ecs::schedule::State; ///[`DetectChangesMut::bypass_change_detection`]: bevy_ecs::change_detection::DetectChangesMut::bypass_change_detection #[derive(Debug, Clone, Resource, Reflect)] #[reflect(Default)] -pub struct Input { +pub struct Input { /// A collection of every button that is currently being pressed. pressed: HashSet, /// A collection of every button that has just been pressed. @@ -52,7 +52,7 @@ pub struct Input { just_released: HashSet, } -impl Default for Input { +impl Default for Input { fn default() -> Self { Self { pressed: Default::default(), @@ -64,7 +64,7 @@ impl Default for Input { impl Input where - T: Typed + Copy + Eq + Hash + Send + Sync + 'static, + T: TypePath + Copy + Eq + Hash + Send + Sync + 'static, { /// Registers a press for the given `input`. pub fn press(&mut self, input: T) { @@ -174,10 +174,12 @@ where #[cfg(test)] mod test { + use bevy_reflect::TypePath; + use crate::Input; /// Used for testing the functionality of [`Input`]. - #[derive(Copy, Clone, Eq, PartialEq, Hash)] + #[derive(TypePath, Copy, Clone, Eq, PartialEq, Hash)] enum DummyInput { Input1, Input2, diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index a3039f08cd151..18c2bf39797d5 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -19,7 +19,7 @@ use bevy_ecs::{ }, world::FromWorld, }; -use bevy_reflect::TypeUuid; +use bevy_reflect::{TypeUuid, TypePath}; use bevy_render::{ extract_component::ExtractComponentPlugin, mesh::{Mesh, MeshVertexBufferLayout}, @@ -106,7 +106,7 @@ use std::marker::PhantomData; /// @group(1) @binding(2) /// var color_sampler: sampler; /// ``` -pub trait Material: AsBindGroup + Send + Sync + Clone + TypeUuid + Sized + 'static { +pub trait Material: AsBindGroup + Send + Sync + Clone + TypeUuid + TypePath + Sized + 'static { /// Returns this material's vertex shader. If [`ShaderRef::Default`] is returned, the default mesh vertex shader /// will be used. fn vertex_shader() -> ShaderRef { 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 ddbdbe8c426e5..ee0ce3d689788 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs @@ -1,9 +1,11 @@ +use std::borrow::Cow; + use crate::container_attributes::ReflectTraits; use crate::field_attributes::{parse_field_attrs, ReflectFieldAttr}; +use crate::type_path::parse_path_no_leading_colon; use crate::fq_std::{FQAny, FQDefault, FQSend, FQSync}; use crate::utility::{members_to_serialization_denylist, WhereClauseOptions}; use crate::utility::members_to_serialization_denylist; -use crate::with_path::parse_path_no_leading_colon; use bit_set::BitSet; use quote::{quote, ToTokens}; @@ -13,8 +15,9 @@ use crate::{ use syn::punctuated::Punctuated; use syn::spanned::Spanned; use syn::{ - parse_str, Data, DeriveInput, Field, Fields, GenericParam, Generics, Ident, Lit, LitStr, Meta, - Path, Token, Type, TypePath, Variant, ImplGenerics, TypeGenerics, WhereClause, + parse_str, AngleBracketedGenericArguments, Data, DeriveInput, Field, Fields, GenericParam, + Generics, Ident, ImplGenerics, Lit, LitStr, Meta, Path, PathSegment, Token, Type, TypeGenerics, + TypePath, Variant, WhereClause, }; pub(crate) enum ReflectDerive<'a> { @@ -186,7 +189,7 @@ impl<'a> ReflectDerive<'a> { return Err(syn::Error::new( pair.span(), format_args!( - "cannot use multuple `#[{TYPE_PATH_ATTRIBUTE_NAME} = \"...\"]`" + "cannot use multuple `#[{TYPE_PATH_ATTRIBUTE_NAME} = \"...\"]` attributes" ), )); } @@ -212,18 +215,8 @@ impl<'a> ReflectDerive<'a> { _ => continue, } } - - let path_to_type = if let Some(alias) = type_path_alias { - PathToType::AliasedNamed { - alias, - ty: Type::Path(TypePath { - qself: None, - path: Path::from(input.ident.clone()), - }), - } - } else { - PathToType::Internal(&input.ident) - }; + + let path_to_type = PathToType::Internal { ident: &input.ident, alias: type_path_alias }; let meta = ReflectMeta::new(path_to_type, &input.generics, traits); @@ -372,16 +365,6 @@ impl<'a> ReflectMeta<'a> { pub fn bevy_reflect_path(&self) -> &Path { &self.bevy_reflect_path } - - /// Use this over [`Generics::split_for_impl`]. - pub fn split_generics_for_impl(&self) -> (ImplGenerics, Option, Option<&WhereClause>) { - let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl(); - if let PathToType::AliasedNamed { .. } = self.path_to_type { - (impl_generics, None, where_clause) - } else { - (impl_generics, Some(ty_generics), where_clause) - } - } /// Whether an impl using this [`ReflectMeta`] should be generic. pub fn impl_is_generic(&self) -> bool { @@ -400,7 +383,7 @@ impl<'a> ReflectMeta<'a> { where_clause_options: &WhereClauseOptions, ) -> proc_macro2::TokenStream { crate::registration::impl_get_type_registration( - self.meta(), + self, where_clause_options, None, ) @@ -572,34 +555,81 @@ impl<'a> EnumVariant<'a> { } pub(crate) enum PathToType<'a> { - /// The name of a type relative to itself. - /// - /// Module and crate are found with [`module_path!()`](core::module_path). - Internal(&'a Ident), - /// Using `::my_crate::foo::Bar` syntax. - External(&'a Path), /// Types without a crate/module (e.g. `bool`). Primtive(&'a Ident), - /// [`PathToType::External`] but with a seperately defined qualified path. - AliasedNamed { ty: Type, alias: Path }, - /// Types without a crate/module and with a seperately defined qualified path. - AliasedAnonymous { ty: Type, alias: LitStr }, + /// Using `::my_crate::foo::Bar` syntax. + /// + /// May have a seperate alias path used for the `TypePath` implementation. + External { path: &'a Path, alias: Option }, + /// The name of a type relative to itself. + /// Module and crate are found with [`module_path!()`](core::module_path). + /// + /// May have a seperate alias path used for the `TypePath` implementation. + Internal { + ident: &'a Ident, + alias: Option, + }, + /// Any [`syn::Type`] with only a defined `type_path` and `short_type_path`. + Anonymous { + qualified_type: Type, + long_type_path: proc_macro2::TokenStream, + short_type_path: proc_macro2::TokenStream, + }, } impl<'a> PathToType<'a> { + /// Returns the path interpreted as an [`Ident`], + /// or [`None`] if anonymous. + fn named_as_ident(&self) -> Option<&Ident> { + match self { + Self::Internal { ident, alias } => Some( + alias + .as_ref() + .map(|path| &path.segments.last().unwrap().ident) + .unwrap_or(ident), + ), + Self::External { path, alias } => Some( + &alias + .as_ref() + .unwrap_or(path) + .segments + .last() + .unwrap() + .ident, + ), + _ => None, + } + } + + /// Returns the path interpreted as a [`Path`], + /// or [`None`] if anonymous or a non-aliased [`PathToType::Internal`]. + fn named_as_path(&self) -> Option<&Path> { + match self { + Self::Internal { ident, alias } => alias.as_ref(), + Self::External { path, alias } => Some(alias.as_ref().unwrap_or(path)), + _ => None, + } + } + /// Returns whether [`crate_name`](PathToType::crate_name) /// and [`module_path`](PathToType::module_path) return [`Some`]. /// - /// This is true for primitives and anonymous paths. + /// This is false for primitives and anonymous paths. pub fn has_module(&self) -> bool { match self { - Self::Primtive(_) | Self::AliasedAnonymous { .. } => false, + Self::Primtive(_) | Self::Anonymous { .. } => false, _ => true, } } - /// Returns an expression for a [`&str`](str). + /// Returns an expression for an `AsRef`. pub fn crate_name(&self) -> Option { + if let Some(path) = self.named_as_path() { + let crate_name = path.segments.first().unwrap().ident.to_string(); + let crate_name = LitStr::new(&crate_name, path.span()); + return Some(quote!(#crate_name)); + } + match self { Self::Internal { .. } => Some(quote! { ::core::module_path!() @@ -607,86 +637,74 @@ impl<'a> PathToType<'a> { .next() .unwrap() }), - &Self::External(&ref path) | Self::AliasedNamed { alias: ref path, .. } => { - let crate_name = path.segments.first().unwrap().ident.to_string(); - let crate_name = LitStr::new(&crate_name, path.span()); - Some(quote!(#crate_name)) - } - Self::Primtive(_) => None, + Self::External { .. } => unreachable!(), + _ => None, } } - /// Returns an expression representing a [`String`]. - pub fn fully_qualified_path(&self) -> proc_macro2::TokenStream { + /// Returns an expression for an `AsRef`. + pub fn long_type_path(&self) -> proc_macro2::TokenStream { + if let Some(ident) = self.named_as_ident() { + let module_path = self.module_path(); + let ident = LitStr::new(&ident.to_string(), ident.span()); + return quote! { + #module_path.to_owned() + ::core::concat!("::", #ident) + }; + } + match self { - Self::Internal(ident) => { - let module_path = self.module_path().unwrap(); - let ident = LitStr::new(&ident.to_string(), ident.span()); - quote! { - #module_path.to_owned() + ::core::concat!("::", #ident) - } - } - Self::External(&ref path) | Self::AliasedNamed { alias: ref path, .. } => { - let module_path = self.module_path().unwrap(); - let ident = &path.segments.last().unwrap().ident; - let ident = LitStr::new(&ident.to_string(), ident.span()); - quote! { - #module_path.to_owned() + ::core::concat!("::", #ident) - } - } Self::Primtive(ident) => { let ident = LitStr::new(&ident.to_string(), ident.span()); quote! { #ident.to_owned() } } + Self::Anonymous { long_type_path, .. } => long_type_path.clone(), + _ => unreachable!(), } } - /// Returns an expression for a [`&str`](str). + /// Returns an expression for an `AsRef`. pub fn module_path(&self) -> Option { + if let Some(path) = self.named_as_path() { + let path = path + .segments + .pairs() + .take(path.segments.len() - 1) + .map(|pair| pair.value().ident.to_string()) + .reduce(|path, ident| path + "::" + &ident) + .unwrap(); + + let path = LitStr::new(&path, path.span()); + return Some(quote! { + #path + }); + } + match self { Self::Internal { .. } => Some(quote! { ::core::module_path!() }), - Self::External(&ref path) | Self::AliasedNamed { alias: ref path, .. } => { - let path = path - .segments - .pairs() - .take(path.segments.len() - 1) - .map(|pair| pair.value().ident.to_string()) - .reduce(|path, ident| path + "::" + &ident) - .unwrap(); - - let path = LitStr::new(&path, path.span()); - Some(quote! { - #path - }) - } - Self::Primtive(_) => None, + Self::External { .. } => unreachable!(), + _ => None, } } /// Returns the name of the type. This is not necessarily a valid qualified path to the type. - pub fn name(&self) -> &Ident { - match self { - Self::Internal(ident) | Self::Primtive(ident) => ident, - Self::External(&ref path) | Self::AliasedNamed { alias: ref path, .. } => { - &path.segments.last().unwrap().ident - } - } + pub fn ident(&self) -> Option<&Ident> { + self.named_as_ident().or_else(|| match self { + Self::Primtive(ident) => Some(ident), + _ => None, + }) } } impl<'a> ToTokens for PathToType<'a> { fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { match self { - Self::Internal(ident) | Self::Primtive(ident) => ident.to_tokens(tokens), - Self::External(path) => path.to_tokens(tokens), - Self::AliasedNamed { - ty, - .. - } | Self::AliasedAnonymous { ty, .. } => ty.to_tokens(tokens), + Self::Internal { ident, .. } | Self::Primtive(ident) => ident.to_tokens(tokens), + Self::External { path, .. } => path.to_tokens(tokens), + Self::Anonymous { qualified_type, .. } => qualified_type.to_tokens(tokens), } } } @@ -706,21 +724,21 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea .map(|param| { let ident = ¶m.ident; quote! { - <#ident as #bevy_reflect_path::WithPath>::type_path() + <#ident as #bevy_reflect_path::TypePath> } }) .collect(); - let ident = path_to_type.name().to_string(); + let ident = path_to_type.ident().unwrap().to_string(); let ident = LitStr::new(&ident, path_to_type.span()); let path = { - let path = path_to_type.fully_qualified_path(); + let path = path_to_type.long_type_path(); if is_generic { let generics = generic_type_paths.iter().map(|type_path| { quote! { - #type_path.path() + #type_path::type_path() } }); @@ -738,7 +756,7 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea if is_generic { let generics = generic_type_paths.iter().map(|type_path| { quote! { - #type_path.short_path() + #type_path::short_type_path() } }); @@ -752,9 +770,9 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea } }; - if path_to_type.has_module() { + if !path_to_type.has_module() { quote! { - #bevy_reflect_path::TypePath::new_anonymous( + #bevy_reflect_path::utility::TypePathStorage::new_anonymous( #path, #short_path, ) @@ -764,7 +782,7 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea let module_path = path_to_type.module_path(); quote! { - #bevy_reflect_path::TypePath::new_named( + #bevy_reflect_path::utility::TypePathStorage::new_named( #path, #short_path, #ident.to_owned(), 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 4147445a57962..ede53e89dba46 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs @@ -23,7 +23,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { let path_to_type = meta.path_to_type(); let bevy_reflect_path = meta.bevy_reflect_path(); - let (impl_generics, ty_generics, where_clause) = meta.split_generics_for_impl(); + let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl(); TokenStream::from(quote! { impl #impl_generics #bevy_reflect_path::FromReflect for #path_to_type #ty_generics #where_clause { fn from_reflect(reflect: &dyn #bevy_reflect_path::Reflect) -> #FQOption { @@ -47,7 +47,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { } = get_variant_constructors(reflect_enum, &ref_value, false); let (impl_generics, ty_generics, where_clause) = - reflect_enum.meta().split_generics_for_impl(); + reflect_enum.meta().generics().split_for_impl(); TokenStream::from(quote! { impl #impl_generics #bevy_reflect_path::FromReflect for #enum_path #ty_generics #where_clause { fn from_reflect(#ref_value: &dyn #bevy_reflect_path::Reflect) -> #FQOption { @@ -117,7 +117,7 @@ fn impl_struct_internal(reflect_struct: &ReflectStruct, is_tuple: bool) -> Token ) }; - let (impl_generics, ty_generics, where_clause) = reflect_struct.meta().split_generics_for_impl(); + let (impl_generics, ty_generics, where_clause) = reflect_struct.meta().generics().split_for_impl(); // Add FromReflect bound for each active field let mut where_from_reflect_clause = if where_clause.is_some() { 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 c845d55ee4db8..9ed8de1f5758e 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs @@ -59,7 +59,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { } }); - let string_name = enum_path.name().to_string(); + let string_name = enum_path.ident().unwrap().to_string(); #[cfg(feature = "documentation")] let info_generator = { @@ -90,7 +90,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { .meta() .get_type_registration(&where_clause_options); let (impl_generics, ty_generics, where_clause) = - reflect_enum.meta().split_generics_for_impl(); + reflect_enum.meta().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/impls/mod.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/mod.rs index 21630f69bad04..97f066c9ff90b 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/mod.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/mod.rs @@ -8,5 +8,5 @@ pub(crate) use enums::impl_enum; pub(crate) use structs::impl_struct; pub(crate) use tuple_structs::impl_tuple_struct; pub(crate) use typed::impl_typed; -pub(crate) use typed::impl_with_path; +pub(crate) use typed::impl_type_path; pub(crate) use values::impl_value; \ No newline at end of file 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 472465da85862..5a833aaa8f129 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs @@ -72,7 +72,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { } }; - let string_name = struct_path.name().to_string(); + let string_name = struct_path.ident().unwrap().to_string(); #[cfg(feature = "documentation")] let info_generator = { @@ -102,7 +102,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { let get_type_registration_impl = reflect_struct.get_type_registration(&where_clause_options); let (impl_generics, ty_generics, where_clause) = - reflect_struct.meta().split_generics_for_impl(); + reflect_struct.meta().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/impls/tuple_structs.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/tuple_structs.rs index 5a74c91ce2f9d..529f0435a2392 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,7 +58,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { } }; - let string_name = struct_path.name().to_string(); + let string_name = struct_path.ident().unwrap().to_string(); #[cfg(feature = "documentation")] let info_generator = { @@ -86,7 +86,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { ); let (impl_generics, ty_generics, where_clause) = - reflect_struct.meta().split_generics_for_impl(); + reflect_struct.meta().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/impls/typed.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs index 60e0eb8426933..dfe973c8aec71 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -3,7 +3,6 @@ use crate::utility::{extend_where_clause, WhereClauseOptions}; use crate::ReflectMeta; use proc_macro2::Ident; use quote::quote; -use syn::spanned::Spanned; fn static_typed_cell( meta: &ReflectMeta, @@ -44,24 +43,62 @@ pub(crate) enum TypedProperty { TypePath, } -pub(crate) fn impl_with_path(meta: &ReflectMeta) -> proc_macro2::TokenStream { +pub(crate) fn impl_type_path(meta: &ReflectMeta) -> proc_macro2::TokenStream { let path_to_type = meta.path_to_type(); let bevy_reflect_path = meta.bevy_reflect_path(); let type_path_cell = static_typed_cell(meta, TypedProperty::TypePath, type_path_generator(meta)); - let (impl_generics, ty_generics, where_clause) = meta.split_generics_for_impl(); + let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl(); // Add Typed bound for each active field let where_reflect_clause = extend_where_clause(where_clause, where_clause_options); quote! { - impl #impl_generics #bevy_reflect_path::WithPath for #path_to_type #ty_generics #where_reflect_clause { - fn type_path() -> &'static #bevy_reflect_path::TypePath { - #type_path_cell + const _: () = { + trait GetStorage { + fn get_storage() -> &'static #bevy_reflect_path::utility::TypePathStorage; } - } + + impl #impl_generics GetStorage for #path_to_type #ty_generics #where_reflect_clause { + #[inline] + fn get_storage() -> &'static #bevy_reflect_path::utility::TypePathStorage { + #type_path_cell + } + } + + impl #impl_generics #bevy_reflect_path::TypePath for #path_to_type #ty_generics #where_reflect_clause { + fn type_path() -> &'static str { + &Self::get_storage().path() + } + + fn short_type_path() -> &'static str { + &Self::get_storage().short_path() + } + + fn type_ident() -> Option<&'static str> { + match Self::get_storage().ident() { + Some(x) => Some(x), + None => None + } + } + + fn crate_name() -> Option<&'static str> { + match Self::get_storage().crate_name() { + Some(x) => Some(x), + None => None + } + } + + fn module_path() -> Option<&'static str> { + match Self::get_storage().module_path() { + Some(x) => Some(x), + None => None + } + } + } + }; } } @@ -73,16 +110,17 @@ pub(crate) fn impl_typed( let path_to_type = meta.path_to_type(); let bevy_reflect_path = meta.bevy_reflect_path(); - let with_path_impl = impl_with_path(meta); + let type_path_impl = impl_type_path(meta); - let type_info_cell = static_typed_cell(meta, TypedProperty::TypeInfo, type_info_generator); + let type_info_cell = + static_typed_cell(meta, TypedProperty::TypeInfo, type_info_generator); - let (impl_generics, ty_generics, where_clause) = meta.split_generics_for_impl(); + let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl(); let where_reflect_clause = extend_where_clause(where_clause, where_clause_options); quote! { - #with_path_impl + #type_path_impl impl #impl_generics #bevy_reflect_path::Typed for #path_to_type #ty_generics #where_reflect_clause { fn type_info() -> &'static #bevy_reflect_path::TypeInfo { 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 074c0d9be3e1e..c34c7375f5272 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs @@ -1,6 +1,6 @@ use crate::fq_std::{FQAny, FQBox, FQClone, FQOption, FQResult}; use crate::impls::impl_typed; -use crate::utility::WhereClauseOptions; +use crate::utility::{WhereClauseOptions, extend_where_clause}; use crate::ReflectMeta; use proc_macro::TokenStream; use quote::quote; @@ -32,7 +32,8 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { }, ); - let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl(); + let (impl_generics, ty_generics, where_clause) = meta.split_generics_for_impl(); + let where_reflect_clause = extend_where_clause(where_clause, &where_clause_options); let get_type_registration_impl = meta.get_type_registration(&where_clause_options); TokenStream::from(quote! { @@ -40,7 +41,7 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { #typed_impl - impl #impl_generics #bevy_reflect_path::Reflect for #path_to_type #ty_generics #where_clause { + impl #impl_generics #bevy_reflect_path::Reflect for #path_to_type #ty_generics #where_result_clause { #[inline] fn type_name(&self) -> &str { ::core::any::type_name::() diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs index bfba7d90fcc72..918fb146d2d25 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs @@ -24,7 +24,7 @@ mod fq_std; mod from_reflect; mod impls; mod reflect_value; -mod with_path; +mod type_path; mod registration; mod trait_reflection; mod type_uuid; @@ -37,8 +37,8 @@ use proc_macro::TokenStream; use quote::quote; use reflect_value::ReflectValueDef; use syn::spanned::Spanned; -use syn::{parse_macro_input, DeriveInput}; -use with_path::WithPathDef; +use syn::{parse_macro_input, DeriveInput, Generics}; +use type_path::NamedTypePathDef; pub(crate) static REFLECT_ATTRIBUTE_NAME: &str = "reflect"; pub(crate) static REFLECT_VALUE_ATTRIBUTE_NAME: &str = "reflect_value"; @@ -89,15 +89,15 @@ pub fn derive_from_reflect(input: TokenStream) -> TokenStream { } } -#[proc_macro_derive(WithPath, attributes(type_path))] -pub fn derive_with_path(input: TokenStream) -> TokenStream { +#[proc_macro_derive(TypePath, attributes(type_path))] +pub fn derive_type_path(input: TokenStream) -> TokenStream { let ast = parse_macro_input!(input as DeriveInput); let derive_data = match ReflectDerive::from_input(&ast) { Ok(data) => data, Err(err) => return err.into_compile_error().into(), }; - impls::impl_with_path(derive_data.meta()).into() + impls::impl_type_path(derive_data.meta()).into() } // From https://github.com/randomPoison/type-uuid @@ -114,9 +114,8 @@ pub fn reflect_trait(args: TokenStream, input: TokenStream) -> TokenStream { #[proc_macro] pub fn impl_reflect_value(input: TokenStream) -> TokenStream { let def = parse_macro_input!(input as ReflectValueDef); - let path_to_type = if def.type_path.leading_colon.is_some() { - PathToType::External(&def.type_path) + PathToType::External { path: &def.type_path, alias: def.alias } } else { PathToType::Primtive(&def.type_path.segments.first().unwrap().ident) }; @@ -199,7 +198,7 @@ pub fn impl_reflect_struct(input: TokenStream) -> TokenStream { pub fn impl_from_reflect_value(input: TokenStream) -> TokenStream { let def = parse_macro_input!(input as ReflectValueDef); let path_to_type = if def.type_path.leading_colon.is_some() { - PathToType::External(&def.type_path) + PathToType::External { path: &def.type_path, alias: def.alias } } else { PathToType::Primtive(&def.type_path.segments.first().unwrap().ident) }; @@ -212,18 +211,17 @@ pub fn impl_from_reflect_value(input: TokenStream) -> TokenStream { } #[proc_macro] -pub fn impl_with_path(input: TokenStream) -> TokenStream { - let def = parse_macro_input!(input as WithPathDef); +pub fn impl_type_path(input: TokenStream) -> TokenStream { + let def = parse_macro_input!(input as NamedTypePathDef); let (path_to_type, generics) = match def { - WithPathDef::External { ref path, ref generics } => (PathToType::External(path), generics), - WithPathDef::AliasedAnonymous { alias, ty, ref generics } => (PathToType::AliasedAnonymous { ty, alias }, generics), - WithPathDef::AliasedNamed { alias, ty, ref generics } => (PathToType::AliasedNamed { ty, alias }, generics), + NamedTypePathDef::External { ref path, alias, generics } => (PathToType::External { path, alias }, generics), + NamedTypePathDef::Primtive(ref ident) => (PathToType::Primtive(ident), Generics::default()) }; - impls::impl_with_path(&ReflectMeta::new( + impls::impl_type_path(&ReflectMeta::new( path_to_type, - generics, + &generics, ReflectTraits::default(), )).into() } diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs b/crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs index 20aafc3bb91a3..868c09334ae40 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs @@ -1,9 +1,10 @@ use crate::container_attributes::ReflectTraits; +use crate::type_path::{parse_path_leading_colon, parse_path_no_leading_colon}; use proc_macro2::Ident; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::token::{Colon2, Paren, Where}; -use syn::{parenthesized, Attribute, Generics, Path, PathSegment}; +use syn::{parenthesized, Attribute, Generics, Path, PathSegment, Token}; /// A struct used to define a simple reflected value type (such as primitives). /// @@ -27,49 +28,36 @@ pub(crate) struct ReflectValueDef { pub type_path: Path, pub generics: Generics, pub traits: Option, + pub alias: Option, } impl Parse for ReflectValueDef { fn parse(input: ParseStream) -> syn::Result { let attrs = input.call(Attribute::parse_outer)?; - let type_path = { - let lookahead = input.lookahead1(); - if lookahead.peek(Colon2) { - // This parses `::foo::Foo` from `::foo::Foo` (leaving the generics). - Path::parse_mod_style(input)? - } else { - let ident = input.parse::()?; - let mut segments = Punctuated::new(); - segments.push(PathSegment::from(ident)); - Path { - leading_colon: None, - segments, - } - } - }; - let generics = input.parse::()?; - let mut lookahead = input.lookahead1(); - let mut where_clause = None; - if lookahead.peek(Where) { - where_clause = Some(input.parse()?); - lookahead = input.lookahead1(); - } + let type_path = Path::parse_mod_style(input)?; + let mut generics = input.parse::()?; + generics.where_clause = input.parse()?; let mut traits = None; - if lookahead.peek(Paren) { + if input.peek(Paren) { let content; parenthesized!(content in input); traits = Some(content.parse::()?); } + + let mut alias = None; + if input.peek(Token![as]) { + alias = Some(parse_path_no_leading_colon(input)?); + }; Ok(ReflectValueDef { attrs, type_path, generics: Generics { - where_clause, ..generics }, traits, + alias, }) } } diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/registration.rs b/crates/bevy_reflect/bevy_reflect_derive/src/registration.rs index 62df8e3b5a5a3..cb0dbabe1bc82 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/registration.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/registration.rs @@ -18,7 +18,7 @@ pub(crate) fn impl_get_type_registration( let path_to_type = meta.path_to_type(); let bevy_reflect_path = meta.bevy_reflect_path(); let registration_data = meta.traits().idents(); - let (impl_generics, ty_generics, where_clause) = meta.split_generics_for_impl(); + let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl(); let serialization_data = serialization_denylist.map(|denylist| { let denylist = denylist.into_iter(); quote! { diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs b/crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs new file mode 100644 index 0000000000000..9fae1ddaf14c6 --- /dev/null +++ b/crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs @@ -0,0 +1,80 @@ +use std::path; + +use proc_macro2::Ident; +use quote::{quote, ToTokens, TokenStreamExt}; +use syn::{ + parse::{Parse, ParseStream}, + Expr, Generics, LitStr, Path, Token, Type, TypeArray, TypeParamBound, TypePath, +}; + +use crate::derive_data::ReflectMeta; + +pub enum NamedTypePathDef { + External { + path: Path, + generics: Generics, + alias: Option, + }, + Primtive(Ident), +} + +pub struct AnonymousTypePathDef { + pub path: Path, + pub generics: Generics, + pub long_type_path: Expr, + pub short_type_path: Expr, +} + +pub fn parse_path_leading_colon(input: ParseStream) -> syn::Result { + let leading = input.parse::()?; + + if input.peek(Token![::]) { + return Err(input.error("did not expect two leading double colons (`::::`)")); + } + + let mut path = Path::parse_mod_style(input)?; + path.leading_colon = Some(leading); + Ok(path) +} + +pub fn parse_path_no_leading_colon(input: ParseStream) -> syn::Result { + if input.peek(Token![::]) { + return Err(input.error("did not expect a leading double colon (`::`)")); + } + + Path::parse_mod_style(input) +} + +impl Parse for NamedTypePathDef { + fn parse(input: ParseStream) -> syn::Result { + let path = Path::parse_mod_style(input)?; + let mut generics = input.parse::()?; + generics.where_clause = input.parse()?; + + if input.is_empty() { + if path.leading_colon.is_none() { + if path.segments.len() == 1 { + let ident = path.segments.into_iter().next().unwrap().ident; + Ok(NamedTypePathDef::Primtive(ident)) + } else { + Err(input.error("non-aliased paths must start with a double colon (`::`)")) + } + } else { + Ok(NamedTypePathDef::External { + path, + generics, + alias: None, + }) + } + + } else { + let _ = input.parse::(); + let alias = parse_path_no_leading_colon(input)?; + Ok(NamedTypePathDef::External { + path, + generics, + alias: Some(alias), + }) + } + } +} diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/with_path.rs b/crates/bevy_reflect/bevy_reflect_derive/src/with_path.rs deleted file mode 100644 index c683d3dbe0ec8..0000000000000 --- a/crates/bevy_reflect/bevy_reflect_derive/src/with_path.rs +++ /dev/null @@ -1,197 +0,0 @@ -use std::path; - -use quote::{quote, ToTokens, TokenStreamExt}; -use syn::{ - parse::{Parse, ParseStream}, - Generics, LitStr, Path, Token, Type, TypeArray, TypeParamBound, TypePath, Expr, -}; - -use crate::derive_data::ReflectMeta; - -pub enum WithPathDef { - External { - path: Path, - generics: Generics, - }, - AliasedNamed { - generics: Generics, - ty: Type, - alias: Path, - }, - AliasedAnonymous { - generics: Generics, - ty: Type, - alias: Type, - }, -} - -pub fn parse_path_leading_colon(input: ParseStream) -> syn::Result { - let leading = input.parse::()?; - - if input.peek(Token![::]) { - return Err(input.error("did not expect two leading double colons (`::::`)")); - } - - let mut path = Path::parse_mod_style(input)?; - path.leading_colon = Some(leading); - Ok(path) -} - -pub fn parse_path_no_leading_colon(input: ParseStream) -> syn::Result { - if input.peek(Token![::]) { - return Err(input.error("did not expect a leading double colon (`::`)")); - } - - Path::parse_mod_style(input) -} - -impl Parse for WithPathDef { - fn parse(input: ParseStream) -> syn::Result { - let (generics, ty) = if input.peek(Token![::]) { - let path = parse_path_leading_colon(input)?; - let mut generics = input.parse::()?; - generics.where_clause = input.parse()?; - - if !input.peek(Token![as]) { - return Ok(WithPathDef::External { path, generics }); - } - - ( - Generics::default(), - Type::Path(TypePath { qself: None, path }), - ) - } else { - let generics = input.parse()?; - let ty = input.parse()?; - (generics, ty) - }; - - let _as_token: Token![as] = input.parse()?; - - let alias = parse_path_no_leading_colon(input)?; - - Ok(WithPathDef::AliasedNamed { - generics, - ty, - alias, - }) - } -} - -macro_rules! format_lit { - ($($arg:tt)*) => {{ - LitStr::new(&format!($($arg)*), proc_macro2::Span::call_site()).to_token_stream() - }} -} - -struct StrExprBuilder<'a> { - meta: &'a ReflectMeta<'a>, - stream: proc_macro2::TokenStream, -} - -impl<'a> StrExprBuilder<'a> { - pub fn new(meta: &'a ReflectMeta<'a>) -> Self { - Self { - meta, - stream: proc_macro2::TokenStream::new(), - } - } - - pub fn append(&mut self, tokens: proc_macro2::TokenStream) { - if self.stream.is_empty() { - quote!((#tokens).to_owned()).to_tokens(&mut self.stream); - } else { - quote!(+ #tokens).to_tokens(&mut self.stream); - } - } - - pub fn append_owned(&mut self, tokens: proc_macro2::TokenStream) { - if self.stream.is_empty() { - quote!(#tokens).to_tokens(&mut self.stream); - } else { - quote!(+ &#tokens).to_tokens(&mut self.stream); - } - } -} - -trait ToAnonymousPath { - fn to_path_str(&self, path: &mut StrExprBuilder) -> syn::Result<()>; - fn to_short_path_str(&self, path: &mut StrExprBuilder) -> syn::Result<()>; -} - -impl ToAnonymousPath for Expr { - fn to_path_str(&self, path: &mut StrExprBuilder) -> syn::Result<()> { - path.append_owned(quote! { - ::std::string::ToString::to_string(#self) - }); - Ok(()) - } - - fn to_short_path_str(&self, path: &mut StrExprBuilder) -> syn::Result<()> { - self.to_path_str(path) - } -} - -impl ToAnonymousPath for Path { - fn to_path_str(&self, path: &mut StrExprBuilder) -> syn::Result<()> { - - path.append_owned(quote! { - ::std::string::ToString::to_string(#self) - }); - Ok(()) - } - - fn to_short_path_str(&self, path: &mut StrExprBuilder) -> syn::Result<()> { - self.to_path_str(path) - } -} - -fn type_to_path_str(ty: &Type, meta: &ReflectMeta) -> syn::Result { - fn path_to_path_str(path: &Path) -> syn::Result { - path.segments. - } - - let bevy_reflect_path = meta.bevy_reflect_path(); - - Ok(match ty { - Type::Array(array) => format_lit!( - "[{elem}; {len}]", - elem = type_to_path_str(&array.elem, meta)?, - len = array.len - ), - Type::BareFn(bare_fn) => type_to_path_str(ty, meta), - Type::Group(group) => type_to_path_str(&group.elem, meta)?, - Type::ImplTrait(_) => todo!(), - Type::Infer(_) => todo!(), - Type::Macro(_) => todo!(), - Type::Never(_) => quote!(!), - Type::Paren(paren) => type_to_path_str(&paren.elem, meta)?, - Type::Path(path) => quote! { - <#path as #bevy_reflect_path::WithPath>::type_path().path() - }, - Type::Ptr(ptr) => format_lit!( - "*{m} {t}", - m = ptr.mutability.map(|_| "mut").unwrap_or_else(|| "const"), - t = type_to_path_str(&ptr.elem, meta)?, - ), - Type::Reference(reference) => format_lit!( - "&{m}{t}", - m = reference.mutability.map(|_| "mut ").unwrap_or_default(), - t = type_to_path_str(&reference.elem, meta)?, - ), - Type::Slice(slice) => format_lit!("[{}]", type_to_path_str(&slice.elem, meta)?), - Type::TraitObject(trait_object) => { - let bounds: syn::Result = trait_object.bounds.iter().filter_map( - |bound| if let TypeParamBound::Trait(t) = bound { - Some(path_to_path_str(&t.path)) - } else { - None - } - ).collect(); - format_lit!("dyn {}", bounds?) - }, - Type::Tuple(_) => todo!(), - Type::Verbatim(_) => todo!(), - _ => todo!(), - }) -} diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index 8853026607a83..6a55a464bd41e 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -1,9 +1,8 @@ -use bevy_reflect_derive::impl_with_path; - use crate::{ self as bevy_reflect, - utility::{NonGenericTypeInfoCell, NonGenericTypePathCell}, DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, - TypeInfo, Typed, TypePath, WithPath, + impl_type_path, + utility::{NonGenericTypeInfoCell, TypePathStorage}, DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, + TypeInfo, Typed, TypePath, impl_type_path_stored, }; use std::{ any::{Any, TypeId}, @@ -304,7 +303,13 @@ impl Typed for DynamicArray { } } -impl_with_path!(DynamicArray as bevy_reflect::DynamicArray); +impl_type_path_stored!(|| TypePathStorage::new_named( + "bevy_reflect::DynamicArray", + "DynamicArray", + "DynamicArray", + "bevy_reflect", + "bevy_reflect" +), impl for DynamicArray); /// An iterator over an [`Array`]. pub struct ArrayIter<'a> { diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index 9946fbfe0b31d..3d788ba63355b 100644 --- a/crates/bevy_reflect/src/enums/dynamic_enum.rs +++ b/crates/bevy_reflect/src/enums/dynamic_enum.rs @@ -1,11 +1,11 @@ -use bevy_reflect_derive::impl_with_path; +use bevy_reflect_derive::impl_type_path; use crate::utility::{NonGenericTypeInfoCell, NonGenericTypePathCell}; use crate::{ self as bevy_reflect, enum_debug, enum_hash, enum_partial_eq, DynamicInfo, DynamicStruct, DynamicTuple, Enum, Reflect, ReflectMut, ReflectOwned, ReflectRef, Struct, Tuple, TypeInfo, Typed, - VariantFieldIter, VariantType, TypePath, WithPath, + VariantFieldIter, VariantType, TypePath, }; use std::any::Any; use std::fmt::Formatter; @@ -434,4 +434,4 @@ impl Typed for DynamicEnum { } } -impl_with_path!(DynamicEnum as bevy_reflect::DynamicEnum); +impl_type_path!(DynamicEnum as bevy_reflect::DynamicEnum); diff --git a/crates/bevy_reflect/src/enums/mod.rs b/crates/bevy_reflect/src/enums/mod.rs index 35716336aebb0..2d6db324aade0 100644 --- a/crates/bevy_reflect/src/enums/mod.rs +++ b/crates/bevy_reflect/src/enums/mod.rs @@ -316,7 +316,7 @@ mod tests { #[test] fn enum_should_allow_generics() { #[derive(Reflect, Debug, PartialEq)] - enum TestEnum { + enum TestEnum { A, B(T), C { value: T }, diff --git a/crates/bevy_reflect/src/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index 7004284dbad74..1c1746dfbe537 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -1,4 +1,4 @@ -use bevy_reflect_derive::impl_with_path; +use bevy_reflect_derive::impl_type_path; use smallvec::SmallVec; use std::any::Any; @@ -6,11 +6,11 @@ use crate::utility::{GenericTypeInfoCell, GenericTypePathCell}; use crate::{ self as bevy_reflect, Array, ArrayIter, FromReflect, FromType, GetTypeRegistration, List, ListInfo, Reflect, - ReflectFromPtr, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypeRegistration, Typed, TypePath, - WithPath + ReflectFromPtr, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypeRegistration, Typed, + TypePath }; -impl Array for SmallVec +impl Array for SmallVec where T::Item: FromReflect, { @@ -48,7 +48,7 @@ where } } -impl List for SmallVec +impl List for SmallVec where T::Item: FromReflect, { @@ -85,7 +85,7 @@ where } } -impl Reflect for SmallVec +impl Reflect for SmallVec where T::Item: FromReflect, { @@ -151,7 +151,7 @@ where } } -impl Typed for SmallVec +impl Typed for SmallVec where T::Item: FromReflect, { @@ -161,9 +161,9 @@ where } } -impl_with_path!(::smallvec::SmallVec); +impl_type_path!(::smallvec::SmallVec); -impl FromReflect for SmallVec +impl FromReflect for SmallVec where T::Item: FromReflect, { @@ -180,7 +180,7 @@ where } } -impl GetTypeRegistration for SmallVec +impl GetTypeRegistration for SmallVec where T::Item: FromReflect, { diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 79f5af3c90dad..09ccde69fb6a8 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -1,15 +1,15 @@ use crate::std_traits::ReflectDefault; -use crate::{self as bevy_reflect, ReflectFromPtr, ReflectOwned}; +use crate::{self as bevy_reflect, ReflectFromPtr, ReflectOwned, impl_type_path_stored}; use crate::{ map_apply, map_partial_eq, Array, ArrayInfo, ArrayIter, DynamicEnum, DynamicMap, Enum, EnumInfo, FromReflect, FromType, GetTypeRegistration, List, ListInfo, Map, MapInfo, MapIter, Reflect, ReflectDeserialize, ReflectMut, ReflectRef, ReflectSerialize, - TupleVariantInfo, TypeInfo, TypePath, TypeRegistration, Typed, UnitVariantInfo, UnnamedField, - ValueInfo, VariantFieldIter, VariantInfo, VariantType, WithPath, impl_with_path, + TupleVariantInfo, TypeInfo, TypeRegistration, Typed, UnitVariantInfo, UnnamedField, + ValueInfo, VariantFieldIter, VariantInfo, VariantType, TypePath, impl_type_path, }; use crate::utility::{ - GenericTypeInfoCell, GenericTypePathCell, NonGenericTypeInfoCell, NonGenericTypePathCell, + GenericTypeInfoCell, GenericTypePathCell, NonGenericTypeInfoCell, NonGenericTypePathCell, TypePathStorage, }; use bevy_reflect_derive::{impl_from_reflect_value, impl_reflect_value}; use bevy_utils::{Duration, Instant}; @@ -102,13 +102,13 @@ impl_reflect_value!(PathBuf( Deserialize, Default )); -impl_reflect_value!(Result()); -impl_reflect_value!(HashSet()); -impl_reflect_value!(Range()); -impl_reflect_value!(RangeInclusive()); -impl_reflect_value!(RangeFrom()); -impl_reflect_value!(RangeTo()); -impl_reflect_value!(RangeToInclusive()); +impl_reflect_value!(Result()); +impl_reflect_value!(HashSet()); +impl_reflect_value!(Range()); +impl_reflect_value!(RangeInclusive()); +impl_reflect_value!(RangeFrom()); +impl_reflect_value!(RangeTo()); +impl_reflect_value!(RangeToInclusive()); impl_reflect_value!(RangeFull()); impl_reflect_value!(Duration( Debug, @@ -158,12 +158,12 @@ impl_from_reflect_value!(f64); impl_from_reflect_value!(String); impl_from_reflect_value!(PathBuf); impl_from_reflect_value!(OsString); -impl_from_reflect_value!(HashSet); -impl_from_reflect_value!(Range); -impl_from_reflect_value!(RangeInclusive); -impl_from_reflect_value!(RangeFrom); -impl_from_reflect_value!(RangeTo); -impl_from_reflect_value!(RangeToInclusive); +impl_from_reflect_value!(HashSet); +impl_from_reflect_value!(Range); +impl_from_reflect_value!(RangeInclusive); +impl_from_reflect_value!(RangeFrom); +impl_from_reflect_value!(RangeTo); +impl_from_reflect_value!(RangeToInclusive); impl_from_reflect_value!(RangeFull); impl_from_reflect_value!(Duration); impl_from_reflect_value!(Instant); @@ -182,7 +182,7 @@ impl_from_reflect_value!(NonZeroI8); macro_rules! impl_reflect_for_veclike { ($ty:path, $insert:expr, $remove:expr, $push:expr, $pop:expr, $sub:ty) => { - impl Array for $ty { + impl Array for $ty { #[inline] fn get(&self, index: usize) -> Option<&dyn Reflect> { <$sub>::get(self, index).map(|value| value as &dyn Reflect) @@ -214,7 +214,7 @@ macro_rules! impl_reflect_for_veclike { } } - impl List for $ty { + impl List for $ty { fn insert(&mut self, index: usize, value: Box) { let value = value.take::().unwrap_or_else(|value| { T::from_reflect(&*value).unwrap_or_else(|| { @@ -246,7 +246,7 @@ macro_rules! impl_reflect_for_veclike { } } - impl Reflect for $ty { + impl Reflect for $ty { fn type_name(&self) -> &str { std::any::type_name::() } @@ -313,16 +313,16 @@ macro_rules! impl_reflect_for_veclike { } } - impl Typed for $ty { + impl Typed for $ty { fn type_info() -> &'static TypeInfo { static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); CELL.get_or_insert::(|| TypeInfo::List(ListInfo::new::())) } } - impl_with_path!($ty where T: FromReflect + WithPath); + impl_type_path!($ty where T: FromReflect + TypePath); - impl GetTypeRegistration for $ty { + impl GetTypeRegistration for $ty { fn get_type_registration() -> TypeRegistration { let mut registration = TypeRegistration::of::<$ty>(); registration.insert::(FromType::<$ty>::from_type()); @@ -330,7 +330,7 @@ macro_rules! impl_reflect_for_veclike { } } - impl FromReflect for $ty { + impl FromReflect for $ty { fn from_reflect(reflect: &dyn Reflect) -> Option { if let ReflectRef::List(ref_list) = reflect.reflect_ref() { let mut new_list = Self::with_capacity(ref_list.len()); @@ -363,7 +363,7 @@ impl_reflect_for_veclike!( VecDeque:: ); -impl Map for HashMap { +impl Map for HashMap { fn get(&self, key: &dyn Reflect) -> Option<&dyn Reflect> { key.downcast_ref::() .and_then(|key| HashMap::get(self, key)) @@ -446,7 +446,7 @@ impl Map for H } } -impl Reflect for HashMap { +impl Reflect for HashMap { fn type_name(&self) -> &str { std::any::type_name::() } @@ -510,19 +510,19 @@ impl Reflect f } } -impl Typed for HashMap { +impl Typed for HashMap { fn type_info() -> &'static TypeInfo { static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); CELL.get_or_insert::(|| TypeInfo::Map(MapInfo::new::())) } } -impl_with_path!( HashMap as hashbrown::HashMap); +impl_type_path!(HashMap as hashbrown::HashMap); impl GetTypeRegistration for HashMap where - K: FromReflect + WithPath + Eq + Hash, - V: FromReflect + WithPath, + K: FromReflect + TypePath + Eq + Hash, + V: FromReflect + TypePath, { fn get_type_registration() -> TypeRegistration { let mut registration = TypeRegistration::of::>(); @@ -531,7 +531,7 @@ where } } -impl FromReflect for HashMap { +impl FromReflect for HashMap { fn from_reflect(reflect: &dyn Reflect) -> Option { if let ReflectRef::Map(ref_map) = reflect.reflect_ref() { let mut new_map = Self::with_capacity(ref_map.len()); @@ -547,7 +547,7 @@ impl FromRefle } } -impl Array for [T; N] { +impl Array for [T; N] { #[inline] fn get(&self, index: usize) -> Option<&dyn Reflect> { <[T]>::get(self, index).map(|value| value as &dyn Reflect) @@ -579,7 +579,7 @@ impl Array for [T; N] { } } -impl Reflect for [T; N] { +impl Reflect for [T; N] { #[inline] fn type_name(&self) -> &str { std::any::type_name::() @@ -661,7 +661,7 @@ impl Reflect for [T; N] { } } -impl FromReflect for [T; N] { +impl FromReflect for [T; N] { fn from_reflect(reflect: &dyn Reflect) -> Option { if let ReflectRef::Array(ref_array) = reflect.reflect_ref() { let mut temp_vec = Vec::with_capacity(ref_array.len()); @@ -675,24 +675,17 @@ impl FromReflect for [T; N] { } } -impl Typed for [T; N] { +impl Typed for [T; N] { fn type_info() -> &'static TypeInfo { static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); CELL.get_or_insert::(|| TypeInfo::Array(ArrayInfo::new::(N))) } } -impl WithPath for [T; N] { - fn type_path() -> &'static TypePath { - static CELL: GenericTypePathCell = GenericTypePathCell::new(); - CELL.get_or_insert::(|| { - TypePath::new_anonymous( - format!("[{name}; {N}]", name = T::type_path().path()), - format!("[{name}; {N}]", name = T::type_path().short_path()), - ) - }) - } -} +impl_type_path_stored!(|| TypePathStorage::new_anonymous( + format!("[{t}; {N}]", t = T::type_path()), + format!("[{t}; {N}]", t = T::short_type_path()), +), impl { T: TypePath, const N: usize } for [T; N]); // TODO: // `FromType::from_type` requires `Deserialize<'de>` to be implemented for `T`. @@ -702,7 +695,7 @@ impl WithPath for [T; N] { macro_rules! impl_array_get_type_registration { ($($N:expr)+) => { $( - impl GetTypeRegistration for [T; $N] { + impl GetTypeRegistration for [T; $N] { fn get_type_registration() -> TypeRegistration { TypeRegistration::of::<[T; $N]>() } @@ -718,13 +711,13 @@ impl_array_get_type_registration! { 30 31 32 } -impl GetTypeRegistration for Option { +impl GetTypeRegistration for Option { fn get_type_registration() -> TypeRegistration { TypeRegistration::of::>() } } -impl Enum for Option { +impl Enum for Option { fn field(&self, _name: &str) -> Option<&dyn Reflect> { None } @@ -795,7 +788,7 @@ impl Enum for Option { } } -impl Reflect for Option { +impl Reflect for Option { #[inline] fn type_name(&self) -> &str { std::any::type_name::() @@ -909,7 +902,7 @@ impl Reflect for Option { } } -impl FromReflect for Option { +impl FromReflect for Option { fn from_reflect(reflect: &dyn Reflect) -> Option { if let ReflectRef::Enum(dyn_enum) = reflect.reflect_ref() { match dyn_enum.variant_name() { @@ -947,7 +940,7 @@ impl FromReflect for Option { } } -impl Typed for Option { +impl Typed for Option { fn type_info() -> &'static TypeInfo { static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); CELL.get_or_insert::(|| { @@ -962,7 +955,7 @@ impl Typed for Option { } } -impl_with_path!(::core::option::Option); +impl_type_path!(::core::option::Option); impl Reflect for Cow<'static, str> { fn type_name(&self) -> &str { @@ -1051,15 +1044,17 @@ impl Typed for Cow<'static, str> { } } -impl WithPath for Cow<'static, str> { - fn type_path() -> &'static TypePath { - todo!() - } -} +impl_type_path_stored!(|| TypePathStorage::new_named( + "core::borrow::Cow::", + "Cow", + "Cow", + "core", + "core::borrow" +), impl for Cow<'static, str>); -impl GetTypeRegistration for Cow<'static, str> { +impl GetTypeRegistration for Cow<'static, str>c Path { fn get_type_registration() -> TypeRegistration { - let mut registration = TypeRegistration::of::>(); + let mut registration = TypeRegistration:Cow<'static, str>>(); registration.insert::(FromType::>::from_type()); registration.insert::(FromType::>::from_type()); registration.insert::(FromType::>::from_type()); @@ -1067,9 +1062,9 @@ impl GetTypeRegistration for Cow<'static, str> { } } -impl FromReflect for Cow<'static, str> { +impl FromReflect for Cow<'static, str>c Path { fn from_reflect(reflect: &dyn crate::Reflect) -> Option { - Some( + Some( reflect .as_any() .downcast_ref::>()? @@ -1165,7 +1160,7 @@ impl Typed for &'static Path { } } -impl_with_path!(&'static ::std::path::Path); +impl_type_path_stored!(|| TypePathStorage::new_anonymous("&std::path::Path", "&Path"), impl for &'static Path); impl diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 1a6eefb6839d8..7b0c7c6ddefdc 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -653,38 +653,40 @@ mod tests { #[test] fn reflect_type_path() { - #[derive(WithPath)] + #[derive(TypePath)] struct A; - #[derive(WithPath)] + #[derive(TypePath)] #[type_path = "my_alias::B"] struct B; - #[derive(WithPath)] - struct C(PhantomData); + #[derive(TypePath)] + struct C(PhantomData); - #[derive(WithPath)] + #[derive(TypePath)] #[type_path = "my_alias::D"] - struct D(PhantomData); + struct D(PhantomData); - struct E; - impl_with_path!(E); + // struct E; + // impl_type_path!(E); - struct F; - impl_with_path!(F as my_alias::F); + // struct F; + // impl_type_path!(F as my_alias::F); - struct G(PhantomData); - impl_with_path!(G); + // struct G(PhantomData); + // impl_type_path!(G); - struct H(PhantomData); - impl_with_path!(H as my_alias::H); + // struct H(PhantomData); + // impl_type_path!(H as my_alias::H); A::type_path(); B::type_path(); C::::type_path(); D::::type_path(); - E::::type_path(); - F::::type_path(); + // E::type_path(); + // F::type_path(); + // G::::type_path(); + // H::::type_path(); } #[test] @@ -740,7 +742,7 @@ mod tests { // Struct (generic) #[derive(Reflect)] - struct MyGenericStruct { + struct MyGenericStruct { foo: T, bar: usize, } diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index e86d080c766c1..088a1f9dcf02e 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -1,13 +1,13 @@ use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; -use bevy_reflect_derive::type_path_for; +use bevy_reflect_derive::impl_type_path; -use crate::utility::{NonGenericTypeInfoCell, NonGenericTypePathCell}; +use crate::utility::NonGenericTypeInfoCell; use crate::{ self as bevy_reflect, Array, ArrayIter, DynamicArray, DynamicInfo, FromReflect, Reflect, ReflectMut, ReflectOwned, - ReflectRef, TypeInfo, Typed, TypePath, WithPath, + ReflectRef, TypeInfo, Typed, }; /// An ordered, mutable list of [Reflect] items. This corresponds to types like [`std::vec::Vec`]. @@ -329,13 +329,8 @@ impl Typed for DynamicList { CELL.get_or_set(|| TypeInfo::Dynamic(DynamicInfo::new::())) } } - -impl WithPath for DynamicList { - fn type_path() -> &'static TypePath { - static CELL: NonGenericTypePathCell = NonGenericTypePathCell::new(); - CELL.get_or_set(|| type_path_for!(::bevy_reflect::DynamicList)) - } -} + +impl_type_path!(DynamicList as bevy_reflect::DynamicList); impl IntoIterator for DynamicList { type Item = Box; diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index 512617c7aa206..d38110aa07e8a 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -2,13 +2,14 @@ use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; use std::hash::Hash; -use bevy_reflect_derive::type_path_for; +use bevy_reflect_derive::impl_type_path; use bevy_utils::{Entry, HashMap}; -use crate::utility::{NonGenericTypeInfoCell, NonGenericTypePathCell}; +use crate::utility::NonGenericTypeInfoCell; use crate::{ - self as bevy_reflect, DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, - TypePath, Typed, + self as bevy_reflect, + DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, + Typed, }; /// An ordered mapping between [`Reflect`] values. @@ -353,13 +354,10 @@ impl Typed for DynamicMap { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); CELL.get_or_set(|| TypeInfo::Dynamic(DynamicInfo::new::())) } - - fn type_path() -> &'static TypePath { - static CELL: NonGenericTypePathCell = NonGenericTypePathCell::new(); - CELL.get_or_set(|| type_path_for!(::bevy_reflect::DynamicMap)) - } } +impl_type_path!(DynamicMap as bevy_reflect::DynamicMap); + /// An iterator over the key-value pairs of a [`Map`]. pub struct MapIter<'a> { pub(crate) map: &'a dyn Map, diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index 1970c921decd2..78851c89ebf73 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -1,7 +1,9 @@ use crate::{ - array_debug, enum_debug, list_debug, map_debug, serde::Serializable, struct_debug, tuple_debug, - tuple_struct_debug, Array, Enum, List, Map, Struct, Tuple, TupleStruct, TypeInfo, Typed, - ValueInfo, TypePath, utility::{NonGenericTypePathCell}, + array_debug, enum_debug, impl_type_path_stored, list_debug, map_debug, + serde::Serializable, + struct_debug, tuple_debug, tuple_struct_debug, + utility::{NonGenericTypePathCell, TypePathStorage}, + Array, Enum, List, Map, Struct, Tuple, TupleStruct, TypeInfo, Typed, ValueInfo, }; use std::{ any::{self, Any, TypeId}, @@ -226,13 +228,13 @@ impl Typed for dyn Reflect { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); CELL.get_or_set(|| TypeInfo::Value(ValueInfo::new::())) } - - fn type_path() -> &'static TypePath { - static CELL: NonGenericTypePathCell = NonGenericTypePathCell::new(); - CELL.get_or_set(|| TypePath::new_anonymous("dyn bevy_reflect::Reflect".to_owned(), "dyn Reflect".to_owned())) - } } +impl_type_path_stored!(|| TypePathStorage::new_anonymous( + "dyn bevy_reflect::Reflect", + "dyn Reflect" +), impl for dyn Reflect); + #[deny(rustdoc::broken_intra_doc_links)] impl dyn Reflect { /// Downcasts the value to type `T`, consuming the trait object. diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index e80c324d89121..fba091f2f2142 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -1,9 +1,9 @@ use crate::utility::{NonGenericTypeInfoCell, NonGenericTypePathCell}; use crate::{ self as bevy_reflect, - DynamicInfo, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, TypePath, WithPath, + DynamicInfo, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, TypePath, }; -use bevy_reflect_derive::{type_path_for, impl_with_path}; +use bevy_reflect_derive::impl_type_path; use bevy_utils::{Entry, HashMap}; use std::fmt::{Debug, Formatter}; use std::{ @@ -481,14 +481,9 @@ impl Typed for DynamicStruct { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); CELL.get_or_set(|| TypeInfo::Dynamic(DynamicInfo::new::())) } - - fn type_path() -> &'static TypePath { - static CELL: NonGenericTypePathCell = NonGenericTypePathCell::new(); - CELL.get_or_set(|| type_path_for!(::bevy_reflect::DynamicStruct)) - } } -impl_with_path!(::bevy_reflect::DynamicStruct); +impl_type_path!(DynamicStruct as bevy_reflect::DynamicStruct); /// Compares a [`Struct`] with a [`Reflect`] value. /// diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index 091c9d137801b..f315db81b7dba 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -1,9 +1,9 @@ -use bevy_reflect_derive::type_path_for; - -use crate::utility::{GenericTypePathCell, NonGenericTypeInfoCell, NonGenericTypePathCell}; +use crate::utility::{NonGenericTypeInfoCell, impl_type_path_stored, TypePathStorage}; use crate::{ - self as bevy_reflect, DynamicInfo, FromReflect, GetTypeRegistration, Reflect, ReflectMut, - ReflectOwned, ReflectRef, TypeInfo, TypePath, TypeRegistration, Typed, UnnamedField, WithPath, + self as bevy_reflect, + impl_type_path, + DynamicInfo, FromReflect, GetTypeRegistration, Reflect, ReflectMut, + ReflectOwned, ReflectRef, TypeInfo, TypeRegistration, Typed, UnnamedField, TypePath, }; use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; @@ -380,12 +380,7 @@ impl Typed for DynamicTuple { } } -impl WithPath for DynamicTuple { - fn type_path() -> &'static TypePath { - static CELL: NonGenericTypePathCell = NonGenericTypePathCell::new(); - CELL.get_or_set(|| type_path_for!(::bevy_reflect::DynamicTuple)) - } -} +impl_type_path!(DynamicTuple as bevy_reflect::DynamicTuple); /// Applies the elements of `b` to the corresponding elements of `a`. /// @@ -461,7 +456,7 @@ pub fn tuple_debug(dyn_tuple: &dyn Tuple, f: &mut std::fmt::Formatter<'_>) -> st macro_rules! impl_reflect_tuple { {$($index:tt : $name:tt),*} => { - impl<$($name: Reflect + WithPath),*> Tuple for ($($name,)*) { + impl<$($name: Reflect + TypePath),*> Tuple for ($($name,)*) { #[inline] fn field(&self, index: usize) -> Option<&dyn Reflect> { match index { @@ -513,7 +508,7 @@ macro_rules! impl_reflect_tuple { } } - impl<$($name: Reflect + WithPath),*> Reflect for ($($name,)*) { + impl<$($name: Reflect + TypePath),*> Reflect for ($($name,)*) { fn type_name(&self) -> &str { std::any::type_name::() } @@ -576,7 +571,7 @@ macro_rules! impl_reflect_tuple { } } - impl <$($name: Reflect + WithPath),*> Typed for ($($name,)*) { + impl <$($name: Reflect + TypePath),*> Typed for ($($name,)*) { fn type_info() -> &'static TypeInfo { static CELL: $crate::utility::GenericTypeInfoCell = $crate::utility::GenericTypeInfoCell::new(); CELL.get_or_insert::(|| { @@ -589,25 +584,22 @@ macro_rules! impl_reflect_tuple { } } - impl <$($name: Reflect + WithPath),*> WithPath for ($($name,)*) { - fn type_path() -> &'static TypePath { - static CELL: GenericTypePathCell = GenericTypePathCell::new(); - CELL.get_or_insert::(|| { - TypePath::new_anonymous( - "(".to_owned() $(+ <$name as WithPath>::type_path().path())* + ")", - "(".to_owned() $(+ <$name as WithPath>::type_path().short_path())* + ")", - ) - }) - } - } + impl_type_path_stored!( + || TypePathStorage::new_anonymous( + "(".to_owned() $(+ <$name as TypePath>::type_path())* + ")", + "(".to_owned() $(+ <$name as TypePath>::short_type_path())* + ")", + ), + impl { $($name: Reflect + TypePath),* } for ($($name,)*) + ); + - impl<$($name: Reflect + WithPath),*> GetTypeRegistration for ($($name,)*) { + impl<$($name: Reflect + TypePath),*> GetTypeRegistration for ($($name,)*) { fn get_type_registration() -> TypeRegistration { TypeRegistration::of::<($($name,)*)>() } } - impl<$($name: FromReflect + WithPath),*> FromReflect for ($($name,)*) + impl<$($name: FromReflect + TypePath),*> FromReflect for ($($name,)*) { fn from_reflect(reflect: &dyn Reflect) -> Option { if let ReflectRef::Tuple(_ref_tuple) = reflect.reflect_ref() { diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index cd03812c1742b..c007f99c28db0 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -1,9 +1,9 @@ -use bevy_reflect_derive::type_path_for; +use bevy_reflect_derive::impl_type_path; -use crate::utility::{NonGenericTypeInfoCell, NonGenericTypePathCell}; +use crate::utility::NonGenericTypeInfoCell; use crate::{ self as bevy_reflect, - DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, UnnamedField, TypePath, WithPath, + DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, UnnamedField, }; use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; @@ -386,7 +386,7 @@ impl Typed for DynamicTupleStruct { } } -impl_with_path!(::bevy_reflect::DynamicTupleStruct); +impl_type_path!(DynamicTupleStruct as bevy_reflect::DynamicTupleStruct); /// Compares a [`TupleStruct`] with a [`Reflect`] value. /// diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index 28c0e03ba498e..8bc5ec0fe0656 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -1,5 +1,5 @@ use crate::{ - ArrayInfo, EnumInfo, ListInfo, MapInfo, Reflect, StructInfo, TupleInfo, TupleStructInfo, WithPath, + ArrayInfo, EnumInfo, ListInfo, MapInfo, Reflect, StructInfo, TupleInfo, TupleStructInfo, TypePath, }; use std::any::{Any, TypeId}; @@ -66,7 +66,7 @@ use std::any::{Any, TypeId}; /// ``` /// /// [utility]: crate::utility -pub trait Typed: WithPath + Reflect { +pub trait Typed: Reflect { /// Returns the compile-time [info] for the underlying type. /// /// [info]: TypeInfo diff --git a/crates/bevy_reflect/src/type_path.rs b/crates/bevy_reflect/src/type_path.rs index a49d777830013..0295c43ddf14d 100644 --- a/crates/bevy_reflect/src/type_path.rs +++ b/crates/bevy_reflect/src/type_path.rs @@ -1,72 +1,26 @@ -pub trait WithPath { - /// Returns the [path] of the underlying type. +pub trait TypePath: 'static { + /// Returns the fully qualified path of the underlying type. /// - /// [path]: TypePath - fn type_path() -> &'static TypePath; -} - -pub struct TypePath { - path: String, - short_path: String, - ident: Option, - crate_name: Option, - module_path: Option, -} - -impl TypePath { - pub fn new_primitive(name: String) -> Self { - Self { - path: name.clone(), - short_path: name.clone(), - ident: Some(name), - crate_name: None, - module_path: None, - - } - } + /// For [`Option<()>`], this is `core::option::Option::<()>`. + fn type_path() -> &'static str; - pub fn new_anonymous(path: String, short_path: String) -> Self { - Self { - path, - short_path, - ident: None, - crate_name: None, - module_path: None, - } - } + /// Returns a short pretty-print enabled path to the type. + /// + /// For [`Option<()>`], this is `Option<()>`. + fn short_type_path() -> &'static str; - pub fn new_named(path: String, short_path: String, ident: String, crate_name: String, module_path: String) -> Self { - Self { - path, - short_path, - ident: Some(ident), - crate_name: Some(crate_name), - module_path: Some(module_path), - } - } + /// Returns the name of the type, or [`None`] if it is anonymous. + /// + /// For [`Option<()>`], this is `Option`. + fn type_ident() -> Option<&'static str>; - #[inline] - pub fn path(&self) -> &str { - &self.path - } - - #[inline] - pub fn short_path(&self) -> &str { - &self.short_path - } - - #[inline] - pub fn ident(&self) -> Option<&str> { - self.ident.as_deref() - } - - #[inline] - pub fn crate_name(&self) -> Option<&str> { - self.crate_name.as_deref() - } - - #[inline] - pub fn module_path(&self) -> Option<&str> { - self.module_path.as_deref() - } + /// Returns the name of the crate the type is in, or [`None`] if it is anonymous or a primitive. + /// + /// For [`Option<()>`], this is `core`. + fn crate_name() -> Option<&'static str>; + + /// Returns the path to the moudle the type is in, or [`None`] if it is anonymous or a primitive. + /// + /// For [`Option<()>`], this is `core::option`. + fn module_path() -> Option<&'static str>; } \ No newline at end of file diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index 6df9df1eb6eb6..1a7470939198a 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -7,18 +7,17 @@ use parking_lot::RwLock; use std::any::{Any, TypeId}; mod sealed { - use crate::{TypePath, TypeInfo}; + use crate::{utility::TypePathStorage, TypeInfo}; trait Sealed {} impl Sealed for TypeInfo {} - impl Sealed for TypePath {} + impl Sealed for TypePathStorage {} pub trait TypedProperty: 'static {} impl TypedProperty for T {} } pub use sealed::TypedProperty; - /// A container for [`TypeInfo`] or [`TypePath`] over non-generic types, allowing instances to be stored statically. /// /// This is specifically meant for use with _non_-generic types. If your type _is_ generic, @@ -80,7 +79,7 @@ pub use sealed::TypedProperty; pub struct NonGenericTypedCell(OnceBox); pub type NonGenericTypeInfoCell = NonGenericTypedCell; -pub type NonGenericTypePathCell = NonGenericTypedCell; +pub type NonGenericTypePathCell = NonGenericTypedCell; impl NonGenericTypedCell { /// Initialize a [`NonGenericTypedCell`] for non-generic types. @@ -157,7 +156,7 @@ impl NonGenericTypedCell { pub struct GenericTypedCell(OnceBox>>); pub type GenericTypeInfoCell = GenericTypedCell; -pub type GenericTypePathCell = GenericTypedCell; +pub type GenericTypePathCell = GenericTypedCell; impl GenericTypedCell { /// Initialize a [`GenericTypedCell`] for generic types. @@ -190,3 +189,163 @@ impl GenericTypedCell { }) } } + +pub struct TypePathStorage { + path: String, + short_path: String, + ident: Option, + crate_name: Option, + module_path: Option, +} + +impl TypePathStorage { + pub fn new_primitive>(name: A) -> Self { + Self { + path: name.as_ref().to_owned(), + short_path: name.as_ref().to_owned(), + ident: Some(name.as_ref().to_owned()), + crate_name: None, + module_path: None, + } + } + + pub fn new_anonymous, B: AsRef>( + path: A, + short_path: B, + ) -> Self { + Self { + path: path.as_ref().to_owned(), + short_path: short_path.as_ref().to_owned(), + ident: None, + crate_name: None, + module_path: None, + } + } + + pub fn new_named( + path: A, + short_path: B, + ident: C, + crate_name: D, + module_path: E, + ) -> Self + where + A: AsRef, + B: AsRef, + C: AsRef, + D: AsRef, + E: AsRef, + { + Self { + path: path.as_ref().to_owned(), + short_path: short_path.as_ref().to_owned(), + ident: Some(ident.as_ref().to_owned()), + crate_name: Some(crate_name.as_ref().to_owned()), + module_path: Some(module_path.as_ref().to_owned()), + } + } + + #[inline] + pub fn path(&self) -> &str { + &self.path + } + + #[inline] + pub fn short_path(&self) -> &str { + &self.short_path + } + + #[inline] + pub fn ident(&self) -> Option<&str> { + self.ident.as_deref() + } + + #[inline] + pub fn crate_name(&self) -> Option<&str> { + self.crate_name.as_deref() + } + + #[inline] + pub fn module_path(&self) -> Option<&str> { + self.module_path.as_deref() + } +} + +pub mod __private { + #[macro_export] + macro_rules! void_tokens { + ($($tokens: tt)*) => {}; + } + + #[macro_export] + macro_rules! first_present { + ({ $($first:tt)* } $( { $($rest:tt)* } )*) => { + $($first)* + } + } + + pub use first_present; + pub use void_tokens; +} + +#[macro_export] +macro_rules! impl_type_path_stored { + ($storage_fn: expr, impl$({ $($param:tt)* })? for $($impl_tt: tt)+) => { + const _: () = { + trait GetStorage { + fn get_storage() -> &'static $crate::utility::TypePathStorage; + } + + impl$(< $($param)* >)? GetStorage for $($impl_tt)+ { + #[inline] + fn get_storage() -> &'static $crate::utility::TypePathStorage { + $crate::utility::__private::first_present!( + $({ + $crate::utility::__private::void_tokens!($($param)*); + static CELL: $crate::utility::GenericTypePathCell = $crate::utility::GenericTypePathCell::new(); + return CELL.get_or_insert::($storage_fn); + })? + { + static CELL: $crate::utility::NonGenericTypePathCell = $crate::utility::NonGenericTypePathCell::new(); + return CELL.get_or_set($storage_fn); + } + ); + } + } + + impl $(< $($param)* >)? $crate::TypePath for $($impl_tt)+ { + fn type_path() -> &'static str { + &Self::get_storage().path() + } + + fn short_type_path() -> &'static str { + &Self::get_storage().short_path() + } + + fn type_ident() -> Option<&'static str> { + match Self::get_storage().ident() { + Some(x) => Some(x), + None => None + } + } + + fn crate_name() -> Option<&'static str> { + match Self::get_storage().crate_name() { + Some(x) => Some(x), + None => None + } + } + + fn module_path() -> Option<&'static str> { + match Self::get_storage().module_path() { + Some(x) => Some(x), + None => None + } + } + } + }; + } +} +pub use impl_type_path_stored; + +struct TyPath; diff --git a/crates/bevy_render/src/mesh/mesh/mod.rs b/crates/bevy_render/src/mesh/mesh/mod.rs index d58c5e2cf703d..3493c626505c9 100644 --- a/crates/bevy_render/src/mesh/mesh/mod.rs +++ b/crates/bevy_render/src/mesh/mesh/mod.rs @@ -12,7 +12,7 @@ use bevy_core::cast_slice; use bevy_derive::EnumVariantMeta; use bevy_ecs::system::{lifetimeless::SRes, SystemParamItem}; use bevy_math::*; -use bevy_reflect::TypeUuid; +use bevy_reflect::{TypeUuid, TypePath}; use bevy_utils::{tracing::error, Hashed}; use std::{collections::BTreeMap, hash::Hash, iter::FusedIterator}; use thiserror::Error; @@ -25,7 +25,7 @@ pub const INDEX_BUFFER_ASSET_INDEX: u64 = 0; pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10; // TODO: allow values to be unloaded after been submitting to the GPU to conserve memory -#[derive(Debug, TypeUuid, Clone)] +#[derive(Debug, TypeUuid, TypePath, Clone)] #[uuid = "8ecbac0f-f545-4473-ad43-e1f4243af51e"] pub struct Mesh { primitive_topology: PrimitiveTopology, diff --git a/crates/bevy_render/src/mesh/mesh/skinning.rs b/crates/bevy_render/src/mesh/mesh/skinning.rs index 3c3cef062de06..78da53d3cd8a3 100644 --- a/crates/bevy_render/src/mesh/mesh/skinning.rs +++ b/crates/bevy_render/src/mesh/mesh/skinning.rs @@ -6,7 +6,7 @@ use bevy_ecs::{ reflect::ReflectMapEntities, }; use bevy_math::Mat4; -use bevy_reflect::{Reflect, TypeUuid}; +use bevy_reflect::{Reflect, TypeUuid, TypePath}; use std::ops::Deref; #[derive(Component, Debug, Default, Clone, Reflect)] @@ -26,7 +26,7 @@ impl MapEntities for SkinnedMesh { } } -#[derive(Debug, TypeUuid)] +#[derive(Debug, TypeUuid, TypePath)] #[uuid = "b9f155a9-54ec-4026-988f-e0a03e99a76f"] pub struct SkinnedMeshInverseBindposes(Box<[Mat4]>); diff --git a/crates/bevy_render/src/render_resource/shader.rs b/crates/bevy_render/src/render_resource/shader.rs index 63e8b5b64f655..d5069e8652123 100644 --- a/crates/bevy_render/src/render_resource/shader.rs +++ b/crates/bevy_render/src/render_resource/shader.rs @@ -1,7 +1,7 @@ use super::ShaderDefVal; use crate::define_atomic_id; use bevy_asset::{AssetLoader, AssetPath, Handle, LoadContext, LoadedAsset}; -use bevy_reflect::TypeUuid; +use bevy_reflect::{TypeUuid, TypePath}; use bevy_utils::{tracing::error, BoxedFuture, HashMap}; use naga::{back::wgsl::WriterFlags, valid::Capabilities, valid::ModuleInfo, Module}; use once_cell::sync::Lazy; @@ -25,7 +25,7 @@ pub enum ShaderReflectError { } /// A shader, as defined by its [`ShaderSource`] and [`ShaderStage`](naga::ShaderStage) /// This is an "unprocessed" shader. It can contain preprocessor directives. -#[derive(Debug, Clone, TypeUuid)] +#[derive(Debug, Clone, TypeUuid, TypePath)] #[uuid = "d95bc916-6c55-4de3-9622-37e7b6969fda"] pub struct Shader { source: Source, diff --git a/crates/bevy_scene/src/dynamic_scene.rs b/crates/bevy_scene/src/dynamic_scene.rs index c0eb067b2ca8b..c9e199501e7d2 100644 --- a/crates/bevy_scene/src/dynamic_scene.rs +++ b/crates/bevy_scene/src/dynamic_scene.rs @@ -6,7 +6,7 @@ use bevy_ecs::{ reflect::{ReflectComponent, ReflectMapEntities}, world::World, }; -use bevy_reflect::{Reflect, TypeRegistryArc, TypeUuid}; +use bevy_reflect::{Reflect, TypeRegistryArc, TypeUuid, TypePath}; #[cfg(feature = "serialize")] use crate::serde::SceneSerializer; @@ -20,7 +20,7 @@ use serde::Serialize; /// * adding the [`Handle`](bevy_asset::Handle) to an entity (the scene will only be /// visible if the entity already has [`Transform`](bevy_transform::components::Transform) and /// [`GlobalTransform`](bevy_transform::components::GlobalTransform) components) -#[derive(Default, TypeUuid)] +#[derive(Default, TypeUuid, TypePath)] #[uuid = "749479b1-fb8c-4ff8-a775-623aa76014f5"] pub struct DynamicScene { pub entities: Vec, diff --git a/crates/bevy_scene/src/scene.rs b/crates/bevy_scene/src/scene.rs index 4df757aa5838f..206d2097baf97 100644 --- a/crates/bevy_scene/src/scene.rs +++ b/crates/bevy_scene/src/scene.rs @@ -4,7 +4,7 @@ use bevy_ecs::{ reflect::{ReflectComponent, ReflectMapEntities}, world::World, }; -use bevy_reflect::TypeUuid; +use bevy_reflect::{TypeUuid, TypePath}; use crate::{DynamicScene, InstanceInfo, SceneSpawnError}; @@ -14,7 +14,7 @@ use crate::{DynamicScene, InstanceInfo, SceneSpawnError}; /// * adding the [`Handle`](bevy_asset::Handle) to an entity (the scene will only be /// visible if the entity already has [`Transform`](bevy_transform::components::Transform) and /// [`GlobalTransform`](bevy_transform::components::GlobalTransform) components) -#[derive(Debug, TypeUuid)] +#[derive(Debug, TypeUuid, TypePath)] #[uuid = "c156503c-edd9-4ec7-8d33-dab392df03cd"] pub struct Scene { pub world: World, diff --git a/crates/bevy_sprite/src/mesh2d/material.rs b/crates/bevy_sprite/src/mesh2d/material.rs index c5f0e0fb5d72b..a4299dd80b1ab 100644 --- a/crates/bevy_sprite/src/mesh2d/material.rs +++ b/crates/bevy_sprite/src/mesh2d/material.rs @@ -14,7 +14,7 @@ use bevy_ecs::{ world::FromWorld, }; use bevy_log::error; -use bevy_reflect::TypeUuid; +use bevy_reflect::{TypeUuid, TypePath}; use bevy_render::{ extract_component::ExtractComponentPlugin, mesh::{Mesh, MeshVertexBufferLayout}, @@ -111,7 +111,7 @@ use crate::{ /// @group(1) @binding(2) /// var color_sampler: sampler; /// ``` -pub trait Material2d: AsBindGroup + Send + Sync + Clone + TypeUuid + Sized + 'static { +pub trait Material2d: AsBindGroup + Send + Sync + Clone + TypeUuid + TypePath + Sized + 'static { /// Returns this material's vertex shader. If [`ShaderRef::Default`] is returned, the default mesh vertex shader /// will be used. fn vertex_shader() -> ShaderRef { diff --git a/crates/bevy_text/src/font.rs b/crates/bevy_text/src/font.rs index 56fe1e60fc0de..aab2db9d94db1 100644 --- a/crates/bevy_text/src/font.rs +++ b/crates/bevy_text/src/font.rs @@ -1,11 +1,11 @@ use ab_glyph::{FontArc, FontVec, InvalidFont, OutlinedGlyph}; -use bevy_reflect::TypeUuid; +use bevy_reflect::{TypeUuid, TypePath}; use bevy_render::{ render_resource::{Extent3d, TextureDimension, TextureFormat}, texture::Image, }; -#[derive(Debug, TypeUuid)] +#[derive(Debug, TypeUuid, TypePath)] #[uuid = "97059ac6-c9ba-4da9-95b6-bed82c3ce198"] pub struct Font { pub font: FontArc, diff --git a/crates/bevy_text/src/font_atlas_set.rs b/crates/bevy_text/src/font_atlas_set.rs index 9468a5405fcfb..0aa0209ba2ce1 100644 --- a/crates/bevy_text/src/font_atlas_set.rs +++ b/crates/bevy_text/src/font_atlas_set.rs @@ -2,6 +2,7 @@ use crate::{error::TextError, Font, FontAtlas}; use ab_glyph::{GlyphId, OutlinedGlyph, Point}; use bevy_asset::{Assets, Handle}; use bevy_math::Vec2; +use bevy_reflect::TypePath; use bevy_reflect::TypeUuid; use bevy_render::texture::Image; use bevy_sprite::TextureAtlas; @@ -10,7 +11,7 @@ use bevy_utils::HashMap; type FontSizeKey = FloatOrd; -#[derive(TypeUuid)] +#[derive(TypeUuid, TypePath)] #[uuid = "73ba778b-b6b5-4f45-982d-d21b6b86ace2"] pub struct FontAtlasSet { font_atlases: HashMap>, diff --git a/examples/3d/lines.rs b/examples/3d/lines.rs index 8ff8c8dee6cdf..c8ecb82dd45d4 100644 --- a/examples/3d/lines.rs +++ b/examples/3d/lines.rs @@ -3,7 +3,7 @@ use bevy::{ pbr::{MaterialPipeline, MaterialPipelineKey}, prelude::*, - reflect::TypeUuid, + reflect::{TypeUuid, TypePath}, render::{ mesh::{MeshVertexBufferLayout, PrimitiveTopology}, render_resource::{ @@ -62,7 +62,7 @@ fn setup( }); } -#[derive(Default, AsBindGroup, TypeUuid, Debug, Clone)] +#[derive(Default, AsBindGroup, TypeUuid, TypePath, Debug, Clone)] #[uuid = "050ce6ac-080a-4d8c-b6b5-b5bab7560d8f"] struct LineMaterial { #[uniform(0)] diff --git a/examples/asset/custom_asset.rs b/examples/asset/custom_asset.rs index 50089d5dfb5fb..3c9dfa0205ac7 100644 --- a/examples/asset/custom_asset.rs +++ b/examples/asset/custom_asset.rs @@ -3,12 +3,12 @@ use bevy::{ asset::{AssetLoader, LoadContext, LoadedAsset}, prelude::*, - reflect::TypeUuid, + reflect::{TypeUuid, TypePath}, utils::BoxedFuture, }; use serde::Deserialize; -#[derive(Debug, Deserialize, TypeUuid)] +#[derive(Debug, Deserialize, TypeUuid, TypePath)] #[uuid = "39cadc56-aa9c-4543-8640-a018b74b5052"] pub struct CustomAsset { pub value: i32, diff --git a/examples/reflection/generic_reflection.rs b/examples/reflection/generic_reflection.rs index b91a4fa0733bc..f4c049d3a7ed6 100644 --- a/examples/reflection/generic_reflection.rs +++ b/examples/reflection/generic_reflection.rs @@ -1,6 +1,6 @@ //! Demonstrates how reflection is used with generic Rust types. -use bevy::prelude::*; +use bevy::{prelude::*, reflect::TypePath}; use std::any::TypeId; fn main() { @@ -13,7 +13,7 @@ fn main() { } #[derive(Reflect)] -struct MyType { +struct MyType { value: T, } diff --git a/examples/shader/animate_shader.rs b/examples/shader/animate_shader.rs index cb5d09038a4a3..7bf1f62afe48f 100644 --- a/examples/shader/animate_shader.rs +++ b/examples/shader/animate_shader.rs @@ -1,7 +1,7 @@ //! A shader that uses dynamic data like the time since startup. //! The time data is in the globals binding which is part of the `mesh_view_bindings` shader import. -use bevy::{prelude::*, reflect::TypeUuid, render::render_resource::*}; +use bevy::{prelude::*, reflect::{TypeUuid, TypePath}, render::render_resource::*}; fn main() { App::new() @@ -31,7 +31,7 @@ fn setup( }); } -#[derive(AsBindGroup, TypeUuid, Debug, Clone)] +#[derive(AsBindGroup, TypeUuid, TypePath, Debug, Clone)] #[uuid = "a3d71c04-d054-4946-80f8-ba6cfbc90cad"] struct CustomMaterial {} diff --git a/examples/shader/array_texture.rs b/examples/shader/array_texture.rs index 4f935369a00d2..628b6847a2b32 100644 --- a/examples/shader/array_texture.rs +++ b/examples/shader/array_texture.rs @@ -1,7 +1,7 @@ use bevy::{ asset::LoadState, prelude::*, - reflect::TypeUuid, + reflect::{TypeUuid, TypePath}, render::render_resource::{AsBindGroup, ShaderRef}, }; @@ -89,7 +89,7 @@ fn create_array_texture( } } -#[derive(AsBindGroup, Debug, Clone, TypeUuid)] +#[derive(AsBindGroup, Debug, Clone, TypeUuid, TypePath)] #[uuid = "9c5a0ddf-1eaf-41b4-9832-ed736fd26af3"] struct ArrayTextureMaterial { #[texture(0, dimension = "2d_array")] diff --git a/examples/shader/custom_vertex_attribute.rs b/examples/shader/custom_vertex_attribute.rs index e98ca56a24b7e..52587a771bb28 100644 --- a/examples/shader/custom_vertex_attribute.rs +++ b/examples/shader/custom_vertex_attribute.rs @@ -3,7 +3,7 @@ use bevy::{ pbr::{MaterialPipeline, MaterialPipelineKey}, prelude::*, - reflect::TypeUuid, + reflect::{TypeUuid, TypePath}, render::{ mesh::{MeshVertexAttribute, MeshVertexBufferLayout}, render_resource::{ @@ -57,7 +57,7 @@ fn setup( } // This is the struct that will be passed to your shader -#[derive(AsBindGroup, Debug, Clone, TypeUuid)] +#[derive(AsBindGroup, Debug, Clone, TypeUuid, TypePath)] #[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"] pub struct CustomMaterial { #[uniform(0)] diff --git a/examples/shader/post_processing.rs b/examples/shader/post_processing.rs index ea306fd97069f..5831aa03f873b 100644 --- a/examples/shader/post_processing.rs +++ b/examples/shader/post_processing.rs @@ -6,7 +6,7 @@ use bevy::{ core_pipeline::clear_color::ClearColorConfig, prelude::*, - reflect::TypeUuid, + reflect::{TypeUuid, TypePath}, render::{ camera::RenderTarget, render_resource::{ @@ -171,7 +171,7 @@ fn main_camera_cube_rotator_system( // Region below declares of the custom material handling post processing effect /// Our custom post processing material -#[derive(AsBindGroup, TypeUuid, Clone)] +#[derive(AsBindGroup, TypeUuid, TypePath, Clone)] #[uuid = "bc2f08eb-a0fb-43f1-a908-54871ea597d5"] struct PostProcessingMaterial { /// In this example, this image will be the result of the main camera. diff --git a/examples/shader/shader_defs.rs b/examples/shader/shader_defs.rs index 4735406ace235..dd28649edfbba 100644 --- a/examples/shader/shader_defs.rs +++ b/examples/shader/shader_defs.rs @@ -3,7 +3,7 @@ use bevy::{ pbr::{MaterialPipeline, MaterialPipelineKey}, prelude::*, - reflect::TypeUuid, + reflect::{TypeUuid, TypePath}, render::{ mesh::MeshVertexBufferLayout, render_resource::{ @@ -75,7 +75,7 @@ impl Material for CustomMaterial { } // This is the struct that will be passed to your shader -#[derive(AsBindGroup, TypeUuid, Debug, Clone)] +#[derive(AsBindGroup, TypeUuid, TypePath, Debug, Clone)] #[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"] #[bind_group_data(CustomMaterialKey)] pub struct CustomMaterial { diff --git a/examples/shader/shader_material.rs b/examples/shader/shader_material.rs index d501d6c092952..c8d7fb4b9d0b8 100644 --- a/examples/shader/shader_material.rs +++ b/examples/shader/shader_material.rs @@ -2,7 +2,7 @@ use bevy::{ prelude::*, - reflect::TypeUuid, + reflect::{TypeUuid, TypePath}, render::render_resource::{AsBindGroup, ShaderRef}, }; @@ -53,7 +53,7 @@ impl Material for CustomMaterial { } // This is the struct that will be passed to your shader -#[derive(AsBindGroup, TypeUuid, Debug, Clone)] +#[derive(AsBindGroup, TypeUuid, TypePath, Debug, Clone)] #[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"] pub struct CustomMaterial { #[uniform(0)] diff --git a/examples/shader/shader_material_glsl.rs b/examples/shader/shader_material_glsl.rs index 01409b2634939..15f471b87b708 100644 --- a/examples/shader/shader_material_glsl.rs +++ b/examples/shader/shader_material_glsl.rs @@ -3,7 +3,7 @@ use bevy::{ pbr::{MaterialPipeline, MaterialPipelineKey}, prelude::*, - reflect::TypeUuid, + reflect::{TypeUuid, TypePath}, render::{ mesh::MeshVertexBufferLayout, render_resource::{ @@ -47,7 +47,7 @@ fn setup( } // This is the struct that will be passed to your shader -#[derive(AsBindGroup, Clone, TypeUuid)] +#[derive(AsBindGroup, Clone, TypeUuid, TypePath)] #[uuid = "4ee9c363-1124-4113-890e-199d81b00281"] pub struct CustomMaterial { #[uniform(0)] diff --git a/examples/shader/shader_material_screenspace_texture.rs b/examples/shader/shader_material_screenspace_texture.rs index 9fd63f8588d5a..57f70ba700b8e 100644 --- a/examples/shader/shader_material_screenspace_texture.rs +++ b/examples/shader/shader_material_screenspace_texture.rs @@ -2,7 +2,7 @@ use bevy::{ prelude::*, - reflect::TypeUuid, + reflect::{TypeUuid, TypePath}, render::render_resource::{AsBindGroup, ShaderRef}, }; @@ -66,7 +66,7 @@ fn rotate_camera(mut camera: Query<&mut Transform, With>, time: Res< cam_transform.look_at(Vec3::ZERO, Vec3::Y); } -#[derive(AsBindGroup, Debug, Clone, TypeUuid)] +#[derive(AsBindGroup, Debug, Clone, TypeUuid, TypePath)] #[uuid = "b62bb455-a72c-4b56-87bb-81e0554e234f"] pub struct CustomMaterial { #[texture(0)] From 8ea850f634a6e994afe72d4743d359711bc92ed5 Mon Sep 17 00:00:00 2001 From: radiish Date: Fri, 13 Jan 2023 20:45:27 +0000 Subject: [PATCH 03/52] `type_name` attributes --- crates/bevy_asset/src/asset_server.rs | 2 +- crates/bevy_audio/src/audio_output.rs | 2 +- crates/bevy_audio/src/audio_source.rs | 2 +- crates/bevy_ecs/src/reflect.rs | 2 +- crates/bevy_gltf/src/lib.rs | 2 +- crates/bevy_input/src/input.rs | 2 +- crates/bevy_pbr/src/material.rs | 6 +- .../bevy_reflect_derive/src/derive_data.rs | 80 ++++++--- .../bevy_reflect_derive/src/from_reflect.rs | 4 +- .../bevy_reflect_derive/src/impls/mod.rs | 4 +- .../bevy_reflect_derive/src/impls/typed.rs | 27 ++- .../bevy_reflect_derive/src/lib.rs | 82 ++++++--- .../bevy_reflect_derive/src/reflect_value.rs | 21 +-- .../bevy_reflect_derive/src/registration.rs | 4 +- .../bevy_reflect_derive/src/type_path.rs | 115 ++++++++----- crates/bevy_reflect/src/array.rs | 16 +- crates/bevy_reflect/src/enums/dynamic_enum.rs | 11 +- crates/bevy_reflect/src/impls/glam.rs | 49 +++++- crates/bevy_reflect/src/impls/rect.rs | 1 + crates/bevy_reflect/src/impls/smallvec.rs | 21 ++- crates/bevy_reflect/src/impls/std.rs | 157 +++++++++++++----- crates/bevy_reflect/src/lib.rs | 31 ++-- crates/bevy_reflect/src/list.rs | 7 +- crates/bevy_reflect/src/map.rs | 5 +- crates/bevy_reflect/src/reflect.rs | 8 +- crates/bevy_reflect/src/struct_trait.rs | 8 +- crates/bevy_reflect/src/tuple.rs | 15 +- crates/bevy_reflect/src/tuple_struct.rs | 8 +- crates/bevy_reflect/src/type_info.rs | 4 +- crates/bevy_reflect/src/type_path.rs | 20 +-- crates/bevy_reflect/src/utility.rs | 11 +- crates/bevy_render/src/mesh/mesh/mod.rs | 2 +- crates/bevy_render/src/mesh/mesh/skinning.rs | 2 +- .../bevy_render/src/render_resource/shader.rs | 2 +- crates/bevy_scene/src/dynamic_scene.rs | 2 +- crates/bevy_scene/src/scene.rs | 2 +- crates/bevy_sprite/src/mesh2d/material.rs | 6 +- crates/bevy_text/src/font.rs | 2 +- examples/3d/lines.rs | 2 +- examples/asset/custom_asset.rs | 2 +- examples/shader/animate_shader.rs | 6 +- examples/shader/array_texture.rs | 2 +- examples/shader/custom_vertex_attribute.rs | 2 +- examples/shader/post_processing.rs | 2 +- examples/shader/shader_defs.rs | 2 +- examples/shader/shader_material.rs | 2 +- examples/shader/shader_material_glsl.rs | 2 +- .../shader_material_screenspace_texture.rs | 2 +- 48 files changed, 485 insertions(+), 284 deletions(-) diff --git a/crates/bevy_asset/src/asset_server.rs b/crates/bevy_asset/src/asset_server.rs index b9227ce3734a8..0a350f7d14823 100644 --- a/crates/bevy_asset/src/asset_server.rs +++ b/crates/bevy_asset/src/asset_server.rs @@ -646,7 +646,7 @@ mod test { use crate::{loader::LoadedAsset, update_asset_storage_system}; use bevy_app::App; use bevy_ecs::prelude::*; - use bevy_reflect::{TypeUuid, TypePath}; + use bevy_reflect::{TypePath, TypeUuid}; use bevy_utils::BoxedFuture; #[derive(Debug, TypeUuid, TypePath)] diff --git a/crates/bevy_audio/src/audio_output.rs b/crates/bevy_audio/src/audio_output.rs index 5676a437b5b33..610f56f74f7a6 100644 --- a/crates/bevy_audio/src/audio_output.rs +++ b/crates/bevy_audio/src/audio_output.rs @@ -1,7 +1,7 @@ use crate::{Audio, AudioSource, Decodable}; use bevy_asset::{Asset, Assets}; use bevy_ecs::system::{Res, ResMut, Resource}; -use bevy_reflect::{TypeUuid, TypePath}; +use bevy_reflect::{TypePath, TypeUuid}; use bevy_utils::tracing::warn; use rodio::{OutputStream, OutputStreamHandle, Sink, Source}; use std::marker::PhantomData; diff --git a/crates/bevy_audio/src/audio_source.rs b/crates/bevy_audio/src/audio_source.rs index 589eafbfd42bd..5ec1d0872515c 100644 --- a/crates/bevy_audio/src/audio_source.rs +++ b/crates/bevy_audio/src/audio_source.rs @@ -1,6 +1,6 @@ use anyhow::Result; use bevy_asset::{Asset, AssetLoader, LoadContext, LoadedAsset}; -use bevy_reflect::{TypeUuid, TypePath}; +use bevy_reflect::{TypePath, TypeUuid}; use bevy_utils::BoxedFuture; use std::{io::Cursor, sync::Arc}; diff --git a/crates/bevy_ecs/src/reflect.rs b/crates/bevy_ecs/src/reflect.rs index b865844731b66..c1c02a42dcb43 100644 --- a/crates/bevy_ecs/src/reflect.rs +++ b/crates/bevy_ecs/src/reflect.rs @@ -404,7 +404,7 @@ impl FromType for ReflectResource { } } -impl_reflect_value!(Entity(Hash, PartialEq, Serialize, Deserialize)); +impl_reflect_value!(Entity(Hash, PartialEq, Serialize, Deserialize) in bevy_ecs); impl_from_reflect_value!(Entity); #[derive(Clone)] diff --git a/crates/bevy_gltf/src/lib.rs b/crates/bevy_gltf/src/lib.rs index 77a5b14650eba..c5f40a3de9f55 100644 --- a/crates/bevy_gltf/src/lib.rs +++ b/crates/bevy_gltf/src/lib.rs @@ -9,7 +9,7 @@ use bevy_app::prelude::*; use bevy_asset::{AddAsset, Handle}; use bevy_ecs::{prelude::Component, reflect::ReflectComponent}; use bevy_pbr::StandardMaterial; -use bevy_reflect::{Reflect, TypeUuid, TypePath}; +use bevy_reflect::{Reflect, TypePath, TypeUuid}; use bevy_render::mesh::Mesh; use bevy_scene::Scene; diff --git a/crates/bevy_input/src/input.rs b/crates/bevy_input/src/input.rs index 033e9e3bfb246..3e425490b9f85 100644 --- a/crates/bevy_input/src/input.rs +++ b/crates/bevy_input/src/input.rs @@ -1,5 +1,5 @@ use bevy_ecs::system::Resource; -use bevy_reflect::{std_traits::ReflectDefault, Reflect, Typed, TypePath}; +use bevy_reflect::{std_traits::ReflectDefault, Reflect, TypePath}; use bevy_utils::HashSet; use std::hash::Hash; diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 18c2bf39797d5..30bad3ffa99c1 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -19,7 +19,7 @@ use bevy_ecs::{ }, world::FromWorld, }; -use bevy_reflect::{TypeUuid, TypePath}; +use bevy_reflect::{TypePath, TypeUuid}; use bevy_render::{ extract_component::ExtractComponentPlugin, mesh::{Mesh, MeshVertexBufferLayout}, @@ -106,7 +106,9 @@ use std::marker::PhantomData; /// @group(1) @binding(2) /// var color_sampler: sampler; /// ``` -pub trait Material: AsBindGroup + Send + Sync + Clone + TypeUuid + TypePath + Sized + 'static { +pub trait Material: + AsBindGroup + Send + Sync + Clone + TypeUuid + TypePath + Sized + 'static +{ /// Returns this material's vertex shader. If [`ShaderRef::Default`] is returned, the default mesh vertex shader /// will be used. fn vertex_shader() -> ShaderRef { 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 ee0ce3d689788..922a13ba83b39 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs @@ -1,5 +1,3 @@ -use std::borrow::Cow; - use crate::container_attributes::ReflectTraits; use crate::field_attributes::{parse_field_attrs, ReflectFieldAttr}; use crate::type_path::parse_path_no_leading_colon; @@ -10,14 +8,14 @@ use bit_set::BitSet; use quote::{quote, ToTokens}; use crate::{ - utility, REFLECT_ATTRIBUTE_NAME, REFLECT_VALUE_ATTRIBUTE_NAME, TYPE_PATH_ATTRIBUTE_NAME, + utility, REFLECT_ATTRIBUTE_NAME, REFLECT_VALUE_ATTRIBUTE_NAME, TYPE_NAME_ATTRIBUTE_NAME, + TYPE_PATH_ATTRIBUTE_NAME, }; use syn::punctuated::Punctuated; use syn::spanned::Spanned; use syn::{ - parse_str, AngleBracketedGenericArguments, Data, DeriveInput, Field, Fields, GenericParam, - Generics, Ident, ImplGenerics, Lit, LitStr, Meta, Path, PathSegment, Token, Type, TypeGenerics, - TypePath, Variant, WhereClause, + parse_str, Data, DeriveInput, Field, Fields, GenericParam, Generics, Ident, Lit, LitStr, Meta, + Path, PathSegment, Token, Type, Variant, }; pub(crate) enum ReflectDerive<'a> { @@ -143,7 +141,9 @@ impl<'a> ReflectDerive<'a> { // Should indicate whether `#[reflect_value]` was used. let mut reflect_mode = None; // Should indicate whether `#[type_path = "..."]` was used. - let mut type_path_alias: Option = None; + let mut alias_type_path: Option = None; + + let mut alias_type_name: Option = None; #[cfg(feature = "documentation")] let mut doc = crate::documentation::Documentation::default(); @@ -185,15 +185,6 @@ impl<'a> ReflectDerive<'a> { reflect_mode = Some(ReflectMode::Value); } Meta::NameValue(pair) if pair.path.is_ident(TYPE_PATH_ATTRIBUTE_NAME) => { - if type_path_alias.is_some() { - return Err(syn::Error::new( - pair.span(), - format_args!( - "cannot use multuple `#[{TYPE_PATH_ATTRIBUTE_NAME} = \"...\"]` attributes" - ), - )); - } - let Lit::Str(lit) = pair.lit else { return Err(syn::Error::new( pair.span(), @@ -201,11 +192,21 @@ impl<'a> ReflectDerive<'a> { )); }; - type_path_alias = Some(syn::parse::Parser::parse_str( + alias_type_path = Some(syn::parse::Parser::parse_str( parse_path_no_leading_colon, &lit.value(), )?); } + Meta::NameValue(pair) if pair.path.is_ident(TYPE_NAME_ATTRIBUTE_NAME) => { + let Lit::Str(lit) = pair.lit else { + return Err(syn::Error::new( + pair.span(), + format_args!("`#[{TYPE_NAME_ATTRIBUTE_NAME} = \"...\"]` must be a string literal"), + )); + }; + + alias_type_name = Some(parse_str(&lit.value())?); + } #[cfg(feature = "documentation")] Meta::NameValue(pair) if pair.path.is_ident("doc") => { if let Lit::Str(lit) = pair.lit { @@ -215,8 +216,20 @@ impl<'a> ReflectDerive<'a> { _ => continue, } } - - let path_to_type = PathToType::Internal { ident: &input.ident, alias: type_path_alias }; + if let Some(path) = &mut alias_type_path { + let ident = alias_type_name.unwrap_or(input.ident.clone()); + path.segments.push(PathSegment::from(ident)); + } else if let Some(name) = alias_type_name { + return Err(syn::Error::new( + name.span(), + format!("cannot use `#[{TYPE_NAME_ATTRIBUTE_NAME} = \"...\"]` without a `#[{TYPE_PATH_ATTRIBUTE_NAME} = \"...\"]` attribute."), + )); + } + + let path_to_type = PathToType::Internal { + ident: &input.ident, + alias: alias_type_path, + }; let meta = ReflectMeta::new(path_to_type, &input.generics, traits); @@ -556,7 +569,7 @@ impl<'a> EnumVariant<'a> { pub(crate) enum PathToType<'a> { /// Types without a crate/module (e.g. `bool`). - Primtive(&'a Ident), + Primitive(&'a Ident), /// Using `::my_crate::foo::Bar` syntax. /// /// May have a seperate alias path used for the `TypePath` implementation. @@ -570,6 +583,7 @@ pub(crate) enum PathToType<'a> { alias: Option, }, /// Any [`syn::Type`] with only a defined `type_path` and `short_type_path`. + #[allow(dead_code)] Anonymous { qualified_type: Type, long_type_path: proc_macro2::TokenStream, @@ -605,19 +619,31 @@ impl<'a> PathToType<'a> { /// or [`None`] if anonymous or a non-aliased [`PathToType::Internal`]. fn named_as_path(&self) -> Option<&Path> { match self { - Self::Internal { ident, alias } => alias.as_ref(), + Self::Internal { alias, .. } => alias.as_ref(), Self::External { path, alias } => Some(alias.as_ref().unwrap_or(path)), _ => None, } } + /// Returns whether this [internal] or [external] path is aliased. + /// + /// [internal]: PathToType::Internal + /// [external]: PathToType::External + pub fn is_alias(&self) -> bool { + match self { + Self::Internal { alias, .. } => alias.is_some(), + Self::External { alias, .. } => alias.is_some(), + _ => false, + } + } + /// Returns whether [`crate_name`](PathToType::crate_name) /// and [`module_path`](PathToType::module_path) return [`Some`]. /// /// This is false for primitives and anonymous paths. - pub fn has_module(&self) -> bool { + pub fn is_named(&self) -> bool { match self { - Self::Primtive(_) | Self::Anonymous { .. } => false, + Self::Primitive(_) | Self::Anonymous { .. } => false, _ => true, } } @@ -653,7 +679,7 @@ impl<'a> PathToType<'a> { } match self { - Self::Primtive(ident) => { + Self::Primitive(ident) => { let ident = LitStr::new(&ident.to_string(), ident.span()); quote! { #ident.to_owned() @@ -693,7 +719,7 @@ impl<'a> PathToType<'a> { /// Returns the name of the type. This is not necessarily a valid qualified path to the type. pub fn ident(&self) -> Option<&Ident> { self.named_as_ident().or_else(|| match self { - Self::Primtive(ident) => Some(ident), + Self::Primitive(ident) => Some(ident), _ => None, }) } @@ -702,7 +728,7 @@ impl<'a> PathToType<'a> { impl<'a> ToTokens for PathToType<'a> { fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { match self { - Self::Internal { ident, .. } | Self::Primtive(ident) => ident.to_tokens(tokens), + Self::Internal { ident, .. } | Self::Primitive(ident) => ident.to_tokens(tokens), Self::External { path, .. } => path.to_tokens(tokens), Self::Anonymous { qualified_type, .. } => qualified_type.to_tokens(tokens), } @@ -770,7 +796,7 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea } }; - if !path_to_type.has_module() { + if !path_to_type.is_named() { quote! { #bevy_reflect_path::utility::TypePathStorage::new_anonymous( #path, 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 ede53e89dba46..2e3958bd609f4 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs @@ -78,7 +78,6 @@ fn impl_struct_internal(reflect_struct: &ReflectStruct, is_tuple: bool) -> Token let fqoption = FQOption.into_token_stream(); let struct_path = reflect_struct.meta().path_to_type(); - let generics = reflect_struct.meta().generics(); let bevy_reflect_path = reflect_struct.meta().bevy_reflect_path(); let ref_struct = Ident::new("__ref_struct", Span::call_site()); @@ -117,7 +116,8 @@ fn impl_struct_internal(reflect_struct: &ReflectStruct, is_tuple: bool) -> Token ) }; - let (impl_generics, ty_generics, where_clause) = reflect_struct.meta().generics().split_for_impl(); + let (impl_generics, ty_generics, where_clause) = + reflect_struct.meta().generics().split_for_impl(); // Add FromReflect bound for each active field let mut where_from_reflect_clause = if where_clause.is_some() { diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/impls/mod.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/mod.rs index 97f066c9ff90b..db5418b446348 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/mod.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/mod.rs @@ -7,6 +7,6 @@ mod values; pub(crate) use enums::impl_enum; pub(crate) use structs::impl_struct; pub(crate) use tuple_structs::impl_tuple_struct; -pub(crate) use typed::impl_typed; pub(crate) use typed::impl_type_path; -pub(crate) use values::impl_value; \ No newline at end of file +pub(crate) use typed::impl_typed; +pub(crate) use values::impl_value; 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 dfe973c8aec71..edff342091c71 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -1,8 +1,8 @@ - use crate::utility::{extend_where_clause, WhereClauseOptions}; use crate::ReflectMeta; use proc_macro2::Ident; use quote::quote; +use crate::derive_data::{type_path_generator, PathToType, ReflectMeta}; fn static_typed_cell( meta: &ReflectMeta, @@ -43,7 +43,10 @@ pub(crate) enum TypedProperty { TypePath, } -pub(crate) fn impl_type_path(meta: &ReflectMeta) -> proc_macro2::TokenStream { +pub(crate) fn impl_type_path( + meta: &ReflectMeta, + where_clause_options: &WhereClauseOptions, +) -> proc_macro2::TokenStream { let path_to_type = meta.path_to_type(); let bevy_reflect_path = meta.bevy_reflect_path(); @@ -55,8 +58,23 @@ pub(crate) fn impl_type_path(meta: &ReflectMeta) -> proc_macro2::TokenStream { // Add Typed bound for each active field let where_reflect_clause = extend_where_clause(where_clause, where_clause_options); + let primitive_assert = if let PathToType::Primitive(_) = path_to_type { + Some(quote! { + const _: () = { + mod private_scope { + // compiles if it can be named with its ident when there are no imports. + type AssertIsPrimitive = #path_to_type; + } + }; + }) + } else { + None + }; + quote! { const _: () = { + #primitive_assert + trait GetStorage { fn get_storage() -> &'static #bevy_reflect_path::utility::TypePathStorage; } @@ -110,10 +128,9 @@ pub(crate) fn impl_typed( let path_to_type = meta.path_to_type(); let bevy_reflect_path = meta.bevy_reflect_path(); - let type_path_impl = impl_type_path(meta); + let type_path_impl = impl_type_path(meta, where_clause_options); - let type_info_cell = - static_typed_cell(meta, TypedProperty::TypeInfo, type_info_generator); + let type_info_cell = static_typed_cell(meta, TypedProperty::TypeInfo, type_info_generator); let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl(); diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs index 918fb146d2d25..b1a3a4f8633d8 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs @@ -24,15 +24,15 @@ mod fq_std; mod from_reflect; mod impls; mod reflect_value; -mod type_path; mod registration; mod trait_reflection; +mod type_path; mod type_uuid; mod utility; use crate::derive_data::{ReflectDerive, ReflectMeta, ReflectStruct}; use container_attributes::ReflectTraits; -use derive_data::{type_path_generator, PathToType}; +use derive_data::PathToType; use proc_macro::TokenStream; use quote::quote; use reflect_value::ReflectValueDef; @@ -43,8 +43,12 @@ use type_path::NamedTypePathDef; pub(crate) static REFLECT_ATTRIBUTE_NAME: &str = "reflect"; pub(crate) static REFLECT_VALUE_ATTRIBUTE_NAME: &str = "reflect_value"; pub(crate) static TYPE_PATH_ATTRIBUTE_NAME: &str = "type_path"; +pub(crate) static TYPE_NAME_ATTRIBUTE_NAME: &str = "type_name"; -#[proc_macro_derive(Reflect, attributes(reflect, reflect_value, type_path, module))] +#[proc_macro_derive( + Reflect, + attributes(reflect, reflect_value, type_path, type_name, module) +)] pub fn derive_reflect(input: TokenStream) -> TokenStream { let ast = parse_macro_input!(input as DeriveInput); @@ -89,14 +93,14 @@ pub fn derive_from_reflect(input: TokenStream) -> TokenStream { } } -#[proc_macro_derive(TypePath, attributes(type_path))] +#[proc_macro_derive(TypePath, attributes(type_path, type_name))] pub fn derive_type_path(input: TokenStream) -> TokenStream { let ast = parse_macro_input!(input as DeriveInput); let derive_data = match ReflectDerive::from_input(&ast) { Ok(data) => data, Err(err) => return err.into_compile_error().into(), }; - + impls::impl_type_path(derive_data.meta()).into() } @@ -114,10 +118,15 @@ pub fn reflect_trait(args: TokenStream, input: TokenStream) -> TokenStream { #[proc_macro] pub fn impl_reflect_value(input: TokenStream) -> TokenStream { let def = parse_macro_input!(input as ReflectValueDef); - let path_to_type = if def.type_path.leading_colon.is_some() { - PathToType::External { path: &def.type_path, alias: def.alias } + + let default_name = &def.type_path.segments.last().unwrap().ident; + let path_to_type = if !def.type_path.leading_colon.is_some() && def.alias.is_empty() { + PathToType::Primitive(default_name) } else { - PathToType::Primtive(&def.type_path.segments.first().unwrap().ident) + PathToType::External { + path: &def.type_path, + alias: def.alias.into_path(default_name), + } }; let meta = ReflectMeta::new(path_to_type, &def.generics, def.traits.unwrap_or_default()); @@ -166,6 +175,15 @@ pub fn impl_reflect_struct(input: TokenStream) -> TokenStream { match derive_data { ReflectDerive::Struct(struct_data) => { + if !struct_data.meta().path_to_type().is_alias() { + return syn::Error::new( + struct_data.meta().path_to_type().span(), + format!("a #[{TYPE_PATH_ATTRIBUTE_NAME} = \"...\"] attribute must be specified when using `impl_reflect_struct`") + ) + .into_compile_error() + .into(); + } + let impl_struct: proc_macro2::TokenStream = impls::impl_struct(&struct_data).into(); let impl_from_struct: proc_macro2::TokenStream = from_reflect::impl_struct(&struct_data).into(); @@ -197,10 +215,15 @@ pub fn impl_reflect_struct(input: TokenStream) -> TokenStream { #[proc_macro] pub fn impl_from_reflect_value(input: TokenStream) -> TokenStream { let def = parse_macro_input!(input as ReflectValueDef); - let path_to_type = if def.type_path.leading_colon.is_some() { - PathToType::External { path: &def.type_path, alias: def.alias } + + let default_name = &def.type_path.segments.last().unwrap().ident; + let path_to_type = if !def.type_path.leading_colon.is_some() && def.alias.is_empty() { + PathToType::Primitive(default_name) } else { - PathToType::Primtive(&def.type_path.segments.first().unwrap().ident) + PathToType::External { + path: &def.type_path, + alias: def.alias.into_path(default_name), + } }; from_reflect::impl_value(&ReflectMeta::new( @@ -213,26 +236,31 @@ pub fn impl_from_reflect_value(input: TokenStream) -> TokenStream { #[proc_macro] pub fn impl_type_path(input: TokenStream) -> TokenStream { let def = parse_macro_input!(input as NamedTypePathDef); - + let (path_to_type, generics) = match def { - NamedTypePathDef::External { ref path, alias, generics } => (PathToType::External { path, alias }, generics), - NamedTypePathDef::Primtive(ref ident) => (PathToType::Primtive(ident), Generics::default()) + NamedTypePathDef::External { + ref path, + alias, + generics, + } => { + let default_name = &path.segments.last().unwrap().ident; + ( + PathToType::External { + path, + alias: alias.into_path(default_name), + }, + generics, + ) + } + NamedTypePathDef::Primtive(ref ident) => { + (PathToType::Primitive(ident), Generics::default()) + } }; - + impls::impl_type_path(&ReflectMeta::new( path_to_type, &generics, ReflectTraits::default(), - )).into() + )) + .into() } - -// #[proc_macro] -// pub fn type_path_for(input: TokenStream) -> TokenStream { -// let def = parse_macro_input!(input as ReflectValueDef); -// type_path_generator(&ReflectMeta::new( -// PathToType::External(&def.type_path), -// &def.generics, -// def.traits.unwrap_or_default(), -// )) -// .into() -// } diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs b/crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs index 868c09334ae40..11b37435aa1be 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs @@ -1,10 +1,8 @@ use crate::container_attributes::ReflectTraits; -use crate::type_path::{parse_path_leading_colon, parse_path_no_leading_colon}; -use proc_macro2::Ident; +use crate::type_path::AliasDef; use syn::parse::{Parse, ParseStream}; -use syn::punctuated::Punctuated; -use syn::token::{Colon2, Paren, Where}; -use syn::{parenthesized, Attribute, Generics, Path, PathSegment, Token}; +use syn::token::Paren; +use syn::{parenthesized, Attribute, Generics, Path}; /// A struct used to define a simple reflected value type (such as primitives). /// @@ -28,7 +26,7 @@ pub(crate) struct ReflectValueDef { pub type_path: Path, pub generics: Generics, pub traits: Option, - pub alias: Option, + pub alias: AliasDef, } impl Parse for ReflectValueDef { @@ -44,18 +42,13 @@ impl Parse for ReflectValueDef { parenthesized!(content in input); traits = Some(content.parse::()?); } - - let mut alias = None; - if input.peek(Token![as]) { - alias = Some(parse_path_no_leading_colon(input)?); - }; + + let alias: AliasDef = input.parse()?; Ok(ReflectValueDef { attrs, type_path, - generics: Generics { - ..generics - }, + generics: Generics { ..generics }, traits, alias, }) diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/registration.rs b/crates/bevy_reflect/bevy_reflect_derive/src/registration.rs index cb0dbabe1bc82..0944e350752c0 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/registration.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/registration.rs @@ -2,11 +2,9 @@ use crate::utility::{extend_where_clause, WhereClauseOptions}; use bit_set::BitSet; -use proc_macro2::Ident; use quote::quote; -use syn::{Generics, Path}; -use crate::derive_data::{PathToType, ReflectMeta}; +use crate::derive_data::ReflectMeta; /// Creates the `GetTypeRegistration` impl for the given type data. #[allow(clippy::too_many_arguments)] diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs b/crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs index 9fae1ddaf14c6..2ab8006875088 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs @@ -1,48 +1,80 @@ -use std::path; - use proc_macro2::Ident; -use quote::{quote, ToTokens, TokenStreamExt}; use syn::{ parse::{Parse, ParseStream}, - Expr, Generics, LitStr, Path, Token, Type, TypeArray, TypeParamBound, TypePath, + Generics, Path, PathSegment, Token, }; -use crate::derive_data::ReflectMeta; +pub fn parse_path_no_leading_colon(input: ParseStream) -> syn::Result { + if input.peek(Token![::]) { + return Err(input.error("did not expect a leading double colon (`::`)")); + } -pub enum NamedTypePathDef { - External { - path: Path, - generics: Generics, - alias: Option, - }, - Primtive(Ident), -} + let path = Path::parse_mod_style(input)?; -pub struct AnonymousTypePathDef { - pub path: Path, - pub generics: Generics, - pub long_type_path: Expr, - pub short_type_path: Expr, + if path.segments.is_empty() { + Err(input.error("expected a path")) + } else { + Ok(path) + } } -pub fn parse_path_leading_colon(input: ParseStream) -> syn::Result { - let leading = input.parse::()?; +pub struct AliasDef { + path_alias: Option, + name_alias: Option, +} - if input.peek(Token![::]) { - return Err(input.error("did not expect two leading double colons (`::::`)")); +impl AliasDef { + pub fn is_empty(&self) -> bool { + self.path_alias.is_none() } - let mut path = Path::parse_mod_style(input)?; - path.leading_colon = Some(leading); - Ok(path) + pub fn into_path(self, default_name: &Ident) -> Option { + if let Some(mut path) = self.path_alias { + let name = PathSegment::from(self.name_alias.unwrap_or_else(|| default_name.clone())); + path.segments.push(name); + Some(path) + } else { + None + } + } } -pub fn parse_path_no_leading_colon(input: ParseStream) -> syn::Result { - if input.peek(Token![::]) { - return Err(input.error("did not expect a leading double colon (`::`)")); +impl Parse for AliasDef { + fn parse(input: ParseStream) -> syn::Result { + if !input.peek(Token![in]) { + return Ok(Self { + path_alias: None, + name_alias: None, + }); + } + + input.parse::()?; + let path_alias = parse_path_no_leading_colon(input)?; + + if !input.peek(Token![as]) { + return Ok(Self { + path_alias: Some(path_alias), + name_alias: None, + }); + } + + input.parse::()?; + let name_alias: Ident = input.parse()?; + + Ok(Self { + path_alias: Some(path_alias), + name_alias: Some(name_alias), + }) } +} - Path::parse_mod_style(input) +pub enum NamedTypePathDef { + External { + path: Path, + generics: Generics, + alias: AliasDef, + }, + Primtive(Ident), } impl Parse for NamedTypePathDef { @@ -51,29 +83,20 @@ impl Parse for NamedTypePathDef { let mut generics = input.parse::()?; generics.where_clause = input.parse()?; - if input.is_empty() { - if path.leading_colon.is_none() { - if path.segments.len() == 1 { - let ident = path.segments.into_iter().next().unwrap().ident; - Ok(NamedTypePathDef::Primtive(ident)) - } else { - Err(input.error("non-aliased paths must start with a double colon (`::`)")) - } + let alias: AliasDef = input.parse()?; + + if path.leading_colon.is_none() && alias.is_empty() { + if path.segments.len() == 1 { + let ident = path.segments.into_iter().next().unwrap().ident; + Ok(NamedTypePathDef::Primtive(ident)) } else { - Ok(NamedTypePathDef::External { - path, - generics, - alias: None, - }) + Err(input.error("non-aliased paths must start with a double colon (`::`)")) } - } else { - let _ = input.parse::(); - let alias = parse_path_no_leading_colon(input)?; Ok(NamedTypePathDef::External { path, generics, - alias: Some(alias), + alias, }) } } diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index 6a55a464bd41e..f4ab8facdbbb5 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, - impl_type_path, - utility::{NonGenericTypeInfoCell, TypePathStorage}, DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, - TypeInfo, Typed, TypePath, impl_type_path_stored, + self as bevy_reflect, utility::NonGenericTypeInfoCell, DynamicInfo, Reflect, ReflectMut, + ReflectOwned, ReflectRef, TypeInfo, Typed, }; use std::{ any::{Any, TypeId}, @@ -303,13 +303,7 @@ impl Typed for DynamicArray { } } -impl_type_path_stored!(|| TypePathStorage::new_named( - "bevy_reflect::DynamicArray", - "DynamicArray", - "DynamicArray", - "bevy_reflect", - "bevy_reflect" -), impl for DynamicArray); +impl_type_path!(DynamicArray in bevy_reflect::DynamicArray); /// An iterator over an [`Array`]. pub struct ArrayIter<'a> { diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index 3d788ba63355b..f4fa5f9217827 100644 --- a/crates/bevy_reflect/src/enums/dynamic_enum.rs +++ b/crates/bevy_reflect/src/enums/dynamic_enum.rs @@ -1,11 +1,10 @@ use bevy_reflect_derive::impl_type_path; -use crate::utility::{NonGenericTypeInfoCell, NonGenericTypePathCell}; +use crate::utility::NonGenericTypeInfoCell; use crate::{ - self as bevy_reflect, - enum_debug, enum_hash, enum_partial_eq, DynamicInfo, DynamicStruct, DynamicTuple, Enum, - Reflect, ReflectMut, ReflectOwned, ReflectRef, Struct, Tuple, TypeInfo, Typed, - VariantFieldIter, VariantType, TypePath, + self as bevy_reflect, enum_debug, enum_hash, enum_partial_eq, DynamicInfo, DynamicStruct, + DynamicTuple, Enum, Reflect, ReflectMut, ReflectOwned, ReflectRef, Struct, Tuple, TypeInfo, + Typed, VariantFieldIter, VariantType, }; use std::any::Any; use std::fmt::Formatter; @@ -434,4 +433,4 @@ impl Typed for DynamicEnum { } } -impl_type_path!(DynamicEnum as bevy_reflect::DynamicEnum); +impl_type_path!(DynamicEnum in bevy_reflect); diff --git a/crates/bevy_reflect/src/impls/glam.rs b/crates/bevy_reflect/src/impls/glam.rs index bb3ab96e3a365..74c20d5cfb277 100644 --- a/crates/bevy_reflect/src/impls/glam.rs +++ b/crates/bevy_reflect/src/impls/glam.rs @@ -6,6 +6,7 @@ use glam::*; impl_reflect_struct!( #[reflect(Debug, Hash, PartialEq, Default)] + #[type_path = "glam"] struct IVec2 { x: i32, y: i32, @@ -13,6 +14,7 @@ impl_reflect_struct!( ); impl_reflect_struct!( #[reflect(Debug, Hash, PartialEq, Default)] + #[type_path = "glam"] struct IVec3 { x: i32, y: i32, @@ -21,6 +23,7 @@ impl_reflect_struct!( ); impl_reflect_struct!( #[reflect(Debug, Hash, PartialEq, Default)] + #[type_path = "glam"] struct IVec4 { x: i32, y: i32, @@ -31,6 +34,7 @@ impl_reflect_struct!( impl_reflect_struct!( #[reflect(Debug, Hash, PartialEq, Default)] + #[type_path = "glam"] struct UVec2 { x: u32, y: u32, @@ -38,6 +42,7 @@ impl_reflect_struct!( ); impl_reflect_struct!( #[reflect(Debug, Hash, PartialEq, Default)] + #[type_path = "glam"] struct UVec3 { x: u32, y: u32, @@ -46,6 +51,7 @@ impl_reflect_struct!( ); impl_reflect_struct!( #[reflect(Debug, Hash, PartialEq, Default)] + #[type_path = "glam"] struct UVec4 { x: u32, y: u32, @@ -56,6 +62,7 @@ impl_reflect_struct!( impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct Vec2 { x: f32, y: f32, @@ -63,6 +70,7 @@ impl_reflect_struct!( ); impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct Vec3 { x: f32, y: f32, @@ -71,6 +79,7 @@ impl_reflect_struct!( ); impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct Vec3A { x: f32, y: f32, @@ -79,6 +88,7 @@ impl_reflect_struct!( ); impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct Vec4 { x: f32, y: f32, @@ -89,6 +99,7 @@ impl_reflect_struct!( impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct BVec2 { x: bool, y: bool, @@ -96,6 +107,7 @@ impl_reflect_struct!( ); impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct BVec3 { x: bool, y: bool, @@ -104,6 +116,7 @@ impl_reflect_struct!( ); impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct BVec4 { x: bool, y: bool, @@ -114,6 +127,7 @@ impl_reflect_struct!( impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct DVec2 { x: f64, y: f64, @@ -121,6 +135,7 @@ impl_reflect_struct!( ); impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct DVec3 { x: f64, y: f64, @@ -129,6 +144,7 @@ impl_reflect_struct!( ); impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct DVec4 { x: f64, y: f64, @@ -139,6 +155,7 @@ impl_reflect_struct!( impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct Mat2 { x_axis: Vec2, y_axis: Vec2, @@ -146,6 +163,7 @@ impl_reflect_struct!( ); impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct Mat3 { x_axis: Vec3, y_axis: Vec3, @@ -154,6 +172,7 @@ impl_reflect_struct!( ); impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct Mat3A { x_axis: Vec3A, y_axis: Vec3A, @@ -162,6 +181,7 @@ impl_reflect_struct!( ); impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct Mat4 { x_axis: Vec4, y_axis: Vec4, @@ -172,6 +192,7 @@ impl_reflect_struct!( impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct DMat2 { x_axis: DVec2, y_axis: DVec2, @@ -179,6 +200,7 @@ impl_reflect_struct!( ); impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct DMat3 { x_axis: DVec3, y_axis: DVec3, @@ -187,6 +209,7 @@ impl_reflect_struct!( ); impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct DMat4 { x_axis: DVec4, y_axis: DVec4, @@ -197,6 +220,7 @@ impl_reflect_struct!( impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct Affine2 { matrix2: Mat2, translation: Vec2, @@ -204,6 +228,7 @@ impl_reflect_struct!( ); impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct Affine3A { matrix3: Mat3A, translation: Vec3A, @@ -212,6 +237,7 @@ impl_reflect_struct!( impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct DAffine2 { matrix2: DMat2, translation: DVec2, @@ -219,6 +245,7 @@ impl_reflect_struct!( ); impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] + #[type_path = "glam"] struct DAffine3 { matrix3: DMat3, translation: DVec3, @@ -229,12 +256,24 @@ impl_reflect_struct!( // mechanisms for read-only fields. I doubt those mechanisms would be added, // so for now quaternions will remain as values. They are represented identically // to Vec4 and DVec4, so you may use those instead and convert between. -impl_reflect_value!(Quat(Debug, PartialEq, Serialize, Deserialize, Default)); -impl_reflect_value!(DQuat(Debug, PartialEq, Serialize, Deserialize, Default)); +impl_reflect_value!(::glam::Quat( + Debug, + PartialEq, + Serialize, + Deserialize, + Default +)); +impl_reflect_value!(::glam::DQuat( + Debug, + PartialEq, + Serialize, + Deserialize, + Default +)); impl_from_reflect_value!(Quat); impl_from_reflect_value!(DQuat); -impl_reflect_value!(EulerRot(Debug, Default)); -impl_reflect_value!(BVec3A(Debug, Default)); -impl_reflect_value!(BVec4A(Debug, Default)); +impl_reflect_value!(::glam::EulerRot(Debug, Default)); +impl_reflect_value!(::glam::BVec3A(Debug, Default)); +impl_reflect_value!(::glam::BVec4A(Debug, Default)); diff --git a/crates/bevy_reflect/src/impls/rect.rs b/crates/bevy_reflect/src/impls/rect.rs index 9db5e1cd85196..b215a58599d20 100644 --- a/crates/bevy_reflect/src/impls/rect.rs +++ b/crates/bevy_reflect/src/impls/rect.rs @@ -6,6 +6,7 @@ use bevy_reflect_derive::impl_reflect_struct; impl_reflect_struct!( #[reflect(Debug, PartialEq, Serialize, Deserialize, Default)] + #[type_path = "bevy_math"] struct Rect { min: Vec2, max: Vec2, diff --git a/crates/bevy_reflect/src/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index 1c1746dfbe537..265b4571f353b 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -2,15 +2,14 @@ use bevy_reflect_derive::impl_type_path; use smallvec::SmallVec; use std::any::Any; -use crate::utility::{GenericTypeInfoCell, GenericTypePathCell}; +use crate::utility::GenericTypeInfoCell; use crate::{ - self as bevy_reflect, - Array, ArrayIter, FromReflect, FromType, GetTypeRegistration, List, ListInfo, Reflect, - ReflectFromPtr, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypeRegistration, Typed, - TypePath + self as bevy_reflect, Array, ArrayIter, FromReflect, FromType, GetTypeRegistration, List, + ListInfo, Reflect, ReflectFromPtr, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, + TypeRegistration, Typed, }; -impl Array for SmallVec +impl Array for SmallVec where T::Item: FromReflect, { @@ -48,7 +47,7 @@ where } } -impl List for SmallVec +impl List for SmallVec where T::Item: FromReflect, { @@ -85,7 +84,7 @@ where } } -impl Reflect for SmallVec +impl Reflect for SmallVec where T::Item: FromReflect, { @@ -161,9 +160,9 @@ where } } -impl_type_path!(::smallvec::SmallVec); +impl_type_path!(::smallvec::SmallVec); -impl FromReflect for SmallVec +impl FromReflect for SmallVec where T::Item: FromReflect, { @@ -180,7 +179,7 @@ where } } -impl GetTypeRegistration for SmallVec +impl GetTypeRegistration for SmallVec where T::Item: FromReflect, { diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 09ccde69fb6a8..3070f121d5097 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -1,16 +1,14 @@ use crate::std_traits::ReflectDefault; -use crate::{self as bevy_reflect, ReflectFromPtr, ReflectOwned, impl_type_path_stored}; +use crate::{self as bevy_reflect, impl_type_path_stored, ReflectFromPtr, ReflectOwned}; use crate::{ - map_apply, map_partial_eq, Array, ArrayInfo, ArrayIter, DynamicEnum, DynamicMap, - Enum, EnumInfo, FromReflect, FromType, GetTypeRegistration, List, ListInfo, Map, MapInfo, - MapIter, Reflect, ReflectDeserialize, ReflectMut, ReflectRef, ReflectSerialize, - TupleVariantInfo, TypeInfo, TypeRegistration, Typed, UnitVariantInfo, UnnamedField, - ValueInfo, VariantFieldIter, VariantInfo, VariantType, TypePath, impl_type_path, + impl_type_path, map_apply, map_partial_eq, Array, ArrayInfo, ArrayIter, DynamicEnum, + DynamicMap, Enum, EnumInfo, FromReflect, FromType, GetTypeRegistration, List, ListInfo, Map, + MapInfo, MapIter, Reflect, ReflectDeserialize, ReflectMut, ReflectRef, ReflectSerialize, + TupleVariantInfo, TypeInfo, TypePath, TypeRegistration, Typed, UnitVariantInfo, UnnamedField, + ValueInfo, VariantFieldIter, VariantInfo, VariantType, }; -use crate::utility::{ - GenericTypeInfoCell, GenericTypePathCell, NonGenericTypeInfoCell, NonGenericTypePathCell, TypePathStorage, -}; +use crate::utility::{GenericTypeInfoCell, NonGenericTypeInfoCell, TypePathStorage}; use bevy_reflect_derive::{impl_from_reflect_value, impl_reflect_value}; use bevy_utils::{Duration, Instant}; use bevy_utils::{HashMap, HashSet}; @@ -94,7 +92,7 @@ impl_reflect_value!(String( Deserialize, Default )); -impl_reflect_value!(PathBuf( +impl_reflect_value!(::std::path::PathBuf( Debug, Hash, PartialEq, @@ -102,15 +100,18 @@ impl_reflect_value!(PathBuf( Deserialize, Default )); -impl_reflect_value!(Result()); -impl_reflect_value!(HashSet()); -impl_reflect_value!(Range()); -impl_reflect_value!(RangeInclusive()); -impl_reflect_value!(RangeFrom()); -impl_reflect_value!(RangeTo()); -impl_reflect_value!(RangeToInclusive()); -impl_reflect_value!(RangeFull()); -impl_reflect_value!(Duration( +impl_reflect_value!( + ::core::result::Result < T: Clone + Reflect + TypePath, + E: Clone + Reflect + TypePath > () +); +impl_reflect_value!(::bevy_utils::HashSet()); +impl_reflect_value!(::core::ops::Range()); +impl_reflect_value!(::core::ops::RangeInclusive()); +impl_reflect_value!(::core::ops::RangeFrom()); +impl_reflect_value!(::core::ops::RangeTo()); +impl_reflect_value!(::core::ops::RangeToInclusive()); +impl_reflect_value!(::core::ops::RangeFull()); +impl_reflect_value!(::core::time::Duration( Debug, Hash, PartialEq, @@ -118,26 +119,104 @@ impl_reflect_value!(Duration( Deserialize, Default )); -impl_reflect_value!(Instant(Debug, Hash, PartialEq)); -impl_reflect_value!(NonZeroI128(Debug, Hash, PartialEq, Serialize, Deserialize)); -impl_reflect_value!(NonZeroU128(Debug, Hash, PartialEq, Serialize, Deserialize)); -impl_reflect_value!(NonZeroIsize(Debug, Hash, PartialEq, Serialize, Deserialize)); -impl_reflect_value!(NonZeroUsize(Debug, Hash, PartialEq, Serialize, Deserialize)); -impl_reflect_value!(NonZeroI64(Debug, Hash, PartialEq, Serialize, Deserialize)); -impl_reflect_value!(NonZeroU64(Debug, Hash, PartialEq, Serialize, Deserialize)); -impl_reflect_value!(NonZeroU32(Debug, Hash, PartialEq, Serialize, Deserialize)); -impl_reflect_value!(NonZeroI32(Debug, Hash, PartialEq, Serialize, Deserialize)); -impl_reflect_value!(NonZeroI16(Debug, Hash, PartialEq, Serialize, Deserialize)); -impl_reflect_value!(NonZeroU16(Debug, Hash, PartialEq, Serialize, Deserialize)); -impl_reflect_value!(NonZeroU8(Debug, Hash, PartialEq, Serialize, Deserialize)); -impl_reflect_value!(NonZeroI8(Debug, Hash, PartialEq, Serialize, Deserialize)); +impl_reflect_value!(::std::time::Instant(Debug, Hash, PartialEq)); +impl_reflect_value!(::core::num::NonZeroI128( + Debug, + Hash, + PartialEq, + Serialize, + Deserialize +)); +impl_reflect_value!(::core::num::NonZeroU128( + Debug, + Hash, + PartialEq, + Serialize, + Deserialize +)); +impl_reflect_value!(::core::num::NonZeroIsize( + Debug, + Hash, + PartialEq, + Serialize, + Deserialize +)); +impl_reflect_value!(::core::num::NonZeroUsize( + Debug, + Hash, + PartialEq, + Serialize, + Deserialize +)); +impl_reflect_value!(::core::num::NonZeroI64( + Debug, + Hash, + PartialEq, + Serialize, + Deserialize +)); +impl_reflect_value!(::core::num::NonZeroU64( + Debug, + Hash, + PartialEq, + Serialize, + Deserialize +)); +impl_reflect_value!(::core::num::NonZeroU32( + Debug, + Hash, + PartialEq, + Serialize, + Deserialize +)); +impl_reflect_value!(::core::num::NonZeroI32( + Debug, + Hash, + PartialEq, + Serialize, + Deserialize +)); +impl_reflect_value!(::core::num::NonZeroI16( + Debug, + Hash, + PartialEq, + Serialize, + Deserialize +)); +impl_reflect_value!(::core::num::NonZeroU16( + Debug, + Hash, + PartialEq, + Serialize, + Deserialize +)); +impl_reflect_value!(::core::num::NonZeroU8( + Debug, + Hash, + PartialEq, + Serialize, + Deserialize +)); +impl_reflect_value!(::core::num::NonZeroI8( + Debug, + Hash, + PartialEq, + Serialize, + Deserialize +)); // `Serialize` and `Deserialize` only for platforms supported by serde: // https://github.com/serde-rs/serde/blob/3ffb86fc70efd3d329519e2dddfa306cc04f167c/serde/src/de/impls.rs#L1732 #[cfg(any(unix, windows))] -impl_reflect_value!(OsString(Debug, Hash, PartialEq, Serialize, Deserialize)); +impl_reflect_value!(::std::ffi::OsString( + Debug, + Hash, + PartialEq, + Serialize, + Deserialize +)); #[cfg(not(any(unix, windows)))] -impl_reflect_value!(OsString(Debug, Hash, PartialEq)); +impl_reflect_value!(::std::ffi::OsString(Debug, Hash, PartialEq)); impl_from_reflect_value!(bool); impl_from_reflect_value!(char); @@ -317,9 +396,9 @@ macro_rules! impl_reflect_for_veclike { fn type_info() -> &'static TypeInfo { static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); CELL.get_or_insert::(|| TypeInfo::List(ListInfo::new::())) - } + } } - + impl_type_path!($ty where T: FromReflect + TypePath); impl GetTypeRegistration for $ty { @@ -517,7 +596,7 @@ impl Typed for } } -impl_type_path!(HashMap as hashbrown::HashMap); +impl_type_path!(HashMap in bevy_utils); impl GetTypeRegistration for HashMap where @@ -531,7 +610,9 @@ where } } -impl FromReflect for HashMap { +impl FromReflect + for HashMap +{ fn from_reflect(reflect: &dyn Reflect) -> Option { if let ReflectRef::Map(ref_map) = reflect.reflect_ref() { let mut new_map = Self::with_capacity(ref_map.len()); diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 7b0c7c6ddefdc..8bd4c431d82e4 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -109,8 +109,8 @@ mod tests { ser::{to_string_pretty, PrettyConfig}, Deserializer, }; - use std::{any::TypeId, marker::PhantomData}; use std::fmt::{Debug, Formatter}; + use std::{any::TypeId, marker::PhantomData}; use super::prelude::*; use super::*; @@ -650,36 +650,41 @@ mod tests { std::any::type_name::() ); } - + #[test] fn reflect_type_path() { #[derive(TypePath)] struct A; - + #[derive(TypePath)] - #[type_path = "my_alias::B"] + #[type_path = "my_alias"] struct B; - + #[derive(TypePath)] struct C(PhantomData); - + #[derive(TypePath)] - #[type_path = "my_alias::D"] + #[type_path = "my_alias"] struct D(PhantomData); - + + #[derive(TypePath)] + #[type_path = "my_alias"] + #[type_name = "Eee"] + struct E(PhantomData); + // struct E; // impl_type_path!(E); - + // struct F; // impl_type_path!(F as my_alias::F); - + // struct G(PhantomData); // impl_type_path!(G); - + // struct H(PhantomData); // impl_type_path!(H as my_alias::H); - - A::type_path(); + + assert_eq!(A::type_path(), "bevy_reflect::tests::A"); B::type_path(); C::::type_path(); D::::type_path(); diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index 088a1f9dcf02e..62ce497fc3649 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -5,9 +5,8 @@ use bevy_reflect_derive::impl_type_path; use crate::utility::NonGenericTypeInfoCell; use crate::{ - self as bevy_reflect, - Array, ArrayIter, DynamicArray, DynamicInfo, FromReflect, Reflect, ReflectMut, ReflectOwned, - ReflectRef, TypeInfo, Typed, + self as bevy_reflect, Array, ArrayIter, DynamicArray, DynamicInfo, FromReflect, Reflect, + ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, }; /// An ordered, mutable list of [Reflect] items. This corresponds to types like [`std::vec::Vec`]. @@ -330,7 +329,7 @@ impl Typed for DynamicList { } } -impl_type_path!(DynamicList as bevy_reflect::DynamicList); +impl_type_path!(DynamicList in bevy_reflect); impl IntoIterator for DynamicList { type Item = Box; diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index d38110aa07e8a..7c61a75dacb2e 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -7,8 +7,7 @@ use bevy_utils::{Entry, HashMap}; use crate::utility::NonGenericTypeInfoCell; use crate::{ - self as bevy_reflect, - DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, + self as bevy_reflect, DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, }; @@ -356,7 +355,7 @@ impl Typed for DynamicMap { } } -impl_type_path!(DynamicMap as bevy_reflect::DynamicMap); +impl_type_path!(DynamicMap in bevy_reflect); /// An iterator over the key-value pairs of a [`Map`]. pub struct MapIter<'a> { diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index 78851c89ebf73..5efa23435603f 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -1,9 +1,7 @@ use crate::{ - array_debug, enum_debug, impl_type_path_stored, list_debug, map_debug, - serde::Serializable, - struct_debug, tuple_debug, tuple_struct_debug, - utility::{NonGenericTypePathCell, TypePathStorage}, - Array, Enum, List, Map, Struct, Tuple, TupleStruct, TypeInfo, Typed, ValueInfo, + array_debug, enum_debug, impl_type_path_stored, list_debug, map_debug, serde::Serializable, + struct_debug, tuple_debug, tuple_struct_debug, utility::TypePathStorage, Array, Enum, List, + Map, Struct, Tuple, TupleStruct, TypeInfo, Typed, ValueInfo, }; use std::{ any::{self, Any, TypeId}, diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index fba091f2f2142..636b3f1a2f970 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -1,7 +1,7 @@ -use crate::utility::{NonGenericTypeInfoCell, NonGenericTypePathCell}; +use crate::utility::NonGenericTypeInfoCell; use crate::{ - self as bevy_reflect, - DynamicInfo, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, TypePath, + self as bevy_reflect, DynamicInfo, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, + TypeInfo, Typed, }; use bevy_reflect_derive::impl_type_path; use bevy_utils::{Entry, HashMap}; @@ -483,7 +483,7 @@ impl Typed for DynamicStruct { } } -impl_type_path!(DynamicStruct as bevy_reflect::DynamicStruct); +impl_type_path!(DynamicStruct in bevy_reflect); /// Compares a [`Struct`] with a [`Reflect`] value. /// diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index f315db81b7dba..e1f2d761bff7c 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -1,9 +1,8 @@ -use crate::utility::{NonGenericTypeInfoCell, impl_type_path_stored, TypePathStorage}; +use crate::utility::{impl_type_path_stored, NonGenericTypeInfoCell, TypePathStorage}; use crate::{ - self as bevy_reflect, - impl_type_path, - DynamicInfo, FromReflect, GetTypeRegistration, Reflect, ReflectMut, - ReflectOwned, ReflectRef, TypeInfo, TypeRegistration, Typed, UnnamedField, TypePath, + self as bevy_reflect, impl_type_path, DynamicInfo, FromReflect, GetTypeRegistration, Reflect, + ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, TypeRegistration, Typed, + UnnamedField, }; use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; @@ -380,7 +379,7 @@ impl Typed for DynamicTuple { } } -impl_type_path!(DynamicTuple as bevy_reflect::DynamicTuple); +impl_type_path!(DynamicTuple in bevy_reflect); /// Applies the elements of `b` to the corresponding elements of `a`. /// @@ -583,7 +582,7 @@ macro_rules! impl_reflect_tuple { }) } } - + impl_type_path_stored!( || TypePathStorage::new_anonymous( "(".to_owned() $(+ <$name as TypePath>::type_path())* + ")", @@ -591,7 +590,7 @@ macro_rules! impl_reflect_tuple { ), impl { $($name: Reflect + TypePath),* } for ($($name,)*) ); - + impl<$($name: Reflect + TypePath),*> GetTypeRegistration for ($($name,)*) { fn get_type_registration() -> TypeRegistration { diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index c007f99c28db0..eb001bb06853b 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -2,8 +2,8 @@ use bevy_reflect_derive::impl_type_path; use crate::utility::NonGenericTypeInfoCell; use crate::{ - self as bevy_reflect, - DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, UnnamedField, + self as bevy_reflect, DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, + Typed, UnnamedField, }; use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; @@ -383,10 +383,10 @@ impl Typed for DynamicTupleStruct { fn type_info() -> &'static TypeInfo { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); CELL.get_or_set(|| TypeInfo::Dynamic(DynamicInfo::new::())) - } + } } -impl_type_path!(DynamicTupleStruct as bevy_reflect::DynamicTupleStruct); +impl_type_path!(DynamicTupleStruct in bevy_reflect); /// Compares a [`TupleStruct`] with a [`Reflect`] value. /// diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index 8bc5ec0fe0656..42e011c14915f 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -1,5 +1,5 @@ use crate::{ - ArrayInfo, EnumInfo, ListInfo, MapInfo, Reflect, StructInfo, TupleInfo, TupleStructInfo, TypePath, + ArrayInfo, EnumInfo, ListInfo, MapInfo, Reflect, StructInfo, TupleInfo, TupleStructInfo, }; use std::any::{Any, TypeId}; @@ -276,4 +276,4 @@ impl DynamicInfo { pub fn docs(&self) -> Option<&'static str> { self.docs } -} \ No newline at end of file +} diff --git a/crates/bevy_reflect/src/type_path.rs b/crates/bevy_reflect/src/type_path.rs index 0295c43ddf14d..3a1afa0a9156f 100644 --- a/crates/bevy_reflect/src/type_path.rs +++ b/crates/bevy_reflect/src/type_path.rs @@ -1,26 +1,26 @@ pub trait TypePath: 'static { /// Returns the fully qualified path of the underlying type. /// - /// 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. /// - /// 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. /// - /// For [`Option<()>`], this is `Option`. + /// For [`Option<()>`], this is `Option`. fn type_ident() -> Option<&'static str>; - + /// Returns the name of the crate the type is in, or [`None`] if it is anonymous or a primitive. /// - /// For [`Option<()>`], this is `core`. + /// For [`Option<()>`], this is `core`. fn crate_name() -> Option<&'static str>; - + /// Returns the path to the moudle the type is in, or [`None`] if it is anonymous or a primitive. /// - /// For [`Option<()>`], this is `core::option`. + /// For [`Option<()>`], this is `core::option`. fn module_path() -> Option<&'static str>; -} \ No newline at end of file +} diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index 1a7470939198a..5055283a33d82 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -1,6 +1,6 @@ //! Helpers for working with Bevy reflection. -use crate::{TypeInfo, TypePath}; +use crate::TypeInfo; use bevy_utils::HashMap; use once_cell::race::OnceBox; use parking_lot::RwLock; @@ -209,10 +209,7 @@ impl TypePathStorage { } } - pub fn new_anonymous, B: AsRef>( - path: A, - short_path: B, - ) -> Self { + pub fn new_anonymous, B: AsRef>(path: A, short_path: B) -> Self { Self { path: path.as_ref().to_owned(), short_path: short_path.as_ref().to_owned(), @@ -295,7 +292,7 @@ macro_rules! impl_type_path_stored { trait GetStorage { fn get_storage() -> &'static $crate::utility::TypePathStorage; } - + impl$(< $($param)* >)? GetStorage for $($impl_tt)+ { #[inline] fn get_storage() -> &'static $crate::utility::TypePathStorage { @@ -347,5 +344,3 @@ macro_rules! impl_type_path_stored { } } pub use impl_type_path_stored; - -struct TyPath; diff --git a/crates/bevy_render/src/mesh/mesh/mod.rs b/crates/bevy_render/src/mesh/mesh/mod.rs index 3493c626505c9..698669879b5b2 100644 --- a/crates/bevy_render/src/mesh/mesh/mod.rs +++ b/crates/bevy_render/src/mesh/mesh/mod.rs @@ -12,7 +12,7 @@ use bevy_core::cast_slice; use bevy_derive::EnumVariantMeta; use bevy_ecs::system::{lifetimeless::SRes, SystemParamItem}; use bevy_math::*; -use bevy_reflect::{TypeUuid, TypePath}; +use bevy_reflect::{TypePath, TypeUuid}; use bevy_utils::{tracing::error, Hashed}; use std::{collections::BTreeMap, hash::Hash, iter::FusedIterator}; use thiserror::Error; diff --git a/crates/bevy_render/src/mesh/mesh/skinning.rs b/crates/bevy_render/src/mesh/mesh/skinning.rs index 78da53d3cd8a3..d80b6758434a9 100644 --- a/crates/bevy_render/src/mesh/mesh/skinning.rs +++ b/crates/bevy_render/src/mesh/mesh/skinning.rs @@ -6,7 +6,7 @@ use bevy_ecs::{ reflect::ReflectMapEntities, }; use bevy_math::Mat4; -use bevy_reflect::{Reflect, TypeUuid, TypePath}; +use bevy_reflect::{Reflect, TypePath, TypeUuid}; use std::ops::Deref; #[derive(Component, Debug, Default, Clone, Reflect)] diff --git a/crates/bevy_render/src/render_resource/shader.rs b/crates/bevy_render/src/render_resource/shader.rs index d5069e8652123..c9f29b7569472 100644 --- a/crates/bevy_render/src/render_resource/shader.rs +++ b/crates/bevy_render/src/render_resource/shader.rs @@ -1,7 +1,7 @@ use super::ShaderDefVal; use crate::define_atomic_id; use bevy_asset::{AssetLoader, AssetPath, Handle, LoadContext, LoadedAsset}; -use bevy_reflect::{TypeUuid, TypePath}; +use bevy_reflect::{TypePath, TypeUuid}; use bevy_utils::{tracing::error, BoxedFuture, HashMap}; use naga::{back::wgsl::WriterFlags, valid::Capabilities, valid::ModuleInfo, Module}; use once_cell::sync::Lazy; diff --git a/crates/bevy_scene/src/dynamic_scene.rs b/crates/bevy_scene/src/dynamic_scene.rs index c9e199501e7d2..fccce3eae8b53 100644 --- a/crates/bevy_scene/src/dynamic_scene.rs +++ b/crates/bevy_scene/src/dynamic_scene.rs @@ -6,7 +6,7 @@ use bevy_ecs::{ reflect::{ReflectComponent, ReflectMapEntities}, world::World, }; -use bevy_reflect::{Reflect, TypeRegistryArc, TypeUuid, TypePath}; +use bevy_reflect::{Reflect, TypePath, TypeRegistryArc, TypeUuid}; #[cfg(feature = "serialize")] use crate::serde::SceneSerializer; diff --git a/crates/bevy_scene/src/scene.rs b/crates/bevy_scene/src/scene.rs index 206d2097baf97..6e03a1e2dd329 100644 --- a/crates/bevy_scene/src/scene.rs +++ b/crates/bevy_scene/src/scene.rs @@ -4,7 +4,7 @@ use bevy_ecs::{ reflect::{ReflectComponent, ReflectMapEntities}, world::World, }; -use bevy_reflect::{TypeUuid, TypePath}; +use bevy_reflect::{TypePath, TypeUuid}; use crate::{DynamicScene, InstanceInfo, SceneSpawnError}; diff --git a/crates/bevy_sprite/src/mesh2d/material.rs b/crates/bevy_sprite/src/mesh2d/material.rs index a4299dd80b1ab..f498893c88fbb 100644 --- a/crates/bevy_sprite/src/mesh2d/material.rs +++ b/crates/bevy_sprite/src/mesh2d/material.rs @@ -14,7 +14,7 @@ use bevy_ecs::{ world::FromWorld, }; use bevy_log::error; -use bevy_reflect::{TypeUuid, TypePath}; +use bevy_reflect::{TypePath, TypeUuid}; use bevy_render::{ extract_component::ExtractComponentPlugin, mesh::{Mesh, MeshVertexBufferLayout}, @@ -111,7 +111,9 @@ use crate::{ /// @group(1) @binding(2) /// var color_sampler: sampler; /// ``` -pub trait Material2d: AsBindGroup + Send + Sync + Clone + TypeUuid + TypePath + Sized + 'static { +pub trait Material2d: + AsBindGroup + Send + Sync + Clone + TypeUuid + TypePath + Sized + 'static +{ /// Returns this material's vertex shader. If [`ShaderRef::Default`] is returned, the default mesh vertex shader /// will be used. fn vertex_shader() -> ShaderRef { diff --git a/crates/bevy_text/src/font.rs b/crates/bevy_text/src/font.rs index aab2db9d94db1..72d65b6e2a4e2 100644 --- a/crates/bevy_text/src/font.rs +++ b/crates/bevy_text/src/font.rs @@ -1,5 +1,5 @@ use ab_glyph::{FontArc, FontVec, InvalidFont, OutlinedGlyph}; -use bevy_reflect::{TypeUuid, TypePath}; +use bevy_reflect::{TypePath, TypeUuid}; use bevy_render::{ render_resource::{Extent3d, TextureDimension, TextureFormat}, texture::Image, diff --git a/examples/3d/lines.rs b/examples/3d/lines.rs index c8ecb82dd45d4..cd680273ffa48 100644 --- a/examples/3d/lines.rs +++ b/examples/3d/lines.rs @@ -3,7 +3,7 @@ use bevy::{ pbr::{MaterialPipeline, MaterialPipelineKey}, prelude::*, - reflect::{TypeUuid, TypePath}, + reflect::{TypePath, TypeUuid}, render::{ mesh::{MeshVertexBufferLayout, PrimitiveTopology}, render_resource::{ diff --git a/examples/asset/custom_asset.rs b/examples/asset/custom_asset.rs index 3c9dfa0205ac7..fdeeec45abd30 100644 --- a/examples/asset/custom_asset.rs +++ b/examples/asset/custom_asset.rs @@ -3,7 +3,7 @@ use bevy::{ asset::{AssetLoader, LoadContext, LoadedAsset}, prelude::*, - reflect::{TypeUuid, TypePath}, + reflect::{TypePath, TypeUuid}, utils::BoxedFuture, }; use serde::Deserialize; diff --git a/examples/shader/animate_shader.rs b/examples/shader/animate_shader.rs index 7bf1f62afe48f..21668cbf0da00 100644 --- a/examples/shader/animate_shader.rs +++ b/examples/shader/animate_shader.rs @@ -1,7 +1,11 @@ //! A shader that uses dynamic data like the time since startup. //! The time data is in the globals binding which is part of the `mesh_view_bindings` shader import. -use bevy::{prelude::*, reflect::{TypeUuid, TypePath}, render::render_resource::*}; +use bevy::{ + prelude::*, + reflect::{TypePath, TypeUuid}, + render::render_resource::*, +}; fn main() { App::new() diff --git a/examples/shader/array_texture.rs b/examples/shader/array_texture.rs index 628b6847a2b32..9c5b8f63e7278 100644 --- a/examples/shader/array_texture.rs +++ b/examples/shader/array_texture.rs @@ -1,7 +1,7 @@ use bevy::{ asset::LoadState, prelude::*, - reflect::{TypeUuid, TypePath}, + reflect::{TypePath, TypeUuid}, render::render_resource::{AsBindGroup, ShaderRef}, }; diff --git a/examples/shader/custom_vertex_attribute.rs b/examples/shader/custom_vertex_attribute.rs index 52587a771bb28..fb6299ef7fcfa 100644 --- a/examples/shader/custom_vertex_attribute.rs +++ b/examples/shader/custom_vertex_attribute.rs @@ -3,7 +3,7 @@ use bevy::{ pbr::{MaterialPipeline, MaterialPipelineKey}, prelude::*, - reflect::{TypeUuid, TypePath}, + reflect::{TypePath, TypeUuid}, render::{ mesh::{MeshVertexAttribute, MeshVertexBufferLayout}, render_resource::{ diff --git a/examples/shader/post_processing.rs b/examples/shader/post_processing.rs index 5831aa03f873b..ec6ad40cd0c02 100644 --- a/examples/shader/post_processing.rs +++ b/examples/shader/post_processing.rs @@ -6,7 +6,7 @@ use bevy::{ core_pipeline::clear_color::ClearColorConfig, prelude::*, - reflect::{TypeUuid, TypePath}, + reflect::{TypePath, TypeUuid}, render::{ camera::RenderTarget, render_resource::{ diff --git a/examples/shader/shader_defs.rs b/examples/shader/shader_defs.rs index dd28649edfbba..c4fe88ccb60b1 100644 --- a/examples/shader/shader_defs.rs +++ b/examples/shader/shader_defs.rs @@ -3,7 +3,7 @@ use bevy::{ pbr::{MaterialPipeline, MaterialPipelineKey}, prelude::*, - reflect::{TypeUuid, TypePath}, + reflect::{TypePath, TypeUuid}, render::{ mesh::MeshVertexBufferLayout, render_resource::{ diff --git a/examples/shader/shader_material.rs b/examples/shader/shader_material.rs index c8d7fb4b9d0b8..711dee13bb089 100644 --- a/examples/shader/shader_material.rs +++ b/examples/shader/shader_material.rs @@ -2,7 +2,7 @@ use bevy::{ prelude::*, - reflect::{TypeUuid, TypePath}, + reflect::{TypePath, TypeUuid}, render::render_resource::{AsBindGroup, ShaderRef}, }; diff --git a/examples/shader/shader_material_glsl.rs b/examples/shader/shader_material_glsl.rs index 15f471b87b708..38a40990837bc 100644 --- a/examples/shader/shader_material_glsl.rs +++ b/examples/shader/shader_material_glsl.rs @@ -3,7 +3,7 @@ use bevy::{ pbr::{MaterialPipeline, MaterialPipelineKey}, prelude::*, - reflect::{TypeUuid, TypePath}, + reflect::{TypePath, TypeUuid}, render::{ mesh::MeshVertexBufferLayout, render_resource::{ diff --git a/examples/shader/shader_material_screenspace_texture.rs b/examples/shader/shader_material_screenspace_texture.rs index 57f70ba700b8e..b3d50e762c2a3 100644 --- a/examples/shader/shader_material_screenspace_texture.rs +++ b/examples/shader/shader_material_screenspace_texture.rs @@ -2,7 +2,7 @@ use bevy::{ prelude::*, - reflect::{TypeUuid, TypePath}, + reflect::{TypePath, TypeUuid}, render::render_resource::{AsBindGroup, ShaderRef}, }; From fc45a9a900157fc172551a8fe689b52067ada679 Mon Sep 17 00:00:00 2001 From: radiish Date: Fri, 13 Jan 2023 21:06:48 +0000 Subject: [PATCH 04/52] better test --- crates/bevy_reflect/src/lib.rs | 60 +++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 8bd4c431d82e4..d4e92b20b7f2e 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -654,40 +654,54 @@ mod tests { #[test] fn reflect_type_path() { #[derive(TypePath)] - struct A; + struct Derive; #[derive(TypePath)] #[type_path = "my_alias"] - struct B; + struct DerivePath; #[derive(TypePath)] - struct C(PhantomData); + #[type_path = "my_alias"] + #[type_name = "MyDerivePathName"] + struct DerivePathName; #[derive(TypePath)] - #[type_path = "my_alias"] - struct D(PhantomData); + struct DeriveG(PhantomData); #[derive(TypePath)] #[type_path = "my_alias"] - #[type_name = "Eee"] - struct E(PhantomData); - - // struct E; - // impl_type_path!(E); - - // struct F; - // impl_type_path!(F as my_alias::F); + struct DerivePathG(PhantomData); - // struct G(PhantomData); - // impl_type_path!(G); - - // struct H(PhantomData); - // impl_type_path!(H as my_alias::H); - - assert_eq!(A::type_path(), "bevy_reflect::tests::A"); - B::type_path(); - C::::type_path(); - D::::type_path(); + #[derive(TypePath)] + #[type_path = "my_alias"] + #[type_name = "MyDerivePathNameG"] + struct DerivePathNameG(PhantomData); + + struct Macro; + impl_type_path!(Macro in my_alias); + + struct MacroName; + impl_type_path!(MacroName in my_alias as MyMacroName); + + struct MacroG(PhantomData); + impl_type_path!(MacroG in my_alias); + + struct MacroNameG(PhantomData); + impl_type_path!(MacroNameG in my_alias as MyMacroNameG); + + 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::<()>"); + // E::type_path(); // F::type_path(); // G::::type_path(); From 190cf5c3074895df14bd748ae71aca798df11b8e Mon Sep 17 00:00:00 2001 From: radiish Date: Fri, 13 Jan 2023 21:07:22 +0000 Subject: [PATCH 05/52] `cargo fmt --all` --- crates/bevy_reflect/src/lib.rs | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index d4e92b20b7f2e..0b322429de092 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -676,7 +676,7 @@ mod tests { #[type_path = "my_alias"] #[type_name = "MyDerivePathNameG"] struct DerivePathNameG(PhantomData); - + struct Macro; impl_type_path!(Macro in my_alias); @@ -693,15 +693,27 @@ mod tests { 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!( + 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_eq!( + MacroNameG::<()>::type_path(), + "my_alias::MyMacroNameG::<()>" + ); + // E::type_path(); // F::type_path(); // G::::type_path(); From 171d528060799d3dcea0543cebfa6a3ade74fa1d Mon Sep 17 00:00:00 2001 From: radiish Date: Sat, 14 Jan 2023 11:14:35 +0000 Subject: [PATCH 06/52] first pass docs --- .../bevy_reflect_derive/src/derive_data.rs | 114 +++--------------- .../bevy_reflect_derive/src/impls/typed.rs | 99 ++++++++++++++- .../bevy_reflect_derive/src/lib.rs | 2 +- crates/bevy_reflect/src/type_path.rs | 63 ++++++++++ crates/bevy_reflect/src/utility.rs | 32 +---- 5 files changed, 181 insertions(+), 129 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 922a13ba83b39..a822aa0a0a869 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs @@ -5,7 +5,7 @@ use crate::fq_std::{FQAny, FQDefault, FQSend, FQSync}; use crate::utility::{members_to_serialization_denylist, WhereClauseOptions}; use crate::utility::members_to_serialization_denylist; use bit_set::BitSet; -use quote::{quote, ToTokens}; +use quote::{quote, ToTokens, TokenStreamExt}; use crate::{ utility, REFLECT_ATTRIBUTE_NAME, REFLECT_VALUE_ATTRIBUTE_NAME, TYPE_NAME_ATTRIBUTE_NAME, @@ -227,7 +227,7 @@ impl<'a> ReflectDerive<'a> { } let path_to_type = PathToType::Internal { - ident: &input.ident, + name: &input.ident, alias: alias_type_path, }; @@ -567,23 +567,27 @@ impl<'a> EnumVariant<'a> { } } +/// Represents a path to a type. pub(crate) enum PathToType<'a> { - /// Types without a crate/module (e.g. `bool`). + /// Types without a crate/module that can be named from any scope (e.g. `bool`). Primitive(&'a Ident), /// Using `::my_crate::foo::Bar` syntax. /// /// May have a seperate alias path used for the `TypePath` implementation. External { path: &'a Path, alias: Option }, - /// The name of a type relative to itself. - /// Module and crate are found with [`module_path!()`](core::module_path). + /// The name of a type relative to its scope. + /// The type must be able to be named from just its name. /// /// May have a seperate alias path used for the `TypePath` implementation. + /// + /// Module and crate are found with [`module_path!()`](core::module_path), + /// if there is no alias specified. Internal { - ident: &'a Ident, + name: &'a Ident, alias: Option, }, /// Any [`syn::Type`] with only a defined `type_path` and `short_type_path`. - #[allow(dead_code)] + #[allow(dead_code)] // Not currently used but may be useful in the future due to its generality. Anonymous { qualified_type: Type, long_type_path: proc_macro2::TokenStream, @@ -593,10 +597,10 @@ pub(crate) enum PathToType<'a> { impl<'a> PathToType<'a> { /// Returns the path interpreted as an [`Ident`], - /// or [`None`] if anonymous. + /// or [`None`] if anonymous or primitive. fn named_as_ident(&self) -> Option<&Ident> { match self { - Self::Internal { ident, alias } => Some( + Self::Internal { name: ident, alias } => Some( alias .as_ref() .map(|path| &path.segments.last().unwrap().ident) @@ -616,7 +620,7 @@ impl<'a> PathToType<'a> { } /// Returns the path interpreted as a [`Path`], - /// or [`None`] if anonymous or a non-aliased [`PathToType::Internal`]. + /// or [`None`] if anonymous, primitive, or a non-aliased [`PathToType::Internal`]. fn named_as_path(&self) -> Option<&Path> { match self { Self::Internal { alias, .. } => alias.as_ref(), @@ -629,7 +633,7 @@ impl<'a> PathToType<'a> { /// /// [internal]: PathToType::Internal /// [external]: PathToType::External - pub fn is_alias(&self) -> bool { + pub fn is_aliased(&self) -> bool { match self { Self::Internal { alias, .. } => alias.is_some(), Self::External { alias, .. } => alias.is_some(), @@ -728,93 +732,9 @@ impl<'a> PathToType<'a> { impl<'a> ToTokens for PathToType<'a> { fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { match self { - Self::Internal { ident, .. } | Self::Primitive(ident) => ident.to_tokens(tokens), + Self::Internal { name: ident, .. } | Self::Primitive(ident) => ident.to_tokens(tokens), Self::External { path, .. } => path.to_tokens(tokens), Self::Anonymous { qualified_type, .. } => qualified_type.to_tokens(tokens), } } -} - -pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStream { - let path_to_type = meta.path_to_type(); - let generics = meta.generics(); - let bevy_reflect_path = meta.bevy_reflect_path(); - // Whether to use `GenericTypedCell` is not dependent on lifetimes - // (which all have to be 'static anyway). - let is_generic = !generics - .params - .iter() - .all(|param| matches!(param, GenericParam::Lifetime(_))); - let generic_type_paths: Vec = generics - .type_params() - .map(|param| { - let ident = ¶m.ident; - quote! { - <#ident as #bevy_reflect_path::TypePath> - } - }) - .collect(); - - let ident = path_to_type.ident().unwrap().to_string(); - let ident = LitStr::new(&ident, path_to_type.span()); - - let path = { - let path = path_to_type.long_type_path(); - - if is_generic { - let generics = generic_type_paths.iter().map(|type_path| { - quote! { - #type_path::type_path() - } - }); - - quote! { - #path + "::<" #(+ #generics)* + ">" - } - } else { - quote! { - #path - } - } - }; - - let short_path = { - if is_generic { - let generics = generic_type_paths.iter().map(|type_path| { - quote! { - #type_path::short_type_path() - } - }); - - quote! { - ::core::concat!(#ident, "<").to_owned() #(+ #generics)* + ">" - } - } else { - quote! { - #ident.to_owned() - } - } - }; - - if !path_to_type.is_named() { - quote! { - #bevy_reflect_path::utility::TypePathStorage::new_anonymous( - #path, - #short_path, - ) - } - } else { - let crate_name = path_to_type.crate_name(); - let module_path = path_to_type.module_path(); - - quote! { - #bevy_reflect_path::utility::TypePathStorage::new_named( - #path, - #short_path, - #ident.to_owned(), - #crate_name.to_owned(), - #module_path.to_owned(), - ) - } - } -} +} \ No newline at end of file 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 edff342091c71..ecf666aa1b2cd 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -2,8 +2,103 @@ use crate::utility::{extend_where_clause, WhereClauseOptions}; use crate::ReflectMeta; use proc_macro2::Ident; use quote::quote; -use crate::derive_data::{type_path_generator, PathToType, ReflectMeta}; +use crate::derive_data::{PathToType, ReflectMeta}; +use syn::{GenericParam, LitStr, spanned::Spanned}; +/// Returns an expression for a `TypePathStorage`. +pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStream { + let path_to_type = meta.path_to_type(); + let generics = meta.generics(); + let bevy_reflect_path = meta.bevy_reflect_path(); + // Whether to use `GenericTypedCell` is not dependent on lifetimes + // (which all have to be 'static anyway). + let is_generic = !generics + .params + .iter() + .all(|param| matches!(param, GenericParam::Lifetime(_))); + let generic_type_paths: Vec = generics + .type_params() + .map(|param| { + let ident = ¶m.ident; + quote! { + <#ident as #bevy_reflect_path::TypePath> + } + }) + .collect(); + + let ident = path_to_type.ident().unwrap().to_string(); + let ident = LitStr::new(&ident, path_to_type.span()); + + let path = { + let path = path_to_type.long_type_path(); + + if is_generic { + let generics = generic_type_paths.iter().map(|type_path| { + quote! { + #type_path::type_path() + } + }); + + quote! { + #path + "::<" #(+ #generics)* + ">" + } + } else { + quote! { + #path + } + } + }; + + let short_path = { + if is_generic { + let generics = generic_type_paths.iter().map(|type_path| { + quote! { + #type_path::short_type_path() + } + }); + + quote! { + ::core::concat!(#ident, "<").to_owned() #(+ #generics)* + ">" + } + } else { + quote! { + #ident.to_owned() + } + } + }; + + if let PathToType::Primitive(name) = path_to_type { + quote! { + #bevy_reflect_path::utility::TypePathStorage::new_primitive( + #path, + #short_path, + #name, + ) + } + } else if !path_to_type.is_named() { + quote! { + #bevy_reflect_path::utility::TypePathStorage::new_anonymous( + #path, + #short_path, + ) + } + } else { + let crate_name = path_to_type.crate_name(); + let module_path = path_to_type.module_path(); + + quote! { + #bevy_reflect_path::utility::TypePathStorage::new_named( + #path, + #short_path, + #ident.to_owned(), + #crate_name.to_owned(), + #module_path.to_owned(), + ) + } + } +} + +/// Returns an expression for a `NonGenericTypedCell` or `GenericTypedCell`. fn static_typed_cell( meta: &ReflectMeta, property: TypedProperty, @@ -62,7 +157,7 @@ pub(crate) fn impl_type_path( Some(quote! { const _: () = { mod private_scope { - // compiles if it can be named with its ident when there are no imports. + // Compiles if it can be named with its ident when there are no imports. type AssertIsPrimitive = #path_to_type; } }; diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs index b1a3a4f8633d8..2b670909671a0 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs @@ -175,7 +175,7 @@ pub fn impl_reflect_struct(input: TokenStream) -> TokenStream { match derive_data { ReflectDerive::Struct(struct_data) => { - if !struct_data.meta().path_to_type().is_alias() { + if !struct_data.meta().path_to_type().is_aliased() { return syn::Error::new( struct_data.meta().path_to_type().span(), format!("a #[{TYPE_PATH_ATTRIBUTE_NAME} = \"...\"] attribute must be specified when using `impl_reflect_struct`") diff --git a/crates/bevy_reflect/src/type_path.rs b/crates/bevy_reflect/src/type_path.rs index 3a1afa0a9156f..58c26e4a7e805 100644 --- a/crates/bevy_reflect/src/type_path.rs +++ b/crates/bevy_reflect/src/type_path.rs @@ -1,3 +1,66 @@ +/// A static accessor to type paths and names. +/// +/// The engine uses this trait over [`std::any::type_name`] for stability and flexibility. +/// +/// This trait is automatically implemented by the `#[derive(Reflect)]` macro +/// and allows type path information to be processed without an instance of that type. +/// +/// Implementors may have difficulty in generating references with static +/// lifetimes. Luckily, this crate comes with some [utility] structs, to make generating these +/// statics much simpler. +/// +/// # Stability +/// +/// Certain parts of the engine, e.g. [(de)serialization], rely on type paths as identifiers +/// for matching dynamic values to concrete types. +/// +/// Using [`std::any::type_name`], a scene containing `my_crate::foo::MyComponent` would break, +/// failing to deserialize if the component was moved to be `my_crate::bar::MyComponent`. +/// This trait, through attributes when deriving itself or [`Reflect`], can ensure breaking changes are avoidable. +/// +/// The only external factor we rely on for stability when deriving is the [`module_path!`] macro, +/// only if the derive does not provide a `#[type_path = "..."]` attribute. +/// +/// # Example +/// +/// ```rust +/// use bevy_reflect::TypePath; +/// +/// // This type path will not change with compiler versions or recompiles, +/// // although it will not be the same if the definition is moved. +/// #[derive(TypePath)] +/// struct NonStableTypePath; +/// +/// // This type path will never change, even if the definition is moved. +/// #[derive(TypePath)] +/// #[type_path = "my_crate::foo"] +/// struct StableTypePath; +/// +/// // Type paths can have any number of path segments. +/// #[derive(TypePath)] +/// #[type_path = "my_crate::foo::bar::baz"] +/// struct DeeplyNestedStableTypePath; +/// +/// // Including just a crate name! +/// #[derive(TypePath)] +/// #[type_path = "my_crate"] +/// struct ShallowStableTypePath; +/// +/// // We can also rename the identifier/name of types. +/// #[derive(TypePath)] +/// #[type_path = "my_crate::foo"] +/// #[type_name = "RenamedStableTypePath"] +/// struct NamedStableTypePath; +/// +/// // Generics are also supported. +/// #[derive(TypePath)] +/// #[type_path = "my_crate::foo"] +/// struct StableGenericTypePath(T); +/// ``` +/// +/// [utility]: crate::utility +/// [(de)serialization]: crate::serde::UntypedReflectDeserializer +/// [`Reflect`]: crate::Reflect pub trait TypePath: 'static { /// Returns the fully qualified path of the underlying type. /// diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index 5055283a33d82..67e522c0278b8 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -18,7 +18,7 @@ mod sealed { } pub use sealed::TypedProperty; -/// A container for [`TypeInfo`] or [`TypePath`] over non-generic types, allowing instances to be stored statically. +/// A container for [`TypeInfo`] or [`TypePathStorage`] over non-generic types, allowing instances to be stored statically. /// /// This is specifically meant for use with _non_-generic types. If your type _is_ generic, /// then use [`GenericTypedCell`] instead. Otherwise, it will not take into account all @@ -44,19 +44,6 @@ pub use sealed::TypedProperty; /// TypeInfo::Struct(info) /// }) /// } -/// -/// fn type_path() -> &'static TypePath { -/// static CELL: NonGenericTypePathCell = NonGenericTypePathCell::new(); -/// CELL.get_or_set(|| { -/// TypePath::new_named( -/// "my_crate::Foo".to_owned(), -/// "Foo".to_owned(), -/// "Foo".to_owned(), -/// "my_crate".to_owned(), -/// "my_crate".to_owned(), -/// ) -/// }) -/// } /// } /// # /// # impl Reflect for Foo { @@ -87,7 +74,7 @@ impl NonGenericTypedCell { Self(OnceBox::new()) } - /// Returns a reference to the [`TypeInfo`]/[`TypePath`] stored in the cell. + /// Returns a reference to the [`TypeInfo`]/[`TypePathStorage`] stored in the cell. /// /// If there is no entry found, a new one will be generated from the given function. pub fn get_or_set(&self, f: F) -> &T @@ -98,7 +85,7 @@ impl NonGenericTypedCell { } } -/// A container for [`TypeInfo`] or [`TypePath`] over generic types, allowing instances to be stored statically. +/// A container for [`TypeInfo`] or [`TypePathStorage`] over generic types, allowing instances to be stored statically. /// /// This is specifically meant for use with generic types. If your type isn't generic, /// then use [`NonGenericTypedCell`] instead as it should be much more performant. @@ -121,19 +108,6 @@ impl NonGenericTypedCell { /// TypeInfo::TupleStruct(info) /// }) /// } -/// -/// fn type_path() -> &'static TypePath { -/// static CELL: GenericTypePathCell = GenericTypePathCell::new(); -/// CELL.get_or_insert::(|| { -/// TypePath::new_named( -/// "my_crate::Foo::<".to_owned() + T::type_path().path() + ">", -/// "Foo<".to_owned() + T::type_path().short_path() + ">", -/// "Foo".to_owned(), -/// "my_crate".to_owned(), -/// "my_crate".to_owned(), -/// ) -/// }) -/// } /// } /// # /// # impl Reflect for Foo { From 5c7e11358b655308cdac3344185b1f4d68958b4a Mon Sep 17 00:00:00 2001 From: radiish Date: Sat, 14 Jan 2023 11:31:44 +0000 Subject: [PATCH 07/52] primitive fix --- .../bevy_reflect_derive/src/derive_data.rs | 2 +- .../bevy_reflect_derive/src/impls/typed.rs | 28 +++++++++---------- 2 files changed, 14 insertions(+), 16 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 a822aa0a0a869..5073810bc7bf8 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs @@ -5,7 +5,7 @@ use crate::fq_std::{FQAny, FQDefault, FQSend, FQSync}; use crate::utility::{members_to_serialization_denylist, WhereClauseOptions}; use crate::utility::members_to_serialization_denylist; use bit_set::BitSet; -use quote::{quote, ToTokens, TokenStreamExt}; +use quote::{quote, ToTokens}; use crate::{ utility, REFLECT_ATTRIBUTE_NAME, REFLECT_VALUE_ATTRIBUTE_NAME, TYPE_NAME_ATTRIBUTE_NAME, 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 ecf666aa1b2cd..9b3c47c82dba8 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -10,6 +10,14 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea let path_to_type = meta.path_to_type(); let generics = meta.generics(); let bevy_reflect_path = meta.bevy_reflect_path(); + + if let PathToType::Primitive(name) = path_to_type { + let name = LitStr::new(&name.to_string(), name.span()); + return quote! { + #bevy_reflect_path::utility::TypePathStorage::new_primitive(#name) + }; + } + // Whether to use `GenericTypedCell` is not dependent on lifetimes // (which all have to be 'static anyway). let is_generic = !generics @@ -67,15 +75,7 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea } }; - if let PathToType::Primitive(name) = path_to_type { - quote! { - #bevy_reflect_path::utility::TypePathStorage::new_primitive( - #path, - #short_path, - #name, - ) - } - } else if !path_to_type.is_named() { + if !path_to_type.is_named() { quote! { #bevy_reflect_path::utility::TypePathStorage::new_anonymous( #path, @@ -155,12 +155,10 @@ pub(crate) fn impl_type_path( let primitive_assert = if let PathToType::Primitive(_) = path_to_type { Some(quote! { - const _: () = { - mod private_scope { - // Compiles if it can be named with its ident when there are no imports. - type AssertIsPrimitive = #path_to_type; - } - }; + mod private_scope { + // Compiles if it can be named with its ident when there are no imports. + type AssertIsPrimitive = #path_to_type; + } }) } else { None From 0cb050afa0576ed6e450e16c9bacc4addd32de44 Mon Sep 17 00:00:00 2001 From: radiish Date: Sat, 14 Jan 2023 12:26:35 +0000 Subject: [PATCH 08/52] messy rebase & ci --- crates/bevy_asset/src/asset_server.rs | 2 +- crates/bevy_pbr/src/material.rs | 4 +-- .../bevy_reflect_derive/src/derive_data.rs | 25 ++++++++----------- .../bevy_reflect_derive/src/impls/typed.rs | 6 ++--- .../bevy_reflect_derive/src/lib.rs | 4 +-- crates/bevy_reflect/src/impls/glam.rs | 1 - crates/bevy_reflect/src/impls/std.rs | 13 +++++----- crates/bevy_reflect/src/lib.rs | 2 +- crates/bevy_sprite/src/mesh2d/material.rs | 4 +-- examples/3d/skybox.rs | 4 +-- 10 files changed, 30 insertions(+), 35 deletions(-) diff --git a/crates/bevy_asset/src/asset_server.rs b/crates/bevy_asset/src/asset_server.rs index 0a350f7d14823..f90a7716ca45a 100644 --- a/crates/bevy_asset/src/asset_server.rs +++ b/crates/bevy_asset/src/asset_server.rs @@ -97,7 +97,7 @@ pub struct AssetServerInternal { /// use bevy_asset::{AssetServer, Handle}; /// use bevy_ecs::prelude::{Commands, Res}; /// -/// # #[derive(Debug, bevy_reflect::TypeUuid)] +/// # #[derive(Debug, bevy_reflect::TypeUuid, bevy_reflect::TypePath)] /// # #[uuid = "00000000-0000-0000-0000-000000000000"] /// # struct Image; /// diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 30bad3ffa99c1..9486e5f3da99a 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -59,11 +59,11 @@ use std::marker::PhantomData; /// ``` /// # use bevy_pbr::{Material, MaterialMeshBundle}; /// # use bevy_ecs::prelude::*; -/// # use bevy_reflect::TypeUuid; +/// # use bevy_reflect::{TypeUuid, TypePath}; /// # use bevy_render::{render_resource::{AsBindGroup, ShaderRef}, texture::Image, color::Color}; /// # use bevy_asset::{Handle, AssetServer, Assets}; /// -/// #[derive(AsBindGroup, TypeUuid, Debug, Clone)] +/// #[derive(AsBindGroup, TypeUuid, TypePath, Debug, Clone)] /// #[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"] /// pub struct CustomMaterial { /// // Uniform bindings must implement `ShaderType`, which will be used to convert the value to 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 5073810bc7bf8..a4b3d8dff4c38 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs @@ -217,7 +217,7 @@ impl<'a> ReflectDerive<'a> { } } if let Some(path) = &mut alias_type_path { - let ident = alias_type_name.unwrap_or(input.ident.clone()); + let ident = alias_type_name.unwrap_or_else(|| input.ident.clone()); path.segments.push(PathSegment::from(ident)); } else if let Some(name) = alias_type_name { return Err(syn::Error::new( @@ -275,9 +275,9 @@ impl<'a> ReflectDerive<'a> { pub fn meta(&self) -> &ReflectMeta<'a> { match self { - ReflectDerive::Struct(data) => data.meta(), - ReflectDerive::TupleStruct(data) => data.meta(), - ReflectDerive::UnitStruct(data) => data.meta(), + ReflectDerive::Struct(data) + | ReflectDerive::TupleStruct(data) + | ReflectDerive::UnitStruct(data) => data.meta(), ReflectDerive::Enum(data) => data.meta(), ReflectDerive::Value(meta) => meta, } @@ -579,7 +579,7 @@ pub(crate) enum PathToType<'a> { /// The type must be able to be named from just its name. /// /// May have a seperate alias path used for the `TypePath` implementation. - /// + /// /// Module and crate are found with [`module_path!()`](core::module_path), /// if there is no alias specified. Internal { @@ -587,7 +587,8 @@ pub(crate) enum PathToType<'a> { alias: Option, }, /// Any [`syn::Type`] with only a defined `type_path` and `short_type_path`. - #[allow(dead_code)] // Not currently used but may be useful in the future due to its generality. + #[allow(dead_code)] + // Not currently used but may be useful in the future due to its generality. Anonymous { qualified_type: Type, long_type_path: proc_macro2::TokenStream, @@ -635,8 +636,7 @@ impl<'a> PathToType<'a> { /// [external]: PathToType::External pub fn is_aliased(&self) -> bool { match self { - Self::Internal { alias, .. } => alias.is_some(), - Self::External { alias, .. } => alias.is_some(), + Self::Internal { alias, .. } | Self::External { alias, .. } => alias.is_some(), _ => false, } } @@ -646,10 +646,7 @@ impl<'a> PathToType<'a> { /// /// This is false for primitives and anonymous paths. pub fn is_named(&self) -> bool { - match self { - Self::Primitive(_) | Self::Anonymous { .. } => false, - _ => true, - } + matches!(self, Self::Internal { .. } | Self::External { .. }) } /// Returns an expression for an `AsRef`. @@ -722,7 +719,7 @@ impl<'a> PathToType<'a> { /// Returns the name of the type. This is not necessarily a valid qualified path to the type. pub fn ident(&self) -> Option<&Ident> { - self.named_as_ident().or_else(|| match self { + self.named_as_ident().or(match self { Self::Primitive(ident) => Some(ident), _ => None, }) @@ -737,4 +734,4 @@ impl<'a> ToTokens for PathToType<'a> { Self::Anonymous { qualified_type, .. } => qualified_type.to_tokens(tokens), } } -} \ No newline at end of file +} 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 9b3c47c82dba8..e24e82a2fc179 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -2,22 +2,22 @@ use crate::utility::{extend_where_clause, WhereClauseOptions}; use crate::ReflectMeta; use proc_macro2::Ident; use quote::quote; +use syn::{spanned::Spanned, GenericParam, LitStr}; use crate::derive_data::{PathToType, ReflectMeta}; -use syn::{GenericParam, LitStr, spanned::Spanned}; /// Returns an expression for a `TypePathStorage`. pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStream { let path_to_type = meta.path_to_type(); let generics = meta.generics(); let bevy_reflect_path = meta.bevy_reflect_path(); - + if let PathToType::Primitive(name) = path_to_type { let name = LitStr::new(&name.to_string(), name.span()); return quote! { #bevy_reflect_path::utility::TypePathStorage::new_primitive(#name) }; } - + // Whether to use `GenericTypedCell` is not dependent on lifetimes // (which all have to be 'static anyway). let is_generic = !generics diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs index 2b670909671a0..9d1f259e4db34 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs @@ -120,7 +120,7 @@ pub fn impl_reflect_value(input: TokenStream) -> TokenStream { let def = parse_macro_input!(input as ReflectValueDef); let default_name = &def.type_path.segments.last().unwrap().ident; - let path_to_type = if !def.type_path.leading_colon.is_some() && def.alias.is_empty() { + let path_to_type = if def.type_path.leading_colon.is_none() && def.alias.is_empty() { PathToType::Primitive(default_name) } else { PathToType::External { @@ -217,7 +217,7 @@ pub fn impl_from_reflect_value(input: TokenStream) -> TokenStream { let def = parse_macro_input!(input as ReflectValueDef); let default_name = &def.type_path.segments.last().unwrap().ident; - let path_to_type = if !def.type_path.leading_colon.is_some() && def.alias.is_empty() { + let path_to_type = if def.type_path.leading_colon.is_none() && def.alias.is_empty() { PathToType::Primitive(default_name) } else { PathToType::External { diff --git a/crates/bevy_reflect/src/impls/glam.rs b/crates/bevy_reflect/src/impls/glam.rs index 74c20d5cfb277..4a3f50cc62b6f 100644 --- a/crates/bevy_reflect/src/impls/glam.rs +++ b/crates/bevy_reflect/src/impls/glam.rs @@ -59,7 +59,6 @@ impl_reflect_struct!( w: u32, } ); - impl_reflect_struct!( #[reflect(Debug, PartialEq, Default)] #[type_path = "glam"] diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 3070f121d5097..5d5769edf8968 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -1133,9 +1133,9 @@ impl_type_path_stored!(|| TypePathStorage::new_named( "core::borrow" ), impl for Cow<'static, str>); -impl GetTypeRegistration for Cow<'static, str>c Path { +impl GetTypeRegistration for Cow<'static, str> { fn get_type_registration() -> TypeRegistration { - let mut registration = TypeRegistration:Cow<'static, str>>(); + let mut registration = TypeRegistration::of::>(); registration.insert::(FromType::>::from_type()); registration.insert::(FromType::>::from_type()); registration.insert::(FromType::>::from_type()); @@ -1143,9 +1143,9 @@ impl GetTypeRegistration for Cow<'static, str>c Path { } } -impl FromReflect for Cow<'static, str>c Path { +impl FromReflect for Cow<'static, str> { fn from_reflect(reflect: &dyn crate::Reflect) -> Option { - Some( + Some( reflect .as_any() .downcast_ref::>()? @@ -1243,8 +1243,6 @@ impl Typed for &'static Path { impl_type_path_stored!(|| TypePathStorage::new_anonymous("&std::path::Path", "&Path"), impl for &'static Path); -impl - impl GetTypeRegistration for &'static Path { fn get_type_registration() -> TypeRegistration { let mut registration = TypeRegistration::of::(); @@ -1475,4 +1473,5 @@ mod tests { let path = Path::new("hello_world.rs"); let output = <&'static Path as FromReflect>::from_reflect(&path).unwrap(); assert_eq!(path, output); - \ No newline at end of file + } +} diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 0b322429de092..b0cde28748c01 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1022,7 +1022,7 @@ mod tests { struct SomePrimitive; impl_reflect_value!( /// Some primitive for which we have attributed custom documentation. - SomePrimitive + SomePrimitive in bevy_reflect::tests ); let info = ::type_info(); diff --git a/crates/bevy_sprite/src/mesh2d/material.rs b/crates/bevy_sprite/src/mesh2d/material.rs index f498893c88fbb..4803373b9ebfc 100644 --- a/crates/bevy_sprite/src/mesh2d/material.rs +++ b/crates/bevy_sprite/src/mesh2d/material.rs @@ -60,11 +60,11 @@ use crate::{ /// ``` /// # use bevy_sprite::{Material2d, MaterialMesh2dBundle}; /// # use bevy_ecs::prelude::*; -/// # use bevy_reflect::TypeUuid; +/// # use bevy_reflect::{TypeUuid, TypePath}; /// # use bevy_render::{render_resource::{AsBindGroup, ShaderRef}, texture::Image, color::Color}; /// # use bevy_asset::{Handle, AssetServer, Assets}; /// -/// #[derive(AsBindGroup, TypeUuid, Debug, Clone)] +/// #[derive(AsBindGroup, TypeUuid, TypePath, Debug, Clone)] /// #[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"] /// pub struct CustomMaterial { /// // Uniform bindings must implement `ShaderType`, which will be used to convert the value to diff --git a/examples/3d/skybox.rs b/examples/3d/skybox.rs index c9dadafd5b8f1..525b46eb90f83 100644 --- a/examples/3d/skybox.rs +++ b/examples/3d/skybox.rs @@ -7,7 +7,7 @@ use bevy::{ input::mouse::MouseMotion, pbr::{MaterialPipeline, MaterialPipelineKey}, prelude::*, - reflect::TypeUuid, + reflect::{TypePath, TypeUuid}, render::{ mesh::MeshVertexBufferLayout, render_asset::RenderAssets, @@ -196,7 +196,7 @@ fn animate_light_direction( } } -#[derive(Debug, Clone, TypeUuid)] +#[derive(Debug, Clone, TypeUuid, TypePath)] #[uuid = "9509a0f8-3c05-48ee-a13e-a93226c7f488"] struct CubemapMaterial { base_color_texture: Option>, From 6929d9cef0ea72fa392c957da36ee2c68f3e0937 Mon Sep 17 00:00:00 2001 From: radiish Date: Sat, 14 Jan 2023 12:52:00 +0000 Subject: [PATCH 09/52] ci wrangling --- crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs | 2 +- crates/bevy_reflect/src/impls/std.rs | 4 ++-- crates/bevy_reflect/src/utility.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 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 a4b3d8dff4c38..c8e1daf6d21ad 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs @@ -597,7 +597,7 @@ pub(crate) enum PathToType<'a> { } impl<'a> PathToType<'a> { - /// Returns the path interpreted as an [`Ident`], + /// Returns the path interpreted as an [`struct@Ident`], /// or [`None`] if anonymous or primitive. fn named_as_ident(&self) -> Option<&Ident> { match self { diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 5d5769edf8968..d9a4c4df6e7ee 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -111,7 +111,7 @@ impl_reflect_value!(::core::ops::RangeFrom()) impl_reflect_value!(::core::ops::RangeTo()); impl_reflect_value!(::core::ops::RangeToInclusive()); impl_reflect_value!(::core::ops::RangeFull()); -impl_reflect_value!(::core::time::Duration( +impl_reflect_value!(::bevy_utils::Duration( Debug, Hash, PartialEq, @@ -119,7 +119,7 @@ impl_reflect_value!(::core::time::Duration( Deserialize, Default )); -impl_reflect_value!(::std::time::Instant(Debug, Hash, PartialEq)); +impl_reflect_value!(::bevy_utils::Instant(Debug, Hash, PartialEq)); impl_reflect_value!(::core::num::NonZeroI128( Debug, Hash, diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index 67e522c0278b8..df7583390cb62 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -138,9 +138,9 @@ impl GenericTypedCell { Self(OnceBox::new()) } - /// Returns a reference to the [`TypeInfo`]/[`TypePath`] stored in the cell. + /// Returns a reference to the [`TypeInfo`]/[`TypePathStorage`] stored in the cell. /// - /// This method will then return the correct [`TypeInfo`]/[`TypePath`] reference for the given type `T`. + /// This method will then return the correct [`TypeInfo`]/[`TypePathStorage`] reference for the given type `T`. /// If there is no entry found, a new one will be generated from the given function. pub fn get_or_insert(&self, f: F) -> &T where From 7f8f7a9f430414d937a6cad3b8083dbd18364c80 Mon Sep 17 00:00:00 2001 From: radiish Date: Sat, 14 Jan 2023 14:04:16 +0000 Subject: [PATCH 10/52] const generics --- .../bevy_reflect_derive/src/impls/typed.rs | 50 ++++++++++++++++--- crates/bevy_reflect/src/lib.rs | 12 ++--- crates/bevy_reflect/src/type_path.rs | 2 +- 3 files changed, 49 insertions(+), 15 deletions(-) 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 e24e82a2fc179..4a42168fd3a91 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -1,6 +1,7 @@ use crate::utility::{extend_where_clause, WhereClauseOptions}; use crate::ReflectMeta; use proc_macro2::Ident; +use std::borrow::Cow; use quote::quote; use syn::{spanned::Spanned, GenericParam, LitStr}; use crate::derive_data::{PathToType, ReflectMeta}; @@ -24,8 +25,8 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea .params .iter() .all(|param| matches!(param, GenericParam::Lifetime(_))); - let generic_type_paths: Vec = generics - .type_params() + + let ty_generic_paths: Vec<_> = generics.type_params() .map(|param| { let ident = ¶m.ident; quote! { @@ -33,6 +34,30 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea } }) .collect(); + + let const_generic_strings: Vec<_> = generics.const_params().map(|param| { + let ident = ¶m.ident; + let ty = ¶m.ty; + + quote! { + &<#ty as ::std::string::ToString>::to_string(&#ident) + } + }).collect(); + + let comma = quote! { + ", " + }; + + let combine_generics = |ty_generics: Vec| { + let mut generics = ty_generics.into_iter().map(Cow::Owned).chain(const_generic_strings.iter().map(Cow::Borrowed)).flat_map(|t| { + [ + Cow::Borrowed(&comma), + t + ] + }); + generics.next(); // Skip first comma. + generics + }; let ident = path_to_type.ident().unwrap().to_string(); let ident = LitStr::new(&ident, path_to_type.span()); @@ -41,14 +66,19 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea let path = path_to_type.long_type_path(); if is_generic { - let generics = generic_type_paths.iter().map(|type_path| { + let ty_generics: Vec<_> = ty_generic_paths.iter().map(|type_path| { quote! { #type_path::type_path() } - }); + }).collect(); + + let generics = combine_generics(ty_generics); quote! { - #path + "::<" #(+ #generics)* + ">" + #path + + "::<" + #(+ #generics)* + + ">" } } else { quote! { @@ -59,14 +89,18 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea let short_path = { if is_generic { - let generics = generic_type_paths.iter().map(|type_path| { + let ty_generics: Vec<_> = ty_generic_paths.iter().map(|type_path| { quote! { #type_path::short_type_path() } - }); + }).collect(); + + let generics = combine_generics(ty_generics); quote! { - ::core::concat!(#ident, "<").to_owned() #(+ #generics)* + ">" + ::core::concat!(#ident, "<").to_owned() + #(+ #generics)* + + ">" } } else { quote! { diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index b0cde28748c01..afd0f1e19b612 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -670,7 +670,7 @@ mod tests { #[derive(TypePath)] #[type_path = "my_alias"] - struct DerivePathG(PhantomData); + struct DerivePathG(PhantomData); #[derive(TypePath)] #[type_path = "my_alias"] @@ -683,8 +683,8 @@ mod tests { struct MacroName; impl_type_path!(MacroName in my_alias as MyMacroName); - struct MacroG(PhantomData); - impl_type_path!(MacroG in my_alias); + struct MacroG(PhantomData); + impl_type_path!(MacroG in my_alias); struct MacroNameG(PhantomData); impl_type_path!(MacroNameG in my_alias as MyMacroNameG); @@ -698,8 +698,8 @@ mod tests { "bevy_reflect::tests::DeriveG::<()>" ); assert_eq!( - DerivePathG::<()>::type_path(), - "my_alias::DerivePathG::<()>" + DerivePathG::<(), 10>::type_path(), + "my_alias::DerivePathG::<(), 10>" ); assert_eq!( DerivePathNameG::<()>::type_path(), @@ -708,7 +708,7 @@ mod tests { 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!(MacroG::<(), 10>::type_path(), "my_alias::MacroG::<(), 10>"); assert_eq!( MacroNameG::<()>::type_path(), "my_alias::MyMacroNameG::<()>" diff --git a/crates/bevy_reflect/src/type_path.rs b/crates/bevy_reflect/src/type_path.rs index 58c26e4a7e805..2ae6e85d0e4bd 100644 --- a/crates/bevy_reflect/src/type_path.rs +++ b/crates/bevy_reflect/src/type_path.rs @@ -55,7 +55,7 @@ /// // Generics are also supported. /// #[derive(TypePath)] /// #[type_path = "my_crate::foo"] -/// struct StableGenericTypePath(T); +/// struct StableGenericTypePath([T; N]); /// ``` /// /// [utility]: crate::utility From 4fe69899db9fb30c576f1081083b73bb3b4af614 Mon Sep 17 00:00:00 2001 From: radiish Date: Sat, 14 Jan 2023 14:05:41 +0000 Subject: [PATCH 11/52] `cargo fmt --all` --- .../bevy_reflect_derive/src/impls/typed.rs | 73 +++++++++++-------- 1 file changed, 41 insertions(+), 32 deletions(-) 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 4a42168fd3a91..b066c663e51c1 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -25,8 +25,9 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea .params .iter() .all(|param| matches!(param, GenericParam::Lifetime(_))); - - let ty_generic_paths: Vec<_> = generics.type_params() + + let ty_generic_paths: Vec<_> = generics + .type_params() .map(|param| { let ident = ¶m.ident; quote! { @@ -34,28 +35,30 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea } }) .collect(); - - let const_generic_strings: Vec<_> = generics.const_params().map(|param| { - let ident = ¶m.ident; - let ty = ¶m.ty; - - quote! { - &<#ty as ::std::string::ToString>::to_string(&#ident) - } - }).collect(); - + + let const_generic_strings: Vec<_> = generics + .const_params() + .map(|param| { + let ident = ¶m.ident; + let ty = ¶m.ty; + + quote! { + &<#ty as ::std::string::ToString>::to_string(&#ident) + } + }) + .collect(); + let comma = quote! { ", " }; - + let combine_generics = |ty_generics: Vec| { - let mut generics = ty_generics.into_iter().map(Cow::Owned).chain(const_generic_strings.iter().map(Cow::Borrowed)).flat_map(|t| { - [ - Cow::Borrowed(&comma), - t - ] - }); - generics.next(); // Skip first comma. + let mut generics = ty_generics + .into_iter() + .map(Cow::Owned) + .chain(const_generic_strings.iter().map(Cow::Borrowed)) + .flat_map(|t| [Cow::Borrowed(&comma), t]); + generics.next(); // Skip first comma. generics }; @@ -66,12 +69,15 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea let path = path_to_type.long_type_path(); if is_generic { - let ty_generics: Vec<_> = ty_generic_paths.iter().map(|type_path| { - quote! { - #type_path::type_path() - } - }).collect(); - + let ty_generics: Vec<_> = ty_generic_paths + .iter() + .map(|type_path| { + quote! { + #type_path::type_path() + } + }) + .collect(); + let generics = combine_generics(ty_generics); quote! { @@ -89,12 +95,15 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea let short_path = { if is_generic { - let ty_generics: Vec<_> = ty_generic_paths.iter().map(|type_path| { - quote! { - #type_path::short_type_path() - } - }).collect(); - + let ty_generics: Vec<_> = ty_generic_paths + .iter() + .map(|type_path| { + quote! { + #type_path::short_type_path() + } + }) + .collect(); + let generics = combine_generics(ty_generics); quote! { From ec4c78e926529d5cbd9a6f7993a37f2f20f6fa71 Mon Sep 17 00:00:00 2001 From: radiish Date: Fri, 27 Jan 2023 18:30:40 +0000 Subject: [PATCH 12/52] use literals where possible --- .../bevy_reflect_derive/src/derive_data.rs | 39 ++++++-- .../bevy_reflect_derive/src/impls/typed.rs | 95 ++++++++++++------- 2 files changed, 90 insertions(+), 44 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 c8e1daf6d21ad..5ec669caf32f0 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs @@ -649,6 +649,14 @@ impl<'a> PathToType<'a> { matches!(self, Self::Internal { .. } | Self::External { .. }) } + /// Returns the name of the type. This is not necessarily a valid qualified path to the type. + pub fn ident(&self) -> Option<&Ident> { + self.named_as_ident().or(match self { + Self::Primitive(ident) => Some(ident), + _ => None, + }) + } + /// Returns an expression for an `AsRef`. pub fn crate_name(&self) -> Option { if let Some(path) = self.named_as_path() { @@ -670,27 +678,40 @@ impl<'a> PathToType<'a> { } /// Returns an expression for an `AsRef`. - pub fn long_type_path(&self) -> proc_macro2::TokenStream { + pub fn non_generic_path(&self) -> proc_macro2::TokenStream { if let Some(ident) = self.named_as_ident() { let module_path = self.module_path(); let ident = LitStr::new(&ident.to_string(), ident.span()); return quote! { - #module_path.to_owned() + ::core::concat!("::", #ident) + ::core::concat!(#module_path, "::", #ident) }; } match self { Self::Primitive(ident) => { let ident = LitStr::new(&ident.to_string(), ident.span()); - quote! { - #ident.to_owned() - } + ident.to_token_stream() } Self::Anonymous { long_type_path, .. } => long_type_path.clone(), _ => unreachable!(), } } + /// Returns an expression for an `&str`. + pub fn non_generic_short_path(&self) -> proc_macro2::TokenStream { + if let Some(ident) = self.ident() { + let ident = LitStr::new(&ident.to_string(), ident.span()); + return ident.to_token_stream(); + } + + match self { + Self::Anonymous { + short_type_path, .. + } => short_type_path.clone(), + _ => unreachable!(), + } + } + /// Returns an expression for an `AsRef`. pub fn module_path(&self) -> Option { if let Some(path) = self.named_as_path() { @@ -718,10 +739,10 @@ impl<'a> PathToType<'a> { } /// Returns the name of the type. This is not necessarily a valid qualified path to the type. - pub fn ident(&self) -> Option<&Ident> { - self.named_as_ident().or(match self { - Self::Primitive(ident) => Some(ident), - _ => None, + pub fn name(&self) -> Option { + self.ident().map(|ident| { + let lit = LitStr::new(&ident.to_string(), ident.span()); + lit.to_token_stream() }) } } 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 b066c663e51c1..fc6e75a0cafa3 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -3,8 +3,9 @@ use crate::ReflectMeta; use proc_macro2::Ident; use std::borrow::Cow; use quote::quote; -use syn::{spanned::Spanned, GenericParam, LitStr}; -use crate::derive_data::{PathToType, ReflectMeta}; +use syn::{spanned::Spanned, LitStr}; + +use crate::{derive_data::{PathToType, ReflectMeta}, fq_std::FQOption}; /// Returns an expression for a `TypePathStorage`. pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStream { @@ -19,12 +20,7 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea }; } - // Whether to use `GenericTypedCell` is not dependent on lifetimes - // (which all have to be 'static anyway). - let is_generic = !generics - .params - .iter() - .all(|param| matches!(param, GenericParam::Lifetime(_))); + let is_generic = meta.impl_is_generic(); let ty_generic_paths: Vec<_> = generics .type_params() @@ -48,9 +44,7 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea }) .collect(); - let comma = quote! { - ", " - }; + let comma = quote!(", "); let combine_generics = |ty_generics: Vec| { let mut generics = ty_generics @@ -66,7 +60,7 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea let ident = LitStr::new(&ident, path_to_type.span()); let path = { - let path = path_to_type.long_type_path(); + let path = path_to_type.non_generic_path(); if is_generic { let ty_generics: Vec<_> = ty_generic_paths @@ -81,7 +75,7 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea let generics = combine_generics(ty_generics); quote! { - #path + ::std::borrow::ToOwned::to_owned(#path) + "::<" #(+ #generics)* + ">" @@ -107,7 +101,7 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea let generics = combine_generics(ty_generics); quote! { - ::core::concat!(#ident, "<").to_owned() + ::std::borrow::ToOwned::to_owned(::core::concat!(#ident, "<")) #(+ #generics)* + ">" } @@ -188,10 +182,41 @@ pub(crate) fn impl_type_path( let path_to_type = meta.path_to_type(); let bevy_reflect_path = meta.bevy_reflect_path(); - let type_path_cell = - static_typed_cell(meta, TypedProperty::TypePath, type_path_generator(meta)); + let (type_path_storage, type_path, short_type_path) = if meta.impl_is_generic() { + let cell = static_typed_cell(meta, TypedProperty::TypePath, type_path_generator(meta)); - let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl(); + ( + Some(cell), + quote! { + Self::get_storage().path() + }, + quote! { + Self::get_storage().short_path() + }, + ) + } else { + ( + None, + path_to_type.non_generic_path(), + path_to_type.non_generic_short_path(), + ) + }; + + let name = path_to_type.name().map(|name| quote! { + #FQOption::Some(#name) + }).unwrap_or_else(|| quote! { + #FQOption::None + }); + let module_path = path_to_type.module_path().map(|name| quote! { + #FQOption::Some(#name) + }).unwrap_or_else(|| quote! { + #FQOption::None + }); + let crate_name = path_to_type.crate_name().map(|name| quote! { + #FQOption::Some(#name) + }).unwrap_or_else(|| quote! { + #FQOption::None + }); // Add Typed bound for each active field let where_reflect_clause = extend_where_clause(where_clause, where_clause_options); @@ -207,10 +232,10 @@ pub(crate) fn impl_type_path( None }; - quote! { - const _: () = { - #primitive_assert + let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl(); + let type_path_helper = type_path_storage.map(|storage| { + quote! { trait GetStorage { fn get_storage() -> &'static #bevy_reflect_path::utility::TypePathStorage; } @@ -218,38 +243,38 @@ pub(crate) fn impl_type_path( impl #impl_generics GetStorage for #path_to_type #ty_generics #where_reflect_clause { #[inline] fn get_storage() -> &'static #bevy_reflect_path::utility::TypePathStorage { - #type_path_cell + #storage } } + } + }); + + quote! { + const _: () = { + #primitive_assert + + #type_path_helper + impl #impl_generics #bevy_reflect_path::TypePath for #path_to_type #ty_generics #where_reflect_clause { fn type_path() -> &'static str { - &Self::get_storage().path() + #type_path } fn short_type_path() -> &'static str { - &Self::get_storage().short_path() + #short_type_path } fn type_ident() -> Option<&'static str> { - match Self::get_storage().ident() { - Some(x) => Some(x), - None => None - } + #name } fn crate_name() -> Option<&'static str> { - match Self::get_storage().crate_name() { - Some(x) => Some(x), - None => None - } + #crate_name } fn module_path() -> Option<&'static str> { - match Self::get_storage().module_path() { - Some(x) => Some(x), - None => None - } + #module_path } } }; From c54b7763d1abe2e060d33b317f543e79aa53fee0 Mon Sep 17 00:00:00 2001 From: radiish Date: Fri, 27 Jan 2023 19:12:20 +0000 Subject: [PATCH 13/52] remove `TypePathStorage` --- .../bevy_reflect_derive/src/derive_data.rs | 12 +- .../bevy_reflect_derive/src/impls/typed.rs | 297 ++++++++---------- crates/bevy_reflect/src/impls/std.rs | 61 +++- crates/bevy_reflect/src/reflect.rs | 19 +- crates/bevy_reflect/src/tuple.rs | 24 +- crates/bevy_reflect/src/type_path.rs | 12 +- crates/bevy_reflect/src/utility.rs | 174 +--------- 7 files changed, 231 insertions(+), 368 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 5ec669caf32f0..b1442ce8c20be 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs @@ -641,14 +641,6 @@ impl<'a> PathToType<'a> { } } - /// Returns whether [`crate_name`](PathToType::crate_name) - /// and [`module_path`](PathToType::module_path) return [`Some`]. - /// - /// This is false for primitives and anonymous paths. - pub fn is_named(&self) -> bool { - matches!(self, Self::Internal { .. } | Self::External { .. }) - } - /// Returns the name of the type. This is not necessarily a valid qualified path to the type. pub fn ident(&self) -> Option<&Ident> { self.named_as_ident().or(match self { @@ -689,8 +681,8 @@ impl<'a> PathToType<'a> { match self { Self::Primitive(ident) => { - let ident = LitStr::new(&ident.to_string(), ident.span()); - ident.to_token_stream() + let lit = LitStr::new(&ident.to_string(), ident.span()); + lit.to_token_stream() } Self::Anonymous { long_type_path, .. } => long_type_path.clone(), _ => unreachable!(), 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 fc6e75a0cafa3..d6d9ece1145d7 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -1,14 +1,43 @@ use crate::utility::{extend_where_clause, WhereClauseOptions}; use crate::ReflectMeta; use proc_macro2::Ident; +use syn::Generics; use std::borrow::Cow; -use quote::quote; +use quote::{quote, ToTokens}; use syn::{spanned::Spanned, LitStr}; use crate::{derive_data::{PathToType, ReflectMeta}, fq_std::FQOption}; -/// Returns an expression for a `TypePathStorage`. -pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStream { +fn combine_generics( + ty_generics: Vec, + generics: &Generics, +) -> impl Iterator { + let const_generic_strings: Vec<_> = generics + .const_params() + .map(|param| { + let ident = ¶m.ident; + let ty = ¶m.ty; + + quote! { + &<#ty as ::std::string::ToString>::to_string(&#ident) + } + }) + .collect(); + + let mut generics = ty_generics + .into_iter() + .chain(const_generic_strings.into_iter()) + .flat_map(|t| [", ".to_token_stream(), t]); + generics.next(); // Skip first comma. + generics +} + +/// Returns an expression for a `&'static str`, +/// representing either a [long path](long) or [short path](short). +/// +/// [long]: PathToType::non_generic_path +/// [short]: PathToType::non_generic_short_path +fn type_path_generator(long_path: bool, meta: &ReflectMeta) -> proc_macro2::TokenStream { let path_to_type = meta.path_to_type(); let generics = meta.generics(); let bevy_reflect_path = meta.bevy_reflect_path(); @@ -20,8 +49,6 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea }; } - let is_generic = meta.impl_is_generic(); - let ty_generic_paths: Vec<_> = generics .type_params() .map(|param| { @@ -32,107 +59,48 @@ pub(crate) fn type_path_generator(meta: &ReflectMeta) -> proc_macro2::TokenStrea }) .collect(); - let const_generic_strings: Vec<_> = generics - .const_params() - .map(|param| { - let ident = ¶m.ident; - let ty = ¶m.ty; - - quote! { - &<#ty as ::std::string::ToString>::to_string(&#ident) - } - }) - .collect(); - - let comma = quote!(", "); - - let combine_generics = |ty_generics: Vec| { - let mut generics = ty_generics - .into_iter() - .map(Cow::Owned) - .chain(const_generic_strings.iter().map(Cow::Borrowed)) - .flat_map(|t| [Cow::Borrowed(&comma), t]); - generics.next(); // Skip first comma. - generics - }; - let ident = path_to_type.ident().unwrap().to_string(); let ident = LitStr::new(&ident, path_to_type.span()); - let path = { + let path = if long_path { let path = path_to_type.non_generic_path(); - if is_generic { - let ty_generics: Vec<_> = ty_generic_paths - .iter() - .map(|type_path| { - quote! { - #type_path::type_path() - } - }) - .collect(); - - let generics = combine_generics(ty_generics); - - quote! { - ::std::borrow::ToOwned::to_owned(#path) - + "::<" - #(+ #generics)* - + ">" - } - } else { - quote! { - #path - } - } - }; - - let short_path = { - if is_generic { - let ty_generics: Vec<_> = ty_generic_paths - .iter() - .map(|type_path| { - quote! { - #type_path::short_type_path() - } - }) - .collect(); - - let generics = combine_generics(ty_generics); + let ty_generics: Vec<_> = ty_generic_paths + .iter() + .map(|cell| { + quote! { + #cell::type_path() + } + }) + .collect(); - quote! { - ::std::borrow::ToOwned::to_owned(::core::concat!(#ident, "<")) - #(+ #generics)* - + ">" - } - } else { - quote! { - #ident.to_owned() - } - } - }; + let generics = combine_generics(ty_generics, generics); - if !path_to_type.is_named() { quote! { - #bevy_reflect_path::utility::TypePathStorage::new_anonymous( - #path, - #short_path, - ) + ::std::borrow::ToOwned::to_owned(::core::concat!(#path, "::<")) + #(+ #generics)* + + ">" } } else { - let crate_name = path_to_type.crate_name(); - let module_path = path_to_type.module_path(); + let ty_generics: Vec<_> = ty_generic_paths + .iter() + .map(|cell| { + quote! { + #cell::short_type_path() + } + }) + .collect(); + + let generics = combine_generics(ty_generics, generics); quote! { - #bevy_reflect_path::utility::TypePathStorage::new_named( - #path, - #short_path, - #ident.to_owned(), - #crate_name.to_owned(), - #module_path.to_owned(), - ) + ::std::borrow::ToOwned::to_owned(::core::concat!(#ident, "<")) + #(+ #generics)* + + ">" } - } + }; + + path } /// Returns an expression for a `NonGenericTypedCell` or `GenericTypedCell`. @@ -156,7 +124,9 @@ fn static_typed_cell( } } else { let cell_type = match property { - TypedProperty::TypePath => quote!(NonGenericTypePathCell), + TypedProperty::TypePath => unreachable!( + "cannot have a non-generic type path cell. use string literals instead." + ), TypedProperty::TypeInfo => quote!(NonGenericTypeInfoCell), }; @@ -182,51 +152,76 @@ pub(crate) fn impl_type_path( let path_to_type = meta.path_to_type(); let bevy_reflect_path = meta.bevy_reflect_path(); - let (type_path_storage, type_path, short_type_path) = if meta.impl_is_generic() { - let cell = static_typed_cell(meta, TypedProperty::TypePath, type_path_generator(meta)); - + let (type_path, short_type_path) = if meta.impl_is_generic() { + let long_path_cell = static_typed_cell( + meta, + TypedProperty::TypePath, + type_path_generator(true, meta), + ); + let short_path_cell = static_typed_cell( + meta, + TypedProperty::TypePath, + type_path_generator(false, meta), + ); ( - Some(cell), - quote! { - Self::get_storage().path() - }, - quote! { - Self::get_storage().short_path() - }, + long_path_cell.to_token_stream(), + short_path_cell.to_token_stream(), ) } else { ( - None, path_to_type.non_generic_path(), path_to_type.non_generic_short_path(), ) }; - let name = path_to_type.name().map(|name| quote! { - #FQOption::Some(#name) - }).unwrap_or_else(|| quote! { - #FQOption::None - }); - let module_path = path_to_type.module_path().map(|name| quote! { - #FQOption::Some(#name) - }).unwrap_or_else(|| quote! { - #FQOption::None - }); - let crate_name = path_to_type.crate_name().map(|name| quote! { - #FQOption::Some(#name) - }).unwrap_or_else(|| quote! { - #FQOption::None - }); + let name = path_to_type + .name() + .map(|name| { + quote! { + #FQOption::Some(#name) + } + }) + .unwrap_or_else(|| { + quote! { + #FQOption::None + } + }); + let module_path = path_to_type + .module_path() + .map(|name| { + quote! { + #FQOption::Some(#name) + } + }) + .unwrap_or_else(|| { + quote! { + #FQOption::None + } + }); + let crate_name = path_to_type + .crate_name() + .map(|name| { + quote! { + #FQOption::Some(#name) + } + }) + .unwrap_or_else(|| { + quote! { + #FQOption::None + } + }); // Add Typed bound for each active field let where_reflect_clause = extend_where_clause(where_clause, where_clause_options); let primitive_assert = if let PathToType::Primitive(_) = path_to_type { Some(quote! { - mod private_scope { - // Compiles if it can be named with its ident when there are no imports. - type AssertIsPrimitive = #path_to_type; - } + const _: () = { + mod private_scope { + // Compiles if it can be named with its ident when there are no imports. + type AssertIsPrimitive = #path_to_type; + } + }; }) } else { None @@ -234,50 +229,30 @@ pub(crate) fn impl_type_path( let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl(); - let type_path_helper = type_path_storage.map(|storage| { - quote! { - trait GetStorage { - fn get_storage() -> &'static #bevy_reflect_path::utility::TypePathStorage; - } - - impl #impl_generics GetStorage for #path_to_type #ty_generics #where_reflect_clause { - #[inline] - fn get_storage() -> &'static #bevy_reflect_path::utility::TypePathStorage { - #storage - } - } - } - }); - quote! { - const _: () = { - #primitive_assert - - #type_path_helper - + #primitive_assert - impl #impl_generics #bevy_reflect_path::TypePath for #path_to_type #ty_generics #where_reflect_clause { - fn type_path() -> &'static str { - #type_path - } + impl #impl_generics #bevy_reflect_path::TypePath for #path_to_type #ty_generics #where_reflect_clause { + fn type_path() -> &'static str { + #type_path + } - fn short_type_path() -> &'static str { - #short_type_path - } + fn short_type_path() -> &'static str { + #short_type_path + } - fn type_ident() -> Option<&'static str> { - #name - } + fn type_ident() -> Option<&'static str> { + #name + } - fn crate_name() -> Option<&'static str> { - #crate_name - } + fn crate_name() -> Option<&'static str> { + #crate_name + } - fn module_path() -> Option<&'static str> { - #module_path - } + fn module_path() -> Option<&'static str> { + #module_path } - }; + } } } diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index d9a4c4df6e7ee..fd44d6a203c57 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -1,5 +1,5 @@ use crate::std_traits::ReflectDefault; -use crate::{self as bevy_reflect, impl_type_path_stored, ReflectFromPtr, ReflectOwned}; +use crate::{self as bevy_reflect, ReflectFromPtr, ReflectOwned}; use crate::{ impl_type_path, map_apply, map_partial_eq, Array, ArrayInfo, ArrayIter, DynamicEnum, DynamicMap, Enum, EnumInfo, FromReflect, FromType, GetTypeRegistration, List, ListInfo, Map, @@ -8,7 +8,7 @@ use crate::{ ValueInfo, VariantFieldIter, VariantInfo, VariantType, }; -use crate::utility::{GenericTypeInfoCell, NonGenericTypeInfoCell, TypePathStorage}; +use crate::utility::{GenericTypeInfoCell, GenericTypePathCell, NonGenericTypeInfoCell}; use bevy_reflect_derive::{impl_from_reflect_value, impl_reflect_value}; use bevy_utils::{Duration, Instant}; use bevy_utils::{HashMap, HashSet}; @@ -763,10 +763,17 @@ impl Typed for [T; N] { } } -impl_type_path_stored!(|| TypePathStorage::new_anonymous( - format!("[{t}; {N}]", t = T::type_path()), - format!("[{t}; {N}]", t = T::short_type_path()), -), impl { T: TypePath, const N: usize } 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())) + } + + fn short_type_path() -> &'static str { + static CELL: GenericTypePathCell = GenericTypePathCell::new(); + CELL.get_or_insert::(|| format!("[{t}; {N}]", t = T::short_type_path())) + } +} // TODO: // `FromType::from_type` requires `Deserialize<'de>` to be implemented for `T`. @@ -1125,13 +1132,29 @@ impl Typed for Cow<'static, str> { } } -impl_type_path_stored!(|| TypePathStorage::new_named( - "core::borrow::Cow::", - "Cow", - "Cow", - "core", - "core::borrow" -), impl 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 { @@ -1241,7 +1264,17 @@ impl Typed for &'static Path { } } -impl_type_path_stored!(|| TypePathStorage::new_anonymous("&std::path::Path", "&Path"), impl 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 { diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index 5efa23435603f..8431de1369bd4 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -1,7 +1,7 @@ use crate::{ - array_debug, enum_debug, impl_type_path_stored, list_debug, map_debug, serde::Serializable, - struct_debug, tuple_debug, tuple_struct_debug, utility::TypePathStorage, Array, Enum, List, - Map, Struct, Tuple, TupleStruct, TypeInfo, Typed, ValueInfo, + array_debug, enum_debug, list_debug, map_debug, serde::Serializable, struct_debug, tuple_debug, + tuple_struct_debug, Array, Enum, List, Map, Struct, Tuple, TupleStruct, TypeInfo, TypePath, + Typed, ValueInfo, }; use std::{ any::{self, Any, TypeId}, @@ -228,10 +228,15 @@ impl Typed for dyn Reflect { } } -impl_type_path_stored!(|| TypePathStorage::new_anonymous( - "dyn bevy_reflect::Reflect", - "dyn Reflect" -), impl for dyn Reflect); +impl TypePath for dyn Reflect { + fn type_path() -> &'static str { + "dyn bevy_reflect::Reflect" + } + + fn short_type_path() -> &'static str { + "dyn Reflect" + } +} #[deny(rustdoc::broken_intra_doc_links)] impl dyn Reflect { diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index e1f2d761bff7c..e43ee069b5201 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -1,4 +1,4 @@ -use crate::utility::{impl_type_path_stored, NonGenericTypeInfoCell, TypePathStorage}; +use crate::utility::{GenericTypePathCell, NonGenericTypeInfoCell}; use crate::{ self as bevy_reflect, impl_type_path, DynamicInfo, FromReflect, GetTypeRegistration, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, TypeRegistration, Typed, @@ -583,13 +583,21 @@ macro_rules! impl_reflect_tuple { } } - impl_type_path_stored!( - || TypePathStorage::new_anonymous( - "(".to_owned() $(+ <$name as TypePath>::type_path())* + ")", - "(".to_owned() $(+ <$name as TypePath>::short_type_path())* + ")", - ), - impl { $($name: Reflect + TypePath),* } for ($($name,)*) - ); + 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,)*) { diff --git a/crates/bevy_reflect/src/type_path.rs b/crates/bevy_reflect/src/type_path.rs index 2ae6e85d0e4bd..8140a0732f258 100644 --- a/crates/bevy_reflect/src/type_path.rs +++ b/crates/bevy_reflect/src/type_path.rs @@ -75,15 +75,21 @@ pub trait TypePath: 'static { /// Returns the name of the type, or [`None`] if it is anonymous. /// /// For [`Option<()>`], this is `Option`. - fn type_ident() -> Option<&'static str>; + fn type_ident() -> Option<&'static str> { + None + } /// Returns the name of the crate the type is in, or [`None`] if it is anonymous or a primitive. /// /// For [`Option<()>`], this is `core`. - fn crate_name() -> Option<&'static str>; + fn crate_name() -> Option<&'static str> { + None + } /// Returns the path to the moudle the type is in, or [`None`] if it is anonymous or a primitive. /// /// For [`Option<()>`], this is `core::option`. - fn module_path() -> Option<&'static str>; + fn module_path() -> Option<&'static str> { + None + } } diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index df7583390cb62..1980fb88b60e5 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -7,16 +7,16 @@ use parking_lot::RwLock; use std::any::{Any, TypeId}; mod sealed { - use crate::{utility::TypePathStorage, TypeInfo}; + use super::TypeInfo; - trait Sealed {} - impl Sealed for TypeInfo {} - impl Sealed for TypePathStorage {} + pub trait Sealed {} - pub trait TypedProperty: 'static {} - impl TypedProperty for T {} + impl Sealed for TypeInfo {} + impl Sealed for String {} } -pub use sealed::TypedProperty; + +pub trait TypedProperty: sealed::Sealed + 'static {} +impl TypedProperty for T {} /// A container for [`TypeInfo`] or [`TypePathStorage`] over non-generic types, allowing instances to be stored statically. /// @@ -66,7 +66,6 @@ pub use sealed::TypedProperty; pub struct NonGenericTypedCell(OnceBox); pub type NonGenericTypeInfoCell = NonGenericTypedCell; -pub type NonGenericTypePathCell = NonGenericTypedCell; impl NonGenericTypedCell { /// Initialize a [`NonGenericTypedCell`] for non-generic types. @@ -130,7 +129,7 @@ impl NonGenericTypedCell { pub struct GenericTypedCell(OnceBox>>); pub type GenericTypeInfoCell = GenericTypedCell; -pub type GenericTypePathCell = GenericTypedCell; +pub type GenericTypePathCell = GenericTypedCell; impl GenericTypedCell { /// Initialize a [`GenericTypedCell`] for generic types. @@ -162,159 +161,4 @@ impl GenericTypedCell { Box::leak(Box::new(f())) }) } -} - -pub struct TypePathStorage { - path: String, - short_path: String, - ident: Option, - crate_name: Option, - module_path: Option, -} - -impl TypePathStorage { - pub fn new_primitive>(name: A) -> Self { - Self { - path: name.as_ref().to_owned(), - short_path: name.as_ref().to_owned(), - ident: Some(name.as_ref().to_owned()), - crate_name: None, - module_path: None, - } - } - - pub fn new_anonymous, B: AsRef>(path: A, short_path: B) -> Self { - Self { - path: path.as_ref().to_owned(), - short_path: short_path.as_ref().to_owned(), - ident: None, - crate_name: None, - module_path: None, - } - } - - pub fn new_named( - path: A, - short_path: B, - ident: C, - crate_name: D, - module_path: E, - ) -> Self - where - A: AsRef, - B: AsRef, - C: AsRef, - D: AsRef, - E: AsRef, - { - Self { - path: path.as_ref().to_owned(), - short_path: short_path.as_ref().to_owned(), - ident: Some(ident.as_ref().to_owned()), - crate_name: Some(crate_name.as_ref().to_owned()), - module_path: Some(module_path.as_ref().to_owned()), - } - } - - #[inline] - pub fn path(&self) -> &str { - &self.path - } - - #[inline] - pub fn short_path(&self) -> &str { - &self.short_path - } - - #[inline] - pub fn ident(&self) -> Option<&str> { - self.ident.as_deref() - } - - #[inline] - pub fn crate_name(&self) -> Option<&str> { - self.crate_name.as_deref() - } - - #[inline] - pub fn module_path(&self) -> Option<&str> { - self.module_path.as_deref() - } -} - -pub mod __private { - #[macro_export] - macro_rules! void_tokens { - ($($tokens: tt)*) => {}; - } - - #[macro_export] - macro_rules! first_present { - ({ $($first:tt)* } $( { $($rest:tt)* } )*) => { - $($first)* - } - } - - pub use first_present; - pub use void_tokens; -} - -#[macro_export] -macro_rules! impl_type_path_stored { - ($storage_fn: expr, impl$({ $($param:tt)* })? for $($impl_tt: tt)+) => { - const _: () = { - trait GetStorage { - fn get_storage() -> &'static $crate::utility::TypePathStorage; - } - - impl$(< $($param)* >)? GetStorage for $($impl_tt)+ { - #[inline] - fn get_storage() -> &'static $crate::utility::TypePathStorage { - $crate::utility::__private::first_present!( - $({ - $crate::utility::__private::void_tokens!($($param)*); - static CELL: $crate::utility::GenericTypePathCell = $crate::utility::GenericTypePathCell::new(); - return CELL.get_or_insert::($storage_fn); - })? - { - static CELL: $crate::utility::NonGenericTypePathCell = $crate::utility::NonGenericTypePathCell::new(); - return CELL.get_or_set($storage_fn); - } - ); - } - } - - impl $(< $($param)* >)? $crate::TypePath for $($impl_tt)+ { - fn type_path() -> &'static str { - &Self::get_storage().path() - } - - fn short_type_path() -> &'static str { - &Self::get_storage().short_path() - } - - fn type_ident() -> Option<&'static str> { - match Self::get_storage().ident() { - Some(x) => Some(x), - None => None - } - } - - fn crate_name() -> Option<&'static str> { - match Self::get_storage().crate_name() { - Some(x) => Some(x), - None => None - } - } - - fn module_path() -> Option<&'static str> { - match Self::get_storage().module_path() { - Some(x) => Some(x), - None => None - } - } - } - }; - } -} -pub use impl_type_path_stored; +} \ No newline at end of file From b79e3d0376a2fb528116a54426e9c5948f5712f7 Mon Sep 17 00:00:00 2001 From: radiish Date: Fri, 27 Jan 2023 21:44:36 +0000 Subject: [PATCH 14/52] added `DynamicTypePath` --- .../bevy_reflect_derive/src/impls/enums.rs | 5 +++ .../bevy_reflect_derive/src/impls/structs.rs | 5 +++ .../src/impls/tuple_structs.rs | 5 +++ .../bevy_reflect_derive/src/impls/values.rs | 5 +++ crates/bevy_reflect/src/array.rs | 7 +++- crates/bevy_reflect/src/enums/dynamic_enum.rs | 7 +++- crates/bevy_reflect/src/impls/smallvec.rs | 7 +++- crates/bevy_reflect/src/impls/std.rs | 32 ++++++++++++++- crates/bevy_reflect/src/list.rs | 7 +++- crates/bevy_reflect/src/map.rs | 7 +++- crates/bevy_reflect/src/reflect.rs | 9 ++++- crates/bevy_reflect/src/struct_trait.rs | 7 +++- crates/bevy_reflect/src/tuple.rs | 12 +++++- crates/bevy_reflect/src/tuple_struct.rs | 7 +++- crates/bevy_reflect/src/type_path.rs | 40 +++++++++++++++++++ 15 files changed, 152 insertions(+), 10 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 9ed8de1f5758e..17f59bc962552 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs @@ -194,6 +194,11 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { ::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/structs.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs index 5a833aaa8f129..07b4513eb2138 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs @@ -174,6 +174,11 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { ::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 529f0435a2392..863108dd15a52 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 @@ -137,6 +137,11 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { ::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 c34c7375f5272..590d095ee61c1 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs @@ -52,6 +52,11 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { ::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/src/array.rs b/crates/bevy_reflect/src/array.rs index f4ab8facdbbb5..317c06f454817 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -2,7 +2,7 @@ use bevy_reflect_derive::impl_type_path; use crate::{ self as bevy_reflect, utility::NonGenericTypeInfoCell, DynamicInfo, Reflect, ReflectMut, - ReflectOwned, ReflectRef, TypeInfo, Typed, + ReflectOwned, ReflectRef, TypeInfo, Typed, DynamicTypePath, }; use std::{ any::{Any, TypeId}, @@ -183,6 +183,11 @@ impl Reflect for DynamicArray { fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } + + #[inline] + fn get_type_path(&self) -> &dyn DynamicTypePath { + self + } #[inline] fn into_any(self: Box) -> Box { diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index f4fa5f9217827..93f4790664e29 100644 --- a/crates/bevy_reflect/src/enums/dynamic_enum.rs +++ b/crates/bevy_reflect/src/enums/dynamic_enum.rs @@ -4,7 +4,7 @@ use crate::utility::NonGenericTypeInfoCell; use crate::{ self as bevy_reflect, enum_debug, enum_hash, enum_partial_eq, DynamicInfo, DynamicStruct, DynamicTuple, Enum, Reflect, ReflectMut, ReflectOwned, ReflectRef, Struct, Tuple, TypeInfo, - Typed, VariantFieldIter, VariantType, + Typed, VariantFieldIter, VariantType, DynamicTypePath, }; use std::any::Any; use std::fmt::Formatter; @@ -301,6 +301,11 @@ impl Reflect for DynamicEnum { fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } + + #[inline] + fn get_type_path(&self) -> &dyn DynamicTypePath { + self + } #[inline] fn into_any(self: Box) -> Box { diff --git a/crates/bevy_reflect/src/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index 265b4571f353b..fad0dfed98a84 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -6,7 +6,7 @@ use crate::utility::GenericTypeInfoCell; use crate::{ self as bevy_reflect, Array, ArrayIter, FromReflect, FromType, GetTypeRegistration, List, ListInfo, Reflect, ReflectFromPtr, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, - TypeRegistration, Typed, + TypeRegistration, Typed, DynamicTypePath, }; impl Array for SmallVec @@ -95,6 +95,11 @@ where fn get_type_info(&self) -> &'static TypeInfo { ::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/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index fd44d6a203c57..3c30d0e76265d 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -5,7 +5,7 @@ use crate::{ DynamicMap, Enum, EnumInfo, FromReflect, FromType, GetTypeRegistration, List, ListInfo, Map, MapInfo, MapIter, Reflect, ReflectDeserialize, ReflectMut, ReflectRef, ReflectSerialize, TupleVariantInfo, TypeInfo, TypePath, TypeRegistration, Typed, UnitVariantInfo, UnnamedField, - ValueInfo, VariantFieldIter, VariantInfo, VariantType, + ValueInfo, VariantFieldIter, VariantInfo, VariantType, DynamicTypePath }; use crate::utility::{GenericTypeInfoCell, GenericTypePathCell, NonGenericTypeInfoCell}; @@ -333,6 +333,11 @@ macro_rules! impl_reflect_for_veclike { fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } + + #[inline] + fn get_type_path(&self) -> &dyn DynamicTypePath { + self + } fn into_any(self: Box) -> Box { self @@ -533,6 +538,11 @@ impl Reflect f fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } + + #[inline] + fn get_type_path(&self) -> &dyn DynamicTypePath { + self + } fn into_any(self: Box) -> Box { self @@ -669,6 +679,11 @@ impl Reflect for [T; N] { fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } + + #[inline] + fn get_type_path(&self) -> &dyn DynamicTypePath { + self + } #[inline] fn into_any(self: Box) -> Box { @@ -886,6 +901,11 @@ impl Reflect for Option { fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } + + #[inline] + fn get_type_path(&self) -> &dyn DynamicTypePath { + self + } #[inline] fn into_any(self: Box) -> Box { @@ -1053,6 +1073,11 @@ impl Reflect for Cow<'static, str> { fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } + + #[inline] + fn get_type_path(&self) -> &dyn DynamicTypePath { + self + } fn into_any(self: Box) -> Box { self @@ -1185,6 +1210,11 @@ impl Reflect for &'static Path { fn get_type_info(&self) -> &'static TypeInfo { ::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/list.rs b/crates/bevy_reflect/src/list.rs index 62ce497fc3649..866266d3a85c8 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -6,7 +6,7 @@ use bevy_reflect_derive::impl_type_path; use crate::utility::NonGenericTypeInfoCell; use crate::{ self as bevy_reflect, Array, ArrayIter, DynamicArray, DynamicInfo, FromReflect, Reflect, - ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, + ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, DynamicTypePath, }; /// An ordered, mutable list of [Reflect] items. This corresponds to types like [`std::vec::Vec`]. @@ -239,6 +239,11 @@ impl Reflect for DynamicList { fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } + + #[inline] + fn get_type_path(&self) -> &dyn DynamicTypePath { + self + } #[inline] fn into_any(self: Box) -> Box { diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index 7c61a75dacb2e..20a7c481d10a8 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -8,7 +8,7 @@ use bevy_utils::{Entry, HashMap}; use crate::utility::NonGenericTypeInfoCell; use crate::{ self as bevy_reflect, DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, - Typed, + Typed, DynamicTypePath, }; /// An ordered mapping between [`Reflect`] values. @@ -278,6 +278,11 @@ impl Reflect for DynamicMap { fn get_type_info(&self) -> &'static TypeInfo { ::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/reflect.rs b/crates/bevy_reflect/src/reflect.rs index 8431de1369bd4..ddf2d497a4e53 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -1,7 +1,7 @@ use crate::{ array_debug, enum_debug, list_debug, map_debug, serde::Serializable, struct_debug, tuple_debug, tuple_struct_debug, Array, Enum, List, Map, Struct, Tuple, TupleStruct, TypeInfo, TypePath, - Typed, ValueInfo, + Typed, ValueInfo, DynamicTypePath, }; use std::{ any::{self, Any, TypeId}, @@ -83,6 +83,13 @@ pub trait Reflect: Any + Send + Sync { /// [`TypeRegistry::get_type_info`]: crate::TypeRegistry::get_type_info fn get_type_info(&self) -> &'static TypeInfo; + /// Returns the [`TypePath`] implementation for the underlying type. + /// + /// This method suffers the same performance concerns as [`get_type_info`]. + /// + /// [`get_type_info`]: Reflect::get_type_info + fn get_type_path(&self) -> &dyn DynamicTypePath; + /// Returns the value as a [`Box`][std::any::Any]. fn into_any(self: Box) -> Box; diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index 636b3f1a2f970..b112721cd4623 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -1,7 +1,7 @@ use crate::utility::NonGenericTypeInfoCell; use crate::{ self as bevy_reflect, DynamicInfo, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, - TypeInfo, Typed, + TypeInfo, Typed, DynamicTypePath, }; use bevy_reflect_derive::impl_type_path; use bevy_utils::{Entry, HashMap}; @@ -390,6 +390,11 @@ impl Reflect for DynamicStruct { fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } + + #[inline] + fn get_type_path(&self) -> &dyn DynamicTypePath { + self + } #[inline] fn into_any(self: Box) -> Box { diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index e43ee069b5201..4541b8370d3f2 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -2,7 +2,7 @@ use crate::utility::{GenericTypePathCell, NonGenericTypeInfoCell}; use crate::{ self as bevy_reflect, impl_type_path, DynamicInfo, FromReflect, GetTypeRegistration, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, TypeRegistration, Typed, - UnnamedField, + UnnamedField, DynamicTypePath }; use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; @@ -302,6 +302,11 @@ impl Reflect for DynamicTuple { ::type_info() } + #[inline] + fn get_type_path(&self) -> &dyn DynamicTypePath { + self + } + #[inline] fn into_any(self: Box) -> Box { self @@ -516,6 +521,11 @@ macro_rules! impl_reflect_tuple { ::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 eb001bb06853b..44e2f750c1716 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -3,7 +3,7 @@ use bevy_reflect_derive::impl_type_path; use crate::utility::NonGenericTypeInfoCell; use crate::{ self as bevy_reflect, DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, - Typed, UnnamedField, + Typed, UnnamedField, DynamicTypePath, }; use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; @@ -294,6 +294,11 @@ impl Reflect for DynamicTupleStruct { fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } + + #[inline] + fn get_type_path(&self) -> &dyn DynamicTypePath { + self + } #[inline] fn into_any(self: Box) -> Box { diff --git a/crates/bevy_reflect/src/type_path.rs b/crates/bevy_reflect/src/type_path.rs index 8140a0732f258..917b9734a12e4 100644 --- a/crates/bevy_reflect/src/type_path.rs +++ b/crates/bevy_reflect/src/type_path.rs @@ -93,3 +93,43 @@ pub trait TypePath: 'static { None } } + +/// +pub trait DynamicTypePath { + /// See [`TypePath::type_path`]. + fn reflect_type_path(&self) -> &str; + + /// See [`TypePath::short_type_path`]. + fn reflect_short_type_path(&self) -> &str; + + /// See [`TypePath::type_ident`]. + fn reflect_type_ident(&self) -> Option<&str>; + + /// See [`TypePath::crate_name`]. + fn reflect_crate_name(&self) -> Option<&str>; + + /// See [`TypePath::module_path`]. + fn reflect_module_path(&self) -> Option<&str>; +} + +impl DynamicTypePath for T { + fn reflect_type_path(&self) -> &str { + Self::type_path() + } + + fn reflect_short_type_path(&self) -> &str { + Self::short_type_path() + } + + fn reflect_type_ident(&self) -> Option<&str> { + Self::type_ident() + } + + fn reflect_crate_name(&self) -> Option<&str> { + Self::crate_name() + } + + fn reflect_module_path(&self) -> Option<&str> { + Self::module_path() + } +} \ No newline at end of file From 52719c13f835bc9d97ac9fb5e1d78a28bf6097f8 Mon Sep 17 00:00:00 2001 From: radiish Date: Fri, 27 Jan 2023 21:44:56 +0000 Subject: [PATCH 15/52] `cargo fmt --all` --- crates/bevy_reflect/src/array.rs | 6 +++--- crates/bevy_reflect/src/enums/dynamic_enum.rs | 6 +++--- crates/bevy_reflect/src/impls/smallvec.rs | 8 ++++---- crates/bevy_reflect/src/impls/std.rs | 20 +++++++++---------- crates/bevy_reflect/src/list.rs | 6 +++--- crates/bevy_reflect/src/map.rs | 6 +++--- crates/bevy_reflect/src/reflect.rs | 8 ++++---- crates/bevy_reflect/src/struct_trait.rs | 6 +++--- crates/bevy_reflect/src/tuple.rs | 6 +++--- crates/bevy_reflect/src/tuple_struct.rs | 6 +++--- crates/bevy_reflect/src/type_path.rs | 4 ++-- crates/bevy_reflect/src/utility.rs | 2 +- 12 files changed, 42 insertions(+), 42 deletions(-) diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index 317c06f454817..ba60f6a4bc708 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::NonGenericTypeInfoCell, DynamicInfo, Reflect, ReflectMut, - ReflectOwned, ReflectRef, TypeInfo, Typed, DynamicTypePath, + self as bevy_reflect, utility::NonGenericTypeInfoCell, DynamicInfo, DynamicTypePath, Reflect, + ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, }; use std::{ any::{Any, TypeId}, @@ -183,7 +183,7 @@ impl Reflect for DynamicArray { fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } - + #[inline] fn get_type_path(&self) -> &dyn DynamicTypePath { self diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index 93f4790664e29..01c9911380ecf 100644 --- a/crates/bevy_reflect/src/enums/dynamic_enum.rs +++ b/crates/bevy_reflect/src/enums/dynamic_enum.rs @@ -3,8 +3,8 @@ use bevy_reflect_derive::impl_type_path; use crate::utility::NonGenericTypeInfoCell; use crate::{ self as bevy_reflect, enum_debug, enum_hash, enum_partial_eq, DynamicInfo, DynamicStruct, - DynamicTuple, Enum, Reflect, ReflectMut, ReflectOwned, ReflectRef, Struct, Tuple, TypeInfo, - Typed, VariantFieldIter, VariantType, DynamicTypePath, + DynamicTuple, DynamicTypePath, Enum, Reflect, ReflectMut, ReflectOwned, ReflectRef, Struct, + Tuple, TypeInfo, Typed, VariantFieldIter, VariantType, }; use std::any::Any; use std::fmt::Formatter; @@ -301,7 +301,7 @@ impl Reflect for DynamicEnum { fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } - + #[inline] fn get_type_path(&self) -> &dyn DynamicTypePath { self diff --git a/crates/bevy_reflect/src/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index fad0dfed98a84..f6a0470526305 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -4,9 +4,9 @@ use std::any::Any; use crate::utility::GenericTypeInfoCell; use crate::{ - self as bevy_reflect, Array, ArrayIter, FromReflect, FromType, GetTypeRegistration, List, - ListInfo, Reflect, ReflectFromPtr, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, - TypeRegistration, Typed, DynamicTypePath, + self as bevy_reflect, Array, ArrayIter, DynamicTypePath, FromReflect, FromType, + GetTypeRegistration, List, ListInfo, Reflect, ReflectFromPtr, ReflectMut, ReflectOwned, + ReflectRef, TypeInfo, TypePath, TypeRegistration, Typed, }; impl Array for SmallVec @@ -95,7 +95,7 @@ where fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } - + #[inline] fn get_type_path(&self) -> &dyn DynamicTypePath { self diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 3c30d0e76265d..723125a16583f 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -2,10 +2,10 @@ use crate::std_traits::ReflectDefault; use crate::{self as bevy_reflect, ReflectFromPtr, ReflectOwned}; use crate::{ impl_type_path, map_apply, map_partial_eq, Array, ArrayInfo, ArrayIter, DynamicEnum, - DynamicMap, Enum, EnumInfo, FromReflect, FromType, GetTypeRegistration, List, ListInfo, Map, - MapInfo, MapIter, Reflect, ReflectDeserialize, ReflectMut, ReflectRef, ReflectSerialize, - TupleVariantInfo, TypeInfo, TypePath, TypeRegistration, Typed, UnitVariantInfo, UnnamedField, - ValueInfo, VariantFieldIter, VariantInfo, VariantType, DynamicTypePath + DynamicMap, DynamicTypePath, Enum, EnumInfo, FromReflect, FromType, GetTypeRegistration, List, + ListInfo, Map, MapInfo, MapIter, Reflect, ReflectDeserialize, ReflectMut, ReflectRef, + ReflectSerialize, TupleVariantInfo, TypeInfo, TypePath, TypeRegistration, Typed, + UnitVariantInfo, UnnamedField, ValueInfo, VariantFieldIter, VariantInfo, VariantType, }; use crate::utility::{GenericTypeInfoCell, GenericTypePathCell, NonGenericTypeInfoCell}; @@ -333,7 +333,7 @@ macro_rules! impl_reflect_for_veclike { fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } - + #[inline] fn get_type_path(&self) -> &dyn DynamicTypePath { self @@ -538,7 +538,7 @@ impl Reflect f fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } - + #[inline] fn get_type_path(&self) -> &dyn DynamicTypePath { self @@ -679,7 +679,7 @@ impl Reflect for [T; N] { fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } - + #[inline] fn get_type_path(&self) -> &dyn DynamicTypePath { self @@ -901,7 +901,7 @@ impl Reflect for Option { fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } - + #[inline] fn get_type_path(&self) -> &dyn DynamicTypePath { self @@ -1073,7 +1073,7 @@ impl Reflect for Cow<'static, str> { fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } - + #[inline] fn get_type_path(&self) -> &dyn DynamicTypePath { self @@ -1210,7 +1210,7 @@ impl Reflect for &'static Path { fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } - + #[inline] fn get_type_path(&self) -> &dyn DynamicTypePath { self diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index 866266d3a85c8..ae029d092bd58 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -5,8 +5,8 @@ use bevy_reflect_derive::impl_type_path; use crate::utility::NonGenericTypeInfoCell; use crate::{ - self as bevy_reflect, Array, ArrayIter, DynamicArray, DynamicInfo, FromReflect, Reflect, - ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, DynamicTypePath, + self as bevy_reflect, Array, ArrayIter, DynamicArray, DynamicInfo, DynamicTypePath, + FromReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, Typed, }; /// An ordered, mutable list of [Reflect] items. This corresponds to types like [`std::vec::Vec`]. @@ -239,7 +239,7 @@ impl Reflect for DynamicList { fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } - + #[inline] fn get_type_path(&self) -> &dyn DynamicTypePath { self diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index 20a7c481d10a8..e6782f02147b7 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -7,8 +7,8 @@ use bevy_utils::{Entry, HashMap}; use crate::utility::NonGenericTypeInfoCell; use crate::{ - self as bevy_reflect, DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, - Typed, DynamicTypePath, + self as bevy_reflect, DynamicInfo, DynamicTypePath, Reflect, ReflectMut, ReflectOwned, + ReflectRef, TypeInfo, Typed, }; /// An ordered mapping between [`Reflect`] values. @@ -278,7 +278,7 @@ impl Reflect for DynamicMap { fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } - + #[inline] fn get_type_path(&self) -> &dyn DynamicTypePath { self diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index ddf2d497a4e53..73593c61a84a6 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -1,7 +1,7 @@ use crate::{ array_debug, enum_debug, list_debug, map_debug, serde::Serializable, struct_debug, tuple_debug, - tuple_struct_debug, Array, Enum, List, Map, Struct, Tuple, TupleStruct, TypeInfo, TypePath, - Typed, ValueInfo, DynamicTypePath, + tuple_struct_debug, Array, DynamicTypePath, Enum, List, Map, Struct, Tuple, TupleStruct, + TypeInfo, TypePath, Typed, ValueInfo, }; use std::{ any::{self, Any, TypeId}, @@ -84,9 +84,9 @@ pub trait Reflect: Any + Send + Sync { fn get_type_info(&self) -> &'static TypeInfo; /// Returns the [`TypePath`] implementation for the underlying type. - /// + /// /// This method suffers the same performance concerns as [`get_type_info`]. - /// + /// /// [`get_type_info`]: Reflect::get_type_info fn get_type_path(&self) -> &dyn DynamicTypePath; diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index b112721cd4623..b1728063755c0 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -1,7 +1,7 @@ use crate::utility::NonGenericTypeInfoCell; use crate::{ - self as bevy_reflect, DynamicInfo, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, - TypeInfo, Typed, DynamicTypePath, + self as bevy_reflect, DynamicInfo, DynamicTypePath, NamedField, Reflect, ReflectMut, + ReflectOwned, ReflectRef, TypeInfo, Typed, }; use bevy_reflect_derive::impl_type_path; use bevy_utils::{Entry, HashMap}; @@ -390,7 +390,7 @@ impl Reflect for DynamicStruct { fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } - + #[inline] fn get_type_path(&self) -> &dyn DynamicTypePath { self diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index 4541b8370d3f2..461a94f0f4eac 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -1,8 +1,8 @@ use crate::utility::{GenericTypePathCell, NonGenericTypeInfoCell}; use crate::{ - self as bevy_reflect, impl_type_path, DynamicInfo, FromReflect, GetTypeRegistration, Reflect, - ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, TypeRegistration, Typed, - UnnamedField, DynamicTypePath + self as bevy_reflect, impl_type_path, DynamicInfo, DynamicTypePath, FromReflect, + GetTypeRegistration, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, + TypeRegistration, Typed, UnnamedField, }; use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index 44e2f750c1716..e62b21349cc75 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -2,8 +2,8 @@ use bevy_reflect_derive::impl_type_path; use crate::utility::NonGenericTypeInfoCell; use crate::{ - self as bevy_reflect, DynamicInfo, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, - Typed, UnnamedField, DynamicTypePath, + self as bevy_reflect, DynamicInfo, DynamicTypePath, Reflect, ReflectMut, ReflectOwned, + ReflectRef, TypeInfo, Typed, UnnamedField, }; use std::any::{Any, TypeId}; use std::fmt::{Debug, Formatter}; @@ -294,7 +294,7 @@ impl Reflect for DynamicTupleStruct { fn get_type_info(&self) -> &'static TypeInfo { ::type_info() } - + #[inline] fn get_type_path(&self) -> &dyn DynamicTypePath { self diff --git a/crates/bevy_reflect/src/type_path.rs b/crates/bevy_reflect/src/type_path.rs index 917b9734a12e4..f214c76108471 100644 --- a/crates/bevy_reflect/src/type_path.rs +++ b/crates/bevy_reflect/src/type_path.rs @@ -94,7 +94,7 @@ pub trait TypePath: 'static { } } -/// +/// pub trait DynamicTypePath { /// See [`TypePath::type_path`]. fn reflect_type_path(&self) -> &str; @@ -132,4 +132,4 @@ impl DynamicTypePath for T { fn reflect_module_path(&self) -> Option<&str> { Self::module_path() } -} \ No newline at end of file +} diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index 1980fb88b60e5..aebe933755628 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -161,4 +161,4 @@ impl GenericTypedCell { Box::leak(Box::new(f())) }) } -} \ No newline at end of file +} From 973759b2b449f4ed41b6a2156a41ca05c686e853 Mon Sep 17 00:00:00 2001 From: radiish Date: Sat, 28 Jan 2023 07:42:58 +0000 Subject: [PATCH 16/52] fix one implementation --- crates/bevy_reflect/src/array.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index ba60f6a4bc708..2d5ade77ac599 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -308,7 +308,7 @@ impl Typed for DynamicArray { } } -impl_type_path!(DynamicArray in bevy_reflect::DynamicArray); +impl_type_path!(DynamicArray in bevy_reflect); /// An iterator over an [`Array`]. pub struct ArrayIter<'a> { From b523e91350c4b43e70f152e1817138a32b27417b Mon Sep 17 00:00:00 2001 From: radiish Date: Sat, 28 Jan 2023 07:52:21 +0000 Subject: [PATCH 17/52] cleanup --- .../bevy_reflect_derive/src/impls/typed.rs | 49 ++++--------------- .../bevy_reflect_derive/src/utility.rs | 15 +++++- 2 files changed, 23 insertions(+), 41 deletions(-) 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 d6d9ece1145d7..0a669ebbddaf2 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -6,7 +6,10 @@ use std::borrow::Cow; use quote::{quote, ToTokens}; use syn::{spanned::Spanned, LitStr}; -use crate::{derive_data::{PathToType, ReflectMeta}, fq_std::FQOption}; +use crate::{ + derive_data::{PathToType, ReflectMeta}, + utility::wrap_in_option, +}; fn combine_generics( ty_generics: Vec, @@ -63,8 +66,6 @@ fn type_path_generator(long_path: bool, meta: &ReflectMeta) -> proc_macro2::Toke let ident = LitStr::new(&ident, path_to_type.span()); let path = if long_path { - let path = path_to_type.non_generic_path(); - let ty_generics: Vec<_> = ty_generic_paths .iter() .map(|cell| { @@ -75,6 +76,7 @@ fn type_path_generator(long_path: bool, meta: &ReflectMeta) -> proc_macro2::Toke .collect(); let generics = combine_generics(ty_generics, generics); + let path = path_to_type.non_generic_path(); quote! { ::std::borrow::ToOwned::to_owned(::core::concat!(#path, "::<")) @@ -174,42 +176,9 @@ pub(crate) fn impl_type_path( ) }; - let name = path_to_type - .name() - .map(|name| { - quote! { - #FQOption::Some(#name) - } - }) - .unwrap_or_else(|| { - quote! { - #FQOption::None - } - }); - let module_path = path_to_type - .module_path() - .map(|name| { - quote! { - #FQOption::Some(#name) - } - }) - .unwrap_or_else(|| { - quote! { - #FQOption::None - } - }); - let crate_name = path_to_type - .crate_name() - .map(|name| { - quote! { - #FQOption::Some(#name) - } - }) - .unwrap_or_else(|| { - quote! { - #FQOption::None - } - }); + let name = wrap_in_option(path_to_type.name()); + let module_path = wrap_in_option(path_to_type.module_path()); + let crate_name = wrap_in_option(path_to_type.crate_name()); // Add Typed bound for each active field let where_reflect_clause = extend_where_clause(where_clause, where_clause_options); @@ -218,7 +187,7 @@ pub(crate) fn impl_type_path( Some(quote! { const _: () = { mod private_scope { - // Compiles if it can be named with its ident when there are no imports. + // Compiles if it can be named when there are no imports. type AssertIsPrimitive = #path_to_type; } }; diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs b/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs index abe0806a64853..3a76e309f9d07 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs @@ -1,6 +1,6 @@ //! General-purpose utility functions for internal usage within this crate. -use crate::field_attributes::ReflectIgnoreBehavior; +use crate::{field_attributes::ReflectIgnoreBehavior, fq_std::FQOption}; use bevy_macro_utils::BevyManifest; use bit_set::BitSet; use proc_macro2::{Ident, Span}; @@ -213,3 +213,16 @@ where bitset } + +/// Turns an `Option` into a `TokenStream` for an `Option`. +pub(crate) fn wrap_in_option(tokens: Option) -> proc_macro2::TokenStream { + tokens.map(|tokens| { + quote! { + #FQOption::Some(#tokens) + } + }).unwrap_or_else(|| { + quote! { + #FQOption::None + } + }) +} \ No newline at end of file From f867b1e6a87835d9c81ce1c4550a165f3674c553 Mon Sep 17 00:00:00 2001 From: radiish Date: Sat, 28 Jan 2023 08:05:27 +0000 Subject: [PATCH 18/52] fix examples --- examples/audio/decodable.rs | 4 ++-- examples/shader/shader_prepass.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/audio/decodable.rs b/examples/audio/decodable.rs index 1ac2fdd06db86..90850742e3534 100644 --- a/examples/audio/decodable.rs +++ b/examples/audio/decodable.rs @@ -3,14 +3,14 @@ use bevy::audio::AddAudioSource; use bevy::audio::Source; use bevy::prelude::*; -use bevy::reflect::TypeUuid; +use bevy::reflect::{TypePath, TypeUuid}; use bevy::utils::Duration; // This struct usually contains the data for the audio being played. // This is where data read from an audio file would be stored, for example. // Implementing `TypeUuid` will automatically implement `Asset`. // This allows the type to be registered as an asset. -#[derive(TypeUuid)] +#[derive(TypePath, TypeUuid)] #[uuid = "c2090c23-78fd-44f1-8508-c89b1f3cec29"] struct SineAudio { frequency: f32, diff --git a/examples/shader/shader_prepass.rs b/examples/shader/shader_prepass.rs index 6e0f9a934e9ec..ea38af933eadd 100644 --- a/examples/shader/shader_prepass.rs +++ b/examples/shader/shader_prepass.rs @@ -9,7 +9,7 @@ use bevy::{ core_pipeline::prepass::{DepthPrepass, NormalPrepass}, pbr::{NotShadowCaster, PbrPlugin}, prelude::*, - reflect::TypeUuid, + reflect::{TypePath, TypeUuid}, render::render_resource::{AsBindGroup, ShaderRef}, }; @@ -154,7 +154,7 @@ fn setup( } // This is the struct that will be passed to your shader -#[derive(AsBindGroup, TypeUuid, Debug, Clone)] +#[derive(AsBindGroup, TypePath, TypeUuid, Debug, Clone)] #[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"] pub struct CustomMaterial { #[uniform(0)] @@ -194,7 +194,7 @@ fn rotate(mut q: Query<&mut Transform, With>, time: Res::type_path(); - // H::::type_path(); } #[test] diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index 27df34ea767e3..4183a49f3e4ad 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -23,7 +23,7 @@ use std::any::{Any, TypeId}; /// /// ``` /// # use std::any::Any; -/// # use bevy_reflect::{NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, TypeInfo, ValueInfo}; +/// # use bevy_reflect::{DynamicTypePath, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, TypeInfo, ValueInfo}; /// # use bevy_reflect::utility::NonGenericTypeInfoCell; /// use bevy_reflect::Typed; /// @@ -50,6 +50,7 @@ use std::any::{Any, TypeId}; /// # impl Reflect for MyStruct { /// # fn type_name(&self) -> &str { todo!() } /// # fn get_type_info(&self) -> &'static TypeInfo { todo!() } +/// # fn get_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_path.rs b/crates/bevy_reflect/src/type_path.rs index 28412b2c421b0..d458ea0197407 100644 --- a/crates/bevy_reflect/src/type_path.rs +++ b/crates/bevy_reflect/src/type_path.rs @@ -55,7 +55,7 @@ /// // Generics are also supported. /// #[derive(TypePath)] /// #[type_path = "my_crate::foo"] -/// struct StableGenericTypePath([T; N]); +/// struct StableGenericTypePath([T; N]); /// ``` /// /// [utility]: crate::utility diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index e73d5e34fc510..8e0db04e2b7c5 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -52,7 +52,7 @@ impl TypedProperty for T {} /// # impl Reflect for Foo { /// # fn type_name(&self) -> &str { todo!() } /// # fn get_type_info(&self) -> &'static TypeInfo { todo!() } -/// # fn get_type_name(&self) -> &dyn DynamicTypePath { todo!() } +/// # fn get_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!() } @@ -116,7 +116,7 @@ impl NonGenericTypedCell { /// # impl Reflect for Foo { /// # fn type_name(&self) -> &str { todo!() } /// # fn get_type_info(&self) -> &'static TypeInfo { todo!() } -/// # fn get_type_name(&self) -> &dyn DynamicTypePath { todo!() } +/// # fn get_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!() } From 2a2bccfb340a7cefc2b00ae46100a9ab6d4c338c Mon Sep 17 00:00:00 2001 From: radiish Date: Thu, 23 Mar 2023 18:07:02 +0000 Subject: [PATCH 31/52] docs --- .../bevy_reflect/bevy_reflect_derive/src/utility.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs b/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs index f41399869de87..5f269f5d787ea 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::{Generics, Member, Path, Token, Type, WhereClause}; +use syn::{Member, Path, Token, Type, WhereClause}; /// Returns the correct path for `bevy_reflect`. pub(crate) fn get_bevy_reflect_path() -> Path { @@ -75,18 +75,19 @@ pub(crate) struct WhereClauseOptions { } impl WhereClauseOptions { + /// Extends a where clause, adding a `TypePath` bound to each type parameter. pub fn type_path_bounds(meta: &ReflectMeta) -> Self { let bevy_reflect_path = meta.bevy_reflect_path(); Self { - parameter_types: WhereClauseOptions::parameter_types(meta.generics()), + parameter_types: meta + .generics() + .type_params() + .map(|ty| ty.ident.clone()) + .collect(), parameter_trait_bounds: quote! { #bevy_reflect_path::TypePath }, ..Default::default() } } - - pub fn parameter_types(generics: &Generics) -> Box<[Ident]> { - generics.type_params().map(|ty| ty.ident.clone()).collect() - } } impl Default for WhereClauseOptions { From f25cac0ffdae00881b2134e5a3f3ac4b9c96e109 Mon Sep 17 00:00:00 2001 From: radiish Date: Thu, 23 Mar 2023 19:42:13 +0000 Subject: [PATCH 32/52] doc fixes --- crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs | 3 ++- crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs | 6 +++--- 2 files changed, 5 insertions(+), 4 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 a64465dbafaa0..3a4b79ce9ab0e 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs @@ -567,7 +567,7 @@ impl<'a> EnumVariant<'a> { /// Represents a path to a type. /// /// This is used over [`struct@Ident`] or [`Path`] -/// to have the correct semantics for deriving [`TypePath`]. +/// to have the correct semantics for [deriving `TypePath`]. /// /// The type can always be reached with its [`ToTokens`] implementation. /// @@ -575,6 +575,7 @@ impl<'a> EnumVariant<'a> { /// [`type_ident`], [`crate_name`], and [`module_path`] methods /// are equivalent to the methods on the `TypePath` trait. /// +/// [deriving `TypePath`]: crate::derive_type_path /// [`non_generic_type_path`]: ReflectTypePath::non_generic_type_path /// [`non_generic_short_path`]: ReflectTypePath::non_generic_short_path /// [`type_ident`]: ReflectTypePath::type_ident 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 3415f79a01496..7ce94dae3d092 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -33,10 +33,10 @@ fn combine_generics( } /// Returns an expression for a `&'static str`, -/// representing either a [long path](long) or [short path](short). +/// representing either a [long path] or [short path]. /// -/// [long]: ReflectTypePath::non_generic_type_path -/// [short]: ReflectTypePath::non_generic_short_path +/// [long path]: ReflectTypePath::non_generic_type_path +/// [short path]: ReflectTypePath::non_generic_short_path fn type_path_generator(long_path: bool, meta: &ReflectMeta) -> proc_macro2::TokenStream { let path_to_type = meta.path_to_type(); let generics = meta.generics(); From b600b85e9b44515b4ad937ff16f3507a865a09e2 Mon Sep 17 00:00:00 2001 From: radiish Date: Sun, 26 Mar 2023 15:24:51 +0000 Subject: [PATCH 33/52] refactor `TypedProperty` --- .../bevy_reflect_derive/src/impls/typed.rs | 4 +- crates/bevy_reflect/src/utility.rs | 55 +++++++++++++------ 2 files changed, 39 insertions(+), 20 deletions(-) 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 7ce94dae3d092..c7bea0600669c 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -44,9 +44,7 @@ fn type_path_generator(long_path: bool, meta: &ReflectMeta) -> proc_macro2::Toke if let ReflectTypePath::Primitive(name) = path_to_type { let name = LitStr::new(&name.to_string(), name.span()); - return quote! { - #bevy_reflect_path::utility::TypePathStorage::new_primitive(#name) - }; + return quote!(#name); } let ty_generic_paths: Vec<_> = generics diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index 8e0db04e2b7c5..0e7f1f90fc131 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -9,19 +9,36 @@ use std::{ hash::BuildHasher, }; +/// A type that can be stored in a ([`Non`])[`GenericTypeInfoCell`]. +/// +/// [Non]: NonGenericTypeInfoCell +pub trait TypedProperty: sealed::Sealed { + type Stored: 'static; +} + +/// Used to store a [`String`] in a [`GenericTypeInfoCell`] as part of a [`TypePath`] implementation. +/// +/// [TypePath]: crate::TypePath +pub struct TypePathComponent; + mod sealed { - use super::TypeInfo; + use super::{TypeInfo, TypePathComponent, TypedProperty}; pub trait Sealed {} impl Sealed for TypeInfo {} - impl Sealed for String {} -} + impl Sealed for TypePathComponent {} -pub trait TypedProperty: sealed::Sealed + 'static {} -impl TypedProperty for T {} + impl TypedProperty for TypeInfo { + type Stored = Self; + } + + impl TypedProperty for TypePathComponent { + type Stored = String; + } +} -/// A container for [`TypeInfo`] or [`TypePathStorage`] over non-generic types, allowing instances to be stored statically. +/// A container for [`TypeInfo`] over non-generic types, allowing instances to be stored statically. /// /// This is specifically meant for use with _non_-generic types. If your type _is_ generic, /// then use [`GenericTypedCell`] instead. Otherwise, it will not take into account all @@ -67,7 +84,7 @@ impl TypedProperty for T {} /// # fn clone_value(&self) -> Box { todo!() } /// # } /// ``` -pub struct NonGenericTypedCell(OnceBox); +pub struct NonGenericTypedCell(OnceBox); pub type NonGenericTypeInfoCell = NonGenericTypedCell; @@ -77,18 +94,18 @@ impl NonGenericTypedCell { Self(OnceBox::new()) } - /// Returns a reference to the [`TypeInfo`]/[`TypePathStorage`] stored in the cell. + /// Returns a reference to the [`TypeInfo`] stored in the cell. /// /// If there is no entry found, a new one will be generated from the given function. - pub fn get_or_set(&self, f: F) -> &T + pub fn get_or_set(&self, f: F) -> &T::Stored where - F: FnOnce() -> T, + F: FnOnce() -> T::Stored, { self.0.get_or_init(|| Box::new(f())) } } -/// A container for [`TypeInfo`] or [`TypePathStorage`] over generic types, allowing instances to be stored statically. +/// A container for [`TypeInfo`] or [`TypePath` components] over generic types, allowing instances to be stored statically. /// /// This is specifically meant for use with generic types. If your type isn't generic, /// then use [`NonGenericTypedCell`] instead as it should be much more performant. @@ -131,10 +148,12 @@ impl NonGenericTypedCell { /// # fn clone_value(&self) -> Box { todo!() } /// # } /// ``` -pub struct GenericTypedCell(OnceBox>>); +/// +/// [`TypePath` components]: TypePathComponent +pub struct GenericTypedCell(OnceBox>>); pub type GenericTypeInfoCell = GenericTypedCell; -pub type GenericTypePathCell = GenericTypedCell; +pub type GenericTypePathCell = GenericTypedCell; impl GenericTypedCell { /// Initialize a [`GenericTypedCell`] for generic types. @@ -142,14 +161,16 @@ impl GenericTypedCell { Self(OnceBox::new()) } - /// Returns a reference to the [`TypeInfo`]/[`TypePathStorage`] stored in the cell. + /// Returns a reference to the [`TypeInfo`]/[`TypePath` component] stored in the cell. /// - /// This method will then return the correct [`TypeInfo`]/[`TypePathStorage`] reference for the given type `T`. + /// This method will then return the correct [`TypeInfo`]/[`TypePath` component] reference for the given type `T`. /// If there is no entry found, a new one will be generated from the given function. - pub fn get_or_insert(&self, f: F) -> &T + /// + /// [`TypePath` component]: TypePathComponent + pub fn get_or_insert(&self, f: F) -> &T::Stored where G: Any + ?Sized, - F: FnOnce() -> T, + F: FnOnce() -> T::Stored, { let type_id = TypeId::of::(); // let mapping = self.0.get_or_init(|| Box::new(RwLock::default())); From d5ee8e840dd584d8fe610cd9bea2c25df711a179 Mon Sep 17 00:00:00 2001 From: radiish Date: Sun, 26 Mar 2023 15:51:25 +0000 Subject: [PATCH 34/52] improve `(Non)GenericTypeCell` --- .../bevy_reflect_derive/src/derive_data.rs | 2 +- .../bevy_reflect_derive/src/impls/typed.rs | 2 +- crates/bevy_reflect/src/utility.rs | 91 ++++++++++++++----- 3 files changed, 71 insertions(+), 24 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 3a4b79ce9ab0e..77a8911573f2b 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs @@ -380,7 +380,7 @@ impl<'a> ReflectMeta<'a> { /// Whether an impl using this [`ReflectMeta`] should be generic. pub fn impl_is_generic(&self) -> bool { - // Whether to use `GenericTypedCell` is not dependent on lifetimes + // Whether to use `GenericTypeCell` is not dependent on lifetimes // (which all have to be 'static anyway). !self .generics 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 c7bea0600669c..376026f69a2f3 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -100,7 +100,7 @@ fn type_path_generator(long_path: bool, meta: &ReflectMeta) -> proc_macro2::Toke path } -/// Returns an expression for a `NonGenericTypedCell` or `GenericTypedCell`. +/// Returns an expression for a `NonGenericTypeCell` or `GenericTypeCell` to contain `'static` references. fn static_typed_cell( meta: &ReflectMeta, property: TypedProperty, diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index 0e7f1f90fc131..b65a61734876b 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -9,16 +9,16 @@ use std::{ hash::BuildHasher, }; -/// A type that can be stored in a ([`Non`])[`GenericTypeInfoCell`]. +/// A type that can be stored in a ([`Non`])[`GenericTypeCell`]. /// -/// [Non]: NonGenericTypeInfoCell +/// [`Non`]: NonGenericTypeCell pub trait TypedProperty: sealed::Sealed { type Stored: 'static; } -/// Used to store a [`String`] in a [`GenericTypeInfoCell`] as part of a [`TypePath`] implementation. +/// Used to store a [`String`] in a [`GenericTypePathCell`] as part of a [`TypePath`] implementation. /// -/// [TypePath]: crate::TypePath +/// [`TypePath`]: crate::TypePath pub struct TypePathComponent; mod sealed { @@ -41,9 +41,11 @@ mod sealed { /// A container for [`TypeInfo`] over non-generic types, allowing instances to be stored statically. /// /// This is specifically meant for use with _non_-generic types. If your type _is_ generic, -/// then use [`GenericTypedCell`] instead. Otherwise, it will not take into account all +/// then use [`GenericTypeCell`] instead. Otherwise, it will not take into account all /// monomorphizations of your type. /// +/// Non-generic [`TypePath`]s should be trivially generated with string literals and [`concat!`]. +/// /// ## Example /// /// ``` @@ -84,12 +86,14 @@ mod sealed { /// # fn clone_value(&self) -> Box { todo!() } /// # } /// ``` -pub struct NonGenericTypedCell(OnceBox); +/// +/// [`TypePath`]: crate::TypePath +pub struct NonGenericTypeCell(OnceBox); -pub type NonGenericTypeInfoCell = NonGenericTypedCell; +pub type NonGenericTypeInfoCell = NonGenericTypeCell; -impl NonGenericTypedCell { - /// Initialize a [`NonGenericTypedCell`] for non-generic types. +impl NonGenericTypeCell { + /// Initialize a [`NonGenericTypeCell`] for non-generic types. pub const fn new() -> Self { Self(OnceBox::new()) } @@ -105,12 +109,17 @@ impl NonGenericTypedCell { } } -/// A container for [`TypeInfo`] or [`TypePath` components] over generic types, allowing instances to be stored statically. +/// A container for [`TypedProperty`] over generic types, allowing instances to be stored statically. /// /// This is specifically meant for use with generic types. If your type isn't generic, -/// then use [`NonGenericTypedCell`] instead as it should be much more performant. +/// then use [`NonGenericTypeCell`] instead as it should be much more performant. /// -/// ## Example +/// `#[derive(TypePath)]` and [`impl_type_path`] should always be used over [`GenericTypePathCell`] +/// where possible. +/// +/// ## Examples +/// +/// Implementing [`TypeInfo`] with generics. /// /// ``` /// # use std::any::Any; @@ -149,24 +158,62 @@ impl NonGenericTypedCell { /// # } /// ``` /// -/// [`TypePath` components]: TypePathComponent -pub struct GenericTypedCell(OnceBox>>); +/// Implementing [`TypePath`] with generics. +/// +/// ``` +/// # use std::any::Any; +/// # use bevy_reflect::{DynamicTypePath, Reflect, ReflectMut, ReflectOwned, ReflectRef, TupleStructInfo, Typed, TypeInfo, UnnamedField}; +/// use bevy_reflect::utility::GenericTypePathCell; +/// +/// struct Foo(T); +/// +/// 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())) +/// } +/// +/// fn short_type_path() -> &'static str { +/// static CELL: GenericTypePathCell = GenericTypePathCell::new(); +/// CELL.get_or_insert::(|| format!("Foo<{}>", T::short_type_path())) +/// } +/// } +/// # +/// # impl Reflect for Foo { +/// # fn type_name(&self) -> &str { todo!() } +/// # fn get_type_info(&self) -> &'static TypeInfo { todo!() } +/// # fn get_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!() } +/// # 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 +pub struct GenericTypeCell(OnceBox>>); -pub type GenericTypeInfoCell = GenericTypedCell; -pub type GenericTypePathCell = GenericTypedCell; +pub type GenericTypeInfoCell = GenericTypeCell; +pub type GenericTypePathCell = GenericTypeCell; -impl GenericTypedCell { - /// Initialize a [`GenericTypedCell`] for generic types. +impl GenericTypeCell { + /// Initialize a [`GenericTypeCell`] for generic types. pub const fn new() -> Self { Self(OnceBox::new()) } - /// Returns a reference to the [`TypeInfo`]/[`TypePath` component] stored in the cell. + /// Returns a reference to the [`TypedProperty`] stored in the cell. /// - /// This method will then return the correct [`TypeInfo`]/[`TypePath` component] reference for the given type `T`. + /// This method will then return the correct [`TypedProperty`] reference for the given type `T`. /// If there is no entry found, a new one will be generated from the given function. - /// - /// [`TypePath` component]: TypePathComponent pub fn get_or_insert(&self, f: F) -> &T::Stored where G: Any + ?Sized, From dad224fc675d544908c190382f32dbc3c4a7987c Mon Sep 17 00:00:00 2001 From: radiish Date: Sun, 26 Mar 2023 15:59:53 +0000 Subject: [PATCH 35/52] remove superfluous colon seperators --- .../bevy_reflect_derive/src/impls/typed.rs | 30 +++++++------------ crates/bevy_reflect/src/lib.rs | 13 ++++---- crates/bevy_reflect/src/utility.rs | 2 +- 3 files changed, 16 insertions(+), 29 deletions(-) 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 376026f69a2f3..b34aa07520e08 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -57,10 +57,7 @@ fn type_path_generator(long_path: bool, meta: &ReflectMeta) -> proc_macro2::Toke }) .collect(); - let ident = path_to_type.get_ident().unwrap().to_string(); - let ident = LitStr::new(&ident, path_to_type.span()); - - let path = if long_path { + let (path, ty_generics) = if long_path { let ty_generics: Vec<_> = ty_generic_paths .iter() .map(|cell| { @@ -70,14 +67,7 @@ fn type_path_generator(long_path: bool, meta: &ReflectMeta) -> proc_macro2::Toke }) .collect(); - let generics = combine_generics(ty_generics, generics); - let path = path_to_type.non_generic_type_path(); - - quote! { - ::std::borrow::ToOwned::to_owned(::core::concat!(#path, "::<")) - #(+ #generics)* - + ">" - } + (path_to_type.non_generic_type_path(), ty_generics) } else { let ty_generics: Vec<_> = ty_generic_paths .iter() @@ -88,16 +78,16 @@ fn type_path_generator(long_path: bool, meta: &ReflectMeta) -> proc_macro2::Toke }) .collect(); - let generics = combine_generics(ty_generics, generics); - - quote! { - ::std::borrow::ToOwned::to_owned(::core::concat!(#ident, "<")) - #(+ #generics)* - + ">" - } + (path_to_type.non_generic_short_path(), ty_generics) }; - path + let generics = combine_generics(ty_generics, generics); + + quote! { + ::std::borrow::ToOwned::to_owned(::core::concat!(#path, "<")) + #(+ #generics)* + + ">" + } } /// Returns an expression for a `NonGenericTypeCell` or `GenericTypeCell` to contain `'static` references. diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index e2f1d1e1e2ab5..bdb0416c2b2f5 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1132,24 +1132,21 @@ mod tests { assert_eq!( DeriveG::<()>::type_path(), - "bevy_reflect::tests::DeriveG::<()>" + "bevy_reflect::tests::DeriveG<()>" ); assert_eq!( DerivePathG::<(), 10>::type_path(), - "my_alias::DerivePathG::<(), 10>" + "my_alias::DerivePathG<(), 10>" ); assert_eq!( DerivePathNameG::<()>::type_path(), - "my_alias::MyDerivePathNameG::<()>" + "my_alias::MyDerivePathNameG<()>" ); assert_eq!(Macro::type_path(), "my_alias::Macro"); assert_eq!(MacroName::type_path(), "my_alias::MyMacroName"); - assert_eq!(MacroG::<(), 10>::type_path(), "my_alias::MacroG::<(), 10>"); - assert_eq!( - MacroNameG::<()>::type_path(), - "my_alias::MyMacroNameG::<()>" - ); + assert_eq!(MacroG::<(), 10>::type_path(), "my_alias::MacroG<(), 10>"); + assert_eq!(MacroNameG::<()>::type_path(), "my_alias::MyMacroNameG<()>"); } #[test] diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index b65a61734876b..0308d2c331c9c 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -170,7 +170,7 @@ impl NonGenericTypeCell { /// 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())) +/// CELL.get_or_insert::(|| format!("my_crate::foo::Foo<{}>", T::type_path())) /// } /// /// fn short_type_path() -> &'static str { From 395f907265a1964884e02a2087bc5f198f268bc8 Mon Sep 17 00:00:00 2001 From: radiish Date: Sun, 26 Mar 2023 16:07:53 +0000 Subject: [PATCH 36/52] better tests --- crates/bevy_reflect/src/lib.rs | 47 ++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index bdb0416c2b2f5..1d412cfc120a6 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1090,6 +1090,9 @@ mod tests { #[test] fn reflect_type_path() { + #[derive(TypePath)] + struct Param; + #[derive(TypePath)] struct Derive; @@ -1131,22 +1134,50 @@ mod tests { assert_eq!(DerivePathName::type_path(), "my_alias::MyDerivePathName"); assert_eq!( - DeriveG::<()>::type_path(), - "bevy_reflect::tests::DeriveG<()>" + DeriveG::::type_path(), + "bevy_reflect::tests::DeriveG" ); assert_eq!( - DerivePathG::<(), 10>::type_path(), - "my_alias::DerivePathG<(), 10>" + DerivePathG::::type_path(), + "my_alias::DerivePathG" ); assert_eq!( - DerivePathNameG::<()>::type_path(), - "my_alias::MyDerivePathNameG<()>" + 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::<(), 10>::type_path(), "my_alias::MacroG<(), 10>"); - assert_eq!(MacroNameG::<()>::type_path(), "my_alias::MyMacroNameG<()>"); + assert_eq!( + MacroG::::type_path(), + "my_alias::MacroG" + ); + assert_eq!( + MacroNameG::::type_path(), + "my_alias::MyMacroNameG" + ); + + assert_eq!(Derive::short_type_path(), "Derive"); + assert_eq!(DerivePath::short_type_path(), "DerivePath"); + assert_eq!(DerivePathName::short_type_path(), "MyDerivePathName"); + + assert_eq!(DeriveG::::short_type_path(), "DeriveG"); + assert_eq!( + DerivePathG::::short_type_path(), + "DerivePathG" + ); + assert_eq!( + DerivePathNameG::::short_type_path(), + "MyDerivePathNameG" + ); + + 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" + ); } #[test] From b52debab47411f0aa5646614844461d6e5fd68aa Mon Sep 17 00:00:00 2001 From: radiish Date: Sun, 26 Mar 2023 16:15:24 +0000 Subject: [PATCH 37/52] fix doc test --- crates/bevy_reflect/src/utility.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index 0308d2c331c9c..0aa59be67c7bf 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -126,7 +126,7 @@ impl NonGenericTypeCell { /// # use bevy_reflect::{DynamicTypePath, Reflect, ReflectMut, ReflectOwned, ReflectRef, TupleStructInfo, Typed, TypeInfo, UnnamedField}; /// use bevy_reflect::utility::GenericTypeInfoCell; /// -/// struct Foo(T); +/// struct Foo(T); /// /// impl Typed for Foo { /// fn type_info() -> &'static TypeInfo { @@ -162,12 +162,12 @@ 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, TypeInfo, TypePath}; /// use bevy_reflect::utility::GenericTypePathCell; /// -/// struct Foo(T); +/// 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())) From 1f173cad362317207f4e2295ce9114b0a658ea10 Mon Sep 17 00:00:00 2001 From: radiish Date: Sun, 26 Mar 2023 16:16:57 +0000 Subject: [PATCH 38/52] document `*TypeCell` aliases --- crates/bevy_reflect/src/utility.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index 0aa59be67c7bf..849605e7d013f 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -90,6 +90,7 @@ mod sealed { /// [`TypePath`]: crate::TypePath pub struct NonGenericTypeCell(OnceBox); +/// See [`NonGenericTypeCell`]. pub type NonGenericTypeInfoCell = NonGenericTypeCell; impl NonGenericTypeCell { @@ -201,7 +202,9 @@ impl NonGenericTypeCell { /// [`TypePath`]: crate::TypePath pub struct GenericTypeCell(OnceBox>>); +/// See [`GenericTypeCell`]. pub type GenericTypeInfoCell = GenericTypeCell; +/// See [`GenericTypeCell`]. pub type GenericTypePathCell = GenericTypeCell; impl GenericTypeCell { From a68ebce1f8fb3c71c957a6f1355d867ae4da6aaf Mon Sep 17 00:00:00 2001 From: radiish Date: Sun, 26 Mar 2023 16:35:53 +0000 Subject: [PATCH 39/52] fix various ci --- .../bevy_reflect_derive/src/derive_data.rs | 4 ++-- crates/bevy_reflect/bevy_reflect_derive/src/utility.rs | 3 ++- crates/bevy_reflect/src/lib.rs | 2 +- crates/bevy_reflect/src/reflect.rs | 2 +- .../tests/reflect_derive/generics.fail.rs | 5 +++-- .../tests/reflect_derive/generics.fail.stderr | 10 +++++----- 6 files changed, 14 insertions(+), 12 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 77a8911573f2b..3e33c3dc4f7f8 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs @@ -470,7 +470,7 @@ impl<'a> ReflectStruct<'a> { let bevy_reflect_path = &self.meta().bevy_reflect_path; WhereClauseOptions { active_types: self.active_types().into(), - active_trait_bounds: quote! { #bevy_reflect_path::Reflect + #bevy_reflect_path::TypePath }, + active_trait_bounds: quote! { #bevy_reflect_path::Reflect }, ignored_types: self.ignored_types().into(), ignored_trait_bounds: quote! { #FQAny + #FQSend + #FQSync }, ..WhereClauseOptions::type_path_bounds(self.meta()) @@ -529,7 +529,7 @@ impl<'a> ReflectEnum<'a> { let bevy_reflect_path = &self.meta().bevy_reflect_path; WhereClauseOptions { active_types: self.active_types().into(), - active_trait_bounds: quote! { #bevy_reflect_path::FromReflect + #bevy_reflect_path::TypePath }, + active_trait_bounds: quote! { #bevy_reflect_path::FromReflect }, ignored_types: self.ignored_types().into(), ignored_trait_bounds: quote! { #FQAny + #FQSend + #FQSync + #FQDefault }, ..WhereClauseOptions::type_path_bounds(self.meta()) diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs b/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs index 5f269f5d787ea..07006f333855b 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs @@ -159,9 +159,10 @@ pub(crate) fn extend_where_clause( quote!() }; generic_where_clause.extend(quote! { - #(#parameter_types: #parameter_trait_bounds,)* #(#active_types: #active_trait_bounds,)* #(#ignored_types: #ignored_trait_bounds,)* + // Leave parameter bounds to the end for more sane error messages. + #(#parameter_types: #parameter_trait_bounds,)* }); generic_where_clause } diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 1d412cfc120a6..a2739d2a7a35f 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1167,7 +1167,7 @@ mod tests { "DerivePathG" ); assert_eq!( - DerivePathNameG::::short_type_path(), + DerivePathNameG::::short_type_path(), "MyDerivePathNameG" ); diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index 11566daa14ad8..7cbe8bf73e5f4 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -88,7 +88,7 @@ pub trait Reflect: Any + Send + Sync { /// Returns the [`TypePath`] implementation for the underlying type. /// - /// This method suffers the same performance concerns as [`get_type_info`]. + /// Methods on [`DynamicTypePath`] suffer the same performance concerns as [`get_type_info`]. /// /// [`get_type_info`]: Reflect::get_type_info fn get_type_path(&self) -> &dyn DynamicTypePath; diff --git a/crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/generics.fail.rs b/crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/generics.fail.rs index 964d784d354d0..1ed92883b1033 100644 --- a/crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/generics.fail.rs +++ b/crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/generics.fail.rs @@ -1,4 +1,4 @@ -use bevy_reflect::Reflect; +use bevy_reflect::{Reflect, TypePath}; #[derive(Reflect)] struct Foo { @@ -6,10 +6,11 @@ struct Foo { } // Type that doesn't implement Reflect +#[derive(TypePath)] struct NoReflect(f32); fn main() { let mut foo: Box = Box::new(Foo:: { a: NoReflect(42.0) }); // foo doesn't implement Reflect because NoReflect doesn't implement Reflect foo.get_field::("a").unwrap(); -} \ No newline at end of file +} diff --git a/crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/generics.fail.stderr b/crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/generics.fail.stderr index 0f568ed9c524d..d3f6f12524eac 100644 --- a/crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/generics.fail.stderr +++ b/crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/generics.fail.stderr @@ -1,13 +1,13 @@ error[E0599]: no method named `get_field` found for struct `Box<(dyn Reflect + 'static)>` in the current scope - --> tests/reflect_derive/generics.fail.rs:14:9 + --> tests/reflect_derive/generics.fail.rs:15:9 | -14 | foo.get_field::("a").unwrap(); +15 | foo.get_field::("a").unwrap(); | ^^^^^^^^^ method not found in `Box<(dyn Reflect + 'static)>` error[E0277]: the trait bound `NoReflect: Reflect` is not satisfied - --> tests/reflect_derive/generics.fail.rs:12:37 + --> tests/reflect_derive/generics.fail.rs:13:37 | -12 | let mut foo: Box = Box::new(Foo:: { a: NoReflect(42.0) }); +13 | let mut foo: Box = Box::new(Foo:: { a: NoReflect(42.0) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Reflect` is not implemented for `NoReflect` | = help: the following other types implement trait `Reflect`: @@ -24,7 +24,7 @@ note: required for `Foo` to implement `Reflect` --> tests/reflect_derive/generics.fail.rs:3:10 | 3 | #[derive(Reflect)] - | ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ^^^^^^^ 4 | struct Foo { | ^^^^^^ = note: required for the cast from `Foo` to the object type `dyn Reflect` From a42c641b30898831d841a81b8dd32e0e5047b255 Mon Sep 17 00:00:00 2001 From: radiish Date: Mon, 27 Mar 2023 17:45:54 +0000 Subject: [PATCH 40/52] ci tweaks --- crates/bevy_reflect/Cargo.toml | 1 - crates/bevy_reflect/src/impls/std.rs | 4 +++- .../tests/reflect_derive/generics.fail.stderr | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/bevy_reflect/Cargo.toml b/crates/bevy_reflect/Cargo.toml index 43e5cc4b453ab..836dfc590ec73 100644 --- a/crates/bevy_reflect/Cargo.toml +++ b/crates/bevy_reflect/Cargo.toml @@ -38,7 +38,6 @@ smallvec = { version = "1.6", features = [ "const_generics", ], optional = true } glam = { version = "0.23", features = ["serde"], optional = true } -ahash = "0.7.6" [dev-dependencies] ron = "0.8.0" diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index c8333609631e0..4facb9785b72d 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -14,6 +14,7 @@ use crate::utility::{ use bevy_reflect_derive::{impl_from_reflect_value, impl_reflect_value}; use bevy_utils::HashSet; use bevy_utils::{Duration, Instant}; +use std::collections::hash_map::RandomState; use std::{ any::Any, borrow::Cow, @@ -662,7 +663,8 @@ macro_rules! impl_reflect_for_hashmap { }; } -impl_type_path!(ahash::RandomState in ahash::random_state); +impl_type_path!(::std::collections::hash_map::RandomState); +impl_type_path!(::bevy_utils::hashbrown::hash_map::DefaultHashBuilder); impl_reflect_for_hashmap!(::bevy_utils::hashbrown::HashMap); impl_reflect_for_hashmap!(::std::collections::HashMap); diff --git a/crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/generics.fail.stderr b/crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/generics.fail.stderr index d3f6f12524eac..71f7969872772 100644 --- a/crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/generics.fail.stderr +++ b/crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/generics.fail.stderr @@ -24,7 +24,7 @@ note: required for `Foo` to implement `Reflect` --> tests/reflect_derive/generics.fail.rs:3:10 | 3 | #[derive(Reflect)] - | ^^^^^^^ + | ^^^^^^^ unsatisfied trait bound introduced in this `derive` macro 4 | struct Foo { | ^^^^^^ = note: required for the cast from `Foo` to the object type `dyn Reflect` From a771aeaec1a8efb5815d48fafefc2d3372b274f0 Mon Sep 17 00:00:00 2001 From: radiish Date: Mon, 27 Mar 2023 18:31:39 +0000 Subject: [PATCH 41/52] prefix custom paths --- .../bevy_reflect_derive/src/lib.rs | 12 ++--- .../bevy_reflect_derive/src/reflect_value.rs | 6 +-- .../bevy_reflect_derive/src/type_path.rs | 53 +++++++++---------- crates/bevy_reflect/src/array.rs | 2 +- crates/bevy_reflect/src/enums/dynamic_enum.rs | 2 +- crates/bevy_reflect/src/impls/std.rs | 27 ++++++---- crates/bevy_reflect/src/lib.rs | 8 +-- crates/bevy_reflect/src/list.rs | 2 +- crates/bevy_reflect/src/map.rs | 2 +- crates/bevy_reflect/src/struct_trait.rs | 2 +- crates/bevy_reflect/src/tuple.rs | 2 +- crates/bevy_reflect/src/tuple_struct.rs | 2 +- 12 files changed, 62 insertions(+), 58 deletions(-) diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs index 6908cea1621be..299e013b0b56b 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs @@ -296,12 +296,12 @@ pub fn impl_reflect_value(input: TokenStream) -> TokenStream { let def = parse_macro_input!(input as ReflectValueDef); let default_name = &def.type_path.segments.last().unwrap().ident; - let path_to_type = if def.type_path.leading_colon.is_none() && def.alias.is_empty() { + let path_to_type = if def.type_path.leading_colon.is_none() && def.custom_path.is_none() { ReflectTypePath::Primitive(default_name) } else { ReflectTypePath::External { path: &def.type_path, - custom_path: def.alias.into_path(default_name), + custom_path: def.custom_path.map(|path| path.into_path(default_name)), } }; @@ -409,12 +409,12 @@ pub fn impl_from_reflect_value(input: TokenStream) -> TokenStream { let def = parse_macro_input!(input as ReflectValueDef); let default_name = &def.type_path.segments.last().unwrap().ident; - let path_to_type = if def.type_path.leading_colon.is_none() && def.alias.is_empty() { + let path_to_type = if def.type_path.leading_colon.is_none() && def.custom_path.is_none() { ReflectTypePath::Primitive(default_name) } else { ReflectTypePath::External { path: &def.type_path, - custom_path: def.alias.into_path(default_name), + custom_path: def.custom_path.map(|alias| alias.into_path(default_name)), } }; @@ -432,14 +432,14 @@ pub fn impl_type_path(input: TokenStream) -> TokenStream { let (path_to_type, generics) = match def { NamedTypePathDef::External { ref path, - custom_path: alias, + custom_path, generics, } => { let default_name = &path.segments.last().unwrap().ident; ( ReflectTypePath::External { path, - custom_path: alias.into_path(default_name), + custom_path: custom_path.map(|path| path.into_path(default_name)), }, generics, ) diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs b/crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs index 6e5b30ba0ace6..df08df2c45e26 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs @@ -26,7 +26,7 @@ pub(crate) struct ReflectValueDef { pub type_path: Path, pub generics: Generics, pub traits: Option, - pub alias: CustomPathDef, + pub custom_path: Option, } impl Parse for ReflectValueDef { @@ -43,14 +43,14 @@ impl Parse for ReflectValueDef { traits = Some(content.parse::()?); } - let alias: CustomPathDef = input.parse()?; + let custom_path = CustomPathDef::parse_parenthesized(input)?; Ok(ReflectValueDef { attrs, type_path, generics: Generics { ..generics }, traits, - alias, + custom_path, }) } } diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs b/crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs index 163f65e9fa1c2..e60795da346cf 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs @@ -1,6 +1,8 @@ use proc_macro2::Ident; use syn::{ + parenthesized, parse::{Parse, ParseStream}, + token::Paren, Generics, Path, PathSegment, Token, }; @@ -18,43 +20,40 @@ pub fn parse_path_no_leading_colon(input: ParseStream) -> syn::Result { } } +/// An alias for a `TypePath`. +/// +/// This is the parenthesized part of `(in my_crate::foo as MyType) SomeType`. pub struct CustomPathDef { - custom_path: Option, - custom_name: Option, + path: Path, + name: Option, } impl CustomPathDef { - pub fn is_empty(&self) -> bool { - self.custom_path.is_none() + pub fn into_path(mut self, default_name: &Ident) -> Path { + let name = PathSegment::from(self.name.unwrap_or_else(|| default_name.clone())); + self.path.segments.push(name); + self.path } - pub fn into_path(self, default_name: &Ident) -> Option { - if let Some(mut path) = self.custom_path { - let name = PathSegment::from(self.custom_name.unwrap_or_else(|| default_name.clone())); - path.segments.push(name); - Some(path) + pub fn parse_parenthesized(input: ParseStream) -> syn::Result> { + if input.peek(Paren) { + let path; + parenthesized!(path in input); + Ok(Some(path.call(Self::parse)?)) } else { - None + Ok(None) } } -} -impl Parse for CustomPathDef { fn parse(input: ParseStream) -> syn::Result { - if !input.peek(Token![in]) { - return Ok(Self { - custom_path: None, - custom_name: None, - }); - } - input.parse::()?; + let custom_path = parse_path_no_leading_colon(input)?; if !input.peek(Token![as]) { return Ok(Self { - custom_path: Some(custom_path), - custom_name: None, + path: custom_path, + name: None, }); } @@ -62,8 +61,8 @@ impl Parse for CustomPathDef { let custom_name: Ident = input.parse()?; Ok(Self { - custom_path: Some(custom_path), - custom_name: Some(custom_name), + path: custom_path, + name: Some(custom_name), }) } } @@ -72,20 +71,20 @@ pub enum NamedTypePathDef { External { path: Path, generics: Generics, - custom_path: CustomPathDef, + custom_path: Option, }, Primtive(Ident), } impl Parse for NamedTypePathDef { fn parse(input: ParseStream) -> syn::Result { + let custom_path = CustomPathDef::parse_parenthesized(input)?; + let path = Path::parse_mod_style(input)?; let mut generics = input.parse::()?; generics.where_clause = input.parse()?; - let custom_path: CustomPathDef = input.parse()?; - - if path.leading_colon.is_none() && custom_path.is_empty() { + if path.leading_colon.is_none() && custom_path.is_none() { if path.segments.len() == 1 { let ident = path.segments.into_iter().next().unwrap().ident; Ok(NamedTypePathDef::Primtive(ident)) diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index d0836e6ea5a0b..a2363fad0fce6 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -337,7 +337,7 @@ impl Typed for DynamicArray { } } -impl_type_path!(DynamicArray in bevy_reflect); +impl_type_path!((in bevy_reflect) DynamicArray); /// An iterator over an [`Array`]. pub struct ArrayIter<'a> { diff --git a/crates/bevy_reflect/src/enums/dynamic_enum.rs b/crates/bevy_reflect/src/enums/dynamic_enum.rs index 6eb72752b2b09..4ea2110d24874 100644 --- a/crates/bevy_reflect/src/enums/dynamic_enum.rs +++ b/crates/bevy_reflect/src/enums/dynamic_enum.rs @@ -433,4 +433,4 @@ impl Typed for DynamicEnum { } } -impl_type_path!(DynamicEnum in bevy_reflect); +impl_type_path!((in bevy_reflect) DynamicEnum); diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 4facb9785b72d..24067ff8f15d8 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -14,7 +14,6 @@ use crate::utility::{ use bevy_reflect_derive::{impl_from_reflect_value, impl_reflect_value}; use bevy_utils::HashSet; use bevy_utils::{Duration, Instant}; -use std::collections::hash_map::RandomState; use std::{ any::Any, borrow::Cow, @@ -619,14 +618,6 @@ macro_rules! impl_reflect_for_hashmap { } } - impl_type_path!( - $ty - where - K: FromReflect + Eq + Hash, - V: FromReflect, - S: BuildHasher + Send + Sync + 'static, - ); - impl GetTypeRegistration for $ty where K: FromReflect + TypePath + Eq + Hash, @@ -664,10 +655,24 @@ macro_rules! impl_reflect_for_hashmap { } impl_type_path!(::std::collections::hash_map::RandomState); -impl_type_path!(::bevy_utils::hashbrown::hash_map::DefaultHashBuilder); +impl_type_path!((in hashbrown::hash_map) bevy_utils::hashbrown::hash_map::DefaultHashBuilder); -impl_reflect_for_hashmap!(::bevy_utils::hashbrown::HashMap); +impl_reflect_for_hashmap!(bevy_utils::hashbrown::HashMap); impl_reflect_for_hashmap!(::std::collections::HashMap); +impl_type_path!( + (in hashbrown) bevy_utils::hashbrown::HashMap + where + K: FromReflect + Eq + Hash, + V: FromReflect, + S: BuildHasher + Send + Sync + 'static, +); +impl_type_path!( + ::std::collections::HashMap + where + K: FromReflect + Eq + Hash, + V: FromReflect, + S: BuildHasher + Send + Sync + 'static, +); impl Array for [T; N] { #[inline] diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index a2739d2a7a35f..a14088bba9c2b 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1118,16 +1118,16 @@ mod tests { struct DerivePathNameG(PhantomData); struct Macro; - impl_type_path!(Macro in my_alias); + impl_type_path!((in my_alias) Macro); struct MacroName; - impl_type_path!(MacroName in my_alias as MyMacroName); + impl_type_path!((in my_alias as MyMacroName) MacroName); struct MacroG(PhantomData); - impl_type_path!(MacroG in my_alias); + impl_type_path!((in my_alias) MacroG); struct MacroNameG(PhantomData); - impl_type_path!(MacroNameG in my_alias as MyMacroNameG); + 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"); diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index a9fc45f85f154..b8235977beb89 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -366,7 +366,7 @@ impl Typed for DynamicList { } } -impl_type_path!(DynamicList in bevy_reflect); +impl_type_path!((in bevy_reflect) DynamicList); impl IntoIterator for DynamicList { type Item = Box; diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index fa2476a166fd3..e63a022e0a22f 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -382,7 +382,7 @@ impl Typed for DynamicMap { } } -impl_type_path!(DynamicMap in bevy_reflect); +impl_type_path!((in bevy_reflect) DynamicMap); /// An iterator over the key-value pairs of a [`Map`]. pub struct MapIter<'a> { diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index b737d62b9ea00..102b72648c400 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -492,7 +492,7 @@ impl Typed for DynamicStruct { } } -impl_type_path!(DynamicStruct in bevy_reflect); +impl_type_path!((in bevy_reflect) DynamicStruct); /// Compares a [`Struct`] with a [`Reflect`] value. /// diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index 44b38e786d6c3..4a50f66017adb 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -388,7 +388,7 @@ impl Typed for DynamicTuple { } } -impl_type_path!(DynamicTuple in bevy_reflect); +impl_type_path!((in bevy_reflect) DynamicTuple); /// Applies the elements of `b` to the corresponding elements of `a`. /// diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index 4117ad2270081..9cea19c3d844b 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -394,7 +394,7 @@ impl Typed for DynamicTupleStruct { } } -impl_type_path!(DynamicTupleStruct in bevy_reflect); +impl_type_path!((in bevy_reflect) DynamicTupleStruct); /// Compares a [`TupleStruct`] with a [`Reflect`] value. /// From c12ad4b54ecb3ff83318b7fa960fc090b9547dd7 Mon Sep 17 00:00:00 2001 From: radiish Date: Mon, 27 Mar 2023 18:34:18 +0000 Subject: [PATCH 42/52] `path_to_type` -> `type_path` --- .../bevy_reflect_derive/src/derive_data.rs | 16 ++++----- .../bevy_reflect_derive/src/from_reflect.rs | 10 +++--- .../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 | 34 +++++++++---------- .../bevy_reflect_derive/src/impls/values.rs | 4 +-- .../bevy_reflect_derive/src/lib.rs | 16 ++++----- .../bevy_reflect_derive/src/registration.rs | 4 +-- 9 files changed, 45 insertions(+), 45 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 3e33c3dc4f7f8..d5985f32f00f5 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) struct ReflectMeta<'a> { /// The registered traits for this type. traits: ReflectTraits, /// The name of this type. - path_to_type: ReflectTypePath<'a>, + type_path: ReflectTypePath<'a>, /// The generics defined on this type. generics: &'a Generics, /// A cached instance of the path to the `bevy_reflect` crate. @@ -225,12 +225,12 @@ impl<'a> ReflectDerive<'a> { )); } - let path_to_type = ReflectTypePath::Internal { + let type_path = ReflectTypePath::Internal { ident: &input.ident, custom_path, }; - let meta = ReflectMeta::new(path_to_type, &input.generics, traits); + let meta = ReflectMeta::new(type_path, &input.generics, traits); #[cfg(feature = "documentation")] let meta = meta.with_docs(doc); @@ -338,13 +338,13 @@ impl<'a> ReflectDerive<'a> { impl<'a> ReflectMeta<'a> { pub fn new( - path_to_type: ReflectTypePath<'a>, + type_path: ReflectTypePath<'a>, generics: &'a Generics, traits: ReflectTraits, ) -> Self { Self { traits, - path_to_type, + type_path, generics, bevy_reflect_path: utility::get_bevy_reflect_path(), #[cfg(feature = "documentation")] @@ -364,8 +364,8 @@ impl<'a> ReflectMeta<'a> { } /// The name of this struct. - pub fn path_to_type(&self) -> &'a ReflectTypePath { - &self.path_to_type + pub fn type_path(&self) -> &'a ReflectTypePath { + &self.type_path } /// The generics associated with this struct. @@ -486,7 +486,7 @@ impl<'a> ReflectEnum<'a> { /// Returns the given ident as a qualified unit variant of this enum. pub fn get_unit(&self, variant: &Ident) -> proc_macro2::TokenStream { - let name = self.meta.path_to_type(); + let name = self.meta.type_path(); quote! { #name::#variant } 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 f9e29459e69e6..cca809cc8803c 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs @@ -22,13 +22,13 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { /// Implements `FromReflect` for the given value type pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { - let path_to_type = meta.path_to_type(); + let type_path = meta.type_path(); let bevy_reflect_path = meta.bevy_reflect_path(); let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl(); TokenStream::from(quote! { - impl #impl_generics #bevy_reflect_path::FromReflect for #path_to_type #ty_generics #where_clause { + impl #impl_generics #bevy_reflect_path::FromReflect for #type_path #ty_generics #where_clause { fn from_reflect(reflect: &dyn #bevy_reflect_path::Reflect) -> #FQOption { - #FQOption::Some(#FQClone::clone(::downcast_ref::<#path_to_type #ty_generics>(::as_any(reflect))?)) + #FQOption::Some(#FQClone::clone(::downcast_ref::<#type_path #ty_generics>(::as_any(reflect))?)) } } }) @@ -38,7 +38,7 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { let fqoption = FQOption.into_token_stream(); - let enum_path = reflect_enum.meta().path_to_type(); + let enum_path = reflect_enum.meta().type_path(); let bevy_reflect_path = reflect_enum.meta().bevy_reflect_path(); let ref_value = Ident::new("__param0", Span::call_site()); @@ -78,7 +78,7 @@ impl MemberValuePair { fn impl_struct_internal(reflect_struct: &ReflectStruct, is_tuple: bool) -> TokenStream { let fqoption = FQOption.into_token_stream(); - let struct_path = reflect_struct.meta().path_to_type(); + let struct_path = reflect_struct.meta().type_path(); let bevy_reflect_path = reflect_struct.meta().bevy_reflect_path(); let ref_struct = Ident::new("__ref_struct", Span::call_site()); 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 b93acc044fbb4..b908a5f3b37dc 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs @@ -10,7 +10,7 @@ use syn::Fields; pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { let bevy_reflect_path = reflect_enum.meta().bevy_reflect_path(); - let enum_path = reflect_enum.meta().path_to_type(); + let enum_path = reflect_enum.meta().type_path(); let ref_name = Ident::new("__name_param", Span::call_site()); let ref_index = Ident::new("__index_param", Span::call_site()); 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 53280fb180356..69f0bbc5275f5 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs @@ -10,7 +10,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { let fqoption = FQOption.into_token_stream(); let bevy_reflect_path = reflect_struct.meta().bevy_reflect_path(); - let struct_path = reflect_struct.meta().path_to_type(); + let struct_path = reflect_struct.meta().type_path(); let field_names = reflect_struct .active_fields() 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 3fa0fe155db4d..cb92a255285d8 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 @@ -11,7 +11,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { let fqoption = FQOption.into_token_stream(); let bevy_reflect_path = reflect_struct.meta().bevy_reflect_path(); - let struct_path = reflect_struct.meta().path_to_type(); + let struct_path = reflect_struct.meta().type_path(); let field_idents = reflect_struct .active_fields() 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 b34aa07520e08..a4315a3b7b6f3 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -38,11 +38,11 @@ fn combine_generics( /// [long path]: ReflectTypePath::non_generic_type_path /// [short path]: ReflectTypePath::non_generic_short_path fn type_path_generator(long_path: bool, meta: &ReflectMeta) -> proc_macro2::TokenStream { - let path_to_type = meta.path_to_type(); + let type_path = meta.type_path(); let generics = meta.generics(); let bevy_reflect_path = meta.bevy_reflect_path(); - if let ReflectTypePath::Primitive(name) = path_to_type { + if let ReflectTypePath::Primitive(name) = type_path { let name = LitStr::new(&name.to_string(), name.span()); return quote!(#name); } @@ -67,7 +67,7 @@ fn type_path_generator(long_path: bool, meta: &ReflectMeta) -> proc_macro2::Toke }) .collect(); - (path_to_type.non_generic_type_path(), ty_generics) + (type_path.non_generic_type_path(), ty_generics) } else { let ty_generics: Vec<_> = ty_generic_paths .iter() @@ -78,7 +78,7 @@ fn type_path_generator(long_path: bool, meta: &ReflectMeta) -> proc_macro2::Toke }) .collect(); - (path_to_type.non_generic_short_path(), ty_generics) + (type_path.non_generic_short_path(), ty_generics) }; let generics = combine_generics(ty_generics, generics); @@ -136,10 +136,10 @@ pub(crate) fn impl_type_path( meta: &ReflectMeta, where_clause_options: &WhereClauseOptions, ) -> proc_macro2::TokenStream { - let path_to_type = meta.path_to_type(); + let type_path = meta.type_path(); let bevy_reflect_path = meta.bevy_reflect_path(); - let (type_path, short_type_path) = if meta.impl_is_generic() { + let (long_type_path, short_type_path) = if meta.impl_is_generic() { let long_path_cell = static_typed_cell( meta, TypedProperty::TypePath, @@ -156,21 +156,21 @@ pub(crate) fn impl_type_path( ) } else { ( - path_to_type.non_generic_type_path(), - path_to_type.non_generic_short_path(), + type_path.non_generic_type_path(), + type_path.non_generic_short_path(), ) }; - let type_ident = wrap_in_option(path_to_type.type_ident()); - let module_path = wrap_in_option(path_to_type.module_path()); - let crate_name = wrap_in_option(path_to_type.crate_name()); + let type_ident = wrap_in_option(type_path.type_ident()); + let module_path = wrap_in_option(type_path.module_path()); + let crate_name = wrap_in_option(type_path.crate_name()); - let primitive_assert = if let ReflectTypePath::Primitive(_) = path_to_type { + let primitive_assert = if let ReflectTypePath::Primitive(_) = type_path { Some(quote! { const _: () = { mod private_scope { // Compiles if it can be named when there are no imports. - type AssertIsPrimitive = #path_to_type; + type AssertIsPrimitive = #type_path; } }; }) @@ -186,9 +186,9 @@ pub(crate) fn impl_type_path( quote! { #primitive_assert - impl #impl_generics #bevy_reflect_path::TypePath for #path_to_type #ty_generics #where_reflect_clause { + impl #impl_generics #bevy_reflect_path::TypePath for #type_path #ty_generics #where_reflect_clause { fn type_path() -> &'static str { - #type_path + #long_type_path } fn short_type_path() -> &'static str { @@ -215,7 +215,7 @@ pub(crate) fn impl_typed( where_clause_options: &WhereClauseOptions, type_info_generator: proc_macro2::TokenStream, ) -> proc_macro2::TokenStream { - let path_to_type = meta.path_to_type(); + let type_path = meta.type_path(); let bevy_reflect_path = meta.bevy_reflect_path(); let type_info_cell = static_typed_cell(meta, TypedProperty::TypeInfo, type_info_generator); @@ -225,7 +225,7 @@ pub(crate) fn impl_typed( let where_reflect_clause = extend_where_clause(where_clause, where_clause_options); quote! { - impl #impl_generics #bevy_reflect_path::Typed for #path_to_type #ty_generics #where_reflect_clause { + impl #impl_generics #bevy_reflect_path::Typed for #type_path #ty_generics #where_reflect_clause { fn type_info() -> &'static #bevy_reflect_path::TypeInfo { #type_info_cell } 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 fb3e7348e78cb..b1328c66863d8 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs @@ -8,7 +8,7 @@ use quote::quote; /// Implements `GetTypeRegistration` and `Reflect` for the given type data. pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { let bevy_reflect_path = meta.bevy_reflect_path(); - let path_to_type = meta.path_to_type(); + let type_path = meta.type_path(); let hash_fn = meta.traits().get_hash_impl(bevy_reflect_path); let partial_eq_fn = meta.traits().get_partial_eq_impl(bevy_reflect_path); @@ -45,7 +45,7 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { #typed_impl - impl #impl_generics #bevy_reflect_path::Reflect for #path_to_type #ty_generics #where_reflect_clause { + 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::() diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs index 299e013b0b56b..e9f82fd1cb25e 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs @@ -296,7 +296,7 @@ pub fn impl_reflect_value(input: TokenStream) -> TokenStream { let def = parse_macro_input!(input as ReflectValueDef); let default_name = &def.type_path.segments.last().unwrap().ident; - let path_to_type = if def.type_path.leading_colon.is_none() && def.custom_path.is_none() { + let type_path = if def.type_path.leading_colon.is_none() && def.custom_path.is_none() { ReflectTypePath::Primitive(default_name) } else { ReflectTypePath::External { @@ -305,7 +305,7 @@ pub fn impl_reflect_value(input: TokenStream) -> TokenStream { } }; - let meta = ReflectMeta::new(path_to_type, &def.generics, def.traits.unwrap_or_default()); + let meta = ReflectMeta::new(type_path, &def.generics, def.traits.unwrap_or_default()); #[cfg(feature = "documentation")] let meta = meta.with_docs(documentation::Documentation::from_attributes(&def.attrs)); @@ -351,9 +351,9 @@ pub fn impl_reflect_struct(input: TokenStream) -> TokenStream { match derive_data { ReflectDerive::Struct(struct_data) => { - if !struct_data.meta().path_to_type().has_custom_path() { + if !struct_data.meta().type_path().has_custom_path() { return syn::Error::new( - struct_data.meta().path_to_type().span(), + struct_data.meta().type_path().span(), format!("a #[{TYPE_PATH_ATTRIBUTE_NAME} = \"...\"] attribute must be specified when using `impl_reflect_struct`") ) .into_compile_error() @@ -409,7 +409,7 @@ pub fn impl_from_reflect_value(input: TokenStream) -> TokenStream { let def = parse_macro_input!(input as ReflectValueDef); let default_name = &def.type_path.segments.last().unwrap().ident; - let path_to_type = if def.type_path.leading_colon.is_none() && def.custom_path.is_none() { + let type_path = if def.type_path.leading_colon.is_none() && def.custom_path.is_none() { ReflectTypePath::Primitive(default_name) } else { ReflectTypePath::External { @@ -419,7 +419,7 @@ pub fn impl_from_reflect_value(input: TokenStream) -> TokenStream { }; from_reflect::impl_value(&ReflectMeta::new( - path_to_type, + type_path, &def.generics, def.traits.unwrap_or_default(), )) @@ -429,7 +429,7 @@ pub fn impl_from_reflect_value(input: TokenStream) -> TokenStream { pub fn impl_type_path(input: TokenStream) -> TokenStream { let def = parse_macro_input!(input as NamedTypePathDef); - let (path_to_type, generics) = match def { + let (type_path, generics) = match def { NamedTypePathDef::External { ref path, custom_path, @@ -449,7 +449,7 @@ pub fn impl_type_path(input: TokenStream) -> TokenStream { } }; - let meta = ReflectMeta::new(path_to_type, &generics, ReflectTraits::default()); + let meta = ReflectMeta::new(type_path, &generics, ReflectTraits::default()); impls::impl_type_path(&meta, &WhereClauseOptions::type_path_bounds(&meta)).into() } diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/registration.rs b/crates/bevy_reflect/bevy_reflect_derive/src/registration.rs index 0944e350752c0..e4c8ec58773d0 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/registration.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/registration.rs @@ -13,7 +13,7 @@ pub(crate) fn impl_get_type_registration( where_clause_options: &WhereClauseOptions, serialization_denylist: Option<&BitSet>, ) -> proc_macro2::TokenStream { - let path_to_type = meta.path_to_type(); + let type_path = meta.type_path(); let bevy_reflect_path = meta.bevy_reflect_path(); let registration_data = meta.traits().idents(); let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl(); @@ -29,7 +29,7 @@ pub(crate) fn impl_get_type_registration( quote! { #[allow(unused_mut)] - impl #impl_generics #bevy_reflect_path::GetTypeRegistration for #path_to_type #ty_generics #where_reflect_clause { + impl #impl_generics #bevy_reflect_path::GetTypeRegistration for #type_path #ty_generics #where_reflect_clause { fn get_type_registration() -> #bevy_reflect_path::TypeRegistration { let mut registration = #bevy_reflect_path::TypeRegistration::of::(); registration.insert::<#bevy_reflect_path::ReflectFromPtr>(#bevy_reflect_path::FromType::::from_type()); From ee798d66804561ce5a093e22988c3945fbb960c0 Mon Sep 17 00:00:00 2001 From: radiish Date: Tue, 4 Apr 2023 11:34:08 +0000 Subject: [PATCH 43/52] generics on `ReflectTypePath`, prefix custom path --- crates/bevy_ecs/src/reflect.rs | 2 +- .../bevy_reflect_derive/src/derive_data.rs | 56 ++++++++++++------- .../bevy_reflect_derive/src/from_reflect.rs | 11 ++-- .../bevy_reflect_derive/src/impls/enums.rs | 2 +- .../bevy_reflect_derive/src/impls/structs.rs | 7 ++- .../src/impls/tuple_structs.rs | 7 ++- .../bevy_reflect_derive/src/impls/typed.rs | 6 +- .../bevy_reflect_derive/src/impls/values.rs | 2 +- .../bevy_reflect_derive/src/lib.rs | 38 ++++++------- .../bevy_reflect_derive/src/reflect_value.rs | 11 ++-- .../bevy_reflect_derive/src/registration.rs | 2 +- .../bevy_reflect_derive/src/utility.rs | 1 + crates/bevy_reflect/src/lib.rs | 2 +- 13 files changed, 88 insertions(+), 59 deletions(-) diff --git a/crates/bevy_ecs/src/reflect.rs b/crates/bevy_ecs/src/reflect.rs index 909bca75ce6cf..cde0bcd9774fb 100644 --- a/crates/bevy_ecs/src/reflect.rs +++ b/crates/bevy_ecs/src/reflect.rs @@ -407,7 +407,7 @@ impl FromType for ReflectResource { } } -impl_reflect_value!(Entity(Hash, PartialEq, Serialize, Deserialize) in bevy_ecs); +impl_reflect_value!((in bevy_ecs) Entity(Hash, PartialEq, Serialize, Deserialize)); impl_from_reflect_value!(Entity); #[derive(Clone)] 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 d5985f32f00f5..460550ca0a191 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs @@ -43,8 +43,6 @@ pub(crate) struct ReflectMeta<'a> { traits: ReflectTraits, /// The name of this type. type_path: ReflectTypePath<'a>, - /// The generics defined on this type. - generics: &'a Generics, /// A cached instance of the path to the `bevy_reflect` crate. bevy_reflect_path: Path, /// The documentation for this type, if any @@ -228,9 +226,10 @@ impl<'a> ReflectDerive<'a> { let type_path = ReflectTypePath::Internal { ident: &input.ident, custom_path, + generics: &input.generics, }; - let meta = ReflectMeta::new(type_path, &input.generics, traits); + let meta = ReflectMeta::new(type_path, traits); #[cfg(feature = "documentation")] let meta = meta.with_docs(doc); @@ -337,15 +336,10 @@ impl<'a> ReflectDerive<'a> { } impl<'a> ReflectMeta<'a> { - pub fn new( - type_path: ReflectTypePath<'a>, - generics: &'a Generics, - traits: ReflectTraits, - ) -> Self { + pub fn new(type_path: ReflectTypePath<'a>, traits: ReflectTraits) -> Self { Self { traits, type_path, - generics, bevy_reflect_path: utility::get_bevy_reflect_path(), #[cfg(feature = "documentation")] docs: Default::default(), @@ -364,15 +358,10 @@ impl<'a> ReflectMeta<'a> { } /// The name of this struct. - pub fn type_path(&self) -> &'a ReflectTypePath { + pub fn type_path(&self) -> &ReflectTypePath<'a> { &self.type_path } - /// The generics associated with this struct. - pub fn generics(&self) -> &'a Generics { - self.generics - } - /// The cached `bevy_reflect` path. pub fn bevy_reflect_path(&self) -> &Path { &self.bevy_reflect_path @@ -383,7 +372,8 @@ impl<'a> ReflectMeta<'a> { // Whether to use `GenericTypeCell` is not dependent on lifetimes // (which all have to be 'static anyway). !self - .generics + .type_path() + .generics() .params .iter() .all(|param| matches!(param, GenericParam::Lifetime(_))) @@ -610,6 +600,7 @@ pub(crate) enum ReflectTypePath<'a> { External { path: &'a Path, custom_path: Option, + generics: &'a Generics, }, /// The name of a type relative to its scope. /// @@ -622,6 +613,7 @@ pub(crate) enum ReflectTypePath<'a> { Internal { ident: &'a Ident, custom_path: Option, + generics: &'a Generics, }, /// Any [`syn::Type`] with only a defined `type_path` and `short_type_path`. #[allow(dead_code)] @@ -641,13 +633,17 @@ impl<'a> ReflectTypePath<'a> { /// [anonymous]: ReflectTypePath::Anonymous pub fn get_ident(&self) -> Option<&Ident> { match self { - Self::Internal { ident, custom_path } => Some( + Self::Internal { + ident, custom_path, .. + } => Some( custom_path .as_ref() .map(|path| &path.segments.last().unwrap().ident) .unwrap_or(ident), ), - Self::External { path, custom_path } => Some( + Self::External { + path, custom_path, .. + } => Some( &custom_path .as_ref() .unwrap_or(path) @@ -661,6 +657,26 @@ impl<'a> ReflectTypePath<'a> { } } + /// The generics associated with the type. + /// + /// Empty if [anonymous] or [primitive]. + /// + /// [primitive]: ReflectTypePath::Primitive + /// [anonymous]: ReflectTypePath::Anonymous + pub fn generics(&self) -> &'a Generics { + // Use a constant because we need to return a reference of at least 'a. + const EMPTY_GENERICS: &Generics = &Generics { + gt_token: None, + lt_token: None, + where_clause: None, + params: Punctuated::new(), + }; + match self { + Self::Internal { generics, .. } | Self::External { generics, .. } => generics, + _ => EMPTY_GENERICS, + } + } + /// Returns the path interpreted as a [`Path`]. /// /// Returns [`None`] if [anonymous], [primitive], @@ -671,7 +687,9 @@ impl<'a> ReflectTypePath<'a> { pub fn get_path(&self) -> Option<&Path> { match self { Self::Internal { custom_path, .. } => custom_path.as_ref(), - Self::External { path, custom_path } => Some(custom_path.as_ref().unwrap_or(path)), + Self::External { + path, custom_path, .. + } => Some(custom_path.as_ref().unwrap_or(path)), _ => None, } } 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 cca809cc8803c..e4cc7ef6c2de1 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs @@ -24,7 +24,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { let type_path = meta.type_path(); let bevy_reflect_path = meta.bevy_reflect_path(); - let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl(); + let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl(); TokenStream::from(quote! { impl #impl_generics #bevy_reflect_path::FromReflect for #type_path #ty_generics #where_clause { fn from_reflect(reflect: &dyn #bevy_reflect_path::Reflect) -> #FQOption { @@ -48,7 +48,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { } = get_variant_constructors(reflect_enum, &ref_value, false); let (impl_generics, ty_generics, where_clause) = - reflect_enum.meta().generics().split_for_impl(); + reflect_enum.meta().type_path().generics().split_for_impl(); TokenStream::from(quote! { impl #impl_generics #bevy_reflect_path::FromReflect for #enum_path #ty_generics #where_clause { fn from_reflect(#ref_value: &dyn #bevy_reflect_path::Reflect) -> #FQOption { @@ -116,8 +116,11 @@ fn impl_struct_internal(reflect_struct: &ReflectStruct, is_tuple: bool) -> Token ) }; - let (impl_generics, ty_generics, where_clause) = - reflect_struct.meta().generics().split_for_impl(); + let (impl_generics, ty_generics, where_clause) = reflect_struct + .meta() + .type_path() + .generics() + .split_for_impl(); // Add FromReflect bound for each active field let mut where_from_reflect_clause = if where_clause.is_some() { 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 b908a5f3b37dc..49f9847bcb7b5 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs @@ -93,7 +93,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream { .get_type_registration(&where_clause_options); let (impl_generics, ty_generics, where_clause) = - reflect_enum.meta().generics().split_for_impl(); + reflect_enum.meta().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/impls/structs.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs index 69f0bbc5275f5..b2930e61c6dfc 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/structs.rs @@ -96,8 +96,11 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream { let get_type_registration_impl = reflect_struct.get_type_registration(&where_clause_options); - let (impl_generics, ty_generics, where_clause) = - reflect_struct.meta().generics().split_for_impl(); + let (impl_generics, ty_generics, where_clause) = reflect_struct + .meta() + .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/impls/tuple_structs.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/tuple_structs.rs index cb92a255285d8..43691285651ce 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 @@ -87,8 +87,11 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream { let type_path_impl = impl_type_path(reflect_struct.meta(), &where_clause_options); - let (impl_generics, ty_generics, where_clause) = - reflect_struct.meta().generics().split_for_impl(); + let (impl_generics, ty_generics, where_clause) = reflect_struct + .meta() + .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/impls/typed.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs index a4315a3b7b6f3..9851f686449b1 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -39,7 +39,7 @@ fn combine_generics( /// [short path]: ReflectTypePath::non_generic_short_path fn type_path_generator(long_path: bool, meta: &ReflectMeta) -> proc_macro2::TokenStream { let type_path = meta.type_path(); - let generics = meta.generics(); + let generics = type_path.generics(); let bevy_reflect_path = meta.bevy_reflect_path(); if let ReflectTypePath::Primitive(name) = type_path { @@ -178,7 +178,7 @@ pub(crate) fn impl_type_path( None }; - let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl(); + 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); @@ -220,7 +220,7 @@ pub(crate) fn impl_typed( let type_info_cell = static_typed_cell(meta, TypedProperty::TypeInfo, type_info_generator); - let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl(); + 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/impls/values.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs index b1328c66863d8..806641901adf9 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/values.rs @@ -34,7 +34,7 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream { let type_path_impl = impl_type_path(meta, &where_clause_options); - let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl(); + 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); let get_type_registration_impl = meta.get_type_registration(&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 e9f82fd1cb25e..0529a53a43d28 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs @@ -38,7 +38,7 @@ use proc_macro::TokenStream; use quote::quote; use reflect_value::ReflectValueDef; use syn::spanned::Spanned; -use syn::{parse_macro_input, DeriveInput, Generics}; +use syn::{parse_macro_input, DeriveInput}; use type_path::NamedTypePathDef; use type_uuid::TypeUuidDef; use utility::WhereClauseOptions; @@ -302,10 +302,11 @@ pub fn impl_reflect_value(input: TokenStream) -> TokenStream { ReflectTypePath::External { path: &def.type_path, custom_path: def.custom_path.map(|path| path.into_path(default_name)), + generics: &def.generics, } }; - let meta = ReflectMeta::new(type_path, &def.generics, def.traits.unwrap_or_default()); + let meta = ReflectMeta::new(type_path, def.traits.unwrap_or_default()); #[cfg(feature = "documentation")] let meta = meta.with_docs(documentation::Documentation::from_attributes(&def.attrs)); @@ -409,47 +410,44 @@ pub fn impl_from_reflect_value(input: TokenStream) -> TokenStream { let def = parse_macro_input!(input as ReflectValueDef); let default_name = &def.type_path.segments.last().unwrap().ident; - let type_path = if def.type_path.leading_colon.is_none() && def.custom_path.is_none() { + let type_path = if def.type_path.leading_colon.is_none() + && def.custom_path.is_none() + && def.generics.params.is_empty() + { ReflectTypePath::Primitive(default_name) } else { ReflectTypePath::External { path: &def.type_path, custom_path: def.custom_path.map(|alias| alias.into_path(default_name)), + generics: &def.generics, } }; - from_reflect::impl_value(&ReflectMeta::new( - type_path, - &def.generics, - def.traits.unwrap_or_default(), - )) + from_reflect::impl_value(&ReflectMeta::new(type_path, def.traits.unwrap_or_default())) } #[proc_macro] pub fn impl_type_path(input: TokenStream) -> TokenStream { let def = parse_macro_input!(input as NamedTypePathDef); - let (type_path, generics) = match def { + let type_path = match def { NamedTypePathDef::External { ref path, custom_path, - generics, + ref generics, } => { let default_name = &path.segments.last().unwrap().ident; - ( - ReflectTypePath::External { - path, - custom_path: custom_path.map(|path| path.into_path(default_name)), - }, + + ReflectTypePath::External { + path, + custom_path: custom_path.map(|path| path.into_path(default_name)), generics, - ) - } - NamedTypePathDef::Primtive(ref ident) => { - (ReflectTypePath::Primitive(ident), Generics::default()) + } } + NamedTypePathDef::Primtive(ref ident) => ReflectTypePath::Primitive(ident), }; - let meta = ReflectMeta::new(type_path, &generics, ReflectTraits::default()); + let meta = ReflectMeta::new(type_path, ReflectTraits::default()); impls::impl_type_path(&meta, &WhereClauseOptions::type_path_bounds(&meta)).into() } diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs b/crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs index df08df2c45e26..b3d0f663a3a44 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs @@ -19,6 +19,9 @@ use syn::{parenthesized, Attribute, Generics, Path}; /// /// // With generics and where clause /// ::my_crate::foo::Bar where T1: Bar (TraitA, TraitB) +/// +/// // With a custom path (not with impl_from_reflect_value) +/// (in my_crate::bar) Bar(TraitA, TraitB) /// ``` pub(crate) struct ReflectValueDef { #[allow(dead_code)] @@ -32,6 +35,9 @@ pub(crate) struct ReflectValueDef { impl Parse for ReflectValueDef { fn parse(input: ParseStream) -> syn::Result { let attrs = input.call(Attribute::parse_outer)?; + + let custom_path = CustomPathDef::parse_parenthesized(input)?; + let type_path = Path::parse_mod_style(input)?; let mut generics = input.parse::()?; generics.where_clause = input.parse()?; @@ -42,13 +48,10 @@ impl Parse for ReflectValueDef { parenthesized!(content in input); traits = Some(content.parse::()?); } - - let custom_path = CustomPathDef::parse_parenthesized(input)?; - Ok(ReflectValueDef { attrs, type_path, - generics: Generics { ..generics }, + generics, traits, custom_path, }) diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/registration.rs b/crates/bevy_reflect/bevy_reflect_derive/src/registration.rs index e4c8ec58773d0..09bc88518dae0 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/registration.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/registration.rs @@ -16,7 +16,7 @@ pub(crate) fn impl_get_type_registration( let type_path = meta.type_path(); let bevy_reflect_path = meta.bevy_reflect_path(); let registration_data = meta.traits().idents(); - let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl(); + let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl(); let serialization_data = serialization_denylist.map(|denylist| { let denylist = denylist.into_iter(); quote! { diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs b/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs index 07006f333855b..9f00b37d33c80 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs @@ -80,6 +80,7 @@ impl WhereClauseOptions { let bevy_reflect_path = meta.bevy_reflect_path(); Self { parameter_types: meta + .type_path() .generics() .type_params() .map(|ty| ty.ident.clone()) diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index a14088bba9c2b..76406a87c2e9c 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -1482,7 +1482,7 @@ mod tests { struct SomePrimitive; impl_reflect_value!( /// Some primitive for which we have attributed custom documentation. - SomePrimitive in bevy_reflect::tests + (in bevy_reflect::tests) SomePrimitive ); let info = ::type_info(); From b10dbd295c23a070f7dac106cf48dfcde75cbc25 Mon Sep 17 00:00:00 2001 From: radiish Date: Tue, 4 Apr 2023 12:07:29 +0000 Subject: [PATCH 44/52] revert formatting of `Cargo.toml` so ci passes --- crates/bevy_reflect/Cargo.toml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/crates/bevy_reflect/Cargo.toml b/crates/bevy_reflect/Cargo.toml index 836dfc590ec73..240b839162042 100644 --- a/crates/bevy_reflect/Cargo.toml +++ b/crates/bevy_reflect/Cargo.toml @@ -18,9 +18,7 @@ documentation = ["bevy_reflect_derive/documentation"] [dependencies] # bevy -bevy_math = { path = "../bevy_math", version = "0.11.0-dev", features = [ - "serialize", -], optional = true } +bevy_math = { path = "../bevy_math", version = "0.11.0-dev", features = ["serialize"], optional = true } bevy_reflect_derive = { path = "bevy_reflect_derive", version = "0.11.0-dev" } bevy_utils = { path = "../bevy_utils", version = "0.11.0-dev" } bevy_ptr = { path = "../bevy_ptr", version = "0.11.0-dev" } @@ -32,11 +30,7 @@ parking_lot = "0.12.1" thiserror = "1.0" once_cell = "1.11" serde = "1" -smallvec = { version = "1.6", features = [ - "serde", - "union", - "const_generics", -], optional = true } +smallvec = { version = "1.6", features = ["serde", "union", "const_generics"], optional = true } glam = { version = "0.23", features = ["serde"], optional = true } [dev-dependencies] From 04b395b8c2da78bfec666ffe8bc56dabfcd5d5fe Mon Sep 17 00:00:00 2001 From: radiish Date: Tue, 4 Apr 2023 13:57:33 +0000 Subject: [PATCH 45/52] typecell in derive refactor --- .../bevy_reflect_derive/src/derive_data.rs | 139 +++++++++++++----- .../bevy_reflect_derive/src/impls/typed.rs | 100 +------------ 2 files changed, 112 insertions(+), 127 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 460550ca0a191..0c2d215c9b5e4 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs @@ -14,7 +14,7 @@ use syn::punctuated::Punctuated; use syn::spanned::Spanned; use syn::{ parse_str, Data, DeriveInput, Field, Fields, GenericParam, Generics, Ident, Lit, LitStr, Meta, - Path, PathSegment, Token, Type, Variant, + Path, PathSegment, Token, Type, TypeParam, Variant, }; pub(crate) enum ReflectDerive<'a> { @@ -367,18 +367,6 @@ impl<'a> ReflectMeta<'a> { &self.bevy_reflect_path } - /// Whether an impl using this [`ReflectMeta`] should be generic. - pub fn impl_is_generic(&self) -> bool { - // Whether to use `GenericTypeCell` is not dependent on lifetimes - // (which all have to be 'static anyway). - !self - .type_path() - .generics() - .params - .iter() - .all(|param| matches!(param, GenericParam::Lifetime(_))) - } - /// Returns the `GetTypeRegistration` impl as a `TokenStream`. pub fn get_type_registration( &self, @@ -561,13 +549,13 @@ impl<'a> EnumVariant<'a> { /// /// The type can always be reached with its [`ToTokens`] implementation. /// -/// The [`non_generic_type_path`], [`non_generic_short_path`], -/// [`type_ident`], [`crate_name`], and [`module_path`] methods -/// are equivalent to the methods on the `TypePath` trait. +/// The [`short_type_path`], [`type_ident`], [`crate_name`], and [`module_path`] methods +/// have corresponding methods on the `TypePath` trait. +/// [`long_type_path`] corresponds to the `type_path` method on `TypePath`. /// /// [deriving `TypePath`]: crate::derive_type_path -/// [`non_generic_type_path`]: ReflectTypePath::non_generic_type_path -/// [`non_generic_short_path`]: ReflectTypePath::non_generic_short_path +/// [`long_type_path`]: ReflectTypePath::long_type_path +/// [`short_type_path`]: ReflectTypePath::short_type_path /// [`type_ident`]: ReflectTypePath::type_ident /// [`crate_name`]: ReflectTypePath::crate_name /// [`module_path`]: ReflectTypePath::module_path @@ -677,6 +665,19 @@ impl<'a> ReflectTypePath<'a> { } } + /// Whether an implementation of `Typed` or `TypePath` should be generic. + /// + /// Returning true that it should use a `GenericTypeCell` in its implementation. + pub fn impl_is_generic(&self) -> bool { + // Whether to use `GenericTypeCell` is not dependent on lifetimes + // (which all have to be 'static anyway). + !self + .generics() + .params + .iter() + .all(|param| matches!(param, GenericParam::Lifetime(_))) + } + /// Returns the path interpreted as a [`Path`]. /// /// Returns [`None`] if [anonymous], [primitive], @@ -737,27 +738,75 @@ impl<'a> ReflectTypePath<'a> { } } - /// Returns tokens for a `&str` representing the "type path" of the type. + /// Combines type generics and const generics into one expression for a `String`. + /// + /// This string can be used with a `GenericTypePathCell` in a `TypePath` implementation. /// - /// Does not take generics into account. + /// The `ty_generics_fn` param dictates how expressions for `&str` are put into the string. + fn combine_generics( + ty_generic_fn: impl FnMut(&TypeParam) -> proc_macro2::TokenStream, + generics: &Generics, + ) -> proc_macro2::TokenStream { + let ty_generics = generics.type_params().map(ty_generic_fn); + + let const_generics = generics.const_params().map(|param| { + let ident = ¶m.ident; + let ty = ¶m.ty; + + quote! { + &<#ty as ::std::string::ToString>::to_string(&#ident) + } + }); + + let mut combined_params = ty_generics.chain(const_generics); + + combined_params + .next() + .into_iter() + .chain(combined_params.flat_map(|x| { + [ + quote! { + + ", " + + }, + x, + ] + })) + .collect() + } + + /// Returns tokens for a `&str` representing the "type path" of the type. /// /// For `::core::option::Option`, this is `"core::option::Option"`. - pub fn non_generic_type_path(&self) -> proc_macro2::TokenStream { + pub fn long_type_path(&self, bevy_reflect_path: &Path) -> proc_macro2::TokenStream { match self { Self::Primitive(ident) => { let lit = LitStr::new(&ident.to_string(), ident.span()); lit.to_token_stream() } Self::Anonymous { long_type_path, .. } => long_type_path.clone(), - _ => { + Self::Internal { generics, .. } | Self::External { generics, .. } => { let Some(ident) = self.get_ident() else { unreachable!() }; - - let module_path = self.module_path(); let ident = LitStr::new(&ident.to_string(), ident.span()); - quote! { - ::core::concat!(#module_path, "::", #ident) + let module_path = self.module_path(); + + if self.impl_is_generic() { + let generics = ReflectTypePath::combine_generics( + |TypeParam { ident, .. }| { + quote! { + <#ident as #bevy_reflect_path::TypePath>::type_path() + } + }, + generics, + ); + quote! { + ::std::string::ToString::to_string(::core::concat!(#module_path, "::", #ident, "<")) + #generics + ">" + } + } else { + quote! { + ::core::concat!(#module_path, "::", #ident) + } } } } @@ -765,20 +814,40 @@ impl<'a> ReflectTypePath<'a> { /// Returns tokens for a `&str` representing the "short path" of the type. /// - /// Does not take generics into account. - /// /// For `::core::option::Option`, this is `"Option"`. - pub fn non_generic_short_path(&self) -> proc_macro2::TokenStream { - if let Some(ident) = self.get_ident() { - let ident = LitStr::new(&ident.to_string(), ident.span()); - return ident.to_token_stream(); - } - + pub fn short_type_path(&self, bevy_reflect_path: &Path) -> proc_macro2::TokenStream { match self { Self::Anonymous { short_type_path, .. } => short_type_path.clone(), - _ => unreachable!(), + Self::Primitive(ident) => { + let lit = LitStr::new(&ident.to_string(), ident.span()); + lit.to_token_stream() + } + Self::External { generics, .. } | Self::Internal { generics, .. } => { + let Some(ident) = self.get_ident() else { + unreachable!() + }; + let ident = LitStr::new(&ident.to_string(), ident.span()); + + if self.impl_is_generic() { + let generics = ReflectTypePath::combine_generics( + |TypeParam { ident, .. }| { + quote! { + <#ident as #bevy_reflect_path::TypePath>::short_type_path() + } + }, + generics, + ); + quote! { + ::std::string::ToString::to_string(::core::concat!(#ident, "<")) + #generics + ">" + } + } else { + quote! { + #ident + } + } + } } } 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 9851f686449b1..ef160e047200d 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -1,103 +1,19 @@ use crate::utility::{extend_where_clause, WhereClauseOptions}; use quote::{quote, ToTokens}; -use syn::Generics; -use syn::{spanned::Spanned, LitStr}; use crate::{ derive_data::{ReflectMeta, ReflectTypePath}, utility::wrap_in_option, }; -fn combine_generics( - ty_generics: Vec, - generics: &Generics, -) -> impl Iterator { - let const_generic_strings: Vec<_> = generics - .const_params() - .map(|param| { - let ident = ¶m.ident; - let ty = ¶m.ty; - - quote! { - &<#ty as ::std::string::ToString>::to_string(&#ident) - } - }) - .collect(); - - let mut generics = ty_generics - .into_iter() - .chain(const_generic_strings.into_iter()) - .flat_map(|t| [", ".to_token_stream(), t]); - generics.next(); // Skip first comma. - generics -} - -/// Returns an expression for a `&'static str`, -/// representing either a [long path] or [short path]. -/// -/// [long path]: ReflectTypePath::non_generic_type_path -/// [short path]: ReflectTypePath::non_generic_short_path -fn type_path_generator(long_path: bool, meta: &ReflectMeta) -> proc_macro2::TokenStream { - let type_path = meta.type_path(); - let generics = type_path.generics(); - let bevy_reflect_path = meta.bevy_reflect_path(); - - if let ReflectTypePath::Primitive(name) = type_path { - let name = LitStr::new(&name.to_string(), name.span()); - return quote!(#name); - } - - let ty_generic_paths: Vec<_> = generics - .type_params() - .map(|param| { - let ident = ¶m.ident; - quote! { - <#ident as #bevy_reflect_path::TypePath> - } - }) - .collect(); - - let (path, ty_generics) = if long_path { - let ty_generics: Vec<_> = ty_generic_paths - .iter() - .map(|cell| { - quote! { - #cell::type_path() - } - }) - .collect(); - - (type_path.non_generic_type_path(), ty_generics) - } else { - let ty_generics: Vec<_> = ty_generic_paths - .iter() - .map(|cell| { - quote! { - #cell::short_type_path() - } - }) - .collect(); - - (type_path.non_generic_short_path(), ty_generics) - }; - - let generics = combine_generics(ty_generics, generics); - - quote! { - ::std::borrow::ToOwned::to_owned(::core::concat!(#path, "<")) - #(+ #generics)* - + ">" - } -} - -/// Returns an expression for a `NonGenericTypeCell` or `GenericTypeCell` to contain `'static` references. +/// Returns an expression for a `NonGenericTypeCell` or `GenericTypeCell` to generate `'static` references. fn static_typed_cell( meta: &ReflectMeta, property: TypedProperty, generator: proc_macro2::TokenStream, ) -> proc_macro2::TokenStream { let bevy_reflect_path = meta.bevy_reflect_path(); - if meta.impl_is_generic() { + if meta.type_path().impl_is_generic() { let cell_type = match property { TypedProperty::TypePath => quote!(GenericTypePathCell), TypedProperty::TypeInfo => quote!(GenericTypeInfoCell), @@ -112,7 +28,7 @@ fn static_typed_cell( } else { let cell_type = match property { TypedProperty::TypePath => unreachable!( - "cannot have a non-generic type path cell. use string literals instead." + "Cannot have a non-generic type path cell. Use string literals and core::concat instead." ), TypedProperty::TypeInfo => quote!(NonGenericTypeInfoCell), }; @@ -139,16 +55,16 @@ pub(crate) fn impl_type_path( let type_path = meta.type_path(); let bevy_reflect_path = meta.bevy_reflect_path(); - let (long_type_path, short_type_path) = if meta.impl_is_generic() { + let (long_type_path, short_type_path) = if type_path.impl_is_generic() { let long_path_cell = static_typed_cell( meta, TypedProperty::TypePath, - type_path_generator(true, meta), + type_path.long_type_path(bevy_reflect_path), ); let short_path_cell = static_typed_cell( meta, TypedProperty::TypePath, - type_path_generator(false, meta), + type_path.short_type_path(bevy_reflect_path), ); ( long_path_cell.to_token_stream(), @@ -156,8 +72,8 @@ pub(crate) fn impl_type_path( ) } else { ( - type_path.non_generic_type_path(), - type_path.non_generic_short_path(), + type_path.long_type_path(bevy_reflect_path), + type_path.short_type_path(bevy_reflect_path), ) }; From fd02571e843298364088aa550703c8ff8b6f4595 Mon Sep 17 00:00:00 2001 From: radiish Date: Tue, 4 Apr 2023 15:08:08 +0000 Subject: [PATCH 46/52] introduce `StringExpr` --- .../bevy_reflect_derive/src/derive_data.rs | 145 ++++++++---------- .../bevy_reflect_derive/src/impls/typed.rs | 24 +-- .../bevy_reflect_derive/src/utility.rs | 97 +++++++++++- 3 files changed, 171 insertions(+), 95 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 0c2d215c9b5e4..e12c4cc050f7b 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs @@ -2,7 +2,7 @@ use crate::container_attributes::ReflectTraits; use crate::field_attributes::{parse_field_attrs, ReflectFieldAttr}; use crate::fq_std::{FQAny, FQDefault, FQSend, FQSync}; use crate::type_path::parse_path_no_leading_colon; -use crate::utility::{members_to_serialization_denylist, WhereClauseOptions}; +use crate::utility::{members_to_serialization_denylist, StringExpr, WhereClauseOptions}; use bit_set::BitSet; use quote::{quote, ToTokens}; @@ -608,8 +608,8 @@ pub(crate) enum ReflectTypePath<'a> { // Not currently used but may be useful in the future due to its generality. Anonymous { qualified_type: Type, - long_type_path: proc_macro2::TokenStream, - short_type_path: proc_macro2::TokenStream, + long_type_path: StringExpr, + short_type_path: StringExpr, }, } @@ -708,54 +708,53 @@ impl<'a> ReflectTypePath<'a> { } } - /// Returns tokens for a `&str` representing the name of the type's crate. + /// Returns a [`StringExpr`] representing the name of the type's crate. /// /// Returns [`None`] if the type is [primitive] or [anonymous]. /// - /// For non-aliased [internal] paths this is created from [`module_path`]. + /// For non-customised [internal] paths this is created from [`module_path`]. /// /// For `::core::option::Option`, this is `"core"`. /// /// [primitive]: ReflectTypePath::Primitive /// [anonymous]: ReflectTypePath::Anonymous /// [internal]: ReflectTypePath::Internal - pub fn crate_name(&self) -> Option { + pub fn crate_name(&self) -> Option { if let Some(path) = self.get_path() { - let crate_name = path.segments.first().unwrap().ident.to_string(); - let crate_name = LitStr::new(&crate_name, path.span()); - return Some(quote!(#crate_name)); + let crate_name = &path.segments.first().unwrap().ident; + return Some(StringExpr::from_ident(crate_name)); } match self { - Self::Internal { .. } => Some(quote! { + Self::Internal { .. } => Some(StringExpr::Borrowed(quote! { ::core::module_path!() .split(':') .next() .unwrap() - }), + })), Self::External { .. } => unreachable!(), _ => None, } } - /// Combines type generics and const generics into one expression for a `String`. + /// Combines type generics and const generics into one [`StringExpr`]. /// /// This string can be used with a `GenericTypePathCell` in a `TypePath` implementation. /// - /// The `ty_generics_fn` param dictates how expressions for `&str` are put into the string. - fn combine_generics( - ty_generic_fn: impl FnMut(&TypeParam) -> proc_macro2::TokenStream, + /// The `ty_generics_fn` param maps [`TypeParam`]s to [`StringExpr`]s. + fn reduce_generics( generics: &Generics, - ) -> proc_macro2::TokenStream { + ty_generic_fn: impl FnMut(&TypeParam) -> StringExpr, + ) -> StringExpr { let ty_generics = generics.type_params().map(ty_generic_fn); let const_generics = generics.const_params().map(|param| { let ident = ¶m.ident; let ty = ¶m.ty; - quote! { - &<#ty as ::std::string::ToString>::to_string(&#ident) - } + StringExpr::Owned(quote! { + <#ty as ::std::string::ToString>::to_string(&#ident) + }) }); let mut combined_params = ty_generics.chain(const_generics); @@ -763,107 +762,94 @@ impl<'a> ReflectTypePath<'a> { combined_params .next() .into_iter() - .chain(combined_params.flat_map(|x| { - [ - quote! { - + ", " + - }, - x, - ] - })) + .chain(combined_params.flat_map(|x| [StringExpr::Const(quote!(", ")), x])) .collect() } - /// Returns tokens for a `&str` representing the "type path" of the type. + /// Returns a [`StringExpr`] representing the "type path" of the type. /// /// For `::core::option::Option`, this is `"core::option::Option"`. - pub fn long_type_path(&self, bevy_reflect_path: &Path) -> proc_macro2::TokenStream { + pub fn long_type_path(&self, bevy_reflect_path: &Path) -> StringExpr { match self { - Self::Primitive(ident) => { - let lit = LitStr::new(&ident.to_string(), ident.span()); - lit.to_token_stream() - } + Self::Primitive(ident) => StringExpr::from_ident(ident), Self::Anonymous { long_type_path, .. } => long_type_path.clone(), Self::Internal { generics, .. } | Self::External { generics, .. } => { - let Some(ident) = self.get_ident() else { - unreachable!() - }; - let ident = LitStr::new(&ident.to_string(), ident.span()); - let module_path = self.module_path(); + let ident = self.type_ident().unwrap(); + let module_path = self.module_path().unwrap(); if self.impl_is_generic() { - let generics = ReflectTypePath::combine_generics( + let generics = ReflectTypePath::reduce_generics( + generics, |TypeParam { ident, .. }| { - quote! { + StringExpr::Borrowed(quote! { <#ident as #bevy_reflect_path::TypePath>::type_path() - } + }) }, - generics, ); - quote! { - ::std::string::ToString::to_string(::core::concat!(#module_path, "::", #ident, "<")) + #generics + ">" - } + + StringExpr::from_iter([ + module_path, + StringExpr::from_str("::"), + ident, + StringExpr::from_str("<"), + generics, + StringExpr::from_str(">"), + ]) } else { - quote! { - ::core::concat!(#module_path, "::", #ident) - } + StringExpr::from_iter([module_path, StringExpr::from_str("::"), ident]) } } } } - /// Returns tokens for a `&str` representing the "short path" of the type. + /// Returns a [`StringExpr`] representing the "short path" of the type. /// /// For `::core::option::Option`, this is `"Option"`. - pub fn short_type_path(&self, bevy_reflect_path: &Path) -> proc_macro2::TokenStream { + pub fn short_type_path(&self, bevy_reflect_path: &Path) -> StringExpr { match self { Self::Anonymous { short_type_path, .. } => short_type_path.clone(), - Self::Primitive(ident) => { - let lit = LitStr::new(&ident.to_string(), ident.span()); - lit.to_token_stream() - } + Self::Primitive(ident) => StringExpr::from_ident(ident), Self::External { generics, .. } | Self::Internal { generics, .. } => { - let Some(ident) = self.get_ident() else { - unreachable!() - }; - let ident = LitStr::new(&ident.to_string(), ident.span()); + let ident = self.type_ident().unwrap(); if self.impl_is_generic() { - let generics = ReflectTypePath::combine_generics( + let generics = ReflectTypePath::reduce_generics( + generics, |TypeParam { ident, .. }| { - quote! { + StringExpr::Borrowed(quote! { <#ident as #bevy_reflect_path::TypePath>::short_type_path() - } + }) }, - generics, ); - quote! { - ::std::string::ToString::to_string(::core::concat!(#ident, "<")) + #generics + ">" - } + + StringExpr::from_iter([ + ident, + StringExpr::from_str("<"), + generics, + StringExpr::from_str(">"), + ]) } else { - quote! { - #ident - } + ident } } } } - /// Returns tokens for a string literal representing the path to the module + /// Returns a [`StringExpr`] representing the path to the module /// that the type is in. /// /// Returns [`None`] if the type is [primitive] or [anonymous]. /// - /// For non-aliased [internal] paths this is created from [`module_path`]. + /// For non-customised [internal] paths this is created from [`module_path`]. /// /// For `::core::option::Option`, this is `"core::option"`. /// /// [primitive]: ReflectTypePath::Primitive /// [anonymous]: ReflectTypePath::Anonymous /// [internal]: ReflectTypePath::Internal - pub fn module_path(&self) -> Option { + pub fn module_path(&self) -> Option { if let Some(path) = self.get_path() { let path = path .segments @@ -874,21 +860,21 @@ impl<'a> ReflectTypePath<'a> { .unwrap(); let path = LitStr::new(&path, path.span()); - return Some(quote! { + return Some(StringExpr::Const(quote! { #path - }); + })); } match self { - Self::Internal { .. } => Some(quote! { + Self::Internal { .. } => Some(StringExpr::Const(quote! { ::core::module_path!() - }), + })), Self::External { .. } => unreachable!(), _ => None, } } - /// Returns tokens for a string literal representing the type's final ident. + /// Returns a [`StringExpr`] representing the type's final ident. /// /// Returns [`None`] if the type is [anonymous]. /// @@ -897,11 +883,8 @@ impl<'a> ReflectTypePath<'a> { /// For `::core::option::Option`, this is `"Option"`. /// /// [anonymous]: ReflectTypePath::Anonymous - pub fn type_ident(&self) -> Option { - self.get_ident().map(|ident| { - let ident = LitStr::new(&ident.to_string(), ident.span()); - ident.to_token_stream() - }) + pub fn type_ident(&self) -> Option { + self.get_ident().map(StringExpr::from_ident) } } 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 ef160e047200d..290154692c496 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls/typed.rs @@ -1,4 +1,4 @@ -use crate::utility::{extend_where_clause, WhereClauseOptions}; +use crate::utility::{extend_where_clause, StringExpr, WhereClauseOptions}; use quote::{quote, ToTokens}; use crate::{ @@ -7,7 +7,7 @@ use crate::{ }; /// Returns an expression for a `NonGenericTypeCell` or `GenericTypeCell` to generate `'static` references. -fn static_typed_cell( +fn static_type_cell( meta: &ReflectMeta, property: TypedProperty, generator: proc_macro2::TokenStream, @@ -56,15 +56,15 @@ pub(crate) fn impl_type_path( let bevy_reflect_path = meta.bevy_reflect_path(); let (long_type_path, short_type_path) = if type_path.impl_is_generic() { - let long_path_cell = static_typed_cell( + let long_path_cell = static_type_cell( meta, TypedProperty::TypePath, - type_path.long_type_path(bevy_reflect_path), + type_path.long_type_path(bevy_reflect_path).into_owned(), ); - let short_path_cell = static_typed_cell( + let short_path_cell = static_type_cell( meta, TypedProperty::TypePath, - type_path.short_type_path(bevy_reflect_path), + type_path.short_type_path(bevy_reflect_path).into_owned(), ); ( long_path_cell.to_token_stream(), @@ -72,14 +72,14 @@ pub(crate) fn impl_type_path( ) } else { ( - type_path.long_type_path(bevy_reflect_path), - type_path.short_type_path(bevy_reflect_path), + type_path.long_type_path(bevy_reflect_path).into_borrowed(), + type_path.short_type_path(bevy_reflect_path).into_borrowed(), ) }; - let type_ident = wrap_in_option(type_path.type_ident()); - let module_path = wrap_in_option(type_path.module_path()); - let crate_name = wrap_in_option(type_path.crate_name()); + let type_ident = wrap_in_option(type_path.type_ident().map(StringExpr::into_borrowed)); + let module_path = wrap_in_option(type_path.module_path().map(StringExpr::into_borrowed)); + let crate_name = wrap_in_option(type_path.crate_name().map(StringExpr::into_borrowed)); let primitive_assert = if let ReflectTypePath::Primitive(_) = type_path { Some(quote! { @@ -134,7 +134,7 @@ pub(crate) fn impl_typed( let type_path = meta.type_path(); let bevy_reflect_path = meta.bevy_reflect_path(); - let type_info_cell = static_typed_cell(meta, TypedProperty::TypeInfo, type_info_generator); + let type_info_cell = static_type_cell(meta, TypedProperty::TypeInfo, type_info_generator); let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl(); diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs b/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs index 0a09a8b5cca2a..90d2285c1e500 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs @@ -4,8 +4,8 @@ use crate::{derive_data::ReflectMeta, field_attributes::ReflectIgnoreBehavior, f use bevy_macro_utils::BevyManifest; use bit_set::BitSet; use proc_macro2::{Ident, Span}; -use quote::quote; -use syn::{Member, Path, Type, WhereClause}; +use quote::{quote, ToTokens}; +use syn::{LitStr, Member, Path, Type, WhereClause}; /// Returns the correct path for `bevy_reflect`. pub(crate) fn get_bevy_reflect_path() -> Path { @@ -251,3 +251,96 @@ pub(crate) fn wrap_in_option(tokens: Option) -> proc_m }, } } + +/// Contains tokens representing different kinds of string. +#[derive(Clone)] +pub(crate) enum StringExpr { + /// A string that is valid at compile time. + /// + /// This is either a string literal like `"mystring"`, + /// or a string created by a macro like [`module_path`] + /// or [`concat`]. + Const(proc_macro2::TokenStream), + /// A [string slice](str) that is borrowed for a `'static` lifetime. + Borrowed(proc_macro2::TokenStream), + /// An [owned string](String). + Owned(proc_macro2::TokenStream), +} + +impl StringExpr { + /// Creates a [`StringExpr`] by interpreting an [`Ident`] as a [`struct@LitStr`]. + pub fn from_ident(ident: &Ident) -> Self { + Self::Const(LitStr::new(&ident.to_string(), ident.span()).into_token_stream()) + } + + /// Creates a [`StringExpr`] by interpreting a [string slice][str] as a [`struct@LitStr`]. + pub fn from_str(string: &str) -> Self { + Self::Const(string.into_token_stream()) + } + + /// Returns tokens for an [owned string](String). + /// + /// The returned expression will allocate unless the [`StringExpr`] is [already owned]. + /// + /// [already owned]: StringExpr::Owned + pub fn into_owned(self) -> proc_macro2::TokenStream { + match self { + Self::Const(tokens) | Self::Borrowed(tokens) => quote! { + ::std::string::ToString::to_string(#tokens) + }, + Self::Owned(owned) => owned, + } + } + + /// Returns tokens for a statically borrowed [string slice](str). + pub fn into_borrowed(self) -> proc_macro2::TokenStream { + match self { + Self::Const(tokens) | Self::Borrowed(tokens) => tokens, + Self::Owned(owned) => quote! { + &#owned + }, + } + } + + /// Appends a [`StringExpr`] to another. + /// + /// If both expressions are [`StringExpr::Const`] this will use [`concat`] to merge them. + pub fn appended_by(mut self, other: StringExpr) -> Self { + if let Self::Const(tokens) = self { + if let Self::Const(more) = other { + return Self::Const(quote! { + ::core::concat!(#tokens, #more) + }); + } + self = Self::Const(tokens); + } + + let owned = self.into_owned(); + let borrowed = other.into_borrowed(); + Self::Owned(quote! { + #owned + #borrowed + }) + } +} + +impl Default for StringExpr { + fn default() -> Self { + StringExpr::Const("".to_string().to_token_stream()) + } +} + +impl FromIterator for StringExpr { + fn from_iter>(iter: T) -> Self { + let mut iter = iter.into_iter(); + match iter.next() { + Some(mut expr) => { + while let Some(next) = iter.next() { + expr = expr.appended_by(next); + } + + expr + } + None => Default::default(), + } + } +} From 8003efe49d89a3ad5ac82319ea7af0d37b037ee2 Mon Sep 17 00:00:00 2001 From: radiish Date: Tue, 4 Apr 2023 15:26:06 +0000 Subject: [PATCH 47/52] appease clippy --- 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 90d2285c1e500..38710ab135d4c 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs @@ -334,7 +334,7 @@ impl FromIterator for StringExpr { let mut iter = iter.into_iter(); match iter.next() { Some(mut expr) => { - while let Some(next) = iter.next() { + for next in iter { expr = expr.appended_by(next); } From 1010ed960376a3a4c3a4dc985020901793c1eeb9 Mon Sep 17 00:00:00 2001 From: radiish Date: Sun, 23 Apr 2023 10:19:57 +0000 Subject: [PATCH 48/52] review feedback + hashbrown fix --- crates/bevy_pbr/src/material.rs | 4 +- .../bevy_reflect_derive/src/derive_data.rs | 78 ++++++++--------- .../bevy_reflect_derive/src/lib.rs | 85 +++++++++++++++++-- .../bevy_reflect_derive/src/type_path.rs | 8 +- .../bevy_reflect_derive/src/utility.rs | 22 +++-- crates/bevy_reflect/src/enums/mod.rs | 2 +- crates/bevy_reflect/src/impls/smallvec.rs | 2 +- crates/bevy_reflect/src/impls/std.rs | 34 ++++---- crates/bevy_reflect/src/reflect.rs | 13 +-- crates/bevy_reflect/src/type_path.rs | 48 ++++++++--- examples/reflection/generic_reflection.rs | 2 +- 11 files changed, 196 insertions(+), 102 deletions(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 9adb16b6fddf0..4f6da2869a329 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -105,9 +105,7 @@ use std::marker::PhantomData; /// @group(1) @binding(2) /// var color_sampler: sampler; /// ``` -pub trait Material: - AsBindGroup + Send + Sync + Clone + TypeUuid + TypePath + Sized + 'static -{ +pub trait Material: AsBindGroup + Send + Sync + Clone + TypeUuid + TypePath + Sized { /// Returns this material's vertex shader. If [`ShaderRef::Default`] is returned, the default mesh vertex shader /// will be used. fn vertex_shader() -> ShaderRef { 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 e12c4cc050f7b..8f8a4b07932b5 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs @@ -213,14 +213,18 @@ impl<'a> ReflectDerive<'a> { _ => continue, } } - if let Some(path) = &mut custom_path { - let ident = custom_type_name.unwrap_or_else(|| input.ident.clone()); - path.segments.push(PathSegment::from(ident)); - } else if let Some(name) = custom_type_name { - return Err(syn::Error::new( - name.span(), - format!("cannot use `#[{TYPE_NAME_ATTRIBUTE_NAME} = \"...\"]` without a `#[{TYPE_PATH_ATTRIBUTE_NAME} = \"...\"]` attribute."), - )); + match (&mut custom_path, custom_type_name) { + (Some(path), custom_type_name) => { + let ident = custom_type_name.unwrap_or_else(|| input.ident.clone()); + path.segments.push(PathSegment::from(ident)); + } + (None, Some(name)) => { + return Err(syn::Error::new( + name.span(), + format!("cannot use `#[{TYPE_NAME_ATTRIBUTE_NAME} = \"...\"]` without a `#[{TYPE_PATH_ATTRIBUTE_NAME} = \"...\"]` attribute."), + )); + } + _ => (), } let type_path = ReflectTypePath::Internal { @@ -565,7 +569,6 @@ impl<'a> EnumVariant<'a> { /// ```rust,ignore /// # use syn::parse_quote; /// # use bevy_reflect_derive::ReflectTypePath; -/// /// let path: syn::Path = parse_quote!(::core::marker::PhantomData)?; /// /// let type_path = ReflectTypePath::External { @@ -575,7 +578,6 @@ impl<'a> EnumVariant<'a> { /// /// // Eqivalent to "core::marker". /// let module_path = type_path.module_path(); -/// /// # Ok::<(), syn::Error>(()) /// ``` /// @@ -714,7 +716,7 @@ impl<'a> ReflectTypePath<'a> { /// /// For non-customised [internal] paths this is created from [`module_path`]. /// - /// For `::core::option::Option`, this is `"core"`. + /// For `Option`, this is `"core"`. /// /// [primitive]: ReflectTypePath::Primitive /// [anonymous]: ReflectTypePath::Anonymous @@ -722,7 +724,7 @@ impl<'a> ReflectTypePath<'a> { pub fn crate_name(&self) -> Option { if let Some(path) = self.get_path() { let crate_name = &path.segments.first().unwrap().ident; - return Some(StringExpr::from_ident(crate_name)); + return Some(StringExpr::from(crate_name)); } match self { @@ -741,37 +743,37 @@ impl<'a> ReflectTypePath<'a> { /// /// This string can be used with a `GenericTypePathCell` in a `TypePath` implementation. /// - /// The `ty_generics_fn` param maps [`TypeParam`]s to [`StringExpr`]s. + /// The `ty_generic_fn` param maps [`TypeParam`]s to [`StringExpr`]s. fn reduce_generics( generics: &Generics, - ty_generic_fn: impl FnMut(&TypeParam) -> StringExpr, + mut ty_generic_fn: impl FnMut(&TypeParam) -> StringExpr, ) -> StringExpr { - let ty_generics = generics.type_params().map(ty_generic_fn); - - let const_generics = generics.const_params().map(|param| { - let ident = ¶m.ident; - let ty = ¶m.ty; - - StringExpr::Owned(quote! { - <#ty as ::std::string::ToString>::to_string(&#ident) - }) + let mut params = generics.params.iter().filter_map(|param| match param { + GenericParam::Type(type_param) => Some(ty_generic_fn(type_param)), + GenericParam::Const(const_param) => { + let ident = &const_param.ident; + let ty = &const_param.ty; + + Some(StringExpr::Owned(quote! { + <#ty as ::std::string::ToString>::to_string(&#ident) + })) + } + GenericParam::Lifetime(_) => None, }); - let mut combined_params = ty_generics.chain(const_generics); - - combined_params + params .next() .into_iter() - .chain(combined_params.flat_map(|x| [StringExpr::Const(quote!(", ")), x])) + .chain(params.flat_map(|x| [StringExpr::from_str(", "), x])) .collect() } /// Returns a [`StringExpr`] representing the "type path" of the type. /// - /// For `::core::option::Option`, this is `"core::option::Option"`. + /// For `Option`, this is `"core::option::Option"`. pub fn long_type_path(&self, bevy_reflect_path: &Path) -> StringExpr { match self { - Self::Primitive(ident) => StringExpr::from_ident(ident), + Self::Primitive(ident) => StringExpr::from(ident), Self::Anonymous { long_type_path, .. } => long_type_path.clone(), Self::Internal { generics, .. } | Self::External { generics, .. } => { let ident = self.type_ident().unwrap(); @@ -804,13 +806,13 @@ impl<'a> ReflectTypePath<'a> { /// Returns a [`StringExpr`] representing the "short path" of the type. /// - /// For `::core::option::Option`, this is `"Option"`. + /// For `Option`, this is `"Option"`. pub fn short_type_path(&self, bevy_reflect_path: &Path) -> StringExpr { match self { Self::Anonymous { short_type_path, .. } => short_type_path.clone(), - Self::Primitive(ident) => StringExpr::from_ident(ident), + Self::Primitive(ident) => StringExpr::from(ident), Self::External { generics, .. } | Self::Internal { generics, .. } => { let ident = self.type_ident().unwrap(); @@ -844,14 +846,14 @@ impl<'a> ReflectTypePath<'a> { /// /// For non-customised [internal] paths this is created from [`module_path`]. /// - /// For `::core::option::Option`, this is `"core::option"`. + /// For `Option`, this is `"core::option"`. /// /// [primitive]: ReflectTypePath::Primitive /// [anonymous]: ReflectTypePath::Anonymous /// [internal]: ReflectTypePath::Internal pub fn module_path(&self) -> Option { if let Some(path) = self.get_path() { - let path = path + let path_string = path .segments .pairs() .take(path.segments.len() - 1) @@ -859,10 +861,8 @@ impl<'a> ReflectTypePath<'a> { .reduce(|path, ident| path + "::" + &ident) .unwrap(); - let path = LitStr::new(&path, path.span()); - return Some(StringExpr::Const(quote! { - #path - })); + let path_lit = LitStr::new(&path_string, path.span()); + return Some(StringExpr::from_lit(&path_lit)); } match self { @@ -880,11 +880,11 @@ impl<'a> ReflectTypePath<'a> { /// /// This is not necessarily a valid qualified path to the type. /// - /// For `::core::option::Option`, this is `"Option"`. + /// For `Option`, this is `"Option"`. /// /// [anonymous]: ReflectTypePath::Anonymous pub fn type_ident(&self) -> Option { - self.get_ident().map(StringExpr::from_ident) + self.get_ident().map(StringExpr::from) } } diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs index 0529a53a43d28..60b17d5d85ba7 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/lib.rs @@ -59,6 +59,8 @@ pub(crate) static TYPE_NAME_ATTRIBUTE_NAME: &str = "type_name"; /// This macro comes with some helper attributes that can be added to the container item /// in order to provide additional functionality or alter the generated implementations. /// +/// In addition to those listed, this macro can also use the attributes for [`TypePath`] derives. +/// /// ## `#[reflect(Ident)]` /// /// The `#[reflect(Ident)]` attribute is used to add type data registrations to the `GetTypeRegistration` @@ -194,6 +196,21 @@ pub fn derive_from_reflect(input: TokenStream) -> TokenStream { } } +/// Derives the `TypePath` trait, providing a stable alternative to [`std::any::type_name`]. +/// +/// # Container Attributes +/// +/// ## `#[type_path = "my_crate::foo"]` +/// +/// Optionally specifies a custom module path to use instead of [`module_path`]. +/// +/// This path does not include the final identifier. +/// +/// ## `#[type_name = "RenamedType"]` +/// +/// Optionally specifies a new terminating identifier for `TypePath`. +/// +/// To use this attribute, `#[type_path = "..."]` must also be specified. #[proc_macro_derive(TypePath, attributes(type_path, type_name))] pub fn derive_type_path(input: TokenStream) -> TokenStream { let ast = parse_macro_input!(input as DeriveInput); @@ -275,19 +292,28 @@ pub fn reflect_trait(args: TokenStream, input: TokenStream) -> TokenStream { /// The only reason for this macro's existence is so that `bevy_reflect` can easily implement the reflection traits /// on primitives and other Rust types internally. /// +/// Since this macro also implements `TypePath`, the type path must be explicit. +/// See [`impl_type_path!`] for the exact syntax. +/// /// # Examples /// /// Types can be passed with or without registering type data: /// /// ```ignore -/// impl_reflect_value!(foo); -/// impl_reflect_value!(bar(Debug, Default, Serialize, Deserialize)); +/// impl_reflect_value!(::my_crate::Foo); +/// impl_reflect_value!(::my_crate::Bar(Debug, Default, Serialize, Deserialize)); /// ``` /// /// Generic types can also specify their parameters and bounds: /// /// ```ignore -/// impl_reflect_value!(foo where T1: Bar (Default, Serialize, Deserialize)); +/// impl_reflect_value!(::my_crate::Foo where T1: Bar (Default, Serialize, Deserialize)); +/// ``` +/// +/// Custom type paths can be specified: +/// +/// ```ignore +/// impl_reflect_value!((in not_my_crate as NotFoo) Foo(Debug, Default)); /// ``` /// /// [deriving `Reflect`]: Reflect @@ -323,23 +349,27 @@ pub fn impl_reflect_value(input: TokenStream) -> TokenStream { /// which have greater functionality. The type being reflected must be in scope, as you cannot /// qualify it in the macro as e.g. `bevy::prelude::Vec3`. /// +/// It is necessary to add a `#[type_path = "my_crate::foo"]` attribute to all types. +/// /// It may be necessary to add `#[reflect(Default)]` for some types, specifically non-constructible /// foreign types. Without `Default` reflected for such types, you will usually get an arcane /// error message and fail to compile. If the type does not implement `Default`, it may not /// be possible to reflect without extending the macro. /// +/// /// # Example /// Implementing `Reflect` for `bevy::prelude::Vec3` as a struct type: /// ```ignore /// use bevy::prelude::Vec3; /// /// impl_reflect_struct!( -/// #[reflect(PartialEq, Serialize, Deserialize, Default)] -/// struct Vec3 { -/// x: f32, -/// y: f32, -/// z: f32 -/// } +/// #[reflect(PartialEq, Serialize, Deserialize, Default)] +/// #[type_path = "bevy::prelude"] +/// struct Vec3 { +/// x: f32, +/// y: f32, +/// z: f32 +/// } /// ); /// ``` #[proc_macro] @@ -426,6 +456,42 @@ pub fn impl_from_reflect_value(input: TokenStream) -> TokenStream { from_reflect::impl_value(&ReflectMeta::new(type_path, def.traits.unwrap_or_default())) } +/// A replacement for [deriving `TypePath`] for use on foreign types. +/// +/// Since (unlike the derive) this macro may be invoked in a different module to where the type is defined, +/// it requires an 'absolute' path definition. +/// +/// Specifically, a leading `::` denoting a global path must be specified +/// or a preceeding `(in my_crate::foo)` to specify the custom path must be used. +/// +/// # Examples +/// +/// Implementing `TypePath` on a foreign type: +/// ```rust,ignore +/// impl_type_path!(::foreign_crate::foo::bar::Baz); +/// ``` +/// +/// On a generic type: +/// ```rust,ignore +/// impl_type_path!(::foreign_crate::Foo); +/// ``` +/// +/// On a primitive (note this will not compile for a non-primitive type): +/// ```rust,ignore +/// impl_type_path!(bool); +/// ``` +/// +/// With a custom type path: +/// ```rust,ignore +/// impl_type_path!((in other_crate::foo::bar) Baz); +/// ``` +/// +/// With a custom type path and a custom type name: +/// ```rust,ignore +/// impl_type_path!((in other_crate::foo as Baz) Bar); +/// ``` +/// +/// [deriving `TypePath`]: TypePath #[proc_macro] pub fn impl_type_path(input: TokenStream) -> TokenStream { let def = parse_macro_input!(input as NamedTypePathDef); @@ -451,6 +517,7 @@ pub fn impl_type_path(input: TokenStream) -> TokenStream { impls::impl_type_path(&meta, &WhereClauseOptions::type_path_bounds(&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)]`. #[proc_macro] pub fn impl_type_uuid(input: TokenStream) -> TokenStream { diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs b/crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs index e60795da346cf..5a2f8c9fae190 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs @@ -6,7 +6,7 @@ use syn::{ Generics, Path, PathSegment, Token, }; -pub fn parse_path_no_leading_colon(input: ParseStream) -> syn::Result { +pub(crate) fn parse_path_no_leading_colon(input: ParseStream) -> syn::Result { if input.peek(Token![::]) { return Err(input.error("did not expect a leading double colon (`::`)")); } @@ -23,7 +23,7 @@ pub fn parse_path_no_leading_colon(input: ParseStream) -> syn::Result { /// An alias for a `TypePath`. /// /// This is the parenthesized part of `(in my_crate::foo as MyType) SomeType`. -pub struct CustomPathDef { +pub(crate) struct CustomPathDef { path: Path, name: Option, } @@ -67,7 +67,7 @@ impl CustomPathDef { } } -pub enum NamedTypePathDef { +pub(crate) enum NamedTypePathDef { External { path: Path, generics: Generics, @@ -89,7 +89,7 @@ impl Parse for NamedTypePathDef { let ident = path.segments.into_iter().next().unwrap().ident; Ok(NamedTypePathDef::Primtive(ident)) } else { - Err(input.error("non-aliased paths must start with a double colon (`::`)")) + Err(input.error("non-customized paths must start with a double colon (`::`)")) } } else { Ok(NamedTypePathDef::External { diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs b/crates/bevy_reflect/bevy_reflect_derive/src/utility.rs index 38710ab135d4c..3a81c02082a1f 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::{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 { @@ -267,13 +267,23 @@ pub(crate) enum StringExpr { Owned(proc_macro2::TokenStream), } +impl From for StringExpr { + fn from(value: T) -> Self { + Self::from_lit(&LitStr::new(&value.to_string(), value.span())) + } +} + impl StringExpr { - /// Creates a [`StringExpr`] by interpreting an [`Ident`] as a [`struct@LitStr`]. - pub fn from_ident(ident: &Ident) -> Self { - Self::Const(LitStr::new(&ident.to_string(), ident.span()).into_token_stream()) + /// Creates a [constant] [`StringExpr`] from a [`struct@LitStr`]. + /// + /// [constant]: StringExpr::Const + pub fn from_lit(lit: &LitStr) -> Self { + Self::Const(lit.to_token_stream()) } - /// Creates a [`StringExpr`] by interpreting a [string slice][str] as a [`struct@LitStr`]. + /// Creates a [constant] [`StringExpr`] by interpreting a [string slice][str] as a [`struct@LitStr`]. + /// + /// [constant]: StringExpr::Const pub fn from_str(string: &str) -> Self { Self::Const(string.into_token_stream()) } @@ -325,7 +335,7 @@ impl StringExpr { impl Default for StringExpr { fn default() -> Self { - StringExpr::Const("".to_string().to_token_stream()) + StringExpr::from_str("") } } diff --git a/crates/bevy_reflect/src/enums/mod.rs b/crates/bevy_reflect/src/enums/mod.rs index 2d6db324aade0..e8c32e73ef9c5 100644 --- a/crates/bevy_reflect/src/enums/mod.rs +++ b/crates/bevy_reflect/src/enums/mod.rs @@ -316,7 +316,7 @@ mod tests { #[test] fn enum_should_allow_generics() { #[derive(Reflect, Debug, PartialEq)] - enum TestEnum { + enum TestEnum { A, B(T), C { value: T }, diff --git a/crates/bevy_reflect/src/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index 452ad536a8786..0ec2957bdc7f1 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -9,7 +9,7 @@ use crate::{ TypePath, TypeRegistration, Typed, }; -impl List for SmallVec +impl List for SmallVec where T::Item: FromReflect, { diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 24067ff8f15d8..6c8a6bb7ddb2e 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -239,12 +239,12 @@ impl_from_reflect_value!(f64); impl_from_reflect_value!(String); impl_from_reflect_value!(PathBuf); impl_from_reflect_value!(OsString); -impl_from_reflect_value!(HashSet); -impl_from_reflect_value!(Range); -impl_from_reflect_value!(RangeInclusive); -impl_from_reflect_value!(RangeFrom); -impl_from_reflect_value!(RangeTo); -impl_from_reflect_value!(RangeToInclusive); +impl_from_reflect_value!(HashSet); +impl_from_reflect_value!(Range); +impl_from_reflect_value!(RangeInclusive); +impl_from_reflect_value!(RangeFrom); +impl_from_reflect_value!(RangeTo); +impl_from_reflect_value!(RangeToInclusive); impl_from_reflect_value!(RangeFull); impl_from_reflect_value!(Duration); impl_from_reflect_value!(Instant); @@ -449,7 +449,7 @@ macro_rules! impl_reflect_for_hashmap { where K: FromReflect + TypePath + Eq + Hash, V: FromReflect + TypePath, - S: TypePath + BuildHasher + Send + Sync + 'static, + S: TypePath + BuildHasher + Send + Sync, { fn get(&self, key: &dyn Reflect) -> Option<&dyn Reflect> { key.downcast_ref::() @@ -537,7 +537,7 @@ macro_rules! impl_reflect_for_hashmap { where K: FromReflect + TypePath + Eq + Hash, V: FromReflect + TypePath, - S: TypePath + BuildHasher + Send + Sync + 'static, + S: TypePath + BuildHasher + Send + Sync, { fn type_name(&self) -> &str { std::any::type_name::() @@ -610,7 +610,7 @@ macro_rules! impl_reflect_for_hashmap { where K: FromReflect + TypePath + Eq + Hash, V: FromReflect + TypePath, - S: TypePath + BuildHasher + Send + Sync + 'static, + S: TypePath + BuildHasher + Send + Sync, { fn type_info() -> &'static TypeInfo { static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new(); @@ -622,7 +622,7 @@ macro_rules! impl_reflect_for_hashmap { where K: FromReflect + TypePath + Eq + Hash, V: FromReflect + TypePath, - S: TypePath + BuildHasher + Send + Sync + 'static, + S: TypePath + BuildHasher + Send + Sync, { fn get_type_registration() -> TypeRegistration { let mut registration = TypeRegistration::of::(); @@ -635,7 +635,7 @@ macro_rules! impl_reflect_for_hashmap { where K: FromReflect + TypePath + Eq + Hash, V: FromReflect + TypePath, - S: TypePath + BuildHasher + Default + Send + Sync + 'static, + S: TypePath + BuildHasher + Default + Send + Sync, { fn from_reflect(reflect: &dyn Reflect) -> Option { if let ReflectRef::Map(ref_map) = reflect.reflect_ref() { @@ -654,20 +654,20 @@ macro_rules! impl_reflect_for_hashmap { }; } -impl_type_path!(::std::collections::hash_map::RandomState); -impl_type_path!((in hashbrown::hash_map) bevy_utils::hashbrown::hash_map::DefaultHashBuilder); - -impl_reflect_for_hashmap!(bevy_utils::hashbrown::HashMap); impl_reflect_for_hashmap!(::std::collections::HashMap); +impl_type_path!(::std::collections::hash_map::RandomState); impl_type_path!( - (in hashbrown) bevy_utils::hashbrown::HashMap + ::std::collections::HashMap where K: FromReflect + Eq + Hash, V: FromReflect, 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!( - ::std::collections::HashMap + ::bevy_utils::hashbrown::HashMap where K: FromReflect + Eq + Hash, V: FromReflect, diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index 7cbe8bf73e5f4..24cffc8a5ae76 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -1,7 +1,7 @@ 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, TypePath, Typed, ValueInfo, + TypeInfo, Typed, ValueInfo, }; use std::{ any::{self, Any, TypeId}, @@ -90,6 +90,7 @@ pub trait Reflect: Any + Send + Sync { /// /// Methods on [`DynamicTypePath`] suffer the same performance concerns as [`get_type_info`]. /// + /// [`TypePath`]: crate::TypePath /// [`get_type_info`]: Reflect::get_type_info fn get_type_path(&self) -> &dyn DynamicTypePath; @@ -238,16 +239,6 @@ impl Typed for dyn Reflect { } } -impl TypePath for dyn Reflect { - fn type_path() -> &'static str { - "dyn bevy_reflect::Reflect" - } - - fn short_type_path() -> &'static str { - "dyn Reflect" - } -} - #[deny(rustdoc::broken_intra_doc_links)] impl dyn Reflect { /// Downcasts the value to type `T`, consuming the trait object. diff --git a/crates/bevy_reflect/src/type_path.rs b/crates/bevy_reflect/src/type_path.rs index d458ea0197407..387fb11930d9c 100644 --- a/crates/bevy_reflect/src/type_path.rs +++ b/crates/bevy_reflect/src/type_path.rs @@ -15,12 +15,23 @@ /// for matching dynamic values to concrete types. /// /// Using [`std::any::type_name`], a scene containing `my_crate::foo::MyComponent` would break, -/// failing to deserialize if the component was moved to be `my_crate::bar::MyComponent`. +/// failing to deserialize if the component was moved from the `foo` module to the `bar` module, +/// becoming `my_crate::bar::MyComponent`. /// This trait, through attributes when deriving itself or [`Reflect`], can ensure breaking changes are avoidable. /// /// The only external factor we rely on for stability when deriving is the [`module_path!`] macro, /// only if the derive does not provide a `#[type_path = "..."]` attribute. /// +/// # Anonymity +/// +/// Some methods on this trait return `Option<&'static str>` over `&'static str` +/// because not all types define all parts of a type path, for example the array type `[T; N]`. +/// +/// Such types are 'anonymous' in that they have only a defined [`type_path`] and [`short_type_path`] +/// and the methods [`crate_name`], [`module_path`] and [`type_ident`] all return `None`. +/// +/// Primitives are treated like anonymous types, except they also have a defined [`type_ident`]. +/// /// # Example /// /// ```rust @@ -61,34 +72,51 @@ /// [utility]: crate::utility /// [(de)serialization]: crate::serde::UntypedReflectDeserializer /// [`Reflect`]: crate::Reflect +/// [`type_path`]: TypePath::type_path +/// [`short_type_path`]: TypePath::short_type_path +/// [`crate_name`]: TypePath::crate_name +/// [`module_path`]: TypePath::module_path +/// [`type_ident`]: TypePath::type_ident pub trait TypePath: 'static { /// Returns the fully qualified path of the underlying type. /// - /// For [`Option<()>`], this is `"core::option::Option::<()>"`. + /// Generic parameter types are also fully expanded. + /// + /// For `Option`, this is `"core::option::Option"`. fn type_path() -> &'static str; - /// Returns a short pretty-print enabled path to the type. + /// Returns a short, pretty-print enabled path to the type. /// - /// For [`Option<()>`], this is `"Option<()>"`. + /// Generic parameter types are also shortened. + /// + /// For `Option`, this is `"Option"`. fn short_type_path() -> &'static str; - /// Returns the name of the type, or [`None`] if it is anonymous. + /// 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> { None } - /// Returns the name of the crate the type is in, or [`None`] if it is anonymous or a primitive. + /// 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> { None } - /// Returns the path to the moudle the type is in, or [`None`] if it is anonymous or a primitive. + /// 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> { None } diff --git a/examples/reflection/generic_reflection.rs b/examples/reflection/generic_reflection.rs index f3f4342b26733..e7f88427b023c 100644 --- a/examples/reflection/generic_reflection.rs +++ b/examples/reflection/generic_reflection.rs @@ -13,7 +13,7 @@ fn main() { } #[derive(Reflect)] -struct MyType { +struct MyType { value: T, } From 63b85e56578f1e94b8358c0cb3be6d3c8a167bfb Mon Sep 17 00:00:00 2001 From: radiish Date: Mon, 5 Jun 2023 18:30:09 +0100 Subject: [PATCH 49/52] rebase part 2 --- crates/bevy_gltf/src/lib.rs | 5 --- crates/bevy_reflect/src/impls/std.rs | 43 ++++++++++--------- crates/bevy_reflect/src/reflect.rs | 4 +- crates/bevy_reflect/src/utility.rs | 2 +- crates/bevy_render/src/view/visibility/mod.rs | 2 +- crates/bevy_sprite/src/mesh2d/material.rs | 4 +- crates/bevy_text/src/font.rs | 6 +-- examples/2d/custom_gltf_vertex_attribute.rs | 4 +- 8 files changed, 30 insertions(+), 40 deletions(-) diff --git a/crates/bevy_gltf/src/lib.rs b/crates/bevy_gltf/src/lib.rs index b47a2aa5d57cd..7277a906269f5 100644 --- a/crates/bevy_gltf/src/lib.rs +++ b/crates/bevy_gltf/src/lib.rs @@ -12,17 +12,12 @@ use bevy_app::prelude::*; use bevy_asset::{AddAsset, Handle}; use bevy_ecs::{prelude::Component, reflect::ReflectComponent}; use bevy_pbr::StandardMaterial; -<<<<<<< HEAD use bevy_reflect::{Reflect, TypePath, TypeUuid}; -use bevy_render::mesh::Mesh; -======= -use bevy_reflect::{Reflect, TypeUuid}; use bevy_render::{ mesh::{Mesh, MeshVertexAttribute}, renderer::RenderDevice, texture::CompressedImageFormats, }; ->>>>>>> 94dce091a9c9763aa8a9b18f3cb9e42bbb4ecf88 use bevy_scene::Scene; /// Adds support for glTF file loading to the app. diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index e83bd1b3e8c1d..806aff9fa8af0 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -275,22 +275,6 @@ macro_rules! impl_reflect_for_veclike { <$sub>::get_mut(self, index).map(|value| value as &mut dyn Reflect) } - #[inline] - fn len(&self) -> usize { - <$sub>::len(self) - } - - #[inline] - fn iter(&self) -> ListIter { - ListIter::new(self) - } - - #[inline] - fn drain(self: Box) -> Vec> { - self.into_iter() - .map(|value| Box::new(value) as Box) - .collect() - } fn insert(&mut self, index: usize, value: Box) { let value = value.take::().unwrap_or_else(|value| { T::from_reflect(&*value).unwrap_or_else(|| { @@ -320,6 +304,23 @@ macro_rules! impl_reflect_for_veclike { fn pop(&mut self) -> Option> { $pop(self).map(|value| Box::new(value) as Box) } + + #[inline] + fn len(&self) -> usize { + <$sub>::len(self) + } + + #[inline] + fn iter(&self) -> ListIter { + ListIter::new(self) + } + + #[inline] + fn drain(self: Box) -> Vec> { + self.into_iter() + .map(|value| Box::new(value) as Box) + .collect() + } } impl Reflect for $ty { @@ -666,8 +667,8 @@ impl_type_path!(::std::collections::hash_map::RandomState); impl_type_path!( ::std::collections::HashMap where - K: FromReflect + Eq + Hash, - V: FromReflect, + K: FromReflect + Eq + Hash + ?Sized, + V: FromReflect + ?Sized, S: BuildHasher + Send + Sync + 'static, ); @@ -676,8 +677,8 @@ impl_type_path!(::bevy_utils::hashbrown::hash_map::DefaultHashBuilder); impl_type_path!( ::bevy_utils::hashbrown::HashMap where - K: FromReflect + Eq + Hash, - V: FromReflect, + K: FromReflect + Eq + Hash + ?Sized, + V: FromReflect + ?Sized, S: BuildHasher + Send + Sync + 'static, ); @@ -1458,7 +1459,7 @@ impl Typed for Cow<'static, Path> { trait PathOnly: ToOwned {} impl PathOnly for Path {} -impl_type_path!(::alloc::borrow::Cow<'a: 'static, T: PathOnly>); +impl_type_path!(::alloc::borrow::Cow<'a: 'static, T: PathOnly + ?Sized>); impl_type_path!(::std::path::Path); impl FromReflect for Cow<'static, Path> { diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index c4ddd69eb8e88..53bf3aca1a0e5 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -95,10 +95,10 @@ pub trait Reflect: Any + Send + Sync { /// Returns the [`TypePath`] implementation for the underlying type. /// - /// Methods on [`DynamicTypePath`] suffer the same performance concerns as [`get_type_info`]. + /// Methods on [`DynamicTypePath`] suffer the same performance concerns as [`get_represented_type_info`]. /// /// [`TypePath`]: crate::TypePath - /// [`get_type_info`]: Reflect::get_type_info + /// [`get_represented_type_info`]: Reflect::get_represented_type_info fn get_type_path(&self) -> &dyn DynamicTypePath; /// Returns the value as a [`Box`][std::any::Any]. diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index bb78cc5b9c291..8840f3268b2cc 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -99,7 +99,7 @@ impl NonGenericTypeCell { Self(OnceBox::new()) } - /// Returns a reference to the [`TypeInfo`] stored in the cell. + /// Returns a reference to the [`TypedProperty`] stored in the cell. /// /// If there is no entry found, a new one will be generated from the given function. pub fn get_or_set(&self, f: F) -> &T::Stored diff --git a/crates/bevy_render/src/view/visibility/mod.rs b/crates/bevy_render/src/view/visibility/mod.rs index 1b0c275004154..30e8819a641d9 100644 --- a/crates/bevy_render/src/view/visibility/mod.rs +++ b/crates/bevy_render/src/view/visibility/mod.rs @@ -69,7 +69,7 @@ bitflags::bitflags! { const VISIBLE_IN_HIERARCHY = 1 << 1; } } -bevy_reflect::impl_reflect_value!(ComputedVisibilityFlags); +bevy_reflect::impl_reflect_value!((in bevy_render::view) ComputedVisibilityFlags); bevy_reflect::impl_from_reflect_value!(ComputedVisibilityFlags); /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering diff --git a/crates/bevy_sprite/src/mesh2d/material.rs b/crates/bevy_sprite/src/mesh2d/material.rs index 061cef9f636d4..b33c7a5702578 100644 --- a/crates/bevy_sprite/src/mesh2d/material.rs +++ b/crates/bevy_sprite/src/mesh2d/material.rs @@ -111,9 +111,7 @@ use crate::{ /// @group(1) @binding(2) /// var color_sampler: sampler; /// ``` -pub trait Material2d: - AsBindGroup + Send + Sync + Clone + TypeUuid + TypePath + Sized + 'static -{ +pub trait Material2d: AsBindGroup + Send + Sync + Clone + TypeUuid + TypePath + Sized { /// Returns this material's vertex shader. If [`ShaderRef::Default`] is returned, the default mesh vertex shader /// will be used. fn vertex_shader() -> ShaderRef { diff --git a/crates/bevy_text/src/font.rs b/crates/bevy_text/src/font.rs index 60fd753beea61..1d8a465a76ea2 100644 --- a/crates/bevy_text/src/font.rs +++ b/crates/bevy_text/src/font.rs @@ -5,11 +5,7 @@ use bevy_render::{ texture::Image, }; -<<<<<<< HEAD -#[derive(Debug, TypeUuid, TypePath)] -======= -#[derive(Debug, TypeUuid, Clone)] ->>>>>>> 94dce091a9c9763aa8a9b18f3cb9e42bbb4ecf88 +#[derive(Debug, TypeUuid, TypePath, Clone)] #[uuid = "97059ac6-c9ba-4da9-95b6-bed82c3ce198"] pub struct Font { pub font: FontArc, diff --git a/examples/2d/custom_gltf_vertex_attribute.rs b/examples/2d/custom_gltf_vertex_attribute.rs index a0d3c21c848f2..43356f04e4988 100644 --- a/examples/2d/custom_gltf_vertex_attribute.rs +++ b/examples/2d/custom_gltf_vertex_attribute.rs @@ -2,7 +2,7 @@ use bevy::gltf::GltfPlugin; use bevy::prelude::*; -use bevy::reflect::TypeUuid; +use bevy::reflect::{TypePath, TypeUuid}; use bevy::render::mesh::{MeshVertexAttribute, MeshVertexBufferLayout}; use bevy::render::render_resource::*; use bevy::sprite::{ @@ -55,7 +55,7 @@ fn setup( /// This custom material uses barycentric coordinates from /// `ATTRIBUTE_BARYCENTRIC` to shade a white border around each triangle. The /// thickness of the border is animated using the global time shader uniform. -#[derive(AsBindGroup, TypeUuid, Debug, Clone)] +#[derive(AsBindGroup, TypeUuid, TypePath, Debug, Clone)] #[uuid = "50ffce9e-1582-42e9-87cb-2233724426c0"] struct CustomMaterial {} From 6f807a565650dc7b32a0bedd85968b77a89c6af4 Mon Sep 17 00:00:00 2001 From: radiish Date: Mon, 5 Jun 2023 18:44:24 +0100 Subject: [PATCH 50/52] bless rust 1.70 --- .../tests/deref_mut_derive/missing_deref.fail.stderr | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/bevy_macros_compile_fail_tests/tests/deref_mut_derive/missing_deref.fail.stderr b/crates/bevy_macros_compile_fail_tests/tests/deref_mut_derive/missing_deref.fail.stderr index 3e11d49532e94..d4cfc71d7a920 100644 --- a/crates/bevy_macros_compile_fail_tests/tests/deref_mut_derive/missing_deref.fail.stderr +++ b/crates/bevy_macros_compile_fail_tests/tests/deref_mut_derive/missing_deref.fail.stderr @@ -6,6 +6,9 @@ error[E0277]: the trait bound `TupleStruct: Deref` is not satisfied | note: required by a bound in `DerefMut` --> $RUST/core/src/ops/deref.rs + | + | pub trait DerefMut: Deref { + | ^^^^^ required by this bound in `DerefMut` error[E0277]: the trait bound `Struct: Deref` is not satisfied --> tests/deref_mut_derive/missing_deref.fail.rs:7:8 @@ -15,6 +18,9 @@ error[E0277]: the trait bound `Struct: Deref` is not satisfied | note: required by a bound in `DerefMut` --> $RUST/core/src/ops/deref.rs + | + | pub trait DerefMut: Deref { + | ^^^^^ required by this bound in `DerefMut` error[E0277]: the trait bound `TupleStruct: Deref` is not satisfied --> tests/deref_mut_derive/missing_deref.fail.rs:3:10 From 6e22c5ab76c662c6b3fb887fd7788b4846b99a3f Mon Sep 17 00:00:00 2001 From: radiish Date: Mon, 5 Jun 2023 19:45:26 +0100 Subject: [PATCH 51/52] revert compile fail changes --- .../tests/deref_mut_derive/missing_deref.fail.stderr | 6 ------ 1 file changed, 6 deletions(-) diff --git a/crates/bevy_macros_compile_fail_tests/tests/deref_mut_derive/missing_deref.fail.stderr b/crates/bevy_macros_compile_fail_tests/tests/deref_mut_derive/missing_deref.fail.stderr index d4cfc71d7a920..3e11d49532e94 100644 --- a/crates/bevy_macros_compile_fail_tests/tests/deref_mut_derive/missing_deref.fail.stderr +++ b/crates/bevy_macros_compile_fail_tests/tests/deref_mut_derive/missing_deref.fail.stderr @@ -6,9 +6,6 @@ error[E0277]: the trait bound `TupleStruct: Deref` is not satisfied | note: required by a bound in `DerefMut` --> $RUST/core/src/ops/deref.rs - | - | pub trait DerefMut: Deref { - | ^^^^^ required by this bound in `DerefMut` error[E0277]: the trait bound `Struct: Deref` is not satisfied --> tests/deref_mut_derive/missing_deref.fail.rs:7:8 @@ -18,9 +15,6 @@ error[E0277]: the trait bound `Struct: Deref` is not satisfied | note: required by a bound in `DerefMut` --> $RUST/core/src/ops/deref.rs - | - | pub trait DerefMut: Deref { - | ^^^^^ required by this bound in `DerefMut` error[E0277]: the trait bound `TupleStruct: Deref` is not satisfied --> tests/deref_mut_derive/missing_deref.fail.rs:3:10 From 3fea3c6c0b5719dfbd3d4230f5282ec80d82556a Mon Sep 17 00:00:00 2001 From: radiish Date: Mon, 5 Jun 2023 19:54:54 +0100 Subject: [PATCH 52/52] doctest fix --- crates/bevy_reflect/src/utility.rs | 62 +++++++++++++++--------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index 8840f3268b2cc..6344072b08215 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -69,21 +69,21 @@ mod sealed { /// } /// # /// # 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!() } -/// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() } -/// # fn into_reflect(self: Box) -> Box { todo!() } -/// # fn as_reflect(&self) -> &dyn Reflect { todo!() } -/// # fn as_reflect_mut(&mut self) -> &mut dyn Reflect { todo!() } -/// # fn apply(&mut self, value: &dyn Reflect) { todo!() } -/// # fn set(&mut self, value: Box) -> Result<(), Box> { todo!() } -/// # fn reflect_ref(&self) -> ReflectRef { todo!() } -/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() } -/// # fn reflect_owned(self: Box) -> ReflectOwned { todo!() } -/// # fn clone_value(&self) -> Box { todo!() } +/// # fn 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!() } +/// # 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!() } /// # } /// ``` /// @@ -141,21 +141,21 @@ 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!() } -/// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() } -/// # fn into_reflect(self: Box) -> Box { todo!() } -/// # fn as_reflect(&self) -> &dyn Reflect { todo!() } -/// # fn as_reflect_mut(&mut self) -> &mut dyn Reflect { todo!() } -/// # fn apply(&mut self, value: &dyn Reflect) { todo!() } -/// # fn set(&mut self, value: Box) -> Result<(), Box> { todo!() } -/// # fn reflect_ref(&self) -> ReflectRef { todo!() } -/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() } -/// # fn reflect_owned(self: Box) -> ReflectOwned { todo!() } -/// # fn clone_value(&self) -> Box { todo!() } +/// # fn 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!() } +/// # 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!() } /// # } /// ``` /// @@ -182,8 +182,8 @@ impl NonGenericTypeCell { /// # /// # impl Reflect for Foo { /// # fn type_name(&self) -> &str { todo!() } -/// # fn get_type_info(&self) -> &'static TypeInfo { 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!() } /// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() }