diff --git a/crates/bevy_asset/src/path.rs b/crates/bevy_asset/src/path.rs index 67c7c65286..d52bdc02dd 100644 --- a/crates/bevy_asset/src/path.rs +++ b/crates/bevy_asset/src/path.rs @@ -48,7 +48,8 @@ use thiserror::Error; /// clones internal owned [`AssetPaths`](AssetPath). /// This also means that you should use [`AssetPath::parse`] in cases where `&str` is the explicit type. #[derive(Eq, PartialEq, Hash, Clone, Default, Reflect)] -#[reflect_value(Debug, PartialEq, Hash, Serialize, Deserialize)] +#[reflect(opaque)] +#[reflect(Debug, PartialEq, Hash, Serialize, Deserialize)] pub struct AssetPath<'a> { source: AssetSourceId<'a>, path: CowArc<'a, Path>, diff --git a/crates/bevy_ecs/src/entity/mod.rs b/crates/bevy_ecs/src/entity/mod.rs index a6bf45da3d..3ad78f73a2 100644 --- a/crates/bevy_ecs/src/entity/mod.rs +++ b/crates/bevy_ecs/src/entity/mod.rs @@ -144,10 +144,11 @@ type IdCursor = isize; /// [SemVer]: https://semver.org/ #[derive(Clone, Copy)] #[cfg_attr(feature = "bevy_reflect", derive(Reflect))] -#[cfg_attr(feature = "bevy_reflect", reflect_value(Hash, PartialEq, Debug))] +#[cfg_attr(feature = "bevy_reflect", reflect(opaque))] +#[cfg_attr(feature = "bevy_reflect", reflect(Hash, PartialEq, Debug))] #[cfg_attr( all(feature = "bevy_reflect", feature = "serialize"), - reflect_value(Serialize, Deserialize) + reflect(Serialize, Deserialize) )] // Alignment repr necessary to allow LLVM to better output // optimised codegen for `to_bits`, `PartialEq` and `Ord`. diff --git a/crates/bevy_ecs/src/identifier/mod.rs b/crates/bevy_ecs/src/identifier/mod.rs index e9c7df8006..54bb29218b 100644 --- a/crates/bevy_ecs/src/identifier/mod.rs +++ b/crates/bevy_ecs/src/identifier/mod.rs @@ -19,7 +19,8 @@ pub(crate) mod masks; /// entity kinds. #[derive(Debug, Clone, Copy)] #[cfg_attr(feature = "bevy_reflect", derive(Reflect))] -#[cfg_attr(feature = "bevy_reflect", reflect_value(Debug, Hash, PartialEq))] +#[cfg_attr(feature = "bevy_reflect", reflect(opaque))] +#[cfg_attr(feature = "bevy_reflect", reflect(Debug, Hash, PartialEq))] // Alignment repr necessary to allow LLVM to better output // optimised codegen for `to_bits`, `PartialEq` and `Ord`. #[repr(C, align(8))] diff --git a/crates/bevy_reflect/derive/src/container_attributes.rs b/crates/bevy_reflect/derive/src/container_attributes.rs index cef874e927..7aa027cb1f 100644 --- a/crates/bevy_reflect/derive/src/container_attributes.rs +++ b/crates/bevy_reflect/derive/src/container_attributes.rs @@ -3,7 +3,7 @@ //! A container attribute is an attribute which applies to an entire struct or enum //! as opposed to a particular field or variant. An example of such an attribute is //! the derive helper attribute for `Reflect`, which looks like: -//! `#[reflect(PartialEq, Default, ...)]` and `#[reflect_value(PartialEq, Default, ...)]`. +//! `#[reflect(PartialEq, Default, ...)]`. use crate::attribute_parser::terminated_parser; use crate::custom_attributes::CustomAttributes; @@ -23,6 +23,7 @@ mod kw { syn::custom_keyword!(PartialEq); syn::custom_keyword!(Hash); syn::custom_keyword!(no_field_bounds); + syn::custom_keyword!(opaque); } // The "special" trait idents that are used internally for reflection. @@ -188,6 +189,7 @@ pub(crate) struct ContainerAttributes { custom_where: Option, no_field_bounds: bool, custom_attributes: CustomAttributes, + is_opaque: bool, idents: Vec, } @@ -236,6 +238,8 @@ impl ContainerAttributes { self.parse_from_reflect(input, trait_) } else if lookahead.peek(kw::type_path) { self.parse_type_path(input, trait_) + } else if lookahead.peek(kw::opaque) { + self.parse_opaque(input) } else if lookahead.peek(kw::no_field_bounds) { self.parse_no_field_bounds(input) } else if lookahead.peek(kw::Debug) { @@ -336,6 +340,16 @@ impl ContainerAttributes { Ok(()) } + /// Parse `opaque` attribute. + /// + /// Examples: + /// - `#[reflect(opaque)]` + fn parse_opaque(&mut self, input: ParseStream) -> syn::Result<()> { + input.parse::()?; + self.is_opaque = true; + Ok(()) + } + /// Parse `no_field_bounds` attribute. /// /// Examples: @@ -528,6 +542,11 @@ impl ContainerAttributes { pub fn no_field_bounds(&self) -> bool { self.no_field_bounds } + + /// Returns true if the `opaque` attribute was found on this type. + pub fn is_opaque(&self) -> bool { + self.is_opaque + } } /// Adds an identifier to a vector of identifiers if it is not already present. diff --git a/crates/bevy_reflect/derive/src/derive_data.rs b/crates/bevy_reflect/derive/src/derive_data.rs index f68af17537..5c2e99db5b 100644 --- a/crates/bevy_reflect/derive/src/derive_data.rs +++ b/crates/bevy_reflect/derive/src/derive_data.rs @@ -12,10 +12,7 @@ use syn::token::Comma; use crate::remote::RemoteType; use crate::serialization::SerializationDataDef; -use crate::{ - REFLECT_ATTRIBUTE_NAME, REFLECT_VALUE_ATTRIBUTE_NAME, TYPE_NAME_ATTRIBUTE_NAME, - TYPE_PATH_ATTRIBUTE_NAME, -}; +use crate::{REFLECT_ATTRIBUTE_NAME, TYPE_NAME_ATTRIBUTE_NAME, TYPE_PATH_ATTRIBUTE_NAME}; use syn::punctuated::Punctuated; use syn::spanned::Spanned; use syn::{ @@ -28,7 +25,7 @@ pub(crate) enum ReflectDerive<'a> { TupleStruct(ReflectStruct<'a>), UnitStruct(ReflectStruct<'a>), Enum(ReflectEnum<'a>), - Value(ReflectMeta<'a>), + Opaque(ReflectMeta<'a>), } /// Metadata present on all reflected types, including name, generics, and attributes. @@ -135,15 +132,6 @@ pub(crate) enum EnumVariantFields<'a> { Unit, } -/// The method in which the type should be reflected. -#[derive(PartialEq, Eq)] -enum ReflectMode { - /// Reflect the type normally, providing information about all fields/variants. - Normal, - /// Reflect the type as a value. - Value, -} - /// How the macro was invoked. #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub(crate) enum ReflectImplSource { @@ -192,8 +180,6 @@ impl<'a> ReflectDerive<'a> { provenance: ReflectProvenance, ) -> Result { let mut container_attributes = ContainerAttributes::default(); - // Should indicate whether `#[reflect_value]` was used. - let mut reflect_mode = None; // Should indicate whether `#[type_path = "..."]` was used. let mut custom_path: Option = None; // Should indicate whether `#[type_name = "..."]` was used. @@ -205,37 +191,8 @@ impl<'a> ReflectDerive<'a> { for attribute in &input.attrs { match &attribute.meta { Meta::List(meta_list) if meta_list.path.is_ident(REFLECT_ATTRIBUTE_NAME) => { - if !matches!(reflect_mode, None | Some(ReflectMode::Normal)) { - return Err(syn::Error::new( - meta_list.span(), - format_args!("cannot use both `#[{REFLECT_ATTRIBUTE_NAME}]` and `#[{REFLECT_VALUE_ATTRIBUTE_NAME}]`"), - )); - } - - reflect_mode = Some(ReflectMode::Normal); container_attributes.parse_meta_list(meta_list, provenance.trait_)?; } - Meta::List(meta_list) if meta_list.path.is_ident(REFLECT_VALUE_ATTRIBUTE_NAME) => { - if !matches!(reflect_mode, None | Some(ReflectMode::Value)) { - return Err(syn::Error::new( - meta_list.span(), - format_args!("cannot use both `#[{REFLECT_ATTRIBUTE_NAME}]` and `#[{REFLECT_VALUE_ATTRIBUTE_NAME}]`"), - )); - } - - reflect_mode = Some(ReflectMode::Value); - container_attributes.parse_meta_list(meta_list, provenance.trait_)?; - } - Meta::Path(path) if path.is_ident(REFLECT_VALUE_ATTRIBUTE_NAME) => { - if !matches!(reflect_mode, None | Some(ReflectMode::Value)) { - return Err(syn::Error::new( - path.span(), - format_args!("cannot use both `#[{REFLECT_ATTRIBUTE_NAME}]` and `#[{REFLECT_VALUE_ATTRIBUTE_NAME}]`"), - )); - } - - reflect_mode = Some(ReflectMode::Value); - } Meta::NameValue(pair) if pair.path.is_ident(TYPE_PATH_ATTRIBUTE_NAME) => { let syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(lit), @@ -315,11 +272,8 @@ impl<'a> ReflectDerive<'a> { #[cfg(feature = "documentation")] let meta = meta.with_docs(doc); - // Use normal reflection if unspecified - let reflect_mode = reflect_mode.unwrap_or(ReflectMode::Normal); - - if reflect_mode == ReflectMode::Value { - return Ok(Self::Value(meta)); + if meta.attrs().is_opaque() { + return Ok(Self::Opaque(meta)); } return match &input.data { @@ -354,7 +308,7 @@ impl<'a> ReflectDerive<'a> { /// /// # Panics /// - /// Panics when called on [`ReflectDerive::Value`]. + /// Panics when called on [`ReflectDerive::Opaque`]. pub fn set_remote(&mut self, remote_ty: Option>) { match self { Self::Struct(data) | Self::TupleStruct(data) | Self::UnitStruct(data) => { @@ -363,7 +317,7 @@ impl<'a> ReflectDerive<'a> { Self::Enum(data) => { data.meta.remote_ty = remote_ty; } - Self::Value(meta) => { + Self::Opaque(meta) => { meta.remote_ty = remote_ty; } } @@ -376,7 +330,7 @@ impl<'a> ReflectDerive<'a> { data.meta.remote_ty() } Self::Enum(data) => data.meta.remote_ty(), - Self::Value(meta) => meta.remote_ty(), + Self::Opaque(meta) => meta.remote_ty(), } } @@ -385,7 +339,7 @@ impl<'a> ReflectDerive<'a> { match self { Self::Struct(data) | Self::TupleStruct(data) | Self::UnitStruct(data) => data.meta(), Self::Enum(data) => data.meta(), - Self::Value(meta) => meta, + Self::Opaque(meta) => meta, } } @@ -395,7 +349,7 @@ impl<'a> ReflectDerive<'a> { data.where_clause_options() } Self::Enum(data) => data.where_clause_options(), - Self::Value(meta) => WhereClauseOptions::new(meta), + Self::Opaque(meta) => WhereClauseOptions::new(meta), } } diff --git a/crates/bevy_reflect/derive/src/from_reflect.rs b/crates/bevy_reflect/derive/src/from_reflect.rs index 5bc62197b6..026fb33dba 100644 --- a/crates/bevy_reflect/derive/src/from_reflect.rs +++ b/crates/bevy_reflect/derive/src/from_reflect.rs @@ -20,7 +20,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> proc_macro2:: impl_struct_internal(reflect_struct, true) } -pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream { +pub(crate) fn impl_opaque(meta: &ReflectMeta) -> proc_macro2::TokenStream { let type_path = meta.type_path(); let bevy_reflect_path = meta.bevy_reflect_path(); let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl(); diff --git a/crates/bevy_reflect/derive/src/impls/mod.rs b/crates/bevy_reflect/derive/src/impls/mod.rs index 0905d43bd2..6477c4041e 100644 --- a/crates/bevy_reflect/derive/src/impls/mod.rs +++ b/crates/bevy_reflect/derive/src/impls/mod.rs @@ -3,17 +3,17 @@ mod common; mod enums; #[cfg(feature = "functions")] mod func; +mod opaque; mod structs; mod tuple_structs; mod typed; -mod values; pub(crate) use assertions::impl_assertions; pub(crate) use common::{common_partial_reflect_methods, impl_full_reflect}; pub(crate) use enums::impl_enum; #[cfg(feature = "functions")] pub(crate) use func::impl_function_traits; +pub(crate) use opaque::impl_opaque; pub(crate) use structs::impl_struct; pub(crate) use tuple_structs::impl_tuple_struct; pub(crate) use typed::{impl_type_path, impl_typed}; -pub(crate) use values::impl_value; diff --git a/crates/bevy_reflect/derive/src/impls/values.rs b/crates/bevy_reflect/derive/src/impls/opaque.rs similarity index 89% rename from crates/bevy_reflect/derive/src/impls/values.rs rename to crates/bevy_reflect/derive/src/impls/opaque.rs index f2ff2a82d2..5391dae6d6 100644 --- a/crates/bevy_reflect/derive/src/impls/values.rs +++ b/crates/bevy_reflect/derive/src/impls/opaque.rs @@ -5,7 +5,7 @@ use bevy_macro_utils::fq_std::{FQBox, FQClone, FQOption, FQResult}; use quote::quote; /// Implements `GetTypeRegistration` and `Reflect` for the given type data. -pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream { +pub(crate) fn impl_opaque(meta: &ReflectMeta) -> proc_macro2::TokenStream { let bevy_reflect_path = meta.bevy_reflect_path(); let type_path = meta.type_path(); @@ -22,8 +22,8 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream { meta, &where_clause_options, quote! { - let info = #bevy_reflect_path::ValueInfo::new::() #with_docs; - #bevy_reflect_path::TypeInfo::Value(info) + let info = #bevy_reflect_path::OpaqueInfo::new::() #with_docs; + #bevy_reflect_path::TypeInfo::Opaque(info) }, ); @@ -96,22 +96,22 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream { #[inline] fn reflect_kind(&self) -> #bevy_reflect_path::ReflectKind { - #bevy_reflect_path::ReflectKind::Value + #bevy_reflect_path::ReflectKind::Opaque } #[inline] fn reflect_ref(&self) -> #bevy_reflect_path::ReflectRef { - #bevy_reflect_path::ReflectRef::Value(self) + #bevy_reflect_path::ReflectRef::Opaque(self) } #[inline] fn reflect_mut(&mut self) -> #bevy_reflect_path::ReflectMut { - #bevy_reflect_path::ReflectMut::Value(self) + #bevy_reflect_path::ReflectMut::Opaque(self) } #[inline] fn reflect_owned(self: #FQBox) -> #bevy_reflect_path::ReflectOwned { - #bevy_reflect_path::ReflectOwned::Value(self) + #bevy_reflect_path::ReflectOwned::Opaque(self) } #common_methods diff --git a/crates/bevy_reflect/derive/src/lib.rs b/crates/bevy_reflect/derive/src/lib.rs index 38f4488e6d..e7fc27bcfe 100644 --- a/crates/bevy_reflect/derive/src/lib.rs +++ b/crates/bevy_reflect/derive/src/lib.rs @@ -28,7 +28,7 @@ mod from_reflect; mod ident; mod impls; mod meta; -mod reflect_value; +mod reflect_opaque; mod registration; mod remote; mod result_sifter; @@ -44,12 +44,11 @@ use container_attributes::ContainerAttributes; use derive_data::{ReflectImplSource, ReflectProvenance, ReflectTraitToImpl, ReflectTypePath}; use proc_macro::TokenStream; use quote::quote; -use reflect_value::ReflectValueDef; +use reflect_opaque::ReflectOpaqueDef; use syn::{parse_macro_input, DeriveInput}; 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"; @@ -96,10 +95,10 @@ fn match_reflect_impls(ast: DeriveInput, source: ReflectImplSource) -> TokenStre None }, ), - ReflectDerive::Value(meta) => ( - impls::impl_value(&meta), + ReflectDerive::Opaque(meta) => ( + impls::impl_opaque(&meta), if meta.from_reflect().should_auto_derive() { - Some(from_reflect::impl_value(&meta)) + Some(from_reflect::impl_opaque(&meta)) } else { None }, @@ -178,10 +177,10 @@ fn match_reflect_impls(ast: DeriveInput, source: ReflectImplSource) -> TokenStre /// a base value using its [`Default`] implementation avoiding issues with ignored fields /// (for structs and tuple structs only). /// -/// ## `#[reflect_value]` +/// ## `#[reflect(opaque)]` /// -/// The `#[reflect_value]` attribute (which may also take the form `#[reflect_value(Ident)]`), -/// denotes that the item should implement `Reflect` as though it were a base value type. +/// The `#[reflect(opaque)]` attribute denotes that the item should implement `Reflect` as an opaque type, +/// hiding its structure and fields from the reflection API. /// This means that it will forgo implementing `Struct`, `TupleStruct`, or `Enum`. /// /// Furthermore, it requires that the type implements [`Clone`]. @@ -369,7 +368,7 @@ fn match_reflect_impls(ast: DeriveInput, source: ReflectImplSource) -> TokenStre /// ``` /// /// [`reflect_trait`]: macro@reflect_trait -#[proc_macro_derive(Reflect, attributes(reflect, reflect_value, type_path, type_name))] +#[proc_macro_derive(Reflect, attributes(reflect, type_path, type_name))] pub fn derive_reflect(input: TokenStream) -> TokenStream { let ast = parse_macro_input!(input as DeriveInput); match_reflect_impls(ast, ReflectImplSource::DeriveLocalType) @@ -422,7 +421,7 @@ pub fn derive_from_reflect(input: TokenStream) -> TokenStream { } ReflectDerive::TupleStruct(struct_data) => from_reflect::impl_tuple_struct(&struct_data), ReflectDerive::Enum(meta) => from_reflect::impl_enum(&meta), - ReflectDerive::Value(meta) => from_reflect::impl_value(&meta), + ReflectDerive::Opaque(meta) => from_reflect::impl_opaque(&meta), }; TokenStream::from(quote! { @@ -610,10 +609,10 @@ pub fn reflect_remote(args: TokenStream, input: TokenStream) -> TokenStream { /// A macro used to generate reflection trait implementations for the given type. /// -/// This is functionally the same as [deriving `Reflect`] using the `#[reflect_value]` container attribute. +/// This is functionally the same as [deriving `Reflect`] using the `#[reflect(opaque)]` container attribute. /// /// 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. +/// on primitives and other opaque types internally. /// /// Since this macro also implements `TypePath`, the type path must be explicit. /// See [`impl_type_path!`] for the exact syntax. @@ -623,26 +622,26 @@ pub fn reflect_remote(args: TokenStream, input: TokenStream) -> TokenStream { /// Types can be passed with or without registering type data: /// /// ```ignore (bevy_reflect is not accessible from this crate) -/// impl_reflect_value!(my_crate::Foo); -/// impl_reflect_value!(my_crate::Bar(Debug, Default, Serialize, Deserialize)); +/// impl_reflect_opaque!(my_crate::Foo); +/// impl_reflect_opaque!(my_crate::Bar(Debug, Default, Serialize, Deserialize)); /// ``` /// /// Generic types can also specify their parameters and bounds: /// /// ```ignore (bevy_reflect is not accessible from this crate) -/// impl_reflect_value!(my_crate::Foo where T1: Bar (Default, Serialize, Deserialize)); +/// impl_reflect_opaque!(my_crate::Foo where T1: Bar (Default, Serialize, Deserialize)); /// ``` /// /// Custom type paths can be specified: /// /// ```ignore (bevy_reflect is not accessible from this crate) -/// impl_reflect_value!((in not_my_crate as NotFoo) Foo(Debug, Default)); +/// impl_reflect_opaque!((in not_my_crate as NotFoo) Foo(Debug, Default)); /// ``` /// /// [deriving `Reflect`]: Reflect #[proc_macro] -pub fn impl_reflect_value(input: TokenStream) -> TokenStream { - let def = parse_macro_input!(input with ReflectValueDef::parse_reflect); +pub fn impl_reflect_opaque(input: TokenStream) -> TokenStream { + let def = parse_macro_input!(input with ReflectOpaqueDef::parse_reflect); 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() { @@ -660,8 +659,8 @@ pub fn impl_reflect_value(input: TokenStream) -> TokenStream { #[cfg(feature = "documentation")] let meta = meta.with_docs(documentation::Documentation::from_attributes(&def.attrs)); - let reflect_impls = impls::impl_value(&meta); - let from_reflect_impl = from_reflect::impl_value(&meta); + let reflect_impls = impls::impl_opaque(&meta); + let from_reflect_impl = from_reflect::impl_opaque(&meta); TokenStream::from(quote! { const _: () = { @@ -674,8 +673,8 @@ pub fn impl_reflect_value(input: TokenStream) -> TokenStream { /// A replacement for `#[derive(Reflect)]` to be used with foreign types which /// the definitions of cannot be altered. /// -/// This macro is an alternative to [`impl_reflect_value!`] and [`impl_from_reflect_value!`] -/// which implement foreign types as Value types. Note that there is no `impl_from_reflect`, +/// This macro is an alternative to [`impl_reflect_opaque!`] and [`impl_from_reflect_opaque!`] +/// which implement foreign types as Opaque types. Note that there is no `impl_from_reflect`, /// as this macro will do the job of both. This macro implements them using one of the reflect /// variant traits (`bevy_reflect::{Struct, TupleStruct, Enum}`, etc.), /// which have greater functionality. The type being reflected must be in scope, as you cannot @@ -713,26 +712,26 @@ pub fn impl_reflect(input: TokenStream) -> TokenStream { /// A macro used to generate a `FromReflect` trait implementation for the given type. /// /// This is functionally the same as [deriving `FromReflect`] on a type that [derives `Reflect`] using -/// the `#[reflect_value]` container attribute. +/// the `#[reflect(opaque)]` container attribute. /// /// The only reason this macro exists is so that `bevy_reflect` can easily implement `FromReflect` on -/// primitives and other Rust types internally. +/// primitives and other opaque types internally. /// /// Please note that this macro will not work with any type that [derives `Reflect`] normally -/// or makes use of the [`impl_reflect_value!`] macro, as those macros also implement `FromReflect` +/// or makes use of the [`impl_reflect_opaque!`] macro, as those macros also implement `FromReflect` /// by default. /// /// # Examples /// /// ```ignore (bevy_reflect is not accessible from this crate) -/// impl_from_reflect_value!(foo where T1: Bar); +/// impl_from_reflect_opaque!(foo where T1: Bar); /// ``` /// /// [deriving `FromReflect`]: FromReflect /// [derives `Reflect`]: Reflect #[proc_macro] -pub fn impl_from_reflect_value(input: TokenStream) -> TokenStream { - let def = parse_macro_input!(input with ReflectValueDef::parse_from_reflect); +pub fn impl_from_reflect_opaque(input: TokenStream) -> TokenStream { + let def = parse_macro_input!(input with ReflectOpaqueDef::parse_from_reflect); let default_name = &def.type_path.segments.last().unwrap().ident; let type_path = if def.type_path.leading_colon.is_none() @@ -749,7 +748,7 @@ pub fn impl_from_reflect_value(input: TokenStream) -> TokenStream { }; let from_reflect_impl = - from_reflect::impl_value(&ReflectMeta::new(type_path, def.traits.unwrap_or_default())); + from_reflect::impl_opaque(&ReflectMeta::new(type_path, def.traits.unwrap_or_default())); TokenStream::from(quote! { const _: () = { diff --git a/crates/bevy_reflect/derive/src/reflect_value.rs b/crates/bevy_reflect/derive/src/reflect_opaque.rs similarity index 89% rename from crates/bevy_reflect/derive/src/reflect_value.rs rename to crates/bevy_reflect/derive/src/reflect_opaque.rs index 04cfd6a976..24b92dbeae 100644 --- a/crates/bevy_reflect/derive/src/reflect_value.rs +++ b/crates/bevy_reflect/derive/src/reflect_opaque.rs @@ -5,9 +5,7 @@ use syn::parse::ParseStream; use syn::token::Paren; use syn::{parenthesized, Attribute, Generics, Path}; -/// A struct used to define a simple reflected value type (such as primitives). -/// -/// +/// A struct used to define a simple reflection-opaque types (including primitives). /// /// This takes the form: /// @@ -21,10 +19,10 @@ 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) +/// // With a custom path (not with impl_from_reflect_opaque) /// (in my_crate::bar) Bar(TraitA, TraitB) /// ``` -pub(crate) struct ReflectValueDef { +pub(crate) struct ReflectOpaqueDef { #[cfg_attr( not(feature = "documentation"), expect( @@ -39,7 +37,7 @@ pub(crate) struct ReflectValueDef { pub custom_path: Option, } -impl ReflectValueDef { +impl ReflectOpaqueDef { pub fn parse_reflect(input: ParseStream) -> syn::Result { Self::parse(input, ReflectTraitToImpl::Reflect) } @@ -67,7 +65,7 @@ impl ReflectValueDef { attrs }); } - Ok(ReflectValueDef { + Ok(Self { attrs, type_path, generics, diff --git a/crates/bevy_reflect/derive/src/remote.rs b/crates/bevy_reflect/derive/src/remote.rs index c8194caeca..dab2d0562b 100644 --- a/crates/bevy_reflect/derive/src/remote.rs +++ b/crates/bevy_reflect/derive/src/remote.rs @@ -1,9 +1,7 @@ use crate::derive_data::{ReflectImplSource, ReflectProvenance, ReflectTraitToImpl}; use crate::ident::ident_or_index; use crate::impls::impl_assertions; -use crate::{ - from_reflect, impls, ReflectDerive, REFLECT_ATTRIBUTE_NAME, REFLECT_VALUE_ATTRIBUTE_NAME, -}; +use crate::{from_reflect, impls, ReflectDerive, REFLECT_ATTRIBUTE_NAME}; use bevy_macro_utils::fq_std::FQOption; use proc_macro::TokenStream; use proc_macro2::{Ident, Span}; @@ -70,10 +68,10 @@ pub(crate) fn reflect_remote(args: TokenStream, input: TokenStream) -> TokenStre None }, ), - ReflectDerive::Value(meta) => ( - impls::impl_value(&meta), + ReflectDerive::Opaque(meta) => ( + impls::impl_opaque(&meta), if meta.from_reflect().should_auto_derive() { - Some(from_reflect::impl_value(&meta)) + Some(from_reflect::impl_opaque(&meta)) } else { None }, @@ -114,10 +112,10 @@ fn generate_remote_wrapper(input: &DeriveInput, remote_ty: &TypePath) -> proc_ma let vis = &input.vis; let ty_generics = &input.generics; let where_clause = &input.generics.where_clause; - let attrs = input.attrs.iter().filter(|attr| { - !attr.path().is_ident(REFLECT_ATTRIBUTE_NAME) - && !attr.path().is_ident(REFLECT_VALUE_ATTRIBUTE_NAME) - }); + let attrs = input + .attrs + .iter() + .filter(|attr| !attr.path().is_ident(REFLECT_ATTRIBUTE_NAME)); quote! { #(#attrs)* @@ -407,7 +405,7 @@ fn generate_remote_definition_assertions(derive_data: &ReflectDerive) -> proc_ma } } } - ReflectDerive::Value(_) => { + ReflectDerive::Opaque(_) => { // No assertions needed since there are no fields to check proc_macro2::TokenStream::new() } diff --git a/crates/bevy_reflect/src/impls/glam.rs b/crates/bevy_reflect/src/impls/glam.rs index 8ae372dcbe..11f13692de 100644 --- a/crates/bevy_reflect/src/impls/glam.rs +++ b/crates/bevy_reflect/src/impls/glam.rs @@ -1,6 +1,6 @@ use crate as bevy_reflect; use crate::{std_traits::ReflectDefault, ReflectDeserialize, ReflectSerialize}; -use bevy_reflect_derive::{impl_reflect, impl_reflect_value}; +use bevy_reflect_derive::{impl_reflect, impl_reflect_opaque}; use glam::*; impl_reflect!( @@ -343,8 +343,8 @@ impl_reflect!( } ); -impl_reflect_value!(::glam::BVec3A(Debug, Default, Deserialize, Serialize)); -impl_reflect_value!(::glam::BVec4A(Debug, Default, Deserialize, Serialize)); +impl_reflect_opaque!(::glam::BVec3A(Debug, Default, Deserialize, Serialize)); +impl_reflect_opaque!(::glam::BVec4A(Debug, Default, Deserialize, Serialize)); #[cfg(test)] mod tests { diff --git a/crates/bevy_reflect/src/impls/petgraph.rs b/crates/bevy_reflect/src/impls/petgraph.rs index a4d02b4c87..c4bdaa83e1 100644 --- a/crates/bevy_reflect/src/impls/petgraph.rs +++ b/crates/bevy_reflect/src/impls/petgraph.rs @@ -1,14 +1,14 @@ use crate::{ - self as bevy_reflect, impl_reflect_value, prelude::ReflectDefault, ReflectDeserialize, + self as bevy_reflect, impl_reflect_opaque, prelude::ReflectDefault, ReflectDeserialize, ReflectSerialize, }; -impl_reflect_value!(::petgraph::graph::NodeIndex( +impl_reflect_opaque!(::petgraph::graph::NodeIndex( Default, Serialize, Deserialize )); -impl_reflect_value!(::petgraph::graph::DiGraph< +impl_reflect_opaque!(::petgraph::graph::DiGraph< N: ::std::clone::Clone, E: ::std::clone::Clone, Ix: ::petgraph::graph::IndexType diff --git a/crates/bevy_reflect/src/impls/smol_str.rs b/crates/bevy_reflect/src/impls/smol_str.rs index d8bd625c1f..11e5f9da37 100644 --- a/crates/bevy_reflect/src/impls/smol_str.rs +++ b/crates/bevy_reflect/src/impls/smol_str.rs @@ -1,8 +1,8 @@ use crate::{self as bevy_reflect}; use crate::{std_traits::ReflectDefault, ReflectDeserialize, ReflectSerialize}; -use bevy_reflect_derive::impl_reflect_value; +use bevy_reflect_derive::impl_reflect_opaque; -impl_reflect_value!(::smol_str::SmolStr( +impl_reflect_opaque!(::smol_str::SmolStr( Debug, Hash, PartialEq, diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 7ec8fd246f..e62b3b4e14 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -9,12 +9,12 @@ use crate::{ self as bevy_reflect, impl_type_path, map_apply, map_partial_eq, map_try_apply, reflect::impl_full_reflect, set_apply, set_partial_eq, set_try_apply, ApplyError, Array, ArrayInfo, ArrayIter, DynamicMap, DynamicSet, DynamicTypePath, FromReflect, FromType, - GetTypeRegistration, List, ListInfo, ListIter, Map, MapInfo, MapIter, MaybeTyped, + GetTypeRegistration, List, ListInfo, ListIter, Map, MapInfo, MapIter, MaybeTyped, OpaqueInfo, PartialReflect, Reflect, ReflectDeserialize, ReflectFromPtr, ReflectFromReflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, ReflectSerialize, Set, SetInfo, TypeInfo, TypePath, - TypeRegistration, TypeRegistry, Typed, ValueInfo, + TypeRegistration, TypeRegistry, Typed, }; -use bevy_reflect_derive::{impl_reflect, impl_reflect_value}; +use bevy_reflect_derive::{impl_reflect, impl_reflect_opaque}; use std::fmt; use std::{ any::Any, @@ -24,7 +24,7 @@ use std::{ path::Path, }; -impl_reflect_value!(bool( +impl_reflect_opaque!(bool( Debug, Hash, PartialEq, @@ -32,7 +32,7 @@ impl_reflect_value!(bool( Deserialize, Default )); -impl_reflect_value!(char( +impl_reflect_opaque!(char( Debug, Hash, PartialEq, @@ -40,11 +40,11 @@ impl_reflect_value!(char( Deserialize, Default )); -impl_reflect_value!(u8(Debug, Hash, PartialEq, Serialize, Deserialize, Default)); -impl_reflect_value!(u16(Debug, Hash, PartialEq, Serialize, Deserialize, Default)); -impl_reflect_value!(u32(Debug, Hash, PartialEq, Serialize, Deserialize, Default)); -impl_reflect_value!(u64(Debug, Hash, PartialEq, Serialize, Deserialize, Default)); -impl_reflect_value!(u128( +impl_reflect_opaque!(u8(Debug, Hash, PartialEq, Serialize, Deserialize, Default)); +impl_reflect_opaque!(u16(Debug, Hash, PartialEq, Serialize, Deserialize, Default)); +impl_reflect_opaque!(u32(Debug, Hash, PartialEq, Serialize, Deserialize, Default)); +impl_reflect_opaque!(u64(Debug, Hash, PartialEq, Serialize, Deserialize, Default)); +impl_reflect_opaque!(u128( Debug, Hash, PartialEq, @@ -52,7 +52,7 @@ impl_reflect_value!(u128( Deserialize, Default )); -impl_reflect_value!(usize( +impl_reflect_opaque!(usize( Debug, Hash, PartialEq, @@ -60,11 +60,11 @@ impl_reflect_value!(usize( Deserialize, Default )); -impl_reflect_value!(i8(Debug, Hash, PartialEq, Serialize, Deserialize, Default)); -impl_reflect_value!(i16(Debug, Hash, PartialEq, Serialize, Deserialize, Default)); -impl_reflect_value!(i32(Debug, Hash, PartialEq, Serialize, Deserialize, Default)); -impl_reflect_value!(i64(Debug, Hash, PartialEq, Serialize, Deserialize, Default)); -impl_reflect_value!(i128( +impl_reflect_opaque!(i8(Debug, Hash, PartialEq, Serialize, Deserialize, Default)); +impl_reflect_opaque!(i16(Debug, Hash, PartialEq, Serialize, Deserialize, Default)); +impl_reflect_opaque!(i32(Debug, Hash, PartialEq, Serialize, Deserialize, Default)); +impl_reflect_opaque!(i64(Debug, Hash, PartialEq, Serialize, Deserialize, Default)); +impl_reflect_opaque!(i128( Debug, Hash, PartialEq, @@ -72,7 +72,7 @@ impl_reflect_value!(i128( Deserialize, Default )); -impl_reflect_value!(isize( +impl_reflect_opaque!(isize( Debug, Hash, PartialEq, @@ -80,10 +80,10 @@ impl_reflect_value!(isize( Deserialize, Default )); -impl_reflect_value!(f32(Debug, PartialEq, Serialize, Deserialize, Default)); -impl_reflect_value!(f64(Debug, PartialEq, Serialize, Deserialize, Default)); +impl_reflect_opaque!(f32(Debug, PartialEq, Serialize, Deserialize, Default)); +impl_reflect_opaque!(f64(Debug, PartialEq, Serialize, Deserialize, Default)); impl_type_path!(str); -impl_reflect_value!(::alloc::string::String( +impl_reflect_opaque!(::alloc::string::String( Debug, Hash, PartialEq, @@ -91,7 +91,7 @@ impl_reflect_value!(::alloc::string::String( Deserialize, Default )); -impl_reflect_value!(::std::path::PathBuf( +impl_reflect_opaque!(::std::path::PathBuf( Debug, Hash, PartialEq, @@ -99,16 +99,16 @@ impl_reflect_value!(::std::path::PathBuf( Deserialize, Default )); -impl_reflect_value!(::std::any::TypeId(Debug, Hash, PartialEq,)); -impl_reflect_value!(::std::collections::BTreeSet()); -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!(::std::ops::Bound()); -impl_reflect_value!(::bevy_utils::Duration( +impl_reflect_opaque!(::std::any::TypeId(Debug, Hash, PartialEq,)); +impl_reflect_opaque!(::std::collections::BTreeSet()); +impl_reflect_opaque!(::core::ops::Range()); +impl_reflect_opaque!(::core::ops::RangeInclusive()); +impl_reflect_opaque!(::core::ops::RangeFrom()); +impl_reflect_opaque!(::core::ops::RangeTo()); +impl_reflect_opaque!(::core::ops::RangeToInclusive()); +impl_reflect_opaque!(::core::ops::RangeFull()); +impl_reflect_opaque!(::std::ops::Bound()); +impl_reflect_opaque!(::bevy_utils::Duration( Debug, Hash, PartialEq, @@ -116,99 +116,99 @@ impl_reflect_value!(::bevy_utils::Duration( Deserialize, Default )); -impl_reflect_value!(::bevy_utils::Instant(Debug, Hash, PartialEq)); -impl_reflect_value!(::core::num::NonZeroI128( +impl_reflect_opaque!(::bevy_utils::Instant(Debug, Hash, PartialEq)); +impl_reflect_opaque!(::core::num::NonZeroI128( Debug, Hash, PartialEq, Serialize, Deserialize )); -impl_reflect_value!(::core::num::NonZeroU128( +impl_reflect_opaque!(::core::num::NonZeroU128( Debug, Hash, PartialEq, Serialize, Deserialize )); -impl_reflect_value!(::core::num::NonZeroIsize( +impl_reflect_opaque!(::core::num::NonZeroIsize( Debug, Hash, PartialEq, Serialize, Deserialize )); -impl_reflect_value!(::core::num::NonZeroUsize( +impl_reflect_opaque!(::core::num::NonZeroUsize( Debug, Hash, PartialEq, Serialize, Deserialize )); -impl_reflect_value!(::core::num::NonZeroI64( +impl_reflect_opaque!(::core::num::NonZeroI64( Debug, Hash, PartialEq, Serialize, Deserialize )); -impl_reflect_value!(::core::num::NonZeroU64( +impl_reflect_opaque!(::core::num::NonZeroU64( Debug, Hash, PartialEq, Serialize, Deserialize )); -impl_reflect_value!(::core::num::NonZeroU32( +impl_reflect_opaque!(::core::num::NonZeroU32( Debug, Hash, PartialEq, Serialize, Deserialize )); -impl_reflect_value!(::core::num::NonZeroI32( +impl_reflect_opaque!(::core::num::NonZeroI32( Debug, Hash, PartialEq, Serialize, Deserialize )); -impl_reflect_value!(::core::num::NonZeroI16( +impl_reflect_opaque!(::core::num::NonZeroI16( Debug, Hash, PartialEq, Serialize, Deserialize )); -impl_reflect_value!(::core::num::NonZeroU16( +impl_reflect_opaque!(::core::num::NonZeroU16( Debug, Hash, PartialEq, Serialize, Deserialize )); -impl_reflect_value!(::core::num::NonZeroU8( +impl_reflect_opaque!(::core::num::NonZeroU8( Debug, Hash, PartialEq, Serialize, Deserialize )); -impl_reflect_value!(::core::num::NonZeroI8( +impl_reflect_opaque!(::core::num::NonZeroI8( Debug, Hash, PartialEq, Serialize, Deserialize )); -impl_reflect_value!(::core::num::Wrapping()); -impl_reflect_value!(::core::num::Saturating()); -impl_reflect_value!(::std::sync::Arc); +impl_reflect_opaque!(::core::num::Wrapping()); +impl_reflect_opaque!(::core::num::Saturating()); +impl_reflect_opaque!(::std::sync::Arc); // `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!(::std::ffi::OsString( +impl_reflect_opaque!(::std::ffi::OsString( Debug, Hash, PartialEq, @@ -216,8 +216,8 @@ impl_reflect_value!(::std::ffi::OsString( Deserialize )); #[cfg(not(any(unix, windows)))] -impl_reflect_value!(::std::ffi::OsString(Debug, Hash, PartialEq)); -impl_reflect_value!(::alloc::collections::BinaryHeap); +impl_reflect_opaque!(::std::ffi::OsString(Debug, Hash, PartialEq)); +impl_reflect_opaque!(::alloc::collections::BinaryHeap); macro_rules! impl_reflect_for_atomic { ($ty:ty, $ordering:expr) => { @@ -250,8 +250,8 @@ macro_rules! impl_reflect_for_atomic { fn type_info() -> &'static TypeInfo { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); CELL.get_or_set(|| { - let info = ValueInfo::new::(); - TypeInfo::Value(info) + let info = OpaqueInfo::new::(); + TypeInfo::Opaque(info) }) } } @@ -308,19 +308,19 @@ macro_rules! impl_reflect_for_atomic { } #[inline] fn reflect_kind(&self) -> ReflectKind { - ReflectKind::Value + ReflectKind::Opaque } #[inline] fn reflect_ref(&self) -> ReflectRef { - ReflectRef::Value(self) + ReflectRef::Opaque(self) } #[inline] fn reflect_mut(&mut self) -> ReflectMut { - ReflectMut::Value(self) + ReflectMut::Opaque(self) } #[inline] fn reflect_owned(self: Box) -> ReflectOwned { - ReflectOwned::Value(self) + ReflectOwned::Opaque(self) } fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(self, f) @@ -1542,19 +1542,19 @@ impl PartialReflect for Cow<'static, str> { } fn reflect_kind(&self) -> ReflectKind { - ReflectKind::Value + ReflectKind::Opaque } fn reflect_ref(&self) -> ReflectRef { - ReflectRef::Value(self) + ReflectRef::Opaque(self) } fn reflect_mut(&mut self) -> ReflectMut { - ReflectMut::Value(self) + ReflectMut::Opaque(self) } fn reflect_owned(self: Box) -> ReflectOwned { - ReflectOwned::Value(self) + ReflectOwned::Opaque(self) } fn clone_value(&self) -> Box { @@ -1599,7 +1599,7 @@ impl_full_reflect!(for Cow<'static, str>); impl Typed for Cow<'static, str> { fn type_info() -> &'static TypeInfo { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); - CELL.get_or_set(|| TypeInfo::Value(ValueInfo::new::())) + CELL.get_or_set(|| TypeInfo::Opaque(OpaqueInfo::new::())) } } @@ -1844,15 +1844,15 @@ impl PartialReflect for &'static str { } fn reflect_ref(&self) -> ReflectRef { - ReflectRef::Value(self) + ReflectRef::Opaque(self) } fn reflect_mut(&mut self) -> ReflectMut { - ReflectMut::Value(self) + ReflectMut::Opaque(self) } fn reflect_owned(self: Box) -> ReflectOwned { - ReflectOwned::Value(self) + ReflectOwned::Opaque(self) } fn clone_value(&self) -> Box { @@ -1925,7 +1925,7 @@ impl Reflect for &'static str { impl Typed for &'static str { fn type_info() -> &'static TypeInfo { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); - CELL.get_or_set(|| TypeInfo::Value(ValueInfo::new::())) + CELL.get_or_set(|| TypeInfo::Opaque(OpaqueInfo::new::())) } } @@ -1978,19 +1978,19 @@ impl PartialReflect for &'static Path { } fn reflect_kind(&self) -> ReflectKind { - ReflectKind::Value + ReflectKind::Opaque } fn reflect_ref(&self) -> ReflectRef { - ReflectRef::Value(self) + ReflectRef::Opaque(self) } fn reflect_mut(&mut self) -> ReflectMut { - ReflectMut::Value(self) + ReflectMut::Opaque(self) } fn reflect_owned(self: Box) -> ReflectOwned { - ReflectOwned::Value(self) + ReflectOwned::Opaque(self) } fn clone_value(&self) -> Box { @@ -2059,7 +2059,7 @@ impl Reflect for &'static Path { impl Typed for &'static Path { fn type_info() -> &'static TypeInfo { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); - CELL.get_or_set(|| TypeInfo::Value(ValueInfo::new::())) + CELL.get_or_set(|| TypeInfo::Opaque(OpaqueInfo::new::())) } } @@ -2111,19 +2111,19 @@ impl PartialReflect for Cow<'static, Path> { } fn reflect_kind(&self) -> ReflectKind { - ReflectKind::Value + ReflectKind::Opaque } fn reflect_ref(&self) -> ReflectRef { - ReflectRef::Value(self) + ReflectRef::Opaque(self) } fn reflect_mut(&mut self) -> ReflectMut { - ReflectMut::Value(self) + ReflectMut::Opaque(self) } fn reflect_owned(self: Box) -> ReflectOwned { - ReflectOwned::Value(self) + ReflectOwned::Opaque(self) } fn clone_value(&self) -> Box { @@ -2196,7 +2196,7 @@ impl Reflect for Cow<'static, Path> { impl Typed for Cow<'static, Path> { fn type_info() -> &'static TypeInfo { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); - CELL.get_or_set(|| TypeInfo::Value(ValueInfo::new::())) + CELL.get_or_set(|| TypeInfo::Opaque(OpaqueInfo::new::())) } } diff --git a/crates/bevy_reflect/src/impls/uuid.rs b/crates/bevy_reflect/src/impls/uuid.rs index f845dda798..71f708c4d1 100644 --- a/crates/bevy_reflect/src/impls/uuid.rs +++ b/crates/bevy_reflect/src/impls/uuid.rs @@ -1,9 +1,9 @@ use crate as bevy_reflect; use crate::{std_traits::ReflectDefault, ReflectDeserialize, ReflectSerialize}; -use bevy_reflect_derive::impl_reflect_value; +use bevy_reflect_derive::impl_reflect_opaque; -impl_reflect_value!(::uuid::Uuid( +impl_reflect_opaque!(::uuid::Uuid( Serialize, Deserialize, Default, diff --git a/crates/bevy_reflect/src/impls/wgpu_types.rs b/crates/bevy_reflect/src/impls/wgpu_types.rs index c6b547d811..6f99b5d496 100644 --- a/crates/bevy_reflect/src/impls/wgpu_types.rs +++ b/crates/bevy_reflect/src/impls/wgpu_types.rs @@ -1,5 +1,6 @@ -use crate::{self as bevy_reflect, impl_reflect_value, ReflectDeserialize, ReflectSerialize}; -impl_reflect_value!(::wgpu_types::TextureFormat( +use crate::{self as bevy_reflect, impl_reflect_opaque, ReflectDeserialize, ReflectSerialize}; + +impl_reflect_opaque!(::wgpu_types::TextureFormat( Debug, Hash, PartialEq, diff --git a/crates/bevy_reflect/src/kind.rs b/crates/bevy_reflect/src/kind.rs index bd6dfd0434..079f315078 100644 --- a/crates/bevy_reflect/src/kind.rs +++ b/crates/bevy_reflect/src/kind.rs @@ -50,17 +50,21 @@ pub enum ReflectKind { /// [function-like]: Function #[cfg(feature = "functions")] Function, - /// A value-like type. + /// An opaque type. /// - /// This most often represents a primitive or opaque type, - /// where it is not possible, difficult, or not useful to reflect the type further. + /// This most often represents a type where it is either impossible, difficult, + /// or unuseful to reflect the type further. /// - /// For example, `u32` and `String` are examples of value-like types. - /// Additionally, any type that derives [`Reflect`] with the `#[reflect_value]` attribute - /// will be considered a value-like type. + /// This includes types like `String` and `Instant`. /// - /// [`Reflect`]: crate::Reflect - Value, + /// Despite not technically being opaque types, + /// primitives like `u32` `i32` are considered opaque for the purposes of reflection. + /// + /// Additionally, any type that [derives `Reflect`] with the `#[reflect(opaque)]` attribute + /// will be considered an opaque type. + /// + /// [derives `Reflect`]: bevy_reflect_derive::Reflect + Opaque, } impl std::fmt::Display for ReflectKind { @@ -76,7 +80,7 @@ impl std::fmt::Display for ReflectKind { ReflectKind::Enum => f.pad("enum"), #[cfg(feature = "functions")] ReflectKind::Function => f.pad("function"), - ReflectKind::Value => f.pad("value"), + ReflectKind::Opaque => f.pad("opaque"), } } } @@ -97,7 +101,7 @@ macro_rules! impl_reflect_kind_conversions { Self::Enum(_) => ReflectKind::Enum, #[cfg(feature = "functions")] Self::Function(_) => ReflectKind::Function, - Self::Value(_) => ReflectKind::Value, + Self::Opaque(_) => ReflectKind::Opaque, } } } @@ -115,7 +119,7 @@ macro_rules! impl_reflect_kind_conversions { $name::Enum(_) => Self::Enum, #[cfg(feature = "functions")] $name::Function(_) => Self::Function, - $name::Value(_) => Self::Value, + $name::Opaque(_) => Self::Opaque, } } } @@ -133,14 +137,14 @@ pub struct ReflectKindMismatchError { } macro_rules! impl_cast_method { - ($name:ident : Value => $retval:ty) => { + ($name:ident : Opaque => $retval:ty) => { #[doc = "Attempts a cast to a [`PartialReflect`] trait object."] - #[doc = "\n\nReturns an error if `self` is not the [`Self::Value`] variant."] + #[doc = "\n\nReturns an error if `self` is not the [`Self::Opaque`] variant."] pub fn $name(self) -> Result<$retval, ReflectKindMismatchError> { match self { - Self::Value(value) => Ok(value), + Self::Opaque(value) => Ok(value), _ => Err(ReflectKindMismatchError { - expected: ReflectKind::Value, + expected: ReflectKind::Opaque, received: self.kind(), }), } @@ -180,7 +184,7 @@ pub enum ReflectRef<'a> { Enum(&'a dyn Enum), #[cfg(feature = "functions")] Function(&'a dyn Function), - Value(&'a dyn PartialReflect), + Opaque(&'a dyn PartialReflect), } impl_reflect_kind_conversions!(ReflectRef<'_>); @@ -193,7 +197,7 @@ impl<'a> ReflectRef<'a> { impl_cast_method!(as_map: Map => &'a dyn Map); impl_cast_method!(as_set: Set => &'a dyn Set); impl_cast_method!(as_enum: Enum => &'a dyn Enum); - impl_cast_method!(as_value: Value => &'a dyn PartialReflect); + impl_cast_method!(as_opaque: Opaque => &'a dyn PartialReflect); } /// A mutable enumeration of ["kinds"] of a reflected type. @@ -215,7 +219,7 @@ pub enum ReflectMut<'a> { Enum(&'a mut dyn Enum), #[cfg(feature = "functions")] Function(&'a mut dyn Function), - Value(&'a mut dyn PartialReflect), + Opaque(&'a mut dyn PartialReflect), } impl_reflect_kind_conversions!(ReflectMut<'_>); @@ -228,7 +232,7 @@ impl<'a> ReflectMut<'a> { impl_cast_method!(as_map: Map => &'a mut dyn Map); impl_cast_method!(as_set: Set => &'a mut dyn Set); impl_cast_method!(as_enum: Enum => &'a mut dyn Enum); - impl_cast_method!(as_value: Value => &'a mut dyn PartialReflect); + impl_cast_method!(as_opaque: Opaque => &'a mut dyn PartialReflect); } /// An owned enumeration of ["kinds"] of a reflected type. @@ -250,7 +254,7 @@ pub enum ReflectOwned { Enum(Box), #[cfg(feature = "functions")] Function(Box), - Value(Box), + Opaque(Box), } impl_reflect_kind_conversions!(ReflectOwned); @@ -263,7 +267,7 @@ impl ReflectOwned { impl_cast_method!(into_map: Map => Box); impl_cast_method!(into_set: Set => Box); impl_cast_method!(into_enum: Enum => Box); - impl_cast_method!(into_value: Value => Box); + impl_cast_method!(into_value: Opaque => Box); } #[cfg(test)] diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index db9dfff9cf..4bdc65b318 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -164,15 +164,17 @@ //! we can just use the matching [`PartialReflect::as_partial_reflect`], [`PartialReflect::as_partial_reflect_mut`], //! or [`PartialReflect::into_partial_reflect`] methods. //! -//! ## Value Types +//! ## Opaque Types //! -//! Types that do not fall under one of the above subtraits, -//! such as for primitives (e.g. `bool`, `usize`, etc.) -//! and simple types (e.g. `String`, `Duration`), -//! are referred to as _value_ types -//! since methods like [`PartialReflect::reflect_ref`] return a [`ReflectRef::Value`] variant. -//! While most other types contain their own `dyn Reflect` fields and data, -//! these types generally cannot be broken down any further. +//! Some types don't fall under a particular subtrait. +//! +//! These types hide their internal structure to reflection, +//! either because it is not possible, difficult, or not useful to reflect its internals. +//! Such types are known as _opaque_ types. +//! +//! This includes truly opaque types like `String` or `Instant`, +//! but also includes all the primitive types (e.g. `bool`, `usize`, etc.) +//! since they can't be broken down any further. //! //! # Dynamic Types //! @@ -198,7 +200,7 @@ //! //! They are most commonly used as "proxies" for other types, //! where they contain the same data as— and therefore, represent— a concrete type. -//! The [`PartialReflect::clone_value`] method will return a dynamic type for all non-value types, +//! The [`PartialReflect::clone_value`] method will return a dynamic type for all non-opaque types, //! allowing all types to essentially be "cloned". //! And since dynamic types themselves implement [`PartialReflect`], //! we may pass them around just like most other reflected types. @@ -398,7 +400,7 @@ //! The `TypedReflectSerializer` will simply output the serialized data. //! //! The `ReflectDeserializer` can be used to deserialize this map and return a `Box`, -//! where the underlying type will be a dynamic type representing some concrete type (except for value types). +//! where the underlying type will be a dynamic type representing some concrete type (except for opaque types). //! //! Again, it's important to remember that dynamic types may need to be converted to their concrete counterparts //! in order to be used in certain cases. @@ -1792,7 +1794,7 @@ mod tests { // Cow<'static, str> type MyCowStr = Cow<'static, str>; - let info = MyCowStr::type_info().as_value().unwrap(); + let info = MyCowStr::type_info().as_opaque().unwrap(); assert!(info.is::()); assert_eq!(std::any::type_name::(), info.type_path()); @@ -1837,7 +1839,7 @@ mod tests { // Value type MyValue = String; - let info = MyValue::type_info().as_value().unwrap(); + let info = MyValue::type_info().as_opaque().unwrap(); assert!(info.is::()); assert_eq!(MyValue::type_path(), info.type_path()); @@ -1956,7 +1958,7 @@ mod tests { #[derive(Clone)] struct SomePrimitive; - impl_reflect_value!( + impl_reflect_opaque!( /// Some primitive for which we have attributed custom documentation. (in bevy_reflect::tests) SomePrimitive ); @@ -2172,27 +2174,6 @@ bevy_reflect::tests::Test { assert_eq!("Foo".to_string(), format!("{foo:?}")); } - #[test] - fn multiple_reflect_value_lists() { - #[derive(Clone, Hash, PartialEq, Reflect)] - #[reflect_value(Debug, Hash)] - #[reflect_value(PartialEq)] - struct Foo(i32); - - impl Debug for Foo { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "Foo") - } - } - - let foo = Foo(123); - let foo: &dyn PartialReflect = &foo; - - assert!(foo.reflect_hash().is_some()); - assert_eq!(Some(true), foo.reflect_partial_eq(foo)); - assert_eq!("Foo".to_string(), format!("{foo:?}")); - } - #[test] fn custom_debug_function() { #[derive(Reflect)] @@ -2591,7 +2572,8 @@ bevy_reflect::tests::Test { // === Remote Wrapper === // #[reflect_remote(external_crate::TheirType)] #[derive(Clone, Debug, Default)] - #[reflect_value(Debug, Default)] + #[reflect(opaque)] + #[reflect(Debug, Default)] struct MyType { pub value: String, } diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index efb1b6fe47..0c8550107c 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -1,8 +1,7 @@ use crate::{ array_debug, enum_debug, list_debug, map_debug, serde::Serializable, set_debug, struct_debug, - tuple_debug, tuple_struct_debug, DynamicTypePath, DynamicTyped, ReflectKind, + tuple_debug, tuple_struct_debug, DynamicTypePath, DynamicTyped, OpaqueInfo, ReflectKind, ReflectKindMismatchError, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, Typed, - ValueInfo, }; use std::{ any::{Any, TypeId}, @@ -178,7 +177,7 @@ where /// a `List`, while `value` is a `Struct`). /// - If `T` is any complex type and the corresponding fields or elements of /// `self` and `value` are not of the same type. - /// - If `T` is a value type and `self` cannot be downcast to `T` + /// - If `T` is an opaque type and `self` cannot be downcast to `T` fn apply(&mut self, value: &dyn PartialReflect) { PartialReflect::try_apply(self, value).unwrap(); } @@ -266,7 +265,7 @@ where ReflectRef::Enum(dyn_enum) => enum_debug(dyn_enum, f), #[cfg(feature = "functions")] ReflectRef::Function(dyn_function) => dyn_function.fmt(f), - ReflectRef::Value(_) => write!(f, "Reflect({})", self.reflect_type_path()), + ReflectRef::Opaque(_) => write!(f, "Reflect({})", self.reflect_type_path()), } } @@ -497,7 +496,7 @@ impl Debug for dyn Reflect { impl Typed for dyn Reflect { fn type_info() -> &'static TypeInfo { static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new(); - CELL.get_or_set(|| TypeInfo::Value(ValueInfo::new::())) + CELL.get_or_set(|| TypeInfo::Opaque(OpaqueInfo::new::())) } } diff --git a/crates/bevy_reflect/src/serde/de/deserializer.rs b/crates/bevy_reflect/src/serde/de/deserializer.rs index 7af7aa0997..46530c2fe0 100644 --- a/crates/bevy_reflect/src/serde/de/deserializer.rs +++ b/crates/bevy_reflect/src/serde/de/deserializer.rs @@ -32,7 +32,7 @@ use std::fmt; /// /// This deserializer will return a [`Box`] containing the deserialized data. /// -/// For value types (i.e. [`ReflectKind::Value`]) or types that register [`ReflectDeserialize`] type data, +/// For opaque types (i.e. [`ReflectKind::Opaque`]) or types that register [`ReflectDeserialize`] type data, /// this `Box` will contain the expected type. /// For example, deserializing an `i32` will return a `Box` (as a `Box`). /// @@ -69,7 +69,7 @@ use std::fmt; /// /// let output: Box = reflect_deserializer.deserialize(&mut deserializer).unwrap(); /// -/// // Since `MyStruct` is not a value type and does not register `ReflectDeserialize`, +/// // Since `MyStruct` is not an opaque type and does not register `ReflectDeserialize`, /// // we know that its deserialized value will be a `DynamicStruct`, /// // although it will represent `MyStruct`. /// assert!(output.as_partial_reflect().represents::()); @@ -89,7 +89,7 @@ use std::fmt; /// [`ReflectSerializer`]: crate::serde::ReflectSerializer /// [type path]: crate::TypePath::type_path /// [`Box`]: crate::Reflect -/// [`ReflectKind::Value`]: crate::ReflectKind::Value +/// [`ReflectKind::Opaque`]: crate::ReflectKind::Opaque /// [`ReflectDeserialize`]: crate::ReflectDeserialize /// [`Box`]: crate::DynamicStruct /// [`Box`]: crate::DynamicList @@ -165,7 +165,7 @@ impl<'a, 'de> DeserializeSeed<'de> for ReflectDeserializer<'a> { /// /// This deserializer will return a [`Box`] containing the deserialized data. /// -/// For value types (i.e. [`ReflectKind::Value`]) or types that register [`ReflectDeserialize`] type data, +/// For opaque types (i.e. [`ReflectKind::Opaque`]) or types that register [`ReflectDeserialize`] type data, /// this `Box` will contain the expected type. /// For example, deserializing an `i32` will return a `Box` (as a `Box`). /// @@ -202,7 +202,7 @@ impl<'a, 'de> DeserializeSeed<'de> for ReflectDeserializer<'a> { /// /// let output: Box = reflect_deserializer.deserialize(&mut deserializer).unwrap(); /// -/// // Since `MyStruct` is not a value type and does not register `ReflectDeserialize`, +/// // Since `MyStruct` is not an opaque type and does not register `ReflectDeserialize`, /// // we know that its deserialized value will be a `DynamicStruct`, /// // although it will represent `MyStruct`. /// assert!(output.as_partial_reflect().represents::()); @@ -221,7 +221,7 @@ impl<'a, 'de> DeserializeSeed<'de> for ReflectDeserializer<'a> { /// /// [`TypedReflectSerializer`]: crate::serde::TypedReflectSerializer /// [`Box`]: crate::Reflect -/// [`ReflectKind::Value`]: crate::ReflectKind::Value +/// [`ReflectKind::Opaque`]: crate::ReflectKind::Opaque /// [`ReflectDeserialize`]: crate::ReflectDeserialize /// [`Box`]: crate::DynamicStruct /// [`Box`]: crate::DynamicList @@ -345,7 +345,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> { dynamic_enum.set_represented_type(Some(self.registration.type_info())); Ok(Box::new(dynamic_enum)) } - TypeInfo::Value(_) => { + TypeInfo::Opaque(_) => { // This case should already be handled Err(make_custom_error(format_args!( "type `{type_path}` did not register the `ReflectDeserialize` type data. For certain types, this may need to be registered manually using `register_type_data`", diff --git a/crates/bevy_reflect/src/serde/ser/serializer.rs b/crates/bevy_reflect/src/serde/ser/serializer.rs index a6c6d56db6..f6fd518e73 100644 --- a/crates/bevy_reflect/src/serde/ser/serializer.rs +++ b/crates/bevy_reflect/src/serde/ser/serializer.rs @@ -196,7 +196,7 @@ impl<'a> Serialize for TypedReflectSerializer<'a> { } #[cfg(feature = "functions")] ReflectRef::Function(_) => Err(make_custom_error("functions cannot be serialized")), - ReflectRef::Value(_) => Err(serializable.err().unwrap()), + ReflectRef::Opaque(_) => Err(serializable.err().unwrap()), }; #[cfg(feature = "debug_stack")] diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index d1ff268123..d667dda3bb 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -32,7 +32,7 @@ use thiserror::Error; /// /// ``` /// # use std::any::Any; -/// # use bevy_reflect::{DynamicTypePath, NamedField, PartialReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, TypeInfo, TypePath, ValueInfo, ApplyError}; +/// # use bevy_reflect::{DynamicTypePath, NamedField, PartialReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, TypeInfo, TypePath, OpaqueInfo, ApplyError}; /// # use bevy_reflect::utility::NonGenericTypeInfoCell; /// use bevy_reflect::Typed; /// @@ -207,7 +207,7 @@ pub enum TypeInfo { Map(MapInfo), Set(SetInfo), Enum(EnumInfo), - Value(ValueInfo), + Opaque(OpaqueInfo), } impl TypeInfo { @@ -224,7 +224,7 @@ impl TypeInfo { Self::Map(info) => info.ty(), Self::Set(info) => info.ty(), Self::Enum(info) => info.ty(), - Self::Value(info) => info.ty(), + Self::Opaque(info) => info.ty(), } } @@ -272,7 +272,7 @@ impl TypeInfo { Self::Map(info) => info.docs(), Self::Set(info) => info.docs(), Self::Enum(info) => info.docs(), - Self::Value(info) => info.docs(), + Self::Opaque(info) => info.docs(), } } @@ -289,7 +289,7 @@ impl TypeInfo { Self::Map(_) => ReflectKind::Map, Self::Set(_) => ReflectKind::Set, Self::Enum(_) => ReflectKind::Enum, - Self::Value(_) => ReflectKind::Value, + Self::Opaque(_) => ReflectKind::Opaque, } } } @@ -319,7 +319,7 @@ impl TypeInfo { impl_cast_method!(as_array: Array => ArrayInfo); impl_cast_method!(as_map: Map => MapInfo); impl_cast_method!(as_enum: Enum => EnumInfo); - impl_cast_method!(as_value: Value => ValueInfo); + impl_cast_method!(as_opaque: Opaque => OpaqueInfo); } /// The base representation of a Rust type. @@ -516,22 +516,22 @@ macro_rules! impl_type_methods { pub(crate) use impl_type_methods; -/// A container for compile-time info related to general value types, including primitives. +/// A container for compile-time info related to reflection-opaque types, including primitives. /// /// This typically represents a type which cannot be broken down any further. This is often /// due to technical reasons (or by definition), but it can also be a purposeful choice. /// -/// For example, [`i32`] cannot be broken down any further, so it is represented by a [`ValueInfo`]. +/// For example, [`i32`] cannot be broken down any further, so it is represented by an [`OpaqueInfo`]. /// And while [`String`] itself is a struct, its fields are private, so we don't really treat -/// it _as_ a struct. It therefore makes more sense to represent it as a [`ValueInfo`]. +/// it _as_ a struct. It therefore makes more sense to represent it as an [`OpaqueInfo`]. #[derive(Debug, Clone)] -pub struct ValueInfo { +pub struct OpaqueInfo { ty: Type, #[cfg(feature = "documentation")] docs: Option<&'static str>, } -impl ValueInfo { +impl OpaqueInfo { pub fn new() -> Self { Self { ty: Type::of::(), @@ -540,7 +540,7 @@ impl ValueInfo { } } - /// Sets the docstring for this value. + /// Sets the docstring for this type. #[cfg(feature = "documentation")] pub fn with_docs(self, doc: Option<&'static str>) -> Self { Self { docs: doc, ..self } @@ -548,7 +548,7 @@ impl ValueInfo { impl_type_methods!(ty); - /// The docstring of this dynamic value, if any. + /// The docstring of this dynamic type, if any. #[cfg(feature = "documentation")] pub fn docs(&self) -> Option<&'static str> { self.docs diff --git a/crates/bevy_render/src/camera/camera.rs b/crates/bevy_render/src/camera/camera.rs index 654254fd9b..f58f75aaf8 100644 --- a/crates/bevy_render/src/camera/camera.rs +++ b/crates/bevy_render/src/camera/camera.rs @@ -92,7 +92,8 @@ pub struct ComputedCameraValues { /// /// #[derive(Component, Clone, Copy, Reflect)] -#[reflect_value(Component, Default)] +#[reflect(opaque)] +#[reflect(Component, Default)] pub struct Exposure { /// pub ev100: f32, @@ -614,7 +615,8 @@ impl Default for CameraOutputMode { /// Configures the [`RenderGraph`](crate::render_graph::RenderGraph) name assigned to be run for a given [`Camera`] entity. #[derive(Component, Debug, Deref, DerefMut, Reflect, Clone)] -#[reflect_value(Component, Debug)] +#[reflect(opaque)] +#[reflect(Component, Debug)] pub struct CameraRenderGraph(InternedRenderSubGraph); impl CameraRenderGraph { @@ -901,7 +903,8 @@ pub fn camera_system( /// This component lets you control the [`TextureUsages`] field of the main texture generated for the camera #[derive(Component, ExtractComponent, Clone, Copy, Reflect)] -#[reflect_value(Component, Default)] +#[reflect(opaque)] +#[reflect(Component, Default)] pub struct CameraMainTextureUsages(pub TextureUsages); impl Default for CameraMainTextureUsages { fn default() -> Self { diff --git a/crates/bevy_render/src/render_asset.rs b/crates/bevy_render/src/render_asset.rs index 6ba181d77d..5705e0ba71 100644 --- a/crates/bevy_render/src/render_asset.rs +++ b/crates/bevy_render/src/render_asset.rs @@ -91,7 +91,8 @@ bitflags::bitflags! { /// details. #[repr(transparent)] #[derive(Serialize, Deserialize, Hash, Clone, Copy, PartialEq, Eq, Debug, Reflect)] - #[reflect_value(Serialize, Deserialize, Hash, PartialEq, Debug)] + #[reflect(opaque)] + #[reflect(Serialize, Deserialize, Hash, PartialEq, Debug)] pub struct RenderAssetUsages: u8 { const MAIN_WORLD = 1 << 0; const RENDER_WORLD = 1 << 1; diff --git a/crates/bevy_render/src/storage.rs b/crates/bevy_render/src/storage.rs index 4c6baed318..0eb6adaea0 100644 --- a/crates/bevy_render/src/storage.rs +++ b/crates/bevy_render/src/storage.rs @@ -27,7 +27,8 @@ impl Plugin for StoragePlugin { /// A storage buffer that is prepared as a [`RenderAsset`] and uploaded to the GPU. #[derive(Asset, Reflect, Debug, Clone)] -#[reflect_value(Default)] +#[reflect(opaque)] +#[reflect(Default, Debug)] pub struct ShaderStorageBuffer { /// Optional data used to initialize the buffer. pub data: Option>, diff --git a/crates/bevy_render/src/texture/image.rs b/crates/bevy_render/src/texture/image.rs index 55b1560a90..bd3b8e01fd 100644 --- a/crates/bevy_render/src/texture/image.rs +++ b/crates/bevy_render/src/texture/image.rs @@ -167,7 +167,8 @@ impl ImageFormat { } #[derive(Asset, Reflect, Debug, Clone)] -#[reflect_value(Default)] +#[reflect(opaque)] +#[reflect(Default, Debug)] pub struct Image { pub data: Vec, // TODO: this nesting makes accessing Image metadata verbose. Either flatten out descriptor or add accessors diff --git a/examples/reflection/reflection.rs b/examples/reflection/reflection.rs index 283c1c6d18..ba1c4c67ea 100644 --- a/examples/reflection/reflection.rs +++ b/examples/reflection/reflection.rs @@ -104,7 +104,7 @@ fn setup(type_registry: Res) { // Deserializing returns a `Box` value. // Generally, deserializing a value will return the "dynamic" variant of a type. // For example, deserializing a struct will return the DynamicStruct type. - // "Value types" will be deserialized as themselves. + // "Opaque types" will be deserialized as themselves. assert_eq!( reflect_value.reflect_type_path(), DynamicStruct::type_path(), diff --git a/examples/reflection/reflection_types.rs b/examples/reflection/reflection_types.rs index ae083995d8..a097b6e6a6 100644 --- a/examples/reflection/reflection_types.rs +++ b/examples/reflection/reflection_types.rs @@ -53,12 +53,12 @@ pub struct E { } /// By default, deriving with Reflect assumes the type is either a "struct" or an "enum". -/// You can tell reflect to treat your type instead as a "value type" by using the `reflect_value` -/// attribute in place of `reflect`. It is generally a good idea to implement (and reflect) -/// the `PartialEq`, `Serialize`, and `Deserialize` traits on `reflect_value` types to ensure -/// that these values behave as expected when nested underneath Reflect-ed structs. +/// You can tell reflect to treat your type instead as an "opaque type" by using the `#[reflect(opaque)]`. +/// It is generally a good idea to implement (and reflect) the `PartialEq`, `Serialize`, and `Deserialize` +/// traits on opaque types to ensure that these values behave as expected when nested in other reflected types. #[derive(Reflect, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)] -#[reflect_value(PartialEq, Serialize, Deserialize)] +#[reflect(opaque)] +#[reflect(PartialEq, Serialize, Deserialize)] #[allow(dead_code)] enum F { X, @@ -118,10 +118,10 @@ fn setup() { // This variant only exists if the `reflect_functions` feature is enabled. #[cfg(feature = "reflect_functions")] ReflectRef::Function(_) => {} - // `Value` types do not implement any of the other traits above. They are simply a Reflect - // implementation. Value is implemented for core types like i32, usize, f32, and - // String. - ReflectRef::Value(_) => {} + // `Opaque` types do not implement any of the other traits above. They are simply a Reflect + // implementation. Opaque is implemented for opaque types like String and Instant, + // but also include primitive types like i32, usize, and f32 (despite not technically being opaque). + ReflectRef::Opaque(_) => {} } let mut dynamic_list = DynamicList::default();