Make Reflect impls unsafe (Reflect::any must return self) (#1679)

Fixes #1100 

Implementors must make sure that `Reflect::any` and `Reflect::any_mut` both return the `self` reference passed in (both for logical correctness and downcast safety).
This commit is contained in:
Carter Anderson 2021-03-17 22:46:46 +00:00
parent 107dd73687
commit 5fedb6029a
9 changed files with 31 additions and 14 deletions

View File

@ -261,7 +261,8 @@ fn impl_struct(
}
}
impl #impl_generics #bevy_reflect_path::Reflect for #struct_name#ty_generics #where_clause {
// SAFE: any and any_mut both return self
unsafe impl #impl_generics #bevy_reflect_path::Reflect for #struct_name#ty_generics #where_clause {
#[inline]
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
@ -382,7 +383,8 @@ fn impl_tuple_struct(
}
}
impl #impl_generics #bevy_reflect_path::Reflect for #struct_name#ty_generics {
// SAFE: any and any_mut both return self
unsafe impl #impl_generics #bevy_reflect_path::Reflect for #struct_name#ty_generics {
#[inline]
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
@ -457,7 +459,8 @@ fn impl_value(
TokenStream::from(quote! {
#get_type_registration_impl
impl #impl_generics #bevy_reflect_path::Reflect for #type_name#ty_generics #where_clause {
// SAFE: any and any_mut both return self
unsafe impl #impl_generics #bevy_reflect_path::Reflect for #type_name#ty_generics #where_clause {
#[inline]
fn type_name(&self) -> &str {
std::any::type_name::<Self>()

View File

@ -45,7 +45,8 @@ where
}
}
impl<T: Array + Send + Sync + 'static> Reflect for SmallVec<T>
// SAFE: any and any_mut both return self
unsafe impl<T: Array + Send + Sync + 'static> Reflect for SmallVec<T>
where
T::Item: Reflect + Clone,
{

View File

@ -65,7 +65,8 @@ impl<T: Reflect> List for Vec<T> {
}
}
impl<T: Reflect> Reflect for Vec<T> {
// SAFE: any and any_mut both return self
unsafe impl<T: Reflect> Reflect for Vec<T> {
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
}
@ -160,7 +161,8 @@ impl<K: Reflect + Clone + Eq + Hash, V: Reflect + Clone> Map for HashMap<K, V> {
}
}
impl<K: Reflect + Clone + Eq + Hash, V: Reflect + Clone> Reflect for HashMap<K, V> {
// SAFE: any and any_mut both return self
unsafe impl<K: Reflect + Clone + Eq + Hash, V: Reflect + Clone> Reflect for HashMap<K, V> {
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
}
@ -227,7 +229,8 @@ where
}
}
impl Reflect for Cow<'static, str> {
// SAFE: any and any_mut both return self
unsafe impl Reflect for Cow<'static, str> {
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
}

View File

@ -80,7 +80,8 @@ impl List for DynamicList {
}
}
impl Reflect for DynamicList {
// SAFE: any and any_mut both return self
unsafe impl Reflect for DynamicList {
#[inline]
fn type_name(&self) -> &str {
self.name.as_str()

View File

@ -98,7 +98,8 @@ impl Map for DynamicMap {
}
}
impl Reflect for DynamicMap {
// SAFE: any and any_mut both return self
unsafe impl Reflect for DynamicMap {
fn type_name(&self) -> &str {
&self.name
}

View File

@ -22,7 +22,11 @@ pub enum ReflectMut<'a> {
}
/// A reflected rust type.
pub trait Reflect: Any + Send + Sync {
///
/// # 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] will be UB (and also just logically broken).
pub unsafe trait Reflect: Any + Send + Sync {
fn type_name(&self) -> &str;
fn any(&self) -> &dyn Any;
fn any_mut(&mut self) -> &mut dyn Any;

View File

@ -167,7 +167,8 @@ impl Struct for DynamicStruct {
}
}
impl Reflect for DynamicStruct {
// SAFE: any and any_mut both return self
unsafe impl Reflect for DynamicStruct {
#[inline]
fn type_name(&self) -> &str {
&self.name

View File

@ -139,7 +139,8 @@ impl Tuple for DynamicTuple {
}
}
impl Reflect for DynamicTuple {
// SAFE: any and any_mut both return self
unsafe impl Reflect for DynamicTuple {
#[inline]
fn type_name(&self) -> &str {
self.name()
@ -274,7 +275,8 @@ macro_rules! impl_reflect_tuple {
}
}
impl<$($name: Reflect),*> Reflect for ($($name,)*) {
// SAFE: any and any_mut both return self
unsafe impl<$($name: Reflect),*> Reflect for ($($name,)*) {
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
}

View File

@ -123,7 +123,8 @@ impl TupleStruct for DynamicTupleStruct {
}
}
impl Reflect for DynamicTupleStruct {
// SAFE: any and any_mut both return self
unsafe impl Reflect for DynamicTupleStruct {
#[inline]
fn type_name(&self) -> &str {
self.name.as_str()