Skip to content

Commit d80078c

Browse files
bevy_reflect: Introduce reflect_clone_and_take. (#19944)
# Objective There is a pattern that appears in multiple places, involving `reflect_clone`, followed by `take`, followed by `map_err` that produces a `FailedDowncast` in a particular form. ## Solution Introduces `reflect_clone_and_take`, which factors out the repeated code. ## Testing `cargo run -p ci` --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
1 parent f1df61e commit d80078c

File tree

11 files changed

+38
-80
lines changed

11 files changed

+38
-80
lines changed

crates/bevy_reflect/compile_fail/tests/reflect_remote/invalid_definition_fail.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ mod structs {
99

1010
#[reflect_remote(external_crate::TheirStruct)]
1111
//~^ ERROR: `?` operator has incompatible types
12+
//~| ERROR: mismatched types
1213
struct MyStruct {
1314
// Reason: Should be `u32`
1415
pub value: bool,
@@ -25,6 +26,7 @@ mod tuple_structs {
2526

2627
#[reflect_remote(external_crate::TheirStruct)]
2728
//~^ ERROR: `?` operator has incompatible types
29+
//~| ERROR: mismatched types
2830
struct MyStruct(
2931
// Reason: Should be `u32`
3032
pub bool,
@@ -48,6 +50,7 @@ mod enums {
4850
//~| ERROR: variant `enums::external_crate::TheirStruct::Unit` has no field named `0`
4951
//~| ERROR: `?` operator has incompatible types
5052
//~| ERROR: `?` operator has incompatible types
53+
//~| ERROR: mismatched types
5154
enum MyStruct {
5255
// Reason: Should be unit variant
5356
Unit(i32),
@@ -57,6 +60,7 @@ mod enums {
5760
// Reason: Should be `usize`
5861
Struct { value: String },
5962
//~^ ERROR: mismatched types
63+
//~| ERROR: mismatched types
6064
}
6165
}
6266

crates/bevy_reflect/compile_fail/tests/reflect_remote/nested_fail.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ mod incorrect_inner_type {
2626
//~| ERROR: `TheirInner<T>` does not implement `PartialReflect` so cannot be introspected
2727
//~| ERROR: `TheirInner<T>` does not implement `PartialReflect` so cannot be introspected
2828
//~| ERROR: `TheirInner<T>` does not implement `TypePath` so cannot provide dynamic type path information
29-
//~| ERROR: `TheirInner<T>` does not implement `TypePath` so cannot provide dynamic type path information
3029
//~| ERROR: `?` operator has incompatible types
30+
//~| ERROR: mismatched types
3131
struct MyOuter<T: FromReflect + GetTypeRegistration> {
3232
// Reason: Should not use `MyInner<T>` directly
3333
pub inner: MyInner<T>,

crates/bevy_reflect/compile_fail/tests/reflect_remote/type_mismatch_fail.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ mod enums {
7777

7878
#[reflect_remote(external_crate::TheirBar)]
7979
//~^ ERROR: `?` operator has incompatible types
80+
//~| ERROR: mismatched types
8081
enum MyBar {
8182
// Reason: Should use `i32`
8283
Value(u32),

crates/bevy_reflect/derive/src/derive_data.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -722,18 +722,7 @@ impl<'a> ReflectStruct<'a> {
722722
}
723723
} else {
724724
quote! {
725-
#bevy_reflect_path::PartialReflect::reflect_clone(#accessor)?
726-
.take()
727-
.map_err(|value| #bevy_reflect_path::ReflectCloneError::FailedDowncast {
728-
expected: #bevy_reflect_path::__macro_exports::alloc_utils::Cow::Borrowed(
729-
<#field_ty as #bevy_reflect_path::TypePath>::type_path()
730-
),
731-
received: #bevy_reflect_path::__macro_exports::alloc_utils::Cow::Owned(
732-
#bevy_reflect_path::__macro_exports::alloc_utils::ToString::to_string(
733-
#bevy_reflect_path::DynamicTypePath::reflect_type_path(&*value)
734-
)
735-
),
736-
})?
725+
<#field_ty as #bevy_reflect_path::PartialReflect>::reflect_clone_and_take(#accessor)?
737726
}
738727
};
739728

crates/bevy_reflect/derive/src/enum_utility.rs

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -316,9 +316,7 @@ impl<'a> VariantBuilder for ReflectCloneVariantBuilder<'a> {
316316

317317
fn construct_field(&self, field: VariantField) -> TokenStream {
318318
let bevy_reflect_path = self.reflect_enum.meta().bevy_reflect_path();
319-
320319
let field_ty = field.field.reflected_type();
321-
322320
let alias = field.alias;
323321
let alias = match &field.field.attrs.remote {
324322
Some(wrapper_ty) => {
@@ -332,18 +330,7 @@ impl<'a> VariantBuilder for ReflectCloneVariantBuilder<'a> {
332330
match &field.field.attrs.clone {
333331
CloneBehavior::Default => {
334332
quote! {
335-
#bevy_reflect_path::PartialReflect::reflect_clone(#alias)?
336-
.take()
337-
.map_err(|value| #bevy_reflect_path::ReflectCloneError::FailedDowncast {
338-
expected: #bevy_reflect_path::__macro_exports::alloc_utils::Cow::Borrowed(
339-
<#field_ty as #bevy_reflect_path::TypePath>::type_path()
340-
),
341-
received: #bevy_reflect_path::__macro_exports::alloc_utils::Cow::Owned(
342-
#bevy_reflect_path::__macro_exports::alloc_utils::ToString::to_string(
343-
#bevy_reflect_path::DynamicTypePath::reflect_type_path(&*value)
344-
)
345-
),
346-
})?
333+
<#field_ty as #bevy_reflect_path::PartialReflect>::reflect_clone_and_take(#alias)?
347334
}
348335
}
349336
CloneBehavior::Trait => {

crates/bevy_reflect/src/impls/alloc/collections/btree/map.rs

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use crate::{
99
type_registry::{FromType, GetTypeRegistration, ReflectFromPtr, TypeRegistration},
1010
utility::GenericTypeInfoCell,
1111
};
12-
use alloc::borrow::Cow;
1312
use alloc::vec::Vec;
1413
use bevy_platform::prelude::*;
1514
use bevy_reflect_derive::impl_type_path;
@@ -144,21 +143,8 @@ where
144143
fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError> {
145144
let mut map = Self::new();
146145
for (key, value) in self.iter() {
147-
let key =
148-
key.reflect_clone()?
149-
.take()
150-
.map_err(|_| ReflectCloneError::FailedDowncast {
151-
expected: Cow::Borrowed(<Self as TypePath>::type_path()),
152-
received: Cow::Owned(key.reflect_type_path().to_string()),
153-
})?;
154-
let value =
155-
value
156-
.reflect_clone()?
157-
.take()
158-
.map_err(|_| ReflectCloneError::FailedDowncast {
159-
expected: Cow::Borrowed(<Self as TypePath>::type_path()),
160-
received: Cow::Owned(value.reflect_type_path().to_string()),
161-
})?;
146+
let key = key.reflect_clone_and_take()?;
147+
let value = value.reflect_clone_and_take()?;
162148
map.insert(key, value);
163149
}
164150

crates/bevy_reflect/src/impls/macros/list.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,14 +113,7 @@ macro_rules! impl_reflect_for_veclike {
113113
fn reflect_clone(&self) -> Result<bevy_platform::prelude::Box<dyn $crate::reflect::Reflect>, $crate::error::ReflectCloneError> {
114114
Ok(bevy_platform::prelude::Box::new(
115115
self.iter()
116-
.map(|value| {
117-
value.reflect_clone()?.take().map_err(|_| {
118-
$crate::error::ReflectCloneError::FailedDowncast {
119-
expected: alloc::borrow::Cow::Borrowed(<T as $crate::type_path::TypePath>::type_path()),
120-
received: alloc::borrow::Cow::Owned(alloc::string::ToString::to_string(value.reflect_type_path())),
121-
}
122-
})
123-
})
116+
.map(|value| value.reflect_clone_and_take())
124117
.collect::<Result<Self, $crate::error::ReflectCloneError>>()?,
125118
))
126119
}

crates/bevy_reflect/src/impls/macros/map.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -146,18 +146,8 @@ macro_rules! impl_reflect_for_hashmap {
146146
fn reflect_clone(&self) -> Result<bevy_platform::prelude::Box<dyn $crate::reflect::Reflect>, $crate::error::ReflectCloneError> {
147147
let mut map = Self::with_capacity_and_hasher(self.len(), S::default());
148148
for (key, value) in self.iter() {
149-
let key = key.reflect_clone()?.take().map_err(|_| {
150-
$crate::error::ReflectCloneError::FailedDowncast {
151-
expected: alloc::borrow::Cow::Borrowed(<K as $crate::type_path::TypePath>::type_path()),
152-
received: alloc::borrow::Cow::Owned(alloc::string::ToString::to_string(key.reflect_type_path())),
153-
}
154-
})?;
155-
let value = value.reflect_clone()?.take().map_err(|_| {
156-
$crate::error::ReflectCloneError::FailedDowncast {
157-
expected: alloc::borrow::Cow::Borrowed(<V as $crate::type_path::TypePath>::type_path()),
158-
received: alloc::borrow::Cow::Owned(alloc::string::ToString::to_string(value.reflect_type_path())),
159-
}
160-
})?;
149+
let key = key.reflect_clone_and_take()?;
150+
let value = value.reflect_clone_and_take()?;
161151
map.insert(key, value);
162152
}
163153

crates/bevy_reflect/src/impls/macros/set.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,7 @@ macro_rules! impl_reflect_for_hashset {
129129
fn reflect_clone(&self) -> Result<bevy_platform::prelude::Box<dyn $crate::reflect::Reflect>, $crate::error::ReflectCloneError> {
130130
let mut set = Self::with_capacity_and_hasher(self.len(), S::default());
131131
for value in self.iter() {
132-
let value = value.reflect_clone()?.take().map_err(|_| {
133-
$crate::error::ReflectCloneError::FailedDowncast {
134-
expected: alloc::borrow::Cow::Borrowed(<V as $crate::type_path::TypePath>::type_path()),
135-
received: alloc::borrow::Cow::Owned(alloc::string::ToString::to_string(value.reflect_type_path())),
136-
}
137-
})?;
132+
let value = value.reflect_clone_and_take()?;
138133
set.insert(value);
139134
}
140135

crates/bevy_reflect/src/impls/smallvec.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::{
44
ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypeParamInfo, TypePath, TypeRegistration,
55
Typed,
66
};
7-
use alloc::{borrow::Cow, boxed::Box, string::ToString, vec::Vec};
7+
use alloc::{boxed::Box, vec::Vec};
88
use bevy_reflect::ReflectCloneError;
99
use bevy_reflect_derive::impl_type_path;
1010
use core::any::Any;
@@ -137,16 +137,11 @@ where
137137

138138
fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError> {
139139
Ok(Box::new(
140-
self.iter()
141-
.map(|value| {
142-
value
143-
.reflect_clone()?
144-
.take()
145-
.map_err(|_| ReflectCloneError::FailedDowncast {
146-
expected: Cow::Borrowed(<T::Item as TypePath>::type_path()),
147-
received: Cow::Owned(value.reflect_type_path().to_string()),
148-
})
149-
})
140+
// `(**self)` avoids getting `SmallVec<T> as List::iter`, which
141+
// would give us the wrong item type.
142+
(**self)
143+
.iter()
144+
.map(PartialReflect::reflect_clone_and_take)
150145
.collect::<Result<Self, ReflectCloneError>>()?,
151146
))
152147
}

0 commit comments

Comments
 (0)