Have Entity(Ref|Mut)Except look up the component ids on initialization and store them in an Access that can be borrowed by each row.

This commit is contained in:
Chris Russell 2025-07-12 10:15:27 -04:00
parent af0cc64d98
commit 4bb6066a90
5 changed files with 109 additions and 81 deletions

View File

@ -408,10 +408,7 @@ impl<A: Animatable> AnimationCurveEvaluator for AnimatableCurveEvaluator<A> {
self.evaluator.push_blend_register(weight, graph_node) self.evaluator.push_blend_register(weight, graph_node)
} }
fn commit<'a>( fn commit(&mut self, mut entity: AnimationEntityMut) -> Result<(), AnimationEvaluationError> {
&mut self,
mut entity: AnimationEntityMut<'a>,
) -> Result<(), AnimationEvaluationError> {
let property = self.property.get_mut(&mut entity)?; let property = self.property.get_mut(&mut entity)?;
*property = self *property = self
.evaluator .evaluator
@ -596,10 +593,7 @@ impl AnimationCurveEvaluator for WeightsCurveEvaluator {
Ok(()) Ok(())
} }
fn commit<'a>( fn commit(&mut self, mut entity: AnimationEntityMut) -> Result<(), AnimationEvaluationError> {
&mut self,
mut entity: AnimationEntityMut<'a>,
) -> Result<(), AnimationEvaluationError> {
if self.stack_morph_target_weights.is_empty() { if self.stack_morph_target_weights.is_empty() {
return Ok(()); return Ok(());
} }
@ -905,10 +899,7 @@ pub trait AnimationCurveEvaluator: Downcast + Send + Sync + 'static {
/// ///
/// The property on the component must be overwritten with the value from /// The property on the component must be overwritten with the value from
/// the stack, not blended with it. /// the stack, not blended with it.
fn commit<'a>( fn commit(&mut self, entity: AnimationEntityMut) -> Result<(), AnimationEvaluationError>;
&mut self,
entity: AnimationEntityMut<'a>,
) -> Result<(), AnimationEvaluationError>;
} }
impl_downcast!(AnimationCurveEvaluator); impl_downcast!(AnimationCurveEvaluator);

View File

@ -1021,8 +1021,8 @@ pub fn advance_animations(
} }
/// A type alias for [`EntityMutExcept`] as used in animation. /// A type alias for [`EntityMutExcept`] as used in animation.
pub type AnimationEntityMut<'w> = pub type AnimationEntityMut<'w, 's> =
EntityMutExcept<'w, (AnimationTarget, AnimationPlayer, AnimationGraphHandle)>; EntityMutExcept<'w, 's, (AnimationTarget, AnimationPlayer, AnimationGraphHandle)>;
/// A system that modifies animation targets (e.g. bones in a skinned mesh) /// A system that modifies animation targets (e.g. bones in a skinned mesh)
/// according to the currently-playing animations. /// according to the currently-playing animations.

View File

@ -14,7 +14,6 @@ use crate::{
use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref}; use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref};
use bevy_utils::prelude::DebugName; use bevy_utils::prelude::DebugName;
use core::{cell::UnsafeCell, marker::PhantomData, panic::Location}; use core::{cell::UnsafeCell, marker::PhantomData, panic::Location};
use smallvec::SmallVec;
use variadics_please::all_tuples; use variadics_please::all_tuples;
/// Types that can be fetched from a [`World`] using a [`Query`]. /// Types that can be fetched from a [`World`] using a [`Query`].
@ -1160,12 +1159,12 @@ unsafe impl<'a, 'b> QueryData for FilteredEntityMut<'a, 'b> {
/// SAFETY: `EntityRefExcept` guards access to all components in the bundle `B` /// SAFETY: `EntityRefExcept` guards access to all components in the bundle `B`
/// and populates `Access` values so that queries that conflict with this access /// and populates `Access` values so that queries that conflict with this access
/// are rejected. /// are rejected.
unsafe impl<'a, B> WorldQuery for EntityRefExcept<'a, B> unsafe impl<'a, 'b, B> WorldQuery for EntityRefExcept<'a, 'b, B>
where where
B: Bundle, B: Bundle,
{ {
type Fetch<'w> = EntityFetch<'w>; type Fetch<'w> = EntityFetch<'w>;
type State = SmallVec<[ComponentId; 4]>; type State = Access<ComponentId>;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
fetch fetch
@ -1197,15 +1196,9 @@ where
unsafe fn set_table<'w, 's>(_: &mut Self::Fetch<'w>, _: &'s Self::State, _: &'w Table) {} unsafe fn set_table<'w, 's>(_: &mut Self::Fetch<'w>, _: &'s Self::State, _: &'w Table) {}
fn update_component_access( fn update_component_access(
state: &Self::State, my_access: &Self::State,
filtered_access: &mut FilteredAccess<ComponentId>, filtered_access: &mut FilteredAccess<ComponentId>,
) { ) {
let mut my_access = Access::new();
my_access.read_all_components();
for id in state {
my_access.remove_component_read(*id);
}
let access = filtered_access.access_mut(); let access = filtered_access.access_mut();
assert!( assert!(
access.is_compatible(&my_access), access.is_compatible(&my_access),
@ -1216,17 +1209,29 @@ where
} }
fn init_state(world: &mut World) -> Self::State { fn init_state(world: &mut World) -> Self::State {
Self::get_state(world.components()).unwrap() let mut access = Access::new();
access.read_all_components();
B::component_ids(&mut world.components_registrator(), &mut |id| {
access.remove_component_read(id);
});
access
} }
fn get_state(components: &Components) -> Option<Self::State> { fn get_state(components: &Components) -> Option<Self::State> {
let mut ids = SmallVec::new(); let mut access = Access::new();
access.read_all_components();
B::get_component_ids(components, &mut |maybe_id| { B::get_component_ids(components, &mut |maybe_id| {
// If the component isn't registered, we don't have a `ComponentId`
// to use to exclude its access.
// Rather than fail, just try to take additional access.
// This is sound because access checks will run on the resulting access.
// Since the component isn't registered, there are no entities with that
// component, and the extra access will usually have no effect.
if let Some(id) = maybe_id { if let Some(id) = maybe_id {
ids.push(id); access.remove_component_read(id);
} }
}); });
Some(ids) Some(access)
} }
fn matches_component_set(_: &Self::State, _: &impl Fn(ComponentId) -> bool) -> bool { fn matches_component_set(_: &Self::State, _: &impl Fn(ComponentId) -> bool) -> bool {
@ -1235,13 +1240,13 @@ where
} }
/// SAFETY: `Self` is the same as `Self::ReadOnly`. /// SAFETY: `Self` is the same as `Self::ReadOnly`.
unsafe impl<'a, B> QueryData for EntityRefExcept<'a, B> unsafe impl<'a, 'b, B> QueryData for EntityRefExcept<'a, 'b, B>
where where
B: Bundle, B: Bundle,
{ {
const IS_READ_ONLY: bool = true; const IS_READ_ONLY: bool = true;
type ReadOnly = Self; type ReadOnly = Self;
type Item<'w, 's> = EntityRefExcept<'w, B>; type Item<'w, 's> = EntityRefExcept<'w, 's, B>;
fn shrink<'wlong: 'wshort, 'wshort, 's>( fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>, item: Self::Item<'wlong, 's>,
@ -1250,7 +1255,7 @@ where
} }
unsafe fn fetch<'w, 's>( unsafe fn fetch<'w, 's>(
_state: &'s Self::State, access: &'s Self::State,
fetch: &mut Self::Fetch<'w>, fetch: &mut Self::Fetch<'w>,
entity: Entity, entity: Entity,
_: TableRow, _: TableRow,
@ -1259,23 +1264,23 @@ where
.world .world
.get_entity_with_ticks(entity, fetch.last_run, fetch.this_run) .get_entity_with_ticks(entity, fetch.last_run, fetch.this_run)
.unwrap(); .unwrap();
EntityRefExcept::new(cell) EntityRefExcept::new(cell, access)
} }
} }
/// SAFETY: `EntityRefExcept` enforces read-only access to its contained /// SAFETY: `EntityRefExcept` enforces read-only access to its contained
/// components. /// components.
unsafe impl<'a, B> ReadOnlyQueryData for EntityRefExcept<'a, B> where B: Bundle {} unsafe impl<B> ReadOnlyQueryData for EntityRefExcept<'_, '_, B> where B: Bundle {}
/// SAFETY: `EntityMutExcept` guards access to all components in the bundle `B` /// SAFETY: `EntityMutExcept` guards access to all components in the bundle `B`
/// and populates `Access` values so that queries that conflict with this access /// and populates `Access` values so that queries that conflict with this access
/// are rejected. /// are rejected.
unsafe impl<'a, B> WorldQuery for EntityMutExcept<'a, B> unsafe impl<'a, 'b, B> WorldQuery for EntityMutExcept<'a, 'b, B>
where where
B: Bundle, B: Bundle,
{ {
type Fetch<'w> = EntityFetch<'w>; type Fetch<'w> = EntityFetch<'w>;
type State = SmallVec<[ComponentId; 4]>; type State = Access<ComponentId>;
fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {
fetch fetch
@ -1307,15 +1312,9 @@ where
unsafe fn set_table<'w, 's>(_: &mut Self::Fetch<'w>, _: &'s Self::State, _: &'w Table) {} unsafe fn set_table<'w, 's>(_: &mut Self::Fetch<'w>, _: &'s Self::State, _: &'w Table) {}
fn update_component_access( fn update_component_access(
state: &Self::State, my_access: &Self::State,
filtered_access: &mut FilteredAccess<ComponentId>, filtered_access: &mut FilteredAccess<ComponentId>,
) { ) {
let mut my_access = Access::new();
my_access.write_all_components();
for id in state {
my_access.remove_component_read(*id);
}
let access = filtered_access.access_mut(); let access = filtered_access.access_mut();
assert!( assert!(
access.is_compatible(&my_access), access.is_compatible(&my_access),
@ -1326,17 +1325,29 @@ where
} }
fn init_state(world: &mut World) -> Self::State { fn init_state(world: &mut World) -> Self::State {
Self::get_state(world.components()).unwrap() let mut access = Access::new();
access.write_all_components();
B::component_ids(&mut world.components_registrator(), &mut |id| {
access.remove_component_read(id);
});
access
} }
fn get_state(components: &Components) -> Option<Self::State> { fn get_state(components: &Components) -> Option<Self::State> {
let mut ids = SmallVec::new(); let mut access = Access::new();
access.write_all_components();
B::get_component_ids(components, &mut |maybe_id| { B::get_component_ids(components, &mut |maybe_id| {
// If the component isn't registered, we don't have a `ComponentId`
// to use to exclude its access.
// Rather than fail, just try to take additional access.
// This is sound because access checks will run on the resulting access.
// Since the component isn't registered, there are no entities with that
// component, and the extra access will usually have no effect.
if let Some(id) = maybe_id { if let Some(id) = maybe_id {
ids.push(id); access.remove_component_read(id);
} }
}); });
Some(ids) Some(access)
} }
fn matches_component_set(_: &Self::State, _: &impl Fn(ComponentId) -> bool) -> bool { fn matches_component_set(_: &Self::State, _: &impl Fn(ComponentId) -> bool) -> bool {
@ -1346,13 +1357,13 @@ where
/// SAFETY: All accesses that `EntityRefExcept` provides are also accesses that /// SAFETY: All accesses that `EntityRefExcept` provides are also accesses that
/// `EntityMutExcept` provides. /// `EntityMutExcept` provides.
unsafe impl<'a, B> QueryData for EntityMutExcept<'a, B> unsafe impl<'a, 'b, B> QueryData for EntityMutExcept<'a, 'b, B>
where where
B: Bundle, B: Bundle,
{ {
const IS_READ_ONLY: bool = false; const IS_READ_ONLY: bool = false;
type ReadOnly = EntityRefExcept<'a, B>; type ReadOnly = EntityRefExcept<'a, 'b, B>;
type Item<'w, 's> = EntityMutExcept<'w, B>; type Item<'w, 's> = EntityMutExcept<'w, 's, B>;
fn shrink<'wlong: 'wshort, 'wshort, 's>( fn shrink<'wlong: 'wshort, 'wshort, 's>(
item: Self::Item<'wlong, 's>, item: Self::Item<'wlong, 's>,
@ -1361,7 +1372,7 @@ where
} }
unsafe fn fetch<'w, 's>( unsafe fn fetch<'w, 's>(
_state: &'s Self::State, access: &'s Self::State,
fetch: &mut Self::Fetch<'w>, fetch: &mut Self::Fetch<'w>,
entity: Entity, entity: Entity,
_: TableRow, _: TableRow,
@ -1370,7 +1381,7 @@ where
.world .world
.get_entity_with_ticks(entity, fetch.last_run, fetch.this_run) .get_entity_with_ticks(entity, fetch.last_run, fetch.this_run)
.unwrap(); .unwrap();
EntityMutExcept::new(cell) EntityMutExcept::new(cell, access)
} }
} }

View File

@ -970,13 +970,13 @@ unsafe impl<'w, 's, F: QueryFilter> EntitySetIterator
// SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. // SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once.
unsafe impl<'w, 's, F: QueryFilter, B: Bundle> EntitySetIterator unsafe impl<'w, 's, F: QueryFilter, B: Bundle> EntitySetIterator
for QueryIter<'w, 's, EntityRefExcept<'_, B>, F> for QueryIter<'w, 's, EntityRefExcept<'_, '_, B>, F>
{ {
} }
// SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. // SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once.
unsafe impl<'w, 's, F: QueryFilter, B: Bundle> EntitySetIterator unsafe impl<'w, 's, F: QueryFilter, B: Bundle> EntitySetIterator
for QueryIter<'w, 's, EntityMutExcept<'_, B>, F> for QueryIter<'w, 's, EntityMutExcept<'_, '_, B>, F>
{ {
} }

View File

@ -3561,6 +3561,14 @@ impl<'a> From<&'a EntityWorldMut<'_>> for FilteredEntityRef<'a, 'static> {
} }
} }
impl<'w, 's, B: Bundle> From<&'w EntityRefExcept<'_, 's, B>> for FilteredEntityRef<'w, 's> {
fn from(value: &'w EntityRefExcept<'_, 's, B>) -> Self {
// SAFETY:
// - The FilteredEntityRef has the same component access as the given EntityRefExcept.
unsafe { FilteredEntityRef::new(value.entity, value.access) }
}
}
impl PartialEq for FilteredEntityRef<'_, '_> { impl PartialEq for FilteredEntityRef<'_, '_> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.entity() == other.entity() self.entity() == other.entity()
@ -3884,6 +3892,14 @@ impl<'a> From<&'a mut EntityWorldMut<'_>> for FilteredEntityMut<'a, 'static> {
} }
} }
impl<'w, 's, B: Bundle> From<&'w EntityMutExcept<'_, 's, B>> for FilteredEntityMut<'w, 's> {
fn from(value: &'w EntityMutExcept<'_, 's, B>) -> Self {
// SAFETY:
// - The FilteredEntityMut has the same component access as the given EntityMutExcept.
unsafe { FilteredEntityMut::new(value.entity, value.access) }
}
}
impl PartialEq for FilteredEntityMut<'_, '_> { impl PartialEq for FilteredEntityMut<'_, '_> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.entity() == other.entity() self.entity() == other.entity()
@ -3938,23 +3954,28 @@ pub enum TryFromFilteredError {
/// Provides read-only access to a single entity and all its components, save /// Provides read-only access to a single entity and all its components, save
/// for an explicitly-enumerated set. /// for an explicitly-enumerated set.
pub struct EntityRefExcept<'w, B> pub struct EntityRefExcept<'w, 's, B>
where where
B: Bundle, B: Bundle,
{ {
entity: UnsafeEntityCell<'w>, entity: UnsafeEntityCell<'w>,
access: &'s Access<ComponentId>,
phantom: PhantomData<B>, phantom: PhantomData<B>,
} }
impl<'w, B> EntityRefExcept<'w, B> impl<'w, 's, B> EntityRefExcept<'w, 's, B>
where where
B: Bundle, B: Bundle,
{ {
/// # Safety /// # Safety
/// Other users of `UnsafeEntityCell` must only have mutable access to the components in `B`. /// Other users of `UnsafeEntityCell` must only have mutable access to the components in `B`.
pub(crate) unsafe fn new(entity: UnsafeEntityCell<'w>) -> Self { pub(crate) unsafe fn new(
entity: UnsafeEntityCell<'w>,
access: &'s Access<ComponentId>,
) -> Self {
Self { Self {
entity, entity,
access,
phantom: PhantomData, phantom: PhantomData,
} }
} }
@ -4107,34 +4128,34 @@ where
} }
} }
impl<'a, B> From<&'a EntityMutExcept<'_, B>> for EntityRefExcept<'a, B> impl<'w, 's, B> From<&'w EntityMutExcept<'_, 's, B>> for EntityRefExcept<'w, 's, B>
where where
B: Bundle, B: Bundle,
{ {
fn from(entity: &'a EntityMutExcept<'_, B>) -> Self { fn from(entity: &'w EntityMutExcept<'_, 's, B>) -> Self {
// SAFETY: All accesses that `EntityRefExcept` provides are also // SAFETY: All accesses that `EntityRefExcept` provides are also
// accesses that `EntityMutExcept` provides. // accesses that `EntityMutExcept` provides.
unsafe { EntityRefExcept::new(entity.entity) } unsafe { EntityRefExcept::new(entity.entity, entity.access) }
} }
} }
impl<B: Bundle> Clone for EntityRefExcept<'_, B> { impl<B: Bundle> Clone for EntityRefExcept<'_, '_, B> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
*self *self
} }
} }
impl<B: Bundle> Copy for EntityRefExcept<'_, B> {} impl<B: Bundle> Copy for EntityRefExcept<'_, '_, B> {}
impl<B: Bundle> PartialEq for EntityRefExcept<'_, B> { impl<B: Bundle> PartialEq for EntityRefExcept<'_, '_, B> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.entity() == other.entity() self.entity() == other.entity()
} }
} }
impl<B: Bundle> Eq for EntityRefExcept<'_, B> {} impl<B: Bundle> Eq for EntityRefExcept<'_, '_, B> {}
impl<B: Bundle> PartialOrd for EntityRefExcept<'_, B> { impl<B: Bundle> PartialOrd for EntityRefExcept<'_, '_, B> {
/// [`EntityRefExcept`]'s comparison trait implementations match the underlying [`Entity`], /// [`EntityRefExcept`]'s comparison trait implementations match the underlying [`Entity`],
/// and cannot discern between different worlds. /// and cannot discern between different worlds.
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
@ -4142,26 +4163,26 @@ impl<B: Bundle> PartialOrd for EntityRefExcept<'_, B> {
} }
} }
impl<B: Bundle> Ord for EntityRefExcept<'_, B> { impl<B: Bundle> Ord for EntityRefExcept<'_, '_, B> {
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
self.entity().cmp(&other.entity()) self.entity().cmp(&other.entity())
} }
} }
impl<B: Bundle> Hash for EntityRefExcept<'_, B> { impl<B: Bundle> Hash for EntityRefExcept<'_, '_, B> {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.entity().hash(state); self.entity().hash(state);
} }
} }
impl<B: Bundle> ContainsEntity for EntityRefExcept<'_, B> { impl<B: Bundle> ContainsEntity for EntityRefExcept<'_, '_, B> {
fn entity(&self) -> Entity { fn entity(&self) -> Entity {
self.id() self.id()
} }
} }
// SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity. // SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity.
unsafe impl<B: Bundle> EntityEquivalent for EntityRefExcept<'_, B> {} unsafe impl<B: Bundle> EntityEquivalent for EntityRefExcept<'_, '_, B> {}
/// Provides mutable access to all components of an entity, with the exception /// Provides mutable access to all components of an entity, with the exception
/// of an explicit set. /// of an explicit set.
@ -4171,23 +4192,28 @@ unsafe impl<B: Bundle> EntityEquivalent for EntityRefExcept<'_, B> {}
/// queries that might match entities that this query also matches. If you don't /// queries that might match entities that this query also matches. If you don't
/// need access to all components, prefer a standard query with a /// need access to all components, prefer a standard query with a
/// [`crate::query::Without`] filter. /// [`crate::query::Without`] filter.
pub struct EntityMutExcept<'w, B> pub struct EntityMutExcept<'w, 's, B>
where where
B: Bundle, B: Bundle,
{ {
entity: UnsafeEntityCell<'w>, entity: UnsafeEntityCell<'w>,
access: &'s Access<ComponentId>,
phantom: PhantomData<B>, phantom: PhantomData<B>,
} }
impl<'w, B> EntityMutExcept<'w, B> impl<'w, 's, B> EntityMutExcept<'w, 's, B>
where where
B: Bundle, B: Bundle,
{ {
/// # Safety /// # Safety
/// Other users of `UnsafeEntityCell` must not have access to any components not in `B`. /// Other users of `UnsafeEntityCell` must not have access to any components not in `B`.
pub(crate) unsafe fn new(entity: UnsafeEntityCell<'w>) -> Self { pub(crate) unsafe fn new(
entity: UnsafeEntityCell<'w>,
access: &'s Access<ComponentId>,
) -> Self {
Self { Self {
entity, entity,
access,
phantom: PhantomData, phantom: PhantomData,
} }
} }
@ -4203,16 +4229,16 @@ where
/// ///
/// This is useful if you have `&mut EntityMutExcept`, but you need /// This is useful if you have `&mut EntityMutExcept`, but you need
/// `EntityMutExcept`. /// `EntityMutExcept`.
pub fn reborrow(&mut self) -> EntityMutExcept<'_, B> { pub fn reborrow(&mut self) -> EntityMutExcept<'_, 's, B> {
// SAFETY: We have exclusive access to the entire entity and the // SAFETY: We have exclusive access to the entire entity and the
// applicable components. // applicable components.
unsafe { Self::new(self.entity) } unsafe { Self::new(self.entity, self.access) }
} }
/// Gets read-only access to all of the entity's components, except for the /// Gets read-only access to all of the entity's components, except for the
/// ones in `CL`. /// ones in `CL`.
#[inline] #[inline]
pub fn as_readonly(&self) -> EntityRefExcept<'_, B> { pub fn as_readonly(&self) -> EntityRefExcept<'_, 's, B> {
EntityRefExcept::from(self) EntityRefExcept::from(self)
} }
@ -4341,15 +4367,15 @@ where
} }
} }
impl<B: Bundle> PartialEq for EntityMutExcept<'_, B> { impl<B: Bundle> PartialEq for EntityMutExcept<'_, '_, B> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.entity() == other.entity() self.entity() == other.entity()
} }
} }
impl<B: Bundle> Eq for EntityMutExcept<'_, B> {} impl<B: Bundle> Eq for EntityMutExcept<'_, '_, B> {}
impl<B: Bundle> PartialOrd for EntityMutExcept<'_, B> { impl<B: Bundle> PartialOrd for EntityMutExcept<'_, '_, B> {
/// [`EntityMutExcept`]'s comparison trait implementations match the underlying [`Entity`], /// [`EntityMutExcept`]'s comparison trait implementations match the underlying [`Entity`],
/// and cannot discern between different worlds. /// and cannot discern between different worlds.
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
@ -4357,26 +4383,26 @@ impl<B: Bundle> PartialOrd for EntityMutExcept<'_, B> {
} }
} }
impl<B: Bundle> Ord for EntityMutExcept<'_, B> { impl<B: Bundle> Ord for EntityMutExcept<'_, '_, B> {
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
self.entity().cmp(&other.entity()) self.entity().cmp(&other.entity())
} }
} }
impl<B: Bundle> Hash for EntityMutExcept<'_, B> { impl<B: Bundle> Hash for EntityMutExcept<'_, '_, B> {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.entity().hash(state); self.entity().hash(state);
} }
} }
impl<B: Bundle> ContainsEntity for EntityMutExcept<'_, B> { impl<B: Bundle> ContainsEntity for EntityMutExcept<'_, '_, B> {
fn entity(&self) -> Entity { fn entity(&self) -> Entity {
self.id() self.id()
} }
} }
// SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity. // SAFETY: This type represents one Entity. We implement the comparison traits based on that Entity.
unsafe impl<B: Bundle> EntityEquivalent for EntityMutExcept<'_, B> {} unsafe impl<B: Bundle> EntityEquivalent for EntityMutExcept<'_, '_, B> {}
fn bundle_contains_component<B>(components: &Components, query_id: ComponentId) -> bool fn bundle_contains_component<B>(components: &Components, query_id: ComponentId) -> bool
where where