Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/bevy_asset/src/reflect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ impl ReflectAsset {
}
}

impl<A: Asset + FromReflect> FromType<A> for ReflectAsset {
impl<A: Asset + FromReflect + Reflect> FromType<A> for ReflectAsset {
fn from_type() -> Self {
ReflectAsset {
handle_type_id: TypeId::of::<Handle<A>>(),
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ecs/src/reflect/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ impl ReflectBundleFns {
///
/// This is useful if you want to start with the default implementation before overriding some
/// of the functions to create a custom implementation.
pub fn new<T: Bundle + FromReflect + TypePath + BundleFromComponents>() -> Self {
pub fn new<T: Bundle + FromReflect + Reflect + TypePath + BundleFromComponents>() -> Self {
<ReflectBundle as FromType<T>>::from_type().0
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ecs/src/reflect/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ impl ReflectComponentFns {
///
/// This is useful if you want to start with the default implementation before overriding some
/// of the functions to create a custom implementation.
pub fn new<T: Component + FromReflect + TypePath>() -> Self {
pub fn new<T: Component + FromReflect + Reflect + TypePath>() -> Self {
<ReflectComponent as FromType<T>>::from_type().0
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ecs/src/reflect/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ impl ReflectEventFns {
///
/// This is useful if you want to start with the default implementation
/// before overriding some of the functions to create a custom implementation.
pub fn new<'a, T: Event + FromReflect + TypePath>() -> Self
pub fn new<'a, T: Event + FromReflect + Reflect + TypePath>() -> Self
where
T::Trigger<'a>: Default,
{
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_ecs/src/reflect/map_entities.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::entity::{EntityMapper, MapEntities};
use bevy_reflect::{FromReflect, FromType, PartialReflect};
use bevy_reflect::{FromReflect, FromType, PartialReflect, Reflect};

/// For a specific type of value, this maps any fields with values of type [`Entity`] to a new world.
///
Expand All @@ -25,7 +25,7 @@ impl ReflectMapEntities {
}
}

impl<C: FromReflect + MapEntities> FromType<C> for ReflectMapEntities {
impl<C: FromReflect + Reflect + MapEntities> FromType<C> for ReflectMapEntities {
fn from_type() -> Self {
ReflectMapEntities {
map_entities: |reflected, mut mapper| {
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_ecs/src/reflect/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ impl ReflectResourceFns {
///
/// This is useful if you want to start with the default implementation before overriding some
/// of the functions to create a custom implementation.
pub fn new<T: Resource + FromReflect + TypePath>() -> Self {
pub fn new<T: Resource + FromReflect + Reflect + TypePath>() -> Self {
<ReflectResource as FromType<T>>::from_type().0
}
}
Expand Down Expand Up @@ -206,7 +206,7 @@ impl ReflectResource {
}
}

impl<R: Resource + FromReflect + TypePath> FromType<R> for ReflectResource {
impl<R: Resource + FromReflect + Reflect + TypePath> FromType<R> for ReflectResource {
fn from_type() -> Self {
ReflectResource(ReflectResourceFns {
insert: |world, reflected_resource, registry| {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ fn main() {
let mut foo: Box<dyn Struct> = Box::new(Foo::<NoReflect> { a: NoReflect(42.0) });
//~^ ERROR: `NoReflect` does not implement `GetTypeRegistration` so cannot provide type registration information
//~| ERROR: `NoReflect` does not implement `Typed` so cannot provide static type information
//~| ERROR: `NoReflect` does not implement `CastPartialReflect` so cannot be cast to `dyn PartialReflect`

// foo doesn't implement Reflect because NoReflect doesn't implement Reflect
foo.get_field::<NoReflect>("a").unwrap();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,13 @@ mod missing_attribute {
}

mod incorrect_inner_type {
use bevy_reflect::{FromReflect, GetTypeRegistration, reflect_remote};
use bevy_reflect::{FromReflect, GetTypeRegistration, Reflect, reflect_remote};

#[reflect_remote(super::external_crate::TheirOuter<T>)]
//~^ ERROR: `TheirInner<T>` does not implement `PartialReflect` so cannot be introspected
//~| ERROR: `TheirInner<T>` does not implement `PartialReflect` so cannot be introspected
//~| ERROR: `TheirInner<T>` does not implement `PartialReflect` so cannot be introspected
//~| ERROR: `TheirInner<T>` does not implement `TypePath` so cannot provide dynamic type path information
//~^ ERROR: `TheirInner<T>` does not implement `CastPartialReflect` so cannot be cast to `dyn PartialReflect`
//~| ERROR: `?` operator has incompatible types
//~| ERROR: mismatched types
struct MyOuter<T: FromReflect + GetTypeRegistration> {
struct MyOuter<T: FromReflect + Reflect + GetTypeRegistration> {
// Reason: Should not use `MyInner<T>` directly
pub inner: MyInner<T>,
//~^ ERROR: mismatched types
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ mod external_crate {
}

#[reflect_remote(external_crate::TheirOuter<T>)]
struct MyOuter<T: FromReflect + Typed + GetTypeRegistration> {
struct MyOuter<T: FromReflect + Reflect + Typed + GetTypeRegistration> {
#[reflect(remote = MyInner<T>)]
pub inner: external_crate::TheirInner<T>,
}
Expand Down
54 changes: 48 additions & 6 deletions crates/bevy_reflect/derive/src/derive_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,8 @@ impl<'a> ReflectStruct<'a> {
for field in self.fields().iter() {
let field_ty = field.reflected_type();
let member = field.to_member();
let accessor = self.access_for_field(field, false);
let accessor = self.access_for_field(field, false, true);
let non_cast_accessor = self.access_for_field(field, false, false);

match &field.attrs.clone {
CloneBehavior::Default => {
Expand All @@ -729,7 +730,17 @@ impl<'a> ReflectStruct<'a> {
}
} else {
quote! {
<#field_ty as #bevy_reflect_path::PartialReflect>::reflect_clone_and_take(#accessor)?
#FQResult::map_err(
<dyn #bevy_reflect_path::Reflect>::take(
#bevy_reflect_path::PartialReflect::reflect_clone(#accessor)?
),
|_| #bevy_reflect_path::ReflectCloneError::FailedDowncast {
expected: #bevy_reflect_path::__macro_exports::alloc_utils::Cow::Borrowed(<#field_ty as #bevy_reflect_path::TypePath>::type_path()),
received: #bevy_reflect_path::__macro_exports::alloc_utils::Cow::Owned(
#bevy_reflect_path::__macro_exports::alloc_utils::ToString::to_string(#bevy_reflect_path::DynamicTypePath::reflect_type_path(#accessor))
),
}
)?
}
};

Expand All @@ -739,12 +750,28 @@ impl<'a> ReflectStruct<'a> {
}
CloneBehavior::Trait => {
tokens.extend(quote! {
#member: #FQClone::clone(#accessor),
#member: #FQClone::clone(#non_cast_accessor),
});
}
CloneBehavior::Func(clone_fn) => {
let value = if field.attrs.ignore.is_ignored() {
quote!(#clone_fn(#non_cast_accessor))
} else {
quote! {
#clone_fn(#FQOption::ok_or_else(
<dyn #bevy_reflect_path::PartialReflect>::try_downcast_ref(#accessor),
|| #bevy_reflect_path::ReflectCloneError::FailedDowncast {
expected: #bevy_reflect_path::__macro_exports::alloc_utils::Cow::Borrowed(<#field_ty as #bevy_reflect_path::TypePath>::type_path()),
received: #bevy_reflect_path::__macro_exports::alloc_utils::Cow::Owned(
#bevy_reflect_path::__macro_exports::alloc_utils::ToString::to_string(#bevy_reflect_path::DynamicTypePath::reflect_type_path(#accessor))
),
}
)?)
}
};

tokens.extend(quote! {
#member: #clone_fn(#accessor),
#member: #value,
});
}
}
Expand Down Expand Up @@ -779,21 +806,30 @@ impl<'a> ReflectStruct<'a> {

/// Generates an accessor for the given field.
///
/// The mutability of the access can be controlled by the `is_mut` parameter.
/// The mutability of the access can be controlled by the `is_mutable` parameter.
///
/// Generally, this just returns something like `&self.field`.
/// However, if the struct is a remote wrapper, this then becomes `&self.0.field` in order to access the field on the inner type.
///
/// If the field itself is a remote type, the above accessor is further wrapped in a call to `ReflectRemote::as_wrapper[_mut]`.
///
/// If `is_castable` is true, the accessor is wrapped in a call to `CastPartialReflect::as_partial_reflect[_mut]` to handle reflection casting
/// when the field is not a remote type.
pub fn access_for_field(
&self,
field: &StructField<'a>,
is_mutable: bool,
is_castable: bool,
) -> proc_macro2::TokenStream {
let bevy_reflect_path = self.meta().bevy_reflect_path();
let member = field.to_member();

let prefix_tokens = if is_mutable { quote!(&mut) } else { quote!(&) };
let cast_method = if is_mutable {
quote!(as_partial_reflect_mut)
} else {
quote!(as_partial_reflect)
};

let accessor = if self.meta.is_remote_wrapper() {
quote!(self.0.#member)
Expand All @@ -813,7 +849,13 @@ impl<'a> ReflectStruct<'a> {
<#wrapper_ty as #bevy_reflect_path::ReflectRemote>::#method(#prefix_tokens #accessor)
}
}
None => quote!(#prefix_tokens #accessor),
None => {
if is_castable {
quote!(#bevy_reflect_path::cast::CastPartialReflect::#cast_method(#prefix_tokens #accessor))
} else {
quote!(#prefix_tokens #accessor)
}
}
}
}
}
Expand Down
42 changes: 37 additions & 5 deletions crates/bevy_reflect/derive/src/enum_utility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,29 +318,61 @@ impl<'a> VariantBuilder for ReflectCloneVariantBuilder<'a> {
let bevy_reflect_path = self.reflect_enum.meta().bevy_reflect_path();
let field_ty = field.field.reflected_type();
let alias = field.alias;
let alias = match &field.field.attrs.remote {
let non_cast_alias = match &field.field.attrs.remote {
Some(wrapper_ty) => {
quote! {
<#wrapper_ty as #bevy_reflect_path::ReflectRemote>::as_wrapper(#alias)
}
}
None => alias.to_token_stream(),
};
let alias = match &field.field.attrs.remote {
Some(wrapper_ty) => {
quote! {
<#wrapper_ty as #bevy_reflect_path::ReflectRemote>::as_wrapper(#alias)
}
}
None => quote! {
#bevy_reflect_path::cast::CastPartialReflect::as_partial_reflect(#alias)
},
};

match &field.field.attrs.clone {
CloneBehavior::Default => {
quote! {
<#field_ty as #bevy_reflect_path::PartialReflect>::reflect_clone_and_take(#alias)?
#FQResult::map_err(
<dyn #bevy_reflect_path::Reflect>::take(
#bevy_reflect_path::PartialReflect::reflect_clone(#alias)?
),
|_| #bevy_reflect_path::ReflectCloneError::FailedDowncast {
expected: #bevy_reflect_path::__macro_exports::alloc_utils::Cow::Borrowed(<#field_ty as #bevy_reflect_path::TypePath>::type_path()),
received: #bevy_reflect_path::__macro_exports::alloc_utils::Cow::Owned(
#bevy_reflect_path::__macro_exports::alloc_utils::ToString::to_string(#bevy_reflect_path::DynamicTypePath::reflect_type_path(#alias))
),
}
)?
}
}
CloneBehavior::Trait => {
quote! {
#FQClone::clone(#alias)
#FQClone::clone(#non_cast_alias)
}
}
CloneBehavior::Func(clone_fn) => {
quote! {
#clone_fn(#alias)
if field.field.attrs.ignore.is_ignored() {
quote!(#clone_fn(#non_cast_alias))
} else {
quote! {
#clone_fn(#FQOption::ok_or_else(
<dyn #bevy_reflect_path::PartialReflect>::try_downcast_ref(#alias),
|| #bevy_reflect_path::ReflectCloneError::FailedDowncast {
expected: #bevy_reflect_path::__macro_exports::alloc_utils::Cow::Borrowed(<#field_ty as #bevy_reflect_path::TypePath>::type_path()),
received: #bevy_reflect_path::__macro_exports::alloc_utils::Cow::Owned(
#bevy_reflect_path::__macro_exports::alloc_utils::ToString::to_string(#bevy_reflect_path::DynamicTypePath::reflect_type_path(#alias))
),
}
)?)
}
}
}
}
Expand Down
51 changes: 51 additions & 0 deletions crates/bevy_reflect/derive/src/impls/casting.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use crate::derive_data::ReflectMeta;
use crate::where_clause_options::WhereClauseOptions;
use proc_macro2::TokenStream;
use quote::quote;

/// Generates impls for the `CastPartialReflect` and `CastReflect` traits.
pub(crate) fn impl_casting_traits(
meta: &ReflectMeta,
where_clause_options: &WhereClauseOptions,
) -> TokenStream {
let bevy_reflect_path = meta.bevy_reflect_path();
let type_path = meta.type_path();
let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl();
let where_reflect_clause = where_clause_options.extend_where_clause(where_clause);

quote! {
impl #impl_generics #bevy_reflect_path::cast::CastPartialReflect for #type_path #ty_generics #where_reflect_clause {
#[inline]
fn as_partial_reflect(&self) -> &dyn #bevy_reflect_path::PartialReflect {
self
}

#[inline]
fn as_partial_reflect_mut(&mut self) -> &mut dyn #bevy_reflect_path::PartialReflect {
self
}

#[inline]
fn into_partial_reflect(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::PartialReflect> {
self
}
}

impl #impl_generics #bevy_reflect_path::cast::CastReflect for #type_path #ty_generics #where_reflect_clause {
#[inline]
fn as_reflect(&self) -> &dyn #bevy_reflect_path::Reflect {
self
}

#[inline]
fn as_reflect_mut(&mut self) -> &mut dyn #bevy_reflect_path::Reflect {
self
}

#[inline]
fn into_reflect(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::Reflect> {
self
}
}
}
}
35 changes: 5 additions & 30 deletions crates/bevy_reflect/derive/src/impls/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use bevy_macro_utils::fq_std::{FQAny, FQOption, FQResult};

use quote::quote;

use crate::impls::casting::impl_casting_traits;
use crate::{derive_data::ReflectMeta, where_clause_options::WhereClauseOptions};

pub fn impl_full_reflect(where_clause_options: &WhereClauseOptions) -> proc_macro2::TokenStream {
Expand Down Expand Up @@ -48,25 +49,12 @@ pub fn impl_full_reflect(where_clause_options: &WhereClauseOptions) -> proc_macr
}
};

let casting_impls = impl_casting_traits(meta, where_clause_options);

quote! {
impl #impl_generics #bevy_reflect_path::Reflect for #type_path #ty_generics #where_reflect_clause {
#any_impls

#[inline]
fn into_reflect(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::Reflect> {
self
}

#[inline]
fn as_reflect(&self) -> &dyn #bevy_reflect_path::Reflect {
self
}

#[inline]
fn as_reflect_mut(&mut self) -> &mut dyn #bevy_reflect_path::Reflect {
self
}

#[inline]
fn set(
&mut self,
Expand All @@ -76,6 +64,8 @@ pub fn impl_full_reflect(where_clause_options: &WhereClauseOptions) -> proc_macr
#FQResult::Ok(())
}
}

#casting_impls
}
}

Expand Down Expand Up @@ -146,21 +136,6 @@ pub fn common_partial_reflect_methods(
#FQOption::Some(self)
}

#[inline]
fn into_partial_reflect(self: #bevy_reflect_path::__macro_exports::alloc_utils::Box<Self>) -> #bevy_reflect_path::__macro_exports::alloc_utils::Box<dyn #bevy_reflect_path::PartialReflect> {
self
}

#[inline]
fn as_partial_reflect(&self) -> &dyn #bevy_reflect_path::PartialReflect {
self
}

#[inline]
fn as_partial_reflect_mut(&mut self) -> &mut dyn #bevy_reflect_path::PartialReflect {
self
}

#hash_fn

#partial_eq_fn
Expand Down
Loading
Loading