System::type_id Consistency (#11728)
# Objective - Fixes #11679 ## Solution - Added `IntoSystem::system_type_id` which returns the equivalent of `system.into_system().type_id()` without construction. This allows for getting the `TypeId` of functions (a function is an unnamed type and therefore you cannot call `TypeId::of::<apply_deferred::System>()`) - Added default implementation of `System::type_id` to ensure consistency between implementations. Some returned `Self`, while others were returning an inner value instead. This ensures consistency with `IntoSystem::system_type_id`. ## Migration Guide If you use `System::type_id()` on function systems (exclusive or not), ensure you are comparing its value to other `System::type_id()` calls, or `IntoSystem::system_type_id()`. This code wont require any changes, because `IntoSystem`'s are directly compared to each other. ```rust fn test_system() {} let type_id = test_system.type_id(); // ... // No change required assert_eq!(test_system.type_id(), type_id); ``` Likewise, this code wont, because `System`'s are directly compared. ```rust fn test_system() {} let type_id = IntoSystem::into_system(test_system).type_id(); // ... // No change required assert_eq!(IntoSystem::into_system(test_system).type_id(), type_id); ``` The below _does_ require a change, since you're comparing a `System` type to a `IntoSystem` type. ```rust fn test_system() {} // Before assert_eq!(test_system.type_id(), IntoSystem::into_system(test_system).type_id()); // After assert_eq!(test_system.system_type_id(), IntoSystem::into_system(test_system).type_id()); ```
This commit is contained in:
parent
f2cb155abc
commit
950bd2284d
@ -104,7 +104,7 @@ pub fn apply_deferred(world: &mut World) {}
|
||||
|
||||
/// Returns `true` if the [`System`](crate::system::System) is an instance of [`apply_deferred`].
|
||||
pub(super) fn is_apply_deferred(system: &BoxedSystem) -> bool {
|
||||
use std::any::Any;
|
||||
use crate::system::IntoSystem;
|
||||
// deref to use `System::type_id` instead of `Any::type_id`
|
||||
system.as_ref().type_id() == apply_deferred.type_id()
|
||||
system.as_ref().type_id() == apply_deferred.system_type_id()
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
schedule::{InternedScheduleLabel, NodeId, Schedule, ScheduleLabel},
|
||||
system::{IntoSystem, ResMut, Resource, System},
|
||||
system::{IntoSystem, ResMut, Resource},
|
||||
};
|
||||
use bevy_utils::{
|
||||
thiserror::Error,
|
||||
@ -252,10 +252,7 @@ impl Stepping {
|
||||
schedule: impl ScheduleLabel,
|
||||
system: impl IntoSystem<(), (), Marker>,
|
||||
) -> &mut Self {
|
||||
// PERF: ideally we don't actually need to construct the system to retrieve the TypeId.
|
||||
// Unfortunately currently IntoSystem::into_system(system).type_id() != TypeId::of::<I::System>()
|
||||
// If these are aligned, we can use TypeId::of::<I::System>() here
|
||||
let type_id = IntoSystem::into_system(system).type_id();
|
||||
let type_id = system.system_type_id();
|
||||
self.updates.push(Update::SetBehavior(
|
||||
schedule.intern(),
|
||||
SystemIdentifier::Type(type_id),
|
||||
@ -281,7 +278,7 @@ impl Stepping {
|
||||
schedule: impl ScheduleLabel,
|
||||
system: impl IntoSystem<(), (), Marker>,
|
||||
) -> &mut Self {
|
||||
let type_id = IntoSystem::into_system(system).type_id();
|
||||
let type_id = system.system_type_id();
|
||||
self.updates.push(Update::SetBehavior(
|
||||
schedule.intern(),
|
||||
SystemIdentifier::Type(type_id),
|
||||
@ -307,7 +304,7 @@ impl Stepping {
|
||||
schedule: impl ScheduleLabel,
|
||||
system: impl IntoSystem<(), (), Marker>,
|
||||
) -> &mut Self {
|
||||
let type_id = IntoSystem::into_system(system).type_id();
|
||||
let type_id = system.system_type_id();
|
||||
self.updates.push(Update::SetBehavior(
|
||||
schedule.intern(),
|
||||
SystemIdentifier::Type(type_id),
|
||||
@ -354,7 +351,7 @@ impl Stepping {
|
||||
schedule: impl ScheduleLabel,
|
||||
system: impl IntoSystem<(), (), Marker>,
|
||||
) -> &mut Self {
|
||||
let type_id = IntoSystem::into_system(system).type_id();
|
||||
let type_id = system.system_type_id();
|
||||
self.updates.push(Update::ClearBehavior(
|
||||
schedule.intern(),
|
||||
SystemIdentifier::Type(type_id),
|
||||
|
||||
@ -81,10 +81,6 @@ where
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
fn type_id(&self) -> std::any::TypeId {
|
||||
std::any::TypeId::of::<Self>()
|
||||
}
|
||||
|
||||
fn component_access(&self) -> &crate::query::Access<crate::component::ComponentId> {
|
||||
self.system.component_access()
|
||||
}
|
||||
|
||||
@ -142,10 +142,6 @@ where
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
fn type_id(&self) -> std::any::TypeId {
|
||||
std::any::TypeId::of::<Self>()
|
||||
}
|
||||
|
||||
fn component_access(&self) -> &Access<ComponentId> {
|
||||
&self.component_access
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ use crate::{
|
||||
};
|
||||
|
||||
use bevy_utils::all_tuples;
|
||||
use std::{any::TypeId, borrow::Cow, marker::PhantomData};
|
||||
use std::{borrow::Cow, marker::PhantomData};
|
||||
|
||||
/// A function system that runs with exclusive [`World`] access.
|
||||
///
|
||||
@ -65,11 +65,6 @@ where
|
||||
self.system_meta.name.clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn type_id(&self) -> TypeId {
|
||||
TypeId::of::<F>()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn component_access(&self) -> &Access<ComponentId> {
|
||||
self.system_meta.component_access_set.combined_access()
|
||||
@ -250,3 +245,44 @@ macro_rules! impl_exclusive_system_function {
|
||||
// Note that we rely on the highest impl to be <= the highest order of the tuple impls
|
||||
// of `SystemParam` created.
|
||||
all_tuples!(impl_exclusive_system_function, 0, 16, F);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn into_system_type_id_consistency() {
|
||||
fn test<T, In, Out, Marker>(function: T)
|
||||
where
|
||||
T: IntoSystem<In, Out, Marker> + Copy,
|
||||
{
|
||||
fn reference_system(_world: &mut World) {}
|
||||
|
||||
use std::any::TypeId;
|
||||
|
||||
let system = IntoSystem::into_system(function);
|
||||
|
||||
assert_eq!(
|
||||
system.type_id(),
|
||||
function.system_type_id(),
|
||||
"System::type_id should be consistent with IntoSystem::system_type_id"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
system.type_id(),
|
||||
TypeId::of::<T::System>(),
|
||||
"System::type_id should be consistent with TypeId::of::<T::System>()"
|
||||
);
|
||||
|
||||
assert_ne!(
|
||||
system.type_id(),
|
||||
IntoSystem::into_system(reference_system).type_id(),
|
||||
"Different systems should have different TypeIds"
|
||||
);
|
||||
}
|
||||
|
||||
fn exclusive_function_system(_world: &mut World) {}
|
||||
|
||||
test(exclusive_function_system);
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ use crate::{
|
||||
};
|
||||
|
||||
use bevy_utils::all_tuples;
|
||||
use std::{any::TypeId, borrow::Cow, marker::PhantomData};
|
||||
use std::{borrow::Cow, marker::PhantomData};
|
||||
|
||||
#[cfg(feature = "trace")]
|
||||
use bevy_utils::tracing::{info_span, Span};
|
||||
@ -453,11 +453,6 @@ where
|
||||
self.system_meta.name.clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn type_id(&self) -> TypeId {
|
||||
TypeId::of::<F>()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn component_access(&self) -> &Access<ComponentId> {
|
||||
self.system_meta.component_access_set.combined_access()
|
||||
@ -695,3 +690,44 @@ macro_rules! impl_system_function {
|
||||
// Note that we rely on the highest impl to be <= the highest order of the tuple impls
|
||||
// of `SystemParam` created.
|
||||
all_tuples!(impl_system_function, 0, 16, F);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn into_system_type_id_consistency() {
|
||||
fn test<T, In, Out, Marker>(function: T)
|
||||
where
|
||||
T: IntoSystem<In, Out, Marker> + Copy,
|
||||
{
|
||||
fn reference_system() {}
|
||||
|
||||
use std::any::TypeId;
|
||||
|
||||
let system = IntoSystem::into_system(function);
|
||||
|
||||
assert_eq!(
|
||||
system.type_id(),
|
||||
function.system_type_id(),
|
||||
"System::type_id should be consistent with IntoSystem::system_type_id"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
system.type_id(),
|
||||
TypeId::of::<T::System>(),
|
||||
"System::type_id should be consistent with TypeId::of::<T::System>()"
|
||||
);
|
||||
|
||||
assert_ne!(
|
||||
system.type_id(),
|
||||
IntoSystem::into_system(reference_system).type_id(),
|
||||
"Different systems should have different TypeIds"
|
||||
);
|
||||
}
|
||||
|
||||
fn function_system() {}
|
||||
|
||||
test(function_system);
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,7 +114,7 @@ mod system_name;
|
||||
mod system_param;
|
||||
mod system_registry;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::{any::TypeId, borrow::Cow};
|
||||
|
||||
pub use adapter_system::*;
|
||||
pub use combinator::*;
|
||||
@ -195,6 +195,12 @@ pub trait IntoSystem<In, Out, Marker>: Sized {
|
||||
let name = system.name();
|
||||
AdapterSystem::new(f, system, name)
|
||||
}
|
||||
|
||||
/// Get the [`TypeId`] of the [`System`] produced after calling [`into_system`](`IntoSystem::into_system`).
|
||||
#[inline]
|
||||
fn system_type_id(&self) -> TypeId {
|
||||
TypeId::of::<Self::System>()
|
||||
}
|
||||
}
|
||||
|
||||
// All systems implicitly implement IntoSystem.
|
||||
|
||||
@ -31,7 +31,10 @@ pub trait System: Send + Sync + 'static {
|
||||
/// Returns the system's name.
|
||||
fn name(&self) -> Cow<'static, str>;
|
||||
/// Returns the [`TypeId`] of the underlying system type.
|
||||
fn type_id(&self) -> TypeId;
|
||||
#[inline]
|
||||
fn type_id(&self) -> TypeId {
|
||||
TypeId::of::<Self>()
|
||||
}
|
||||
/// Returns the system's component [`Access`].
|
||||
fn component_access(&self) -> &Access<ComponentId>;
|
||||
/// Returns the system's archetype component [`Access`].
|
||||
|
||||
Loading…
Reference in New Issue
Block a user