Make proc macros hygienic in bevy_reflect_derive (#6752)

# Objective

- Fixes #3004 

## Solution

- Replaced all the types with their fully quallified names
- Replaced all trait methods and inherent methods on dyn traits with their fully qualified names
- Made a new file `fq_std.rs` that contains structs corresponding to commonly used Structs and Traits from `std`. These structs are replaced by their respective fully qualified names when used inside `quote!`
This commit is contained in:
Elbert Ronnie 2022-12-05 23:39:44 +00:00
parent 9f0c41f26d
commit f9c52f98b9
14 changed files with 260 additions and 165 deletions

View file

@ -5,6 +5,7 @@
//! the derive helper attribute for `Reflect`, which looks like:
//! `#[reflect(PartialEq, Default, ...)]` and `#[reflect_value(PartialEq, Default, ...)]`.
use crate::fq_std::{FQAny, FQDefault, FQOption};
use crate::utility;
use proc_macro2::{Ident, Span};
use quote::quote_spanned;
@ -222,17 +223,17 @@ impl ReflectTraits {
pub fn get_hash_impl(&self, bevy_reflect_path: &Path) -> Option<proc_macro2::TokenStream> {
match &self.hash {
&TraitImpl::Implemented(span) => Some(quote_spanned! {span=>
fn reflect_hash(&self) -> Option<u64> {
use std::hash::{Hash, Hasher};
let mut hasher = #bevy_reflect_path::ReflectHasher::default();
Hash::hash(&std::any::Any::type_id(self), &mut hasher);
fn reflect_hash(&self) -> #FQOption<u64> {
use ::core::hash::{Hash, Hasher};
let mut hasher: #bevy_reflect_path::ReflectHasher = #FQDefault::default();
Hash::hash(&#FQAny::type_id(self), &mut hasher);
Hash::hash(self, &mut hasher);
Some(hasher.finish())
#FQOption::Some(Hasher::finish(&hasher))
}
}),
&TraitImpl::Custom(ref impl_fn, span) => Some(quote_spanned! {span=>
fn reflect_hash(&self) -> Option<u64> {
Some(#impl_fn(self))
fn reflect_hash(&self) -> #FQOption<u64> {
#FQOption::Some(#impl_fn(self))
}
}),
TraitImpl::NotImplemented => None,
@ -248,18 +249,18 @@ impl ReflectTraits {
) -> Option<proc_macro2::TokenStream> {
match &self.partial_eq {
&TraitImpl::Implemented(span) => Some(quote_spanned! {span=>
fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> Option<bool> {
let value = value.as_any();
if let Some(value) = value.downcast_ref::<Self>() {
Some(std::cmp::PartialEq::eq(self, value))
fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> #FQOption<bool> {
let value = <dyn #bevy_reflect_path::Reflect>::as_any(value);
if let #FQOption::Some(value) = <dyn #FQAny>::downcast_ref::<Self>(value) {
#FQOption::Some(::core::cmp::PartialEq::eq(self, value))
} else {
Some(false)
#FQOption::Some(false)
}
}
}),
&TraitImpl::Custom(ref impl_fn, span) => Some(quote_spanned! {span=>
fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> Option<bool> {
Some(#impl_fn(self, value))
fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> #FQOption<bool> {
#FQOption::Some(#impl_fn(self, value))
}
}),
TraitImpl::NotImplemented => None,
@ -272,12 +273,12 @@ impl ReflectTraits {
pub fn get_debug_impl(&self) -> Option<proc_macro2::TokenStream> {
match &self.debug {
&TraitImpl::Implemented(span) => Some(quote_spanned! {span=>
fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(self, f)
fn debug(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
::core::fmt::Debug::fmt(self, f)
}
}),
&TraitImpl::Custom(ref impl_fn, span) => Some(quote_spanned! {span=>
fn debug(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
fn debug(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
#impl_fn(self, f)
}
}),

View file

@ -1,5 +1,6 @@
//! Contains code related to documentation reflection (requires the `documentation` feature).
use crate::fq_std::FQOption;
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
use syn::{Attribute, Lit, Meta};
@ -69,9 +70,9 @@ impl Documentation {
impl ToTokens for Documentation {
fn to_tokens(&self, tokens: &mut TokenStream) {
if let Some(doc) = self.doc_string() {
quote!(Some(#doc)).to_tokens(tokens);
quote!(#FQOption::Some(#doc)).to_tokens(tokens);
} else {
quote!(None).to_tokens(tokens);
quote!(#FQOption::None).to_tokens(tokens);
}
}
}

View file

@ -1,3 +1,4 @@
use crate::fq_std::FQDefault;
use crate::{
derive_data::{EnumVariantFields, ReflectEnum},
utility::ident_or_index,
@ -39,7 +40,7 @@ pub(crate) fn get_variant_constructors(
let constructor_fields = fields.iter().enumerate().map(|(declar_index, field)| {
let field_ident = ident_or_index(field.data.ident.as_ref(), declar_index);
let field_value = if field.attrs.ignore.is_ignored() {
quote! { Default::default() }
quote! { #FQDefault::default() }
} else {
let error_repr = field.data.ident.as_ref().map_or_else(
|| format!("at index {reflect_index}"),

View file

@ -0,0 +1,77 @@
//! This module contains unit structs that should be used inside `quote!` and `spanned_quote!` using the variable interpolation syntax in place of their equivalent structs and traits present in `std`.
//
//! To create hygienic proc macros, all the names must be its fully qualified form. These unit structs help us to not specify the fully qualified name every single time.
//!
//! # Example
//! Instead of writing this:
//! ```ignore
//! quote!(
//! fn get_id() -> Option<i32> {
//! Some(0)
//! }
//! )
//! ```
//! Or this:
//! ```ignore
//! quote!(
//! fn get_id() -> ::core::option::Option<i32> {
//! ::core::option::Option::Some(0)
//! }
//! )
//! ```
//! We should write this:
//! ```ignore
//! use crate::fq_std::FQOption;
//!
//! quote!(
//! fn get_id() -> #FQOption<i32> {
//! #FQOption::Some(0)
//! }
//! )
//! ```
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
pub(crate) struct FQAny;
pub(crate) struct FQBox;
pub(crate) struct FQClone;
pub(crate) struct FQDefault;
pub(crate) struct FQOption;
pub(crate) struct FQResult;
impl ToTokens for FQAny {
fn to_tokens(&self, tokens: &mut TokenStream) {
quote!(::core::any::Any).to_tokens(tokens);
}
}
impl ToTokens for FQBox {
fn to_tokens(&self, tokens: &mut TokenStream) {
quote!(::std::boxed::Box).to_tokens(tokens);
}
}
impl ToTokens for FQClone {
fn to_tokens(&self, tokens: &mut TokenStream) {
quote!(::core::clone::Clone).to_tokens(tokens);
}
}
impl ToTokens for FQDefault {
fn to_tokens(&self, tokens: &mut TokenStream) {
quote!(::core::default::Default).to_tokens(tokens);
}
}
impl ToTokens for FQOption {
fn to_tokens(&self, tokens: &mut TokenStream) {
quote!(::core::option::Option).to_tokens(tokens);
}
}
impl ToTokens for FQResult {
fn to_tokens(&self, tokens: &mut TokenStream) {
quote!(::core::result::Result).to_tokens(tokens);
}
}

View file

@ -2,10 +2,11 @@ use crate::container_attributes::REFLECT_DEFAULT;
use crate::derive_data::ReflectEnum;
use crate::enum_utility::{get_variant_constructors, EnumVariantConstructors};
use crate::field_attributes::DefaultBehavior;
use crate::fq_std::{FQAny, FQClone, FQDefault, FQOption};
use crate::{ReflectMeta, ReflectStruct};
use proc_macro::TokenStream;
use proc_macro2::Span;
use quote::quote;
use quote::{quote, ToTokens};
use syn::{Field, Ident, Index, Lit, LitInt, LitStr, Member};
/// Implements `FromReflect` for the given struct
@ -25,8 +26,8 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream {
let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl();
TokenStream::from(quote! {
impl #impl_generics #bevy_reflect_path::FromReflect for #type_name #ty_generics #where_clause {
fn from_reflect(reflect: &dyn #bevy_reflect_path::Reflect) -> Option<Self> {
Some(reflect.as_any().downcast_ref::<#type_name #ty_generics>()?.clone())
fn from_reflect(reflect: &dyn #bevy_reflect_path::Reflect) -> #FQOption<Self> {
#FQOption::Some(#FQClone::clone(<dyn #FQAny>::downcast_ref::<#type_name #ty_generics>(<dyn #bevy_reflect_path::Reflect>::as_any(reflect))?))
}
}
})
@ -34,6 +35,8 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream {
/// Implements `FromReflect` for the given enum type
pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
let fqoption = FQOption.into_token_stream();
let type_name = reflect_enum.meta().type_name();
let bevy_reflect_path = reflect_enum.meta().bevy_reflect_path();
@ -47,14 +50,14 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
reflect_enum.meta().generics().split_for_impl();
TokenStream::from(quote! {
impl #impl_generics #bevy_reflect_path::FromReflect for #type_name #ty_generics #where_clause {
fn from_reflect(#ref_value: &dyn #bevy_reflect_path::Reflect) -> Option<Self> {
if let #bevy_reflect_path::ReflectRef::Enum(#ref_value) = #ref_value.reflect_ref() {
match #ref_value.variant_name() {
#(#variant_names => Some(#variant_constructors),)*
name => panic!("variant with name `{}` does not exist on enum `{}`", name, std::any::type_name::<Self>()),
fn from_reflect(#ref_value: &dyn #bevy_reflect_path::Reflect) -> #FQOption<Self> {
if let #bevy_reflect_path::ReflectRef::Enum(#ref_value) = #bevy_reflect_path::Reflect::reflect_ref(#ref_value) {
match #bevy_reflect_path::Enum::variant_name(#ref_value) {
#(#variant_names => #fqoption::Some(#variant_constructors),)*
name => panic!("variant with name `{}` does not exist on enum `{}`", name, ::core::any::type_name::<Self>()),
}
} else {
None
#FQOption::None
}
}
}
@ -72,6 +75,8 @@ 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 generics = reflect_struct.meta().generics();
let bevy_reflect_path = reflect_struct.meta().bevy_reflect_path();
@ -89,21 +94,21 @@ fn impl_struct_internal(reflect_struct: &ReflectStruct, is_tuple: bool) -> Token
let constructor = if reflect_struct.meta().traits().contains(REFLECT_DEFAULT) {
quote!(
let mut __this = Self::default();
let mut __this: Self = #FQDefault::default();
#(
if let Some(__field) = #active_values() {
if let #fqoption::Some(__field) = #active_values() {
// Iff field exists -> use its value
__this.#active_members = __field;
}
)*
Some(__this)
#FQOption::Some(__this)
)
} else {
let MemberValuePair(ignored_members, ignored_values) =
get_ignored_fields(reflect_struct, is_tuple);
quote!(
Some(
#FQOption::Some(
Self {
#(#active_members: #active_values()?,)*
#(#ignored_members: #ignored_values,)*
@ -129,11 +134,11 @@ 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
{
fn from_reflect(reflect: &dyn #bevy_reflect_path::Reflect) -> Option<Self> {
if let #bevy_reflect_path::ReflectRef::#ref_struct_type(#ref_struct) = reflect.reflect_ref() {
fn from_reflect(reflect: &dyn #bevy_reflect_path::Reflect) -> #FQOption<Self> {
if let #bevy_reflect_path::ReflectRef::#ref_struct_type(#ref_struct) = #bevy_reflect_path::Reflect::reflect_ref(reflect) {
#constructor
} else {
None
#FQOption::None
}
}
}
@ -153,7 +158,7 @@ fn get_ignored_fields(reflect_struct: &ReflectStruct, is_tuple: bool) -> MemberV
let value = match &field.attrs.default {
DefaultBehavior::Func(path) => quote! {#path()},
_ => quote! {Default::default()},
_ => quote! {#FQDefault::default()},
};
(member, value)
@ -189,19 +194,19 @@ fn get_active_fields(
let value = match &field.attrs.default {
DefaultBehavior::Func(path) => quote! {
(||
if let Some(field) = #get_field {
if let #FQOption::Some(field) = #get_field {
<#ty as #bevy_reflect_path::FromReflect>::from_reflect(field)
} else {
Some(#path())
#FQOption::Some(#path())
}
)
},
DefaultBehavior::Default => quote! {
(||
if let Some(field) = #get_field {
if let #FQOption::Some(field) = #get_field {
<#ty as #bevy_reflect_path::FromReflect>::from_reflect(field)
} else {
Some(Default::default())
#FQOption::Some(#FQDefault::default())
}
)
},

View file

@ -1,5 +1,6 @@
use crate::derive_data::{EnumVariant, EnumVariantFields, ReflectEnum, StructField};
use crate::enum_utility::{get_variant_constructors, EnumVariantConstructors};
use crate::fq_std::{FQAny, FQBox, FQOption, FQResult};
use crate::impls::impl_typed;
use proc_macro::TokenStream;
use proc_macro2::{Ident, Span};
@ -37,7 +38,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
.get_hash_impl(bevy_reflect_path)
.unwrap_or_else(|| {
quote! {
fn reflect_hash(&self) -> Option<u64> {
fn reflect_hash(&self) -> #FQOption<u64> {
#bevy_reflect_path::enum_hash(self)
}
}
@ -49,7 +50,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
.get_partial_eq_impl(bevy_reflect_path)
.unwrap_or_else(|| {
quote! {
fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> Option<bool> {
fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> #FQOption<bool> {
#bevy_reflect_path::enum_partial_eq(self, value)
}
}
@ -93,45 +94,45 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
#typed_impl
impl #impl_generics #bevy_reflect_path::Enum for #enum_name #ty_generics #where_clause {
fn field(&self, #ref_name: &str) -> Option<&dyn #bevy_reflect_path::Reflect> {
fn field(&self, #ref_name: &str) -> #FQOption<&dyn #bevy_reflect_path::Reflect> {
match self {
#(#enum_field,)*
_ => None,
_ => #FQOption::None,
}
}
fn field_at(&self, #ref_index: usize) -> Option<&dyn #bevy_reflect_path::Reflect> {
fn field_at(&self, #ref_index: usize) -> #FQOption<&dyn #bevy_reflect_path::Reflect> {
match self {
#(#enum_field_at,)*
_ => None,
_ => #FQOption::None,
}
}
fn field_mut(&mut self, #ref_name: &str) -> Option<&mut dyn #bevy_reflect_path::Reflect> {
fn field_mut(&mut self, #ref_name: &str) -> #FQOption<&mut dyn #bevy_reflect_path::Reflect> {
match self {
#(#enum_field,)*
_ => None,
_ => #FQOption::None,
}
}
fn field_at_mut(&mut self, #ref_index: usize) -> Option<&mut dyn #bevy_reflect_path::Reflect> {
fn field_at_mut(&mut self, #ref_index: usize) -> #FQOption<&mut dyn #bevy_reflect_path::Reflect> {
match self {
#(#enum_field_at,)*
_ => None,
_ => #FQOption::None,
}
}
fn index_of(&self, #ref_name: &str) -> Option<usize> {
fn index_of(&self, #ref_name: &str) -> #FQOption<usize> {
match self {
#(#enum_index_of,)*
_ => None,
_ => #FQOption::None,
}
}
fn name_at(&self, #ref_index: usize) -> Option<&str> {
fn name_at(&self, #ref_index: usize) -> #FQOption<&str> {
match self {
#(#enum_name_at,)*
_ => None,
_ => #FQOption::None,
}
}
@ -179,7 +180,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
impl #impl_generics #bevy_reflect_path::Reflect for #enum_name #ty_generics #where_clause {
#[inline]
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
::core::any::type_name::<Self>()
}
#[inline]
@ -188,22 +189,22 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
}
#[inline]
fn into_any(self: Box<Self>) -> Box<dyn std::any::Any> {
fn into_any(self: #FQBox<Self>) -> #FQBox<dyn #FQAny> {
self
}
#[inline]
fn as_any(&self) -> &dyn std::any::Any {
fn as_any(&self) -> &dyn #FQAny {
self
}
#[inline]
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
fn as_any_mut(&mut self) -> &mut dyn #FQAny {
self
}
#[inline]
fn into_reflect(self: Box<Self>) -> Box<dyn #bevy_reflect_path::Reflect> {
fn into_reflect(self: #FQBox<Self>) -> #FQBox<dyn #bevy_reflect_path::Reflect> {
self
}
@ -218,30 +219,30 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
}
#[inline]
fn clone_value(&self) -> Box<dyn #bevy_reflect_path::Reflect> {
Box::new(#bevy_reflect_path::Enum::clone_dynamic(self))
fn clone_value(&self) -> #FQBox<dyn #bevy_reflect_path::Reflect> {
#FQBox::new(#bevy_reflect_path::Enum::clone_dynamic(self))
}
#[inline]
fn set(&mut self, #ref_value: Box<dyn #bevy_reflect_path::Reflect>) -> Result<(), Box<dyn #bevy_reflect_path::Reflect>> {
*self = #ref_value.take()?;
Ok(())
fn set(&mut self, #ref_value: #FQBox<dyn #bevy_reflect_path::Reflect>) -> #FQResult<(), #FQBox<dyn #bevy_reflect_path::Reflect>> {
*self = <dyn #bevy_reflect_path::Reflect>::take(#ref_value)?;
#FQResult::Ok(())
}
#[inline]
fn apply(&mut self, #ref_value: &dyn #bevy_reflect_path::Reflect) {
if let #bevy_reflect_path::ReflectRef::Enum(#ref_value) = #ref_value.reflect_ref() {
if #bevy_reflect_path::Enum::variant_name(self) == #ref_value.variant_name() {
if let #bevy_reflect_path::ReflectRef::Enum(#ref_value) = #bevy_reflect_path::Reflect::reflect_ref(#ref_value) {
if #bevy_reflect_path::Enum::variant_name(self) == #bevy_reflect_path::Enum::variant_name(#ref_value) {
// Same variant -> just update fields
match #ref_value.variant_type() {
match #bevy_reflect_path::Enum::variant_type(#ref_value) {
#bevy_reflect_path::VariantType::Struct => {
for field in #ref_value.iter_fields() {
for field in #bevy_reflect_path::Enum::iter_fields(#ref_value) {
let name = field.name().unwrap();
#bevy_reflect_path::Enum::field_mut(self, name).map(|v| v.apply(field.value()));
}
}
#bevy_reflect_path::VariantType::Tuple => {
for (index, field) in #ref_value.iter_fields().enumerate() {
for (index, field) in ::core::iter::Iterator::enumerate(#bevy_reflect_path::Enum::iter_fields(#ref_value)) {
#bevy_reflect_path::Enum::field_at_mut(self, index).map(|v| v.apply(field.value()));
}
}
@ -249,15 +250,15 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
}
} else {
// New variant -> perform a switch
match #ref_value.variant_name() {
match #bevy_reflect_path::Enum::variant_name(#ref_value) {
#(#variant_names => {
*self = #variant_constructors
})*
name => panic!("variant with name `{}` does not exist on enum `{}`", name, std::any::type_name::<Self>()),
name => panic!("variant with name `{}` does not exist on enum `{}`", name, ::core::any::type_name::<Self>()),
}
}
} else {
panic!("`{}` is not an enum", #ref_value.type_name());
panic!("`{}` is not an enum", #bevy_reflect_path::Reflect::type_name(#ref_value));
}
}
@ -269,7 +270,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
#bevy_reflect_path::ReflectMut::Enum(self)
}
fn reflect_owned(self: Box<Self>) -> #bevy_reflect_path::ReflectOwned {
fn reflect_owned(self: #FQBox<Self>) -> #bevy_reflect_path::ReflectOwned {
#bevy_reflect_path::ReflectOwned::Enum(self)
}
@ -380,7 +381,7 @@ fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Iden
let args = get_field_args(fields, |reflect_idx, declaration_index, field| {
let declar_field = syn::Index::from(declaration_index);
enum_field_at.push(quote! {
#unit { #declar_field : value, .. } if #ref_index == #reflect_idx => Some(value)
#unit { #declar_field : value, .. } if #ref_index == #reflect_idx => #FQOption::Some(value)
});
#[cfg(feature = "documentation")]
@ -406,16 +407,16 @@ fn generate_impls(reflect_enum: &ReflectEnum, ref_index: &Ident, ref_name: &Iden
let field_ident = field.data.ident.as_ref().unwrap();
let field_name = field_ident.to_string();
enum_field.push(quote! {
#unit{ #field_ident, .. } if #ref_name == #field_name => Some(#field_ident)
#unit{ #field_ident, .. } if #ref_name == #field_name => #FQOption::Some(#field_ident)
});
enum_field_at.push(quote! {
#unit{ #field_ident, .. } if #ref_index == #reflect_idx => Some(#field_ident)
#unit{ #field_ident, .. } if #ref_index == #reflect_idx => #FQOption::Some(#field_ident)
});
enum_index_of.push(quote! {
#unit{ .. } if #ref_name == #field_name => Some(#reflect_idx)
#unit{ .. } if #ref_name == #field_name => #FQOption::Some(#reflect_idx)
});
enum_name_at.push(quote! {
#unit{ .. } if #ref_index == #reflect_idx => Some(#field_name)
#unit{ .. } if #ref_index == #reflect_idx => #FQOption::Some(#field_name)
});
#[cfg(feature = "documentation")]

View file

@ -1,11 +1,14 @@
use crate::fq_std::{FQAny, FQBox, FQDefault, FQOption, FQResult};
use crate::impls::impl_typed;
use crate::ReflectStruct;
use proc_macro::TokenStream;
use quote::quote;
use quote::{quote, ToTokens};
use syn::{Index, Member};
/// Implements `Struct`, `GetTypeRegistration`, and `Reflect` for the given derive data.
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();
@ -45,7 +48,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream {
.get_partial_eq_impl(bevy_reflect_path)
.unwrap_or_else(|| {
quote! {
fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> Option<bool> {
fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> #FQOption<bool> {
#bevy_reflect_path::struct_partial_eq(self, value)
}
}
@ -106,38 +109,38 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream {
#typed_impl
impl #impl_generics #bevy_reflect_path::Struct for #struct_name #ty_generics #where_clause {
fn field(&self, name: &str) -> Option<&dyn #bevy_reflect_path::Reflect> {
fn field(&self, name: &str) -> #FQOption<&dyn #bevy_reflect_path::Reflect> {
match name {
#(#field_names => Some(&self.#field_idents),)*
_ => None,
#(#field_names => #fqoption::Some(&self.#field_idents),)*
_ => #FQOption::None,
}
}
fn field_mut(&mut self, name: &str) -> Option<&mut dyn #bevy_reflect_path::Reflect> {
fn field_mut(&mut self, name: &str) -> #FQOption<&mut dyn #bevy_reflect_path::Reflect> {
match name {
#(#field_names => Some(&mut self.#field_idents),)*
_ => None,
#(#field_names => #fqoption::Some(&mut self.#field_idents),)*
_ => #FQOption::None,
}
}
fn field_at(&self, index: usize) -> Option<&dyn #bevy_reflect_path::Reflect> {
fn field_at(&self, index: usize) -> #FQOption<&dyn #bevy_reflect_path::Reflect> {
match index {
#(#field_indices => Some(&self.#field_idents),)*
_ => None,
#(#field_indices => #fqoption::Some(&self.#field_idents),)*
_ => #FQOption::None,
}
}
fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn #bevy_reflect_path::Reflect> {
fn field_at_mut(&mut self, index: usize) -> #FQOption<&mut dyn #bevy_reflect_path::Reflect> {
match index {
#(#field_indices => Some(&mut self.#field_idents),)*
_ => None,
#(#field_indices => #fqoption::Some(&mut self.#field_idents),)*
_ => #FQOption::None,
}
}
fn name_at(&self, index: usize) -> Option<&str> {
fn name_at(&self, index: usize) -> #FQOption<&str> {
match index {
#(#field_indices => Some(#field_names),)*
_ => None,
#(#field_indices => #fqoption::Some(#field_names),)*
_ => #FQOption::None,
}
}
@ -150,9 +153,9 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream {
}
fn clone_dynamic(&self) -> #bevy_reflect_path::DynamicStruct {
let mut dynamic = #bevy_reflect_path::DynamicStruct::default();
dynamic.set_name(self.type_name().to_string());
#(dynamic.insert_boxed(#field_names, self.#field_idents.clone_value());)*
let mut dynamic: #bevy_reflect_path::DynamicStruct = #FQDefault::default();
dynamic.set_name(::std::string::ToString::to_string(#bevy_reflect_path::Reflect::type_name(self)));
#(dynamic.insert_boxed(#field_names, #bevy_reflect_path::Reflect::clone_value(&self.#field_idents));)*
dynamic
}
}
@ -160,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_clause {
#[inline]
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
::core::any::type_name::<Self>()
}
#[inline]
@ -169,22 +172,22 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream {
}
#[inline]
fn into_any(self: Box<Self>) -> Box<dyn std::any::Any> {
fn into_any(self: #FQBox<Self>) -> #FQBox<dyn #FQAny> {
self
}
#[inline]
fn as_any(&self) -> &dyn std::any::Any {
fn as_any(&self) -> &dyn #FQAny {
self
}
#[inline]
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
fn as_any_mut(&mut self) -> &mut dyn #FQAny {
self
}
#[inline]
fn into_reflect(self: Box<Self>) -> Box<dyn #bevy_reflect_path::Reflect> {
fn into_reflect(self: #FQBox<Self>) -> #FQBox<dyn #bevy_reflect_path::Reflect> {
self
}
@ -199,20 +202,21 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream {
}
#[inline]
fn clone_value(&self) -> Box<dyn #bevy_reflect_path::Reflect> {
Box::new(#bevy_reflect_path::Struct::clone_dynamic(self))
fn clone_value(&self) -> #FQBox<dyn #bevy_reflect_path::Reflect> {
#FQBox::new(#bevy_reflect_path::Struct::clone_dynamic(self))
}
#[inline]
fn set(&mut self, value: Box<dyn #bevy_reflect_path::Reflect>) -> Result<(), Box<dyn #bevy_reflect_path::Reflect>> {
*self = value.take()?;
Ok(())
fn set(&mut self, value: #FQBox<dyn #bevy_reflect_path::Reflect>) -> #FQResult<(), #FQBox<dyn #bevy_reflect_path::Reflect>> {
*self = <dyn #bevy_reflect_path::Reflect>::take(value)?;
#FQResult::Ok(())
}
#[inline]
fn apply(&mut self, value: &dyn #bevy_reflect_path::Reflect) {
if let #bevy_reflect_path::ReflectRef::Struct(struct_value) = value.reflect_ref() {
for (i, value) in struct_value.iter_fields().enumerate() {
let name = struct_value.name_at(i).unwrap();
if let #bevy_reflect_path::ReflectRef::Struct(struct_value) = #bevy_reflect_path::Reflect::reflect_ref(value) {
for (i, value) in ::core::iter::Iterator::enumerate(#bevy_reflect_path::Struct::iter_fields(struct_value)) {
let name = #bevy_reflect_path::Struct::name_at(struct_value, i).unwrap();
#bevy_reflect_path::Struct::field_mut(self, name).map(|v| v.apply(value));
}
} else {
@ -228,7 +232,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream {
#bevy_reflect_path::ReflectMut::Struct(self)
}
fn reflect_owned(self: Box<Self>) -> #bevy_reflect_path::ReflectOwned {
fn reflect_owned(self: #FQBox<Self>) -> #bevy_reflect_path::ReflectOwned {
#bevy_reflect_path::ReflectOwned::Struct(self)
}

View file

@ -1,11 +1,14 @@
use crate::fq_std::{FQAny, FQBox, FQDefault, FQOption, FQResult};
use crate::impls::impl_typed;
use crate::ReflectStruct;
use proc_macro::TokenStream;
use quote::quote;
use quote::{quote, ToTokens};
use syn::{Index, Member};
/// Implements `TupleStruct`, `GetTypeRegistration`, and `Reflect` for the given derive data.
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 get_type_registration_impl = reflect_struct.get_type_registration();
@ -29,7 +32,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream {
.get_partial_eq_impl(bevy_reflect_path)
.unwrap_or_else(|| {
quote! {
fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> Option<bool> {
fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> #FQOption<bool> {
#bevy_reflect_path::tuple_struct_partial_eq(self, value)
}
}
@ -89,17 +92,17 @@ 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_clause {
fn field(&self, index: usize) -> Option<&dyn #bevy_reflect_path::Reflect> {
fn field(&self, index: usize) -> #FQOption<&dyn #bevy_reflect_path::Reflect> {
match index {
#(#field_indices => Some(&self.#field_idents),)*
_ => None,
#(#field_indices => #fqoption::Some(&self.#field_idents),)*
_ => #FQOption::None,
}
}
fn field_mut(&mut self, index: usize) -> Option<&mut dyn #bevy_reflect_path::Reflect> {
fn field_mut(&mut self, index: usize) -> #FQOption<&mut dyn #bevy_reflect_path::Reflect> {
match index {
#(#field_indices => Some(&mut self.#field_idents),)*
_ => None,
#(#field_indices => #fqoption::Some(&mut self.#field_idents),)*
_ => #FQOption::None,
}
}
@ -112,9 +115,9 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream {
}
fn clone_dynamic(&self) -> #bevy_reflect_path::DynamicTupleStruct {
let mut dynamic = #bevy_reflect_path::DynamicTupleStruct::default();
dynamic.set_name(self.type_name().to_string());
#(dynamic.insert_boxed(self.#field_idents.clone_value());)*
let mut dynamic: #bevy_reflect_path::DynamicTupleStruct = #FQDefault::default();
dynamic.set_name(::std::string::ToString::to_string(#bevy_reflect_path::Reflect::type_name(self)));
#(dynamic.insert_boxed(#bevy_reflect_path::Reflect::clone_value(&self.#field_idents));)*
dynamic
}
}
@ -122,7 +125,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream {
impl #impl_generics #bevy_reflect_path::Reflect for #struct_name #ty_generics #where_clause {
#[inline]
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
::core::any::type_name::<Self>()
}
#[inline]
@ -131,22 +134,22 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream {
}
#[inline]
fn into_any(self: Box<Self>) -> Box<dyn std::any::Any> {
fn into_any(self: #FQBox<Self>) -> #FQBox<dyn #FQAny> {
self
}
#[inline]
fn as_any(&self) -> &dyn std::any::Any {
fn as_any(&self) -> &dyn #FQAny {
self
}
#[inline]
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
fn as_any_mut(&mut self) -> &mut dyn #FQAny {
self
}
#[inline]
fn into_reflect(self: Box<Self>) -> Box<dyn #bevy_reflect_path::Reflect> {
fn into_reflect(self: #FQBox<Self>) -> #FQBox<dyn #bevy_reflect_path::Reflect> {
self
}
@ -161,19 +164,20 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream {
}
#[inline]
fn clone_value(&self) -> Box<dyn #bevy_reflect_path::Reflect> {
Box::new(#bevy_reflect_path::TupleStruct::clone_dynamic(self))
fn clone_value(&self) -> #FQBox<dyn #bevy_reflect_path::Reflect> {
#FQBox::new(#bevy_reflect_path::TupleStruct::clone_dynamic(self))
}
#[inline]
fn set(&mut self, value: Box<dyn #bevy_reflect_path::Reflect>) -> Result<(), Box<dyn #bevy_reflect_path::Reflect>> {
*self = value.take()?;
Ok(())
fn set(&mut self, value: #FQBox<dyn #bevy_reflect_path::Reflect>) -> #FQResult<(), #FQBox<dyn #bevy_reflect_path::Reflect>> {
*self = <dyn #bevy_reflect_path::Reflect>::take(value)?;
#FQResult::Ok(())
}
#[inline]
fn apply(&mut self, value: &dyn #bevy_reflect_path::Reflect) {
if let #bevy_reflect_path::ReflectRef::TupleStruct(struct_value) = value.reflect_ref() {
for (i, value) in struct_value.iter_fields().enumerate() {
if let #bevy_reflect_path::ReflectRef::TupleStruct(struct_value) = #bevy_reflect_path::Reflect::reflect_ref(value) {
for (i, value) in ::core::iter::Iterator::enumerate(#bevy_reflect_path::TupleStruct::iter_fields(struct_value)) {
#bevy_reflect_path::TupleStruct::field_mut(self, i).map(|v| v.apply(value));
}
} else {
@ -189,7 +193,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream {
#bevy_reflect_path::ReflectMut::TupleStruct(self)
}
fn reflect_owned(self: Box<Self>) -> #bevy_reflect_path::ReflectOwned {
fn reflect_owned(self: #FQBox<Self>) -> #bevy_reflect_path::ReflectOwned {
#bevy_reflect_path::ReflectOwned::TupleStruct(self)
}

View file

@ -1,3 +1,4 @@
use crate::fq_std::{FQAny, FQBox, FQClone, FQOption, FQResult};
use crate::impls::impl_typed;
use crate::ReflectMeta;
use proc_macro::TokenStream;
@ -41,7 +42,7 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream {
impl #impl_generics #bevy_reflect_path::Reflect for #type_name #ty_generics #where_clause {
#[inline]
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
::core::any::type_name::<Self>()
}
#[inline]
@ -50,22 +51,22 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream {
}
#[inline]
fn into_any(self: Box<Self>) -> Box<dyn std::any::Any> {
fn into_any(self: #FQBox<Self>) -> #FQBox<dyn #FQAny> {
self
}
#[inline]
fn as_any(&self) -> &dyn std::any::Any {
fn as_any(&self) -> &dyn #FQAny {
self
}
#[inline]
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
fn as_any_mut(&mut self) -> &mut dyn #FQAny {
self
}
#[inline]
fn into_reflect(self: Box<Self>) -> Box<dyn #bevy_reflect_path::Reflect> {
fn into_reflect(self: #FQBox<Self>) -> #FQBox<dyn #bevy_reflect_path::Reflect> {
self
}
@ -80,24 +81,24 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream {
}
#[inline]
fn clone_value(&self) -> Box<dyn #bevy_reflect_path::Reflect> {
Box::new(std::clone::Clone::clone(self))
fn clone_value(&self) -> #FQBox<dyn #bevy_reflect_path::Reflect> {
#FQBox::new(#FQClone::clone(self))
}
#[inline]
fn apply(&mut self, value: &dyn #bevy_reflect_path::Reflect) {
let value = value.as_any();
if let Some(value) = value.downcast_ref::<Self>() {
*self = std::clone::Clone::clone(value);
let value = #bevy_reflect_path::Reflect::as_any(value);
if let #FQOption::Some(value) = <dyn #FQAny>::downcast_ref::<Self>(value) {
*self = #FQClone::clone(value);
} else {
panic!("Value is not {}.", std::any::type_name::<Self>());
panic!("Value is not {}.", ::core::any::type_name::<Self>());
}
}
#[inline]
fn set(&mut self, value: Box<dyn #bevy_reflect_path::Reflect>) -> Result<(), Box<dyn #bevy_reflect_path::Reflect>> {
*self = value.take()?;
Ok(())
fn set(&mut self, value: #FQBox<dyn #bevy_reflect_path::Reflect>) -> #FQResult<(), #FQBox<dyn #bevy_reflect_path::Reflect>> {
*self = <dyn #bevy_reflect_path::Reflect>::take(value)?;
#FQResult::Ok(())
}
fn reflect_ref(&self) -> #bevy_reflect_path::ReflectRef {
@ -108,7 +109,7 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream {
#bevy_reflect_path::ReflectMut::Value(self)
}
fn reflect_owned(self: Box<Self>) -> #bevy_reflect_path::ReflectOwned {
fn reflect_owned(self: #FQBox<Self>) -> #bevy_reflect_path::ReflectOwned {
#bevy_reflect_path::ReflectOwned::Value(self)
}

View file

@ -20,6 +20,7 @@ mod derive_data;
mod documentation;
mod enum_utility;
mod field_attributes;
mod fq_std;
mod from_reflect;
mod impls;
mod reflect_value;

View file

@ -17,7 +17,7 @@ pub(crate) fn impl_get_type_registration(
let serialization_data = serialization_denylist.map(|denylist| {
let denylist = denylist.into_iter();
quote! {
let ignored_indices = [#(#denylist),*].into_iter();
let ignored_indices = ::core::iter::IntoIterator::into_iter([#(#denylist),*]);
registration.insert::<#bevy_reflect_path::serde::SerializationData>(#bevy_reflect_path::serde::SerializationData::new(ignored_indices));
}
});

View file

@ -1,3 +1,4 @@
use crate::fq_std::{FQBox, FQClone, FQOption, FQResult};
use bevy_macro_utils::BevyManifest;
use proc_macro::TokenStream;
use quote::quote;
@ -55,26 +56,26 @@ pub(crate) fn reflect_trait(_args: &TokenStream, input: TokenStream) -> TokenStr
#item_trait
#[doc = #struct_doc]
#[derive(Clone)]
#[derive(#FQClone)]
#trait_vis struct #reflect_trait_ident {
get_func: fn(&dyn #bevy_reflect_path::Reflect) -> Option<&dyn #trait_ident>,
get_mut_func: fn(&mut dyn #bevy_reflect_path::Reflect) -> Option<&mut dyn #trait_ident>,
get_boxed_func: fn(Box<dyn #bevy_reflect_path::Reflect>) -> Result<Box<dyn #trait_ident>, Box<dyn #bevy_reflect_path::Reflect>>,
get_func: fn(&dyn #bevy_reflect_path::Reflect) -> #FQOption<&dyn #trait_ident>,
get_mut_func: fn(&mut dyn #bevy_reflect_path::Reflect) -> #FQOption<&mut dyn #trait_ident>,
get_boxed_func: fn(#FQBox<dyn #bevy_reflect_path::Reflect>) -> #FQResult<#FQBox<dyn #trait_ident>, #FQBox<dyn #bevy_reflect_path::Reflect>>,
}
impl #reflect_trait_ident {
#[doc = #get_doc]
pub fn get<'a>(&self, reflect_value: &'a dyn #bevy_reflect_path::Reflect) -> Option<&'a dyn #trait_ident> {
pub fn get<'a>(&self, reflect_value: &'a dyn #bevy_reflect_path::Reflect) -> #FQOption<&'a dyn #trait_ident> {
(self.get_func)(reflect_value)
}
#[doc = #get_mut_doc]
pub fn get_mut<'a>(&self, reflect_value: &'a mut dyn #bevy_reflect_path::Reflect) -> Option<&'a mut dyn #trait_ident> {
pub fn get_mut<'a>(&self, reflect_value: &'a mut dyn #bevy_reflect_path::Reflect) -> #FQOption<&'a mut dyn #trait_ident> {
(self.get_mut_func)(reflect_value)
}
#[doc = #get_box_doc]
pub fn get_boxed(&self, reflect_value: Box<dyn #bevy_reflect_path::Reflect>) -> Result<Box<dyn #trait_ident>, Box<dyn #bevy_reflect_path::Reflect>> {
pub fn get_boxed(&self, reflect_value: #FQBox<dyn #bevy_reflect_path::Reflect>) -> #FQResult<#FQBox<dyn #trait_ident>, #FQBox<dyn #bevy_reflect_path::Reflect>> {
(self.get_boxed_func)(reflect_value)
}
}
@ -83,13 +84,13 @@ pub(crate) fn reflect_trait(_args: &TokenStream, input: TokenStream) -> TokenStr
fn from_type() -> Self {
Self {
get_func: |reflect_value| {
reflect_value.downcast_ref::<T>().map(|value| value as &dyn #trait_ident)
<dyn #bevy_reflect_path::Reflect>::downcast_ref::<T>(reflect_value).map(|value| value as &dyn #trait_ident)
},
get_mut_func: |reflect_value| {
reflect_value.downcast_mut::<T>().map(|value| value as &mut dyn #trait_ident)
<dyn #bevy_reflect_path::Reflect>::downcast_mut::<T>(reflect_value).map(|value| value as &mut dyn #trait_ident)
},
get_boxed_func: |reflect_value| {
reflect_value.downcast::<T>().map(|value| value as Box<dyn #trait_ident>)
<dyn #bevy_reflect_path::Reflect>::downcast::<T>(reflect_value).map(|value| value as #FQBox<dyn #trait_ident>)
}
}
}

View file

@ -1,6 +1,5 @@
use crate as bevy_reflect;
use crate::prelude::ReflectDefault;
use crate::reflect::Reflect;
use crate::{ReflectDeserialize, ReflectSerialize};
use bevy_reflect_derive::{impl_from_reflect_value, impl_reflect_struct, impl_reflect_value};
use glam::*;

View file

@ -1,6 +1,5 @@
use crate as bevy_reflect;
use crate::prelude::ReflectDefault;
use crate::reflect::Reflect;
use crate::{ReflectDeserialize, ReflectSerialize};
use bevy_math::{Rect, Vec2};
use bevy_reflect_derive::impl_reflect_struct;