Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bevy_reflect: Add DynamicTyped trait #15108

Merged
merged 3 commits into from
Sep 13, 2024
Merged
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
24 changes: 12 additions & 12 deletions crates/bevy_reflect/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1632,7 +1632,7 @@ mod tests {

// TypeInfo (instance)
let value: &dyn Reflect = &123_i32;
let info = value.get_represented_type_info().unwrap();
let info = value.reflect_type_info();
assert!(info.is::<i32>());

// Struct
Expand All @@ -1653,7 +1653,7 @@ mod tests {
assert_eq!(usize::type_path(), info.field_at(1).unwrap().type_path());

let value: &dyn Reflect = &MyStruct { foo: 123, bar: 321 };
let info = value.get_represented_type_info().unwrap();
let info = value.reflect_type_info();
assert!(info.is::<MyStruct>());

// Struct (generic)
Expand All @@ -1675,7 +1675,7 @@ mod tests {
foo: String::from("Hello!"),
bar: 321,
};
let info = value.get_represented_type_info().unwrap();
let info = value.reflect_type_info();
assert!(info.is::<MyGenericStruct<String>>());

// Struct (dynamic field)
Expand Down Expand Up @@ -1705,7 +1705,7 @@ mod tests {
foo: DynamicStruct::default(),
bar: 321,
};
let info = value.get_represented_type_info().unwrap();
let info = value.reflect_type_info();
assert!(info.is::<MyDynamicStruct>());

// Tuple Struct
Expand All @@ -1731,7 +1731,7 @@ mod tests {
assert!(info.field_at(1).unwrap().type_info().unwrap().is::<f32>());

let value: &dyn Reflect = &(123_u32, 1.23_f32, String::from("Hello!"));
let info = value.get_represented_type_info().unwrap();
let info = value.reflect_type_info();
assert!(info.is::<MyTuple>());

// List
Expand All @@ -1746,7 +1746,7 @@ mod tests {
assert_eq!(usize::type_path(), info.item_ty().path());

let value: &dyn Reflect = &vec![123_usize];
let info = value.get_represented_type_info().unwrap();
let info = value.reflect_type_info();
assert!(info.is::<MyList>());

// List (SmallVec)
Expand All @@ -1763,7 +1763,7 @@ mod tests {

let value: MySmallVec = smallvec::smallvec![String::default(); 2];
let value: &dyn Reflect = &value;
let info = value.get_represented_type_info().unwrap();
let info = value.reflect_type_info();
assert!(info.is::<MySmallVec>());
}

Expand All @@ -1779,7 +1779,7 @@ mod tests {
assert_eq!(3, info.capacity());

let value: &dyn Reflect = &[1usize, 2usize, 3usize];
let info = value.get_represented_type_info().unwrap();
let info = value.reflect_type_info();
assert!(info.is::<MyArray>());

// Cow<'static, str>
Expand All @@ -1791,7 +1791,7 @@ mod tests {
assert_eq!(std::any::type_name::<MyCowStr>(), info.type_path());

let value: &dyn Reflect = &Cow::<'static, str>::Owned("Hello!".to_string());
let info = value.get_represented_type_info().unwrap();
let info = value.reflect_type_info();
assert!(info.is::<MyCowStr>());

// Cow<'static, [u8]>
Expand All @@ -1806,7 +1806,7 @@ mod tests {
assert_eq!(std::any::type_name::<u8>(), info.item_ty().path());

let value: &dyn Reflect = &Cow::<'static, [u8]>::Owned(vec![0, 1, 2, 3]);
let info = value.get_represented_type_info().unwrap();
let info = value.reflect_type_info();
assert!(info.is::<MyCowSlice>());

// Map
Expand All @@ -1824,7 +1824,7 @@ mod tests {
assert_eq!(f32::type_path(), info.value_ty().path());

let value: &dyn Reflect = &MyMap::new();
let info = value.get_represented_type_info().unwrap();
let info = value.reflect_type_info();
assert!(info.is::<MyMap>());

// Value
Expand All @@ -1836,7 +1836,7 @@ mod tests {
assert_eq!(MyValue::type_path(), info.type_path());

let value: &dyn Reflect = &String::from("Hello!");
let info = value.get_represented_type_info().unwrap();
let info = value.reflect_type_info();
assert!(info.is::<MyValue>());
}

Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_reflect/src/reflect.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
array_debug, enum_debug, list_debug, map_debug, serde::Serializable, struct_debug, tuple_debug,
tuple_struct_debug, Array, DynamicTypePath, Enum, List, Map, Set, Struct, Tuple, TupleStruct,
TypeInfo, TypePath, Typed, ValueInfo,
tuple_struct_debug, Array, DynamicTypePath, DynamicTyped, Enum, List, Map, Set, Struct, Tuple,
TupleStruct, TypeInfo, TypePath, Typed, ValueInfo,
};
use std::{
any::{Any, TypeId},
Expand Down Expand Up @@ -408,7 +408,7 @@ where
message = "`{Self}` does not implement `Reflect` so cannot be fully reflected",
note = "consider annotating `{Self}` with `#[derive(Reflect)]`"
)]
pub trait Reflect: PartialReflect + Any {
pub trait Reflect: PartialReflect + DynamicTyped + Any {
/// Returns the value as a [`Box<dyn Any>`][std::any::Any].
///
/// For remote wrapper types, this will return the remote type instead.
Expand Down
7 changes: 1 addition & 6 deletions crates/bevy_reflect/src/serde/ser/serializable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,7 @@ impl<'a> Serializable<'a> {
))
})?;

let info = value.get_represented_type_info().ok_or_else(|| {
make_custom_error(format_args!(
"type `{}` does not represent any type",
value.reflect_type_path(),
))
})?;
let info = value.reflect_type_info();

let registration = type_registry.get(info.type_id()).ok_or_else(|| {
make_custom_error(format_args!(
Expand Down
21 changes: 21 additions & 0 deletions crates/bevy_reflect/src/type_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,27 @@ impl MaybeTyped for DynamicArray {}

impl MaybeTyped for DynamicTuple {}

/// Dynamic dispatch for [`Typed`].
///
/// Since this is a supertrait of [`Reflect`] its methods can be called on a `dyn Reflect`.
///
/// [`Reflect`]: crate::Reflect
#[diagnostic::on_unimplemented(
message = "`{Self}` can not provide dynamic type information through reflection",
note = "consider annotating `{Self}` with `#[derive(Reflect)]`"
)]
pub trait DynamicTyped {
/// See [`Typed::type_info`].
fn reflect_type_info(&self) -> &'static TypeInfo;
}

impl<T: Typed> DynamicTyped for T {
#[inline]
fn reflect_type_info(&self) -> &'static TypeInfo {
Self::type_info()
}
}

/// A [`TypeInfo`]-specific error.
#[derive(Debug, Error)]
pub enum TypeInfoError {
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_reflect/src/utility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ impl<T: TypedProperty> Default for NonGenericTypeCell<T> {
/// # fn reflect_owned(self: Box<Self>) -> ReflectOwned { todo!() }
/// # fn clone_value(&self) -> Box<dyn PartialReflect> { todo!() }
/// # }
/// # impl<T: Reflect + TypePath> Reflect for Foo<T> {
/// # impl<T: Reflect + Typed + TypePath> Reflect for Foo<T> {
/// # fn into_any(self: Box<Self>) -> Box<dyn Any> { todo!() }
/// # fn as_any(&self) -> &dyn Any { todo!() }
/// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() }
Expand Down
4 changes: 2 additions & 2 deletions examples/reflection/type_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ fn main() {
registry.register_type_data::<Zombie, ReflectDamageable>();

// Then at any point we can retrieve the type data from the registry:
let type_id = value.get_represented_type_info().unwrap().type_id();
let type_id = value.reflect_type_info().type_id();
let reflect_damageable = registry
.get_type_data::<ReflectDamageable>(type_id)
.unwrap();
Expand Down Expand Up @@ -133,7 +133,7 @@ fn main() {
// Now we can use `ReflectHealth` to convert `dyn Reflect` into `dyn Health`:
let value: Box<dyn Reflect> = Box::new(Skeleton { health: 50 });

let type_id = value.get_represented_type_info().unwrap().type_id();
let type_id = value.reflect_type_info().type_id();
let reflect_health = registry.get_type_data::<ReflectHealth>(type_id).unwrap();

// Type data generated by `#[reflect_trait]` comes with a `get`, `get_mut`, and `get_boxed` method,
Expand Down