Add compile-time dyn compatible checks for DynEq, DynHash (#17254)

# Objective

- Shrink `bevy_utils` more.
- Refs #11478

## Solution

- Removes `assert_object_safe` from `bevy_utils` by using a compile time
check instead.

## Testing

- CI.

---

## Migration Guide

`assert_object_safe` is no longer exported by `bevy_utils`. Instead, you
can write a compile time check that your trait is "dyn compatible":

```rust
/// Assert MyTrait is dyn compatible
const _: Option<Box<dyn MyTrait>> = None;
```

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
This commit is contained in:
mgi388 2025-01-09 18:30:54 +11:00 committed by GitHub
parent 3742e621ef
commit b20e23dd41
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 6 additions and 48 deletions

View File

@ -22,6 +22,9 @@ pub trait DynEq: Any {
fn dyn_eq(&self, other: &dyn DynEq) -> bool;
}
// Tests that this trait is dyn-compatible
const _: Option<Box<dyn DynEq>> = None;
impl<T> DynEq for T
where
T: Any + Eq,
@ -48,6 +51,9 @@ pub trait DynHash: DynEq {
fn dyn_hash(&self, state: &mut dyn Hasher);
}
// Tests that this trait is dyn-compatible
const _: Option<Box<dyn DynHash>> = None;
impl<T> DynHash for T
where
T: DynEq + Hash,
@ -201,19 +207,3 @@ macro_rules! define_label {
$crate::intern::Interner::new();
};
}
#[cfg(test)]
mod tests {
use super::{DynEq, DynHash};
use bevy_utils::assert_object_safe;
#[test]
fn dyn_eq_object_safe() {
assert_object_safe::<dyn DynEq>();
}
#[test]
fn dyn_hash_object_safe() {
assert_object_safe::<dyn DynHash>();
}
}

View File

@ -26,8 +26,6 @@ pub mod synccell;
pub mod syncunsafecell;
mod default;
mod object_safe;
pub use object_safe::assert_object_safe;
mod once;
#[cfg(feature = "std")]
mod parallel_queue;

View File

@ -1,30 +0,0 @@
/// Assert that a given `T` is [object safe](https://doc.rust-lang.org/reference/items/traits.html#object-safety).
/// Will fail to compile if that is not the case.
///
/// # Examples
///
/// ```rust
/// # use bevy_utils::assert_object_safe;
/// // Concrete types are always object safe
/// struct MyStruct;
/// assert_object_safe::<MyStruct>();
///
/// // Trait objects are where that safety comes into question.
/// // This trait is object safe...
/// trait ObjectSafe { }
/// assert_object_safe::<dyn ObjectSafe>();
/// ```
///
/// ```compile_fail
/// # use bevy_utils::assert_object_safe;
/// // ...but this trait is not.
/// trait NotObjectSafe {
/// const VALUE: usize;
/// }
/// assert_object_safe::<dyn NotObjectSafe>();
/// // Error: the trait `NotObjectSafe` cannot be made into an object
/// ```
pub fn assert_object_safe<T: ?Sized>() {
// This space is left intentionally blank. The type parameter T is sufficient to induce a compiler
// error without a function body.
}