From 6feddee7280c2789d4d22fb7b011442737960128 Mon Sep 17 00:00:00 2001 From: PROMETHIA-27 Date: Mon, 27 Jun 2022 16:52:25 +0000 Subject: [PATCH] Make `Reflect` safe to implement (#5010) # Objective Currently, `Reflect` is unsafe to implement because of a contract in which `any` and `any_mut` must return `self`, or `downcast` will cause UB. This PR makes `Reflect` safe, makes `downcast` not use unsafe, and eliminates this contract. ## Solution This PR adds a method to `Reflect`, `any`. It also renames the old `any` to `as_any`. `any` now takes a `Box` and returns a `Box`. --- ## Changelog ### Added: - `any()` method - `represents()` method ### Changed: - `Reflect` is now a safe trait - `downcast()` is now safe - The old `any` is now called `as_any`, and `any_mut` is now `as_mut_any` ## Migration Guide - Reflect derives should not have to change anything - Manual reflect impls will need to remove the `unsafe` keyword, add `any()` implementations, and rename the old `any` and `any_mut` to `as_any` and `as_mut_any`. - Calls to `any`/`any_mut` must be changed to `as_any`/`as_mut_any` ## Points of discussion: - Should renaming `any` be avoided and instead name the new method `any_box`? - ~~Could there be a performance regression from avoiding the unsafe? I doubt it, but this change does seem to introduce redundant checks.~~ - ~~Could/should `is` and `type_id()` be implemented differently? For example, moving `is` onto `Reflect` as an `fn(&self, TypeId) -> bool`~~ Co-authored-by: PROMETHIA-27 <42193387+PROMETHIA-27@users.noreply.github.com> --- .../src/container_attributes.rs | 2 +- .../bevy_reflect_derive/src/from_reflect.rs | 2 +- .../bevy_reflect_derive/src/impls.rs | 40 ++++++++----- crates/bevy_reflect/src/array.rs | 12 ++-- crates/bevy_reflect/src/impls/smallvec.rs | 11 ++-- crates/bevy_reflect/src/impls/std.rs | 56 ++++++++++++------- crates/bevy_reflect/src/lib.rs | 36 ++++++++++++ crates/bevy_reflect/src/list.rs | 12 ++-- crates/bevy_reflect/src/map.rs | 11 ++-- crates/bevy_reflect/src/reflect.rs | 52 ++++++++++------- crates/bevy_reflect/src/struct_trait.rs | 12 ++-- crates/bevy_reflect/src/tuple.rs | 23 +++++--- crates/bevy_reflect/src/tuple_struct.rs | 12 ++-- crates/bevy_reflect/src/type_info.rs | 7 ++- crates/bevy_reflect/src/utility.rs | 14 +++-- 15 files changed, 206 insertions(+), 96 deletions(-) diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/container_attributes.rs b/crates/bevy_reflect/bevy_reflect_derive/src/container_attributes.rs index 5f2d16c4a6af9..15f9f07759018 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/container_attributes.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/container_attributes.rs @@ -208,7 +208,7 @@ impl ReflectTraits { match &self.partial_eq { TraitImpl::Implemented => Some(quote! { fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> Option { - let value = value.any(); + let value = value.as_any(); if let Some(value) = value.downcast_ref::() { Some(std::cmp::PartialEq::eq(self, value)) } else { diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs b/crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs index 1827424c93d40..b4c9c345f26eb 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/from_reflect.rs @@ -26,7 +26,7 @@ pub(crate) fn impl_value( 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 { - Some(reflect.any().downcast_ref::<#type_name #ty_generics>()?.clone()) + Some(reflect.as_any().downcast_ref::<#type_name #ty_generics>()?.clone()) } } }) diff --git a/crates/bevy_reflect/bevy_reflect_derive/src/impls.rs b/crates/bevy_reflect/bevy_reflect_derive/src/impls.rs index 7aa4ea373df72..38680a35adf38 100644 --- a/crates/bevy_reflect/bevy_reflect_derive/src/impls.rs +++ b/crates/bevy_reflect/bevy_reflect_derive/src/impls.rs @@ -125,8 +125,7 @@ pub(crate) fn impl_struct(derive_data: &ReflectDeriveData) -> TokenStream { } } - // SAFE: any and any_mut both return self - unsafe impl #impl_generics #bevy_reflect_path::Reflect for #struct_name #ty_generics #where_clause { + impl #impl_generics #bevy_reflect_path::Reflect for #struct_name #ty_generics #where_clause { #[inline] fn type_name(&self) -> &str { std::any::type_name::() @@ -138,11 +137,17 @@ pub(crate) fn impl_struct(derive_data: &ReflectDeriveData) -> TokenStream { } #[inline] - fn any(&self) -> &dyn std::any::Any { + fn into_any(self: Box) -> Box { self } + #[inline] - fn any_mut(&mut self) -> &mut dyn std::any::Any { + fn as_any(&self) -> &dyn std::any::Any { + self + } + + #[inline] + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { self } @@ -275,8 +280,7 @@ pub(crate) fn impl_tuple_struct(derive_data: &ReflectDeriveData) -> TokenStream } } - // SAFE: any and any_mut both return self - unsafe impl #impl_generics #bevy_reflect_path::Reflect for #struct_name #ty_generics #where_clause { + impl #impl_generics #bevy_reflect_path::Reflect for #struct_name #ty_generics #where_clause { #[inline] fn type_name(&self) -> &str { std::any::type_name::() @@ -288,11 +292,17 @@ pub(crate) fn impl_tuple_struct(derive_data: &ReflectDeriveData) -> TokenStream } #[inline] - fn any(&self) -> &dyn std::any::Any { + fn into_any(self: Box) -> Box { + self + } + + #[inline] + fn as_any(&self) -> &dyn std::any::Any { self } + #[inline] - fn any_mut(&mut self) -> &mut dyn std::any::Any { + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { self } @@ -372,8 +382,7 @@ pub(crate) fn impl_value( #typed_impl - // SAFE: any and any_mut both return self - unsafe impl #impl_generics #bevy_reflect_path::Reflect for #type_name #ty_generics #where_clause { + impl #impl_generics #bevy_reflect_path::Reflect for #type_name #ty_generics #where_clause { #[inline] fn type_name(&self) -> &str { std::any::type_name::() @@ -385,12 +394,17 @@ pub(crate) fn impl_value( } #[inline] - fn any(&self) -> &dyn std::any::Any { + fn into_any(self: Box) -> Box { + self + } + + #[inline] + fn as_any(&self) -> &dyn std::any::Any { self } #[inline] - fn any_mut(&mut self) -> &mut dyn std::any::Any { + fn as_any_mut(&mut self) -> &mut dyn std::any::Any { self } @@ -411,7 +425,7 @@ pub(crate) fn impl_value( #[inline] fn apply(&mut self, value: &dyn #bevy_reflect_path::Reflect) { - let value = value.any(); + let value = value.as_any(); if let Some(value) = value.downcast_ref::() { *self = value.clone(); } else { diff --git a/crates/bevy_reflect/src/array.rs b/crates/bevy_reflect/src/array.rs index bc8c08a108e80..486966813dd65 100644 --- a/crates/bevy_reflect/src/array.rs +++ b/crates/bevy_reflect/src/array.rs @@ -151,8 +151,7 @@ impl DynamicArray { } } -// SAFE: any and any_mut both return self -unsafe impl Reflect for DynamicArray { +impl Reflect for DynamicArray { #[inline] fn type_name(&self) -> &str { self.name.as_str() @@ -164,12 +163,17 @@ unsafe impl Reflect for DynamicArray { } #[inline] - fn any(&self) -> &dyn Any { + fn into_any(self: Box) -> Box { self } #[inline] - fn any_mut(&mut self) -> &mut dyn Any { + fn as_any(&self) -> &dyn Any { + self + } + + #[inline] + fn as_any_mut(&mut self) -> &mut dyn Any { self } diff --git a/crates/bevy_reflect/src/impls/smallvec.rs b/crates/bevy_reflect/src/impls/smallvec.rs index 2ab1f97869c1e..61d507986b15a 100644 --- a/crates/bevy_reflect/src/impls/smallvec.rs +++ b/crates/bevy_reflect/src/impls/smallvec.rs @@ -55,8 +55,7 @@ where } } -// SAFE: any and any_mut both return self -unsafe impl Reflect for SmallVec +impl Reflect for SmallVec where T::Item: FromReflect + Clone, { @@ -68,11 +67,15 @@ where ::type_info() } - fn any(&self) -> &dyn Any { + fn into_any(self: Box) -> Box { self } - fn any_mut(&mut self) -> &mut dyn Any { + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { self } diff --git a/crates/bevy_reflect/src/impls/std.rs b/crates/bevy_reflect/src/impls/std.rs index 13dae6c634580..6e94741f638b9 100644 --- a/crates/bevy_reflect/src/impls/std.rs +++ b/crates/bevy_reflect/src/impls/std.rs @@ -105,8 +105,7 @@ impl List for Vec { } } -// SAFE: any and any_mut both return self -unsafe impl Reflect for Vec { +impl Reflect for Vec { fn type_name(&self) -> &str { std::any::type_name::() } @@ -115,11 +114,15 @@ unsafe impl Reflect for Vec { ::type_info() } - fn any(&self) -> &dyn Any { + fn into_any(self: Box) -> Box { self } - fn any_mut(&mut self) -> &mut dyn Any { + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { self } @@ -230,8 +233,7 @@ impl Map for HashMap { } } -// SAFE: any and any_mut both return self -unsafe impl Reflect for HashMap { +impl Reflect for HashMap { fn type_name(&self) -> &str { std::any::type_name::() } @@ -240,11 +242,15 @@ unsafe impl Reflect for HashMap { ::type_info() } - fn any(&self) -> &dyn Any { + fn into_any(self: Box) -> Box { self } - fn any_mut(&mut self) -> &mut dyn Any { + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { self } @@ -350,8 +356,7 @@ impl Array for [T; N] { } } -// SAFE: any and any_mut both return self -unsafe impl Reflect for [T; N] { +impl Reflect for [T; N] { #[inline] fn type_name(&self) -> &str { std::any::type_name::() @@ -362,12 +367,17 @@ unsafe impl Reflect for [T; N] { } #[inline] - fn any(&self) -> &dyn Any { + fn into_any(self: Box) -> Box { self } #[inline] - fn any_mut(&mut self) -> &mut dyn Any { + fn as_any(&self) -> &dyn Any { + self + } + + #[inline] + fn as_any_mut(&mut self) -> &mut dyn Any { self } @@ -465,8 +475,7 @@ impl_array_get_type_registration! { 30 31 32 } -// SAFE: any and any_mut both return self -unsafe impl Reflect for Cow<'static, str> { +impl Reflect for Cow<'static, str> { fn type_name(&self) -> &str { std::any::type_name::() } @@ -475,11 +484,15 @@ unsafe impl Reflect for Cow<'static, str> { ::type_info() } - fn any(&self) -> &dyn Any { + fn into_any(self: Box) -> Box { + self + } + + fn as_any(&self) -> &dyn Any { self } - fn any_mut(&mut self) -> &mut dyn Any { + fn as_any_mut(&mut self) -> &mut dyn Any { self } @@ -492,7 +505,7 @@ unsafe impl Reflect for Cow<'static, str> { } fn apply(&mut self, value: &dyn Reflect) { - let value = value.any(); + let value = value.as_any(); if let Some(value) = value.downcast_ref::() { *self = value.clone(); } else { @@ -525,7 +538,7 @@ unsafe impl Reflect for Cow<'static, str> { } fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option { - let value = value.any(); + let value = value.as_any(); if let Some(value) = value.downcast_ref::() { Some(std::cmp::PartialEq::eq(self, value)) } else { @@ -552,7 +565,12 @@ impl GetTypeRegistration for Cow<'static, str> { impl FromReflect for Cow<'static, str> { fn from_reflect(reflect: &dyn crate::Reflect) -> Option { - Some(reflect.any().downcast_ref::>()?.clone()) + Some( + reflect + .as_any() + .downcast_ref::>()? + .clone(), + ) } } diff --git a/crates/bevy_reflect/src/lib.rs b/crates/bevy_reflect/src/lib.rs index 22833c557b871..8c2927d8f359d 100644 --- a/crates/bevy_reflect/src/lib.rs +++ b/crates/bevy_reflect/src/lib.rs @@ -485,6 +485,42 @@ mod tests { assert!(foo.reflect_partial_eq(&dynamic_struct).unwrap()); } + #[test] + fn reflect_downcast() { + #[derive(Reflect, Clone, Debug, PartialEq)] + struct Bar { + y: u8, + z: ::glam::Mat4, + } + + #[derive(Reflect, Clone, Debug, PartialEq)] + struct Foo { + x: i32, + s: String, + b: Bar, + u: usize, + t: (Vec3, String), + } + + let foo = Foo { + x: 123, + s: "String".to_string(), + b: Bar { + y: 255, + z: ::glam::Mat4::from_cols_array(&[ + 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, + 15.0, + ]), + }, + u: 1111111111111, + t: (Vec3::new(3.0, 2.0, 1.0), "Tuple String".to_string()), + }; + + let foo2: Box = Box::new(foo.clone()); + + assert_eq!(foo, *foo2.downcast::().unwrap()); + } + #[test] fn reflect_take() { #[derive(Reflect, Debug, PartialEq)] diff --git a/crates/bevy_reflect/src/list.rs b/crates/bevy_reflect/src/list.rs index 6e86e453be9a1..25d2f179b4b79 100644 --- a/crates/bevy_reflect/src/list.rs +++ b/crates/bevy_reflect/src/list.rs @@ -163,8 +163,7 @@ impl List for DynamicList { } } -// SAFE: any and any_mut both return self -unsafe impl Reflect for DynamicList { +impl Reflect for DynamicList { #[inline] fn type_name(&self) -> &str { self.name.as_str() @@ -176,12 +175,17 @@ unsafe impl Reflect for DynamicList { } #[inline] - fn any(&self) -> &dyn Any { + fn into_any(self: Box) -> Box { self } #[inline] - fn any_mut(&mut self) -> &mut dyn Any { + fn as_any(&self) -> &dyn Any { + self + } + + #[inline] + fn as_any_mut(&mut self) -> &mut dyn Any { self } diff --git a/crates/bevy_reflect/src/map.rs b/crates/bevy_reflect/src/map.rs index 88f0f63a1c85f..89f499731f50b 100644 --- a/crates/bevy_reflect/src/map.rs +++ b/crates/bevy_reflect/src/map.rs @@ -212,8 +212,7 @@ impl Map for DynamicMap { } } -// SAFE: any and any_mut both return self -unsafe impl Reflect for DynamicMap { +impl Reflect for DynamicMap { fn type_name(&self) -> &str { &self.name } @@ -223,11 +222,15 @@ unsafe impl Reflect for DynamicMap { ::type_info() } - fn any(&self) -> &dyn Any { + fn into_any(self: Box) -> Box { self } - fn any_mut(&mut self) -> &mut dyn Any { + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { self } diff --git a/crates/bevy_reflect/src/reflect.rs b/crates/bevy_reflect/src/reflect.rs index a0da96c189e5f..1e4d31449b2c8 100644 --- a/crates/bevy_reflect/src/reflect.rs +++ b/crates/bevy_reflect/src/reflect.rs @@ -2,7 +2,10 @@ use crate::{ array_debug, list_debug, map_debug, serde::Serializable, struct_debug, tuple_debug, tuple_struct_debug, Array, List, Map, Struct, Tuple, TupleStruct, TypeInfo, Typed, ValueInfo, }; -use std::{any::Any, fmt::Debug}; +use std::{ + any::{self, Any, TypeId}, + fmt::Debug, +}; use crate::utility::NonGenericTypeInfoCell; pub use bevy_utils::AHasher as ReflectHasher; @@ -46,15 +49,8 @@ pub enum ReflectMut<'a> { /// /// When using `#[derive(Reflect)]` with a struct or tuple struct, the suitable subtrait for that /// type (`Struct` or `TupleStruct`) is derived automatically. -/// -/// # Safety -/// Implementors _must_ ensure that [`Reflect::any`] and [`Reflect::any_mut`] both return the `self` -/// value passed in. If this is not done, [`Reflect::downcast`](trait.Reflect.html#method.downcast) -/// will be UB (and also just logically broken). -pub unsafe trait Reflect: Any + Send + Sync { - /// Returns the [type name] of the underlying type. - /// - /// [type name]: std::any::type_name +pub trait Reflect: Any + Send + Sync { + /// Returns the [type name][std::any::type_name] of the underlying type. fn type_name(&self) -> &str; /// Returns the [`TypeInfo`] of the underlying type. @@ -67,11 +63,14 @@ pub unsafe trait Reflect: Any + Send + Sync { /// [`TypeRegistry::get_type_info`]: crate::TypeRegistry::get_type_info fn get_type_info(&self) -> &'static TypeInfo; + /// Returns the value as a [`Box`][std::any::Any]. + fn into_any(self: Box) -> Box; + /// Returns the value as a [`&dyn Any`][std::any::Any]. - fn any(&self) -> &dyn Any; + fn as_any(&self) -> &dyn Any; /// Returns the value as a [`&mut dyn Any`][std::any::Any]. - fn any_mut(&mut self) -> &mut dyn Any; + fn as_any_mut(&mut self) -> &mut dyn Any; /// Casts this type to a reflected value fn as_reflect(&self) -> &dyn Reflect; @@ -210,18 +209,14 @@ impl Typed for dyn Reflect { } } +#[deny(rustdoc::broken_intra_doc_links)] impl dyn Reflect { /// Downcasts the value to type `T`, consuming the trait object. /// /// If the underlying value is not of type `T`, returns `Err(self)`. pub fn downcast(self: Box) -> Result, Box> { - // SAFE?: Same approach used by std::any::Box::downcast. ReflectValue is always Any and type - // has been checked. if self.is::() { - unsafe { - let raw: *mut dyn Reflect = Box::into_raw(self); - Ok(Box::from_raw(raw as *mut T)) - } + Ok(self.into_any().downcast().unwrap()) } else { Err(self) } @@ -234,11 +229,26 @@ impl dyn Reflect { self.downcast::().map(|value| *value) } + /// Returns `true` if the underlying value represents a value of type `T`, or `false` + /// otherwise. + /// + /// Read `is` for more information on underlying values and represented types. + #[inline] + pub fn represents(&self) -> bool { + self.type_name() == any::type_name::() + } + /// Returns `true` if the underlying value is of type `T`, or `false` /// otherwise. + /// + /// The underlying value is the concrete type that is stored in this `dyn` object; + /// it can be downcasted to. In the case that this underlying value "represents" + /// a different type, like the Dynamic\*\*\* types do, you can call `represents` + /// to determine what type they represent. Represented types cannot be downcasted + /// to, but you can use [`FromReflect`] to create a value of the represented type from them. #[inline] pub fn is(&self) -> bool { - self.any().is::() + self.type_id() == TypeId::of::() } /// Downcasts the value to type `T` by reference. @@ -246,7 +256,7 @@ impl dyn Reflect { /// If the underlying value is not of type `T`, returns `None`. #[inline] pub fn downcast_ref(&self) -> Option<&T> { - self.any().downcast_ref::() + self.as_any().downcast_ref::() } /// Downcasts the value to type `T` by mutable reference. @@ -254,6 +264,6 @@ impl dyn Reflect { /// If the underlying value is not of type `T`, returns `None`. #[inline] pub fn downcast_mut(&mut self) -> Option<&mut T> { - self.any_mut().downcast_mut::() + self.as_any_mut().downcast_mut::() } } diff --git a/crates/bevy_reflect/src/struct_trait.rs b/crates/bevy_reflect/src/struct_trait.rs index ac06e4a5b0469..6f5075d990081 100644 --- a/crates/bevy_reflect/src/struct_trait.rs +++ b/crates/bevy_reflect/src/struct_trait.rs @@ -337,8 +337,7 @@ impl Struct for DynamicStruct { } } -// SAFE: any and any_mut both return self -unsafe impl Reflect for DynamicStruct { +impl Reflect for DynamicStruct { #[inline] fn type_name(&self) -> &str { &self.name @@ -350,12 +349,17 @@ unsafe impl Reflect for DynamicStruct { } #[inline] - fn any(&self) -> &dyn Any { + fn into_any(self: Box) -> Box { self } #[inline] - fn any_mut(&mut self) -> &mut dyn Any { + fn as_any(&self) -> &dyn Any { + self + } + + #[inline] + fn as_any_mut(&mut self) -> &mut dyn Any { self } diff --git a/crates/bevy_reflect/src/tuple.rs b/crates/bevy_reflect/src/tuple.rs index bab117e5e5d6a..c01f798c8920e 100644 --- a/crates/bevy_reflect/src/tuple.rs +++ b/crates/bevy_reflect/src/tuple.rs @@ -267,8 +267,7 @@ impl Tuple for DynamicTuple { } } -// SAFE: any and any_mut both return self -unsafe impl Reflect for DynamicTuple { +impl Reflect for DynamicTuple { #[inline] fn type_name(&self) -> &str { self.name() @@ -280,12 +279,17 @@ unsafe impl Reflect for DynamicTuple { } #[inline] - fn any(&self) -> &dyn Any { + fn into_any(self: Box) -> Box { self } #[inline] - fn any_mut(&mut self) -> &mut dyn Any { + fn as_any(&self) -> &dyn Any { + self + } + + #[inline] + fn as_any_mut(&mut self) -> &mut dyn Any { self } @@ -460,8 +464,7 @@ macro_rules! impl_reflect_tuple { } } - // SAFE: any and any_mut both return self - unsafe impl<$($name: Reflect),*> Reflect for ($($name,)*) { + impl<$($name: Reflect),*> Reflect for ($($name,)*) { fn type_name(&self) -> &str { std::any::type_name::() } @@ -470,11 +473,15 @@ macro_rules! impl_reflect_tuple { ::type_info() } - fn any(&self) -> &dyn Any { + fn into_any(self: Box) -> Box { + self + } + + fn as_any(&self) -> &dyn Any { self } - fn any_mut(&mut self) -> &mut dyn Any { + fn as_any_mut(&mut self) -> &mut dyn Any { self } diff --git a/crates/bevy_reflect/src/tuple_struct.rs b/crates/bevy_reflect/src/tuple_struct.rs index e3a8afa8a8bb6..27ded3e919984 100644 --- a/crates/bevy_reflect/src/tuple_struct.rs +++ b/crates/bevy_reflect/src/tuple_struct.rs @@ -251,8 +251,7 @@ impl TupleStruct for DynamicTupleStruct { } } -// SAFE: any and any_mut both return self -unsafe impl Reflect for DynamicTupleStruct { +impl Reflect for DynamicTupleStruct { #[inline] fn type_name(&self) -> &str { self.name.as_str() @@ -264,12 +263,17 @@ unsafe impl Reflect for DynamicTupleStruct { } #[inline] - fn any(&self) -> &dyn Any { + fn into_any(self: Box) -> Box { self } #[inline] - fn any_mut(&mut self) -> &mut dyn Any { + fn as_any(&self) -> &dyn Any { + self + } + + #[inline] + fn as_any_mut(&mut self) -> &mut dyn Any { self } diff --git a/crates/bevy_reflect/src/type_info.rs b/crates/bevy_reflect/src/type_info.rs index 2d1d1f5327525..942ba84fdf6e3 100644 --- a/crates/bevy_reflect/src/type_info.rs +++ b/crates/bevy_reflect/src/type_info.rs @@ -45,11 +45,12 @@ use std::any::{Any, TypeId}; /// } /// /// # -/// # unsafe impl Reflect for MyStruct { +/// # impl Reflect for MyStruct { /// # fn type_name(&self) -> &str { todo!() } /// # fn get_type_info(&self) -> &'static TypeInfo { todo!() } -/// # fn any(&self) -> &dyn Any { todo!() } -/// # fn any_mut(&mut self) -> &mut dyn Any { todo!() } +/// # fn into_any(self: Box) -> Box { todo!() } +/// # fn as_any(&self) -> &dyn Any { todo!() } +/// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() } /// # fn as_reflect(&self) -> &dyn Reflect { todo!() } /// # fn as_reflect_mut(&mut self) -> &mut dyn Reflect { todo!() } /// # fn apply(&mut self, value: &dyn Reflect) { todo!() } diff --git a/crates/bevy_reflect/src/utility.rs b/crates/bevy_reflect/src/utility.rs index a597539afdb02..3e38c6dc35932 100644 --- a/crates/bevy_reflect/src/utility.rs +++ b/crates/bevy_reflect/src/utility.rs @@ -34,11 +34,12 @@ use std::any::{Any, TypeId}; /// } /// } /// # -/// # unsafe impl Reflect for Foo { +/// # impl Reflect for Foo { /// # fn type_name(&self) -> &str { todo!() } /// # fn get_type_info(&self) -> &'static TypeInfo { todo!() } -/// # fn any(&self) -> &dyn Any { todo!() } -/// # fn any_mut(&mut self) -> &mut dyn Any { todo!() } +/// # fn into_any(self: Box) -> Box { todo!() } +/// # fn as_any(&self) -> &dyn Any { todo!() } +/// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() } /// # fn as_reflect(&self) -> &dyn Reflect { todo!() } /// # fn as_reflect_mut(&mut self) -> &mut dyn Reflect { todo!() } /// # fn apply(&mut self, value: &dyn Reflect) { todo!() } @@ -94,11 +95,12 @@ impl NonGenericTypeInfoCell { /// } /// } /// # -/// # unsafe impl Reflect for Foo { +/// # impl Reflect for Foo { /// # fn type_name(&self) -> &str { todo!() } /// # fn get_type_info(&self) -> &'static TypeInfo { todo!() } -/// # fn any(&self) -> &dyn Any { todo!() } -/// # fn any_mut(&mut self) -> &mut dyn Any { todo!() } +/// # fn into_any(self: Box) -> Box { todo!() } +/// # fn as_any(&self) -> &dyn Any { todo!() } +/// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() } /// # fn as_reflect(&self) -> &dyn Reflect { todo!() } /// # fn as_reflect_mut(&mut self) -> &mut dyn Reflect { todo!() } /// # fn apply(&mut self, value: &dyn Reflect) { todo!() }