Skip to content

Commit 2b7a3b2

Browse files
soqbalice-i-cecileMrGVSV
authored
reflect: treat proxy types correctly when serializing (#12024)
# Objective - Fixes #12001. - Note this PR doesn't change any feature flags, however flaky the issue revealed they are. ## Solution - Use `FromReflect` to convert proxy types to concrete ones in `ReflectSerialize::get_serializable`. - Use `get_represented_type_info() -> type_id()` to get the correct type id to interact with the registry in `bevy_reflect::serde::ser::get_serializable`. --- ## Changelog - Registering `ReflectSerialize` now imposes additional `FromReflect` and `TypePath` bounds. ## Migration Guide - If `ReflectSerialize` is registered on a type, but `TypePath` or `FromReflect` implementations are omitted (perhaps by `#[reflect(type_path = false)` or `#[reflect(from_reflect = false)]`), the traits must now be implemented. --------- Co-authored-by: Alice Cecile <[email protected]> Co-authored-by: Gino Valente <[email protected]>
1 parent 51edf9c commit 2b7a3b2

File tree

3 files changed

+22
-8
lines changed

3 files changed

+22
-8
lines changed

crates/bevy_reflect/src/serde/ser.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,19 @@ fn get_serializable<'a, E: Error>(
3232
reflect_value: &'a dyn Reflect,
3333
type_registry: &TypeRegistry,
3434
) -> Result<Serializable<'a>, E> {
35+
let info = reflect_value.get_represented_type_info().ok_or_else(|| {
36+
Error::custom(format_args!(
37+
"Type '{}' does not represent any type",
38+
reflect_value.reflect_type_path(),
39+
))
40+
})?;
41+
3542
let reflect_serialize = type_registry
36-
.get_type_data::<ReflectSerialize>(reflect_value.type_id())
43+
.get_type_data::<ReflectSerialize>(info.type_id())
3744
.ok_or_else(|| {
3845
Error::custom(format_args!(
3946
"Type '{}' did not register ReflectSerialize",
40-
reflect_value.reflect_type_path()
47+
info.type_path(),
4148
))
4249
})?;
4350
Ok(reflect_serialize.get_serializable(reflect_value))

crates/bevy_reflect/src/type_registry.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{serde::Serializable, Reflect, TypeInfo, TypePath, Typed};
1+
use crate::{serde::Serializable, FromReflect, Reflect, TypeInfo, TypePath, Typed};
22
use bevy_ptr::{Ptr, PtrMut};
33
use bevy_utils::{HashMap, HashSet, TypeIdMap};
44
use downcast_rs::{impl_downcast, Downcast};
@@ -461,14 +461,20 @@ pub struct ReflectSerialize {
461461
get_serializable: for<'a> fn(value: &'a dyn Reflect) -> Serializable,
462462
}
463463

464-
impl<T: Reflect + erased_serde::Serialize> FromType<T> for ReflectSerialize {
464+
impl<T: TypePath + FromReflect + erased_serde::Serialize> FromType<T> for ReflectSerialize {
465465
fn from_type() -> Self {
466466
ReflectSerialize {
467467
get_serializable: |value| {
468-
let value = value.downcast_ref::<T>().unwrap_or_else(|| {
469-
panic!("ReflectSerialize::get_serialize called with type `{}`, even though it was created for `{}`", value.reflect_type_path(), std::any::type_name::<T>())
470-
});
471-
Serializable::Borrowed(value)
468+
value
469+
.downcast_ref::<T>()
470+
.map(|value| Serializable::Borrowed(value))
471+
.or_else(|| T::from_reflect(value).map(|value| Serializable::Owned(Box::new(value))))
472+
.unwrap_or_else(|| {
473+
panic!(
474+
"FromReflect::from_reflect failed when called on type `{}` with this value: {value:?}",
475+
T::type_path(),
476+
);
477+
})
472478
},
473479
}
474480
}

examples/scene/scene.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ fn save_scene_system(world: &mut World) {
114114
component_b,
115115
ComponentA { x: 1.0, y: 2.0 },
116116
Transform::IDENTITY,
117+
Name::new("joe"),
117118
));
118119
scene_world.spawn(ComponentA { x: 3.0, y: 4.0 });
119120
scene_world.insert_resource(ResourceA { score: 1 });

0 commit comments

Comments
 (0)