Cleanup entity reference types (#17149)

# Objective

Cleanup `EntityRef`, `EntityMut`, and `EntityWorldMut` in preparation
for my "Scoped Entity References" PR.

## Solution

- Switched `EntityRef`/`EntityMut` from tuple structs to normal ones.
- Ensured all conversion trait impls use the same `entity` argument
name.
- Replaced some `unsafe` with delegated calls from `EntityMut` to
`EntityRef`
    - Added `EntityMut::into_readonly` to make the replacements clearer
- Replaced some `unsafe` with delegated calls from `EntityWorldMut` to
`EntityMut` and `EntityRef`
- Added `EntityWorldMut::into_readonly`, `::as_readonly`,
`::into_mutable`, `::as_mutable` to make the replacements clearer

## Testing

Reusing current tests.
This commit is contained in:
Christian Hughes 2025-01-06 13:25:06 -06:00 committed by GitHub
parent 17e3b850bd
commit f64f3ac997
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -49,7 +49,9 @@ use super::{unsafe_world_cell::UnsafeEntityCell, Ref, ON_REMOVE, ON_REPLACE};
/// # bevy_ecs::system::assert_is_system(disjoint_system); /// # bevy_ecs::system::assert_is_system(disjoint_system);
/// ``` /// ```
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct EntityRef<'w>(UnsafeEntityCell<'w>); pub struct EntityRef<'w> {
cell: UnsafeEntityCell<'w>,
}
impl<'w> EntityRef<'w> { impl<'w> EntityRef<'w> {
/// # Safety /// # Safety
@ -58,26 +60,26 @@ impl<'w> EntityRef<'w> {
/// at the same time as the returned [`EntityRef`]. /// at the same time as the returned [`EntityRef`].
#[inline] #[inline]
pub(crate) unsafe fn new(cell: UnsafeEntityCell<'w>) -> Self { pub(crate) unsafe fn new(cell: UnsafeEntityCell<'w>) -> Self {
Self(cell) Self { cell }
} }
/// Returns the [ID](Entity) of the current entity. /// Returns the [ID](Entity) of the current entity.
#[inline] #[inline]
#[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."] #[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."]
pub fn id(&self) -> Entity { pub fn id(&self) -> Entity {
self.0.id() self.cell.id()
} }
/// Gets metadata indicating the location where the current entity is stored. /// Gets metadata indicating the location where the current entity is stored.
#[inline] #[inline]
pub fn location(&self) -> EntityLocation { pub fn location(&self) -> EntityLocation {
self.0.location() self.cell.location()
} }
/// Returns the archetype that the current entity belongs to. /// Returns the archetype that the current entity belongs to.
#[inline] #[inline]
pub fn archetype(&self) -> &Archetype { pub fn archetype(&self) -> &Archetype {
self.0.archetype() self.cell.archetype()
} }
/// Returns `true` if the current entity has a component of type `T`. /// Returns `true` if the current entity has a component of type `T`.
@ -102,7 +104,7 @@ impl<'w> EntityRef<'w> {
/// [`Self::contains_type_id`]. /// [`Self::contains_type_id`].
#[inline] #[inline]
pub fn contains_id(&self, component_id: ComponentId) -> bool { pub fn contains_id(&self, component_id: ComponentId) -> bool {
self.0.contains_id(component_id) self.cell.contains_id(component_id)
} }
/// Returns `true` if the current entity has a component with the type identified by `type_id`. /// Returns `true` if the current entity has a component with the type identified by `type_id`.
@ -114,7 +116,7 @@ impl<'w> EntityRef<'w> {
/// - If you have a [`ComponentId`] instead of a [`TypeId`], consider using [`Self::contains_id`]. /// - If you have a [`ComponentId`] instead of a [`TypeId`], consider using [`Self::contains_id`].
#[inline] #[inline]
pub fn contains_type_id(&self, type_id: TypeId) -> bool { pub fn contains_type_id(&self, type_id: TypeId) -> bool {
self.0.contains_type_id(type_id) self.cell.contains_type_id(type_id)
} }
/// Gets access to the component of type `T` for the current entity. /// Gets access to the component of type `T` for the current entity.
@ -122,7 +124,7 @@ impl<'w> EntityRef<'w> {
#[inline] #[inline]
pub fn get<T: Component>(&self) -> Option<&'w T> { pub fn get<T: Component>(&self) -> Option<&'w T> {
// SAFETY: We have read-only access to all components of this entity. // SAFETY: We have read-only access to all components of this entity.
unsafe { self.0.get::<T>() } unsafe { self.cell.get::<T>() }
} }
/// Gets access to the component of type `T` for the current entity, /// Gets access to the component of type `T` for the current entity,
@ -132,7 +134,7 @@ impl<'w> EntityRef<'w> {
#[inline] #[inline]
pub fn get_ref<T: Component>(&self) -> Option<Ref<'w, T>> { pub fn get_ref<T: Component>(&self) -> Option<Ref<'w, T>> {
// SAFETY: We have read-only access to all components of this entity. // SAFETY: We have read-only access to all components of this entity.
unsafe { self.0.get_ref::<T>() } unsafe { self.cell.get_ref::<T>() }
} }
/// Retrieves the change ticks for the given component. This can be useful for implementing change /// Retrieves the change ticks for the given component. This can be useful for implementing change
@ -140,7 +142,7 @@ impl<'w> EntityRef<'w> {
#[inline] #[inline]
pub fn get_change_ticks<T: Component>(&self) -> Option<ComponentTicks> { pub fn get_change_ticks<T: Component>(&self) -> Option<ComponentTicks> {
// SAFETY: We have read-only access to all components of this entity. // SAFETY: We have read-only access to all components of this entity.
unsafe { self.0.get_change_ticks::<T>() } unsafe { self.cell.get_change_ticks::<T>() }
} }
/// Retrieves the change ticks for the given [`ComponentId`]. This can be useful for implementing change /// Retrieves the change ticks for the given [`ComponentId`]. This can be useful for implementing change
@ -152,7 +154,7 @@ impl<'w> EntityRef<'w> {
#[inline] #[inline]
pub fn get_change_ticks_by_id(&self, component_id: ComponentId) -> Option<ComponentTicks> { pub fn get_change_ticks_by_id(&self, component_id: ComponentId) -> Option<ComponentTicks> {
// SAFETY: We have read-only access to all components of this entity. // SAFETY: We have read-only access to all components of this entity.
unsafe { self.0.get_change_ticks_by_id(component_id) } unsafe { self.cell.get_change_ticks_by_id(component_id) }
} }
/// Returns [untyped read-only reference(s)](Ptr) to component(s) for the /// Returns [untyped read-only reference(s)](Ptr) to component(s) for the
@ -265,7 +267,7 @@ impl<'w> EntityRef<'w> {
component_ids: F, component_ids: F,
) -> Result<F::Ref<'w>, EntityComponentError> { ) -> Result<F::Ref<'w>, EntityComponentError> {
// SAFETY: We have read-only access to all components of this entity. // SAFETY: We have read-only access to all components of this entity.
unsafe { component_ids.fetch_ref(self.0) } unsafe { component_ids.fetch_ref(self.cell) }
} }
/// Returns read-only components for the current entity that match the query `Q`. /// Returns read-only components for the current entity that match the query `Q`.
@ -274,66 +276,67 @@ impl<'w> EntityRef<'w> {
/// ///
/// If the entity does not have the components required by the query `Q`. /// If the entity does not have the components required by the query `Q`.
pub fn components<Q: ReadOnlyQueryData>(&self) -> Q::Item<'w> { pub fn components<Q: ReadOnlyQueryData>(&self) -> Q::Item<'w> {
self.get_components::<Q>().expect(QUERY_MISMATCH_ERROR) self.get_components::<Q>()
.expect("Query does not match the current entity")
} }
/// Returns read-only components for the current entity that match the query `Q`, /// Returns read-only components for the current entity that match the query `Q`,
/// or `None` if the entity does not have the components required by the query `Q`. /// or `None` if the entity does not have the components required by the query `Q`.
pub fn get_components<Q: ReadOnlyQueryData>(&self) -> Option<Q::Item<'w>> { pub fn get_components<Q: ReadOnlyQueryData>(&self) -> Option<Q::Item<'w>> {
// SAFETY: We have read-only access to all components of this entity. // SAFETY: We have read-only access to all components of this entity.
unsafe { self.0.get_components::<Q>() } unsafe { self.cell.get_components::<Q>() }
} }
/// Returns the source code location from which this entity has been spawned. /// Returns the source code location from which this entity has been spawned.
#[cfg(feature = "track_location")] #[cfg(feature = "track_location")]
pub fn spawned_by(&self) -> &'static Location<'static> { pub fn spawned_by(&self) -> &'static Location<'static> {
self.0.spawned_by() self.cell.spawned_by()
} }
} }
impl<'w> From<EntityWorldMut<'w>> for EntityRef<'w> { impl<'w> From<EntityWorldMut<'w>> for EntityRef<'w> {
fn from(entity_mut: EntityWorldMut<'w>) -> EntityRef<'w> { fn from(entity: EntityWorldMut<'w>) -> EntityRef<'w> {
// SAFETY: // SAFETY:
// - `EntityWorldMut` guarantees exclusive access to the entire world. // - `EntityWorldMut` guarantees exclusive access to the entire world.
unsafe { EntityRef::new(entity_mut.into_unsafe_entity_cell()) } unsafe { EntityRef::new(entity.into_unsafe_entity_cell()) }
} }
} }
impl<'a> From<&'a EntityWorldMut<'_>> for EntityRef<'a> { impl<'a> From<&'a EntityWorldMut<'_>> for EntityRef<'a> {
fn from(value: &'a EntityWorldMut<'_>) -> Self { fn from(entity: &'a EntityWorldMut<'_>) -> Self {
// SAFETY: // SAFETY:
// - `EntityWorldMut` guarantees exclusive access to the entire world. // - `EntityWorldMut` guarantees exclusive access to the entire world.
// - `&value` ensures no mutable accesses are active. // - `&entity` ensures no mutable accesses are active.
unsafe { EntityRef::new(value.as_unsafe_entity_cell_readonly()) } unsafe { EntityRef::new(entity.as_unsafe_entity_cell_readonly()) }
} }
} }
impl<'w> From<EntityMut<'w>> for EntityRef<'w> { impl<'w> From<EntityMut<'w>> for EntityRef<'w> {
fn from(value: EntityMut<'w>) -> Self { fn from(entity: EntityMut<'w>) -> Self {
// SAFETY: // SAFETY:
// - `EntityMut` guarantees exclusive access to all of the entity's components. // - `EntityMut` guarantees exclusive access to all of the entity's components.
unsafe { EntityRef::new(value.0) } unsafe { EntityRef::new(entity.cell) }
} }
} }
impl<'a> From<&'a EntityMut<'_>> for EntityRef<'a> { impl<'a> From<&'a EntityMut<'_>> for EntityRef<'a> {
fn from(value: &'a EntityMut<'_>) -> Self { fn from(entity: &'a EntityMut<'_>) -> Self {
// SAFETY: // SAFETY:
// - `EntityMut` guarantees exclusive access to all of the entity's components. // - `EntityMut` guarantees exclusive access to all of the entity's components.
// - `&value` ensures there are no mutable accesses. // - `&entity` ensures there are no mutable accesses.
unsafe { EntityRef::new(value.0) } unsafe { EntityRef::new(entity.cell) }
} }
} }
impl<'a> TryFrom<FilteredEntityRef<'a>> for EntityRef<'a> { impl<'a> TryFrom<FilteredEntityRef<'a>> for EntityRef<'a> {
type Error = TryFromFilteredError; type Error = TryFromFilteredError;
fn try_from(value: FilteredEntityRef<'a>) -> Result<Self, Self::Error> { fn try_from(entity: FilteredEntityRef<'a>) -> Result<Self, Self::Error> {
if !value.access.has_read_all() { if !entity.access.has_read_all() {
Err(TryFromFilteredError::MissingReadAllAccess) Err(TryFromFilteredError::MissingReadAllAccess)
} else { } else {
// SAFETY: check above guarantees read-only access to all components of the entity. // SAFETY: check above guarantees read-only access to all components of the entity.
Ok(unsafe { EntityRef::new(value.entity) }) Ok(unsafe { EntityRef::new(entity.entity) })
} }
} }
} }
@ -341,12 +344,12 @@ impl<'a> TryFrom<FilteredEntityRef<'a>> for EntityRef<'a> {
impl<'a> TryFrom<&'a FilteredEntityRef<'_>> for EntityRef<'a> { impl<'a> TryFrom<&'a FilteredEntityRef<'_>> for EntityRef<'a> {
type Error = TryFromFilteredError; type Error = TryFromFilteredError;
fn try_from(value: &'a FilteredEntityRef<'_>) -> Result<Self, Self::Error> { fn try_from(entity: &'a FilteredEntityRef<'_>) -> Result<Self, Self::Error> {
if !value.access.has_read_all() { if !entity.access.has_read_all() {
Err(TryFromFilteredError::MissingReadAllAccess) Err(TryFromFilteredError::MissingReadAllAccess)
} else { } else {
// SAFETY: check above guarantees read-only access to all components of the entity. // SAFETY: check above guarantees read-only access to all components of the entity.
Ok(unsafe { EntityRef::new(value.entity) }) Ok(unsafe { EntityRef::new(entity.entity) })
} }
} }
} }
@ -354,12 +357,12 @@ impl<'a> TryFrom<&'a FilteredEntityRef<'_>> for EntityRef<'a> {
impl<'a> TryFrom<FilteredEntityMut<'a>> for EntityRef<'a> { impl<'a> TryFrom<FilteredEntityMut<'a>> for EntityRef<'a> {
type Error = TryFromFilteredError; type Error = TryFromFilteredError;
fn try_from(value: FilteredEntityMut<'a>) -> Result<Self, Self::Error> { fn try_from(entity: FilteredEntityMut<'a>) -> Result<Self, Self::Error> {
if !value.access.has_read_all() { if !entity.access.has_read_all() {
Err(TryFromFilteredError::MissingReadAllAccess) Err(TryFromFilteredError::MissingReadAllAccess)
} else { } else {
// SAFETY: check above guarantees read-only access to all components of the entity. // SAFETY: check above guarantees read-only access to all components of the entity.
Ok(unsafe { EntityRef::new(value.entity) }) Ok(unsafe { EntityRef::new(entity.entity) })
} }
} }
} }
@ -367,12 +370,12 @@ impl<'a> TryFrom<FilteredEntityMut<'a>> for EntityRef<'a> {
impl<'a> TryFrom<&'a FilteredEntityMut<'_>> for EntityRef<'a> { impl<'a> TryFrom<&'a FilteredEntityMut<'_>> for EntityRef<'a> {
type Error = TryFromFilteredError; type Error = TryFromFilteredError;
fn try_from(value: &'a FilteredEntityMut<'_>) -> Result<Self, Self::Error> { fn try_from(entity: &'a FilteredEntityMut<'_>) -> Result<Self, Self::Error> {
if !value.access.has_read_all() { if !entity.access.has_read_all() {
Err(TryFromFilteredError::MissingReadAllAccess) Err(TryFromFilteredError::MissingReadAllAccess)
} else { } else {
// SAFETY: check above guarantees read-only access to all components of the entity. // SAFETY: check above guarantees read-only access to all components of the entity.
Ok(unsafe { EntityRef::new(value.entity) }) Ok(unsafe { EntityRef::new(entity.entity) })
} }
} }
} }
@ -436,7 +439,9 @@ unsafe impl TrustedEntityBorrow for EntityRef<'_> {}
/// } /// }
/// # bevy_ecs::system::assert_is_system(disjoint_system); /// # bevy_ecs::system::assert_is_system(disjoint_system);
/// ``` /// ```
pub struct EntityMut<'w>(UnsafeEntityCell<'w>); pub struct EntityMut<'w> {
cell: UnsafeEntityCell<'w>,
}
impl<'w> EntityMut<'w> { impl<'w> EntityMut<'w> {
/// # Safety /// # Safety
@ -444,14 +449,20 @@ impl<'w> EntityMut<'w> {
/// - No accesses to any of the entity's components may exist /// - No accesses to any of the entity's components may exist
/// at the same time as the returned [`EntityMut`]. /// at the same time as the returned [`EntityMut`].
pub(crate) unsafe fn new(cell: UnsafeEntityCell<'w>) -> Self { pub(crate) unsafe fn new(cell: UnsafeEntityCell<'w>) -> Self {
Self(cell) Self { cell }
} }
/// Returns a new instance with a shorter lifetime. /// Returns a new instance with a shorter lifetime.
/// This is useful if you have `&mut EntityMut`, but you need `EntityMut`. /// This is useful if you have `&mut EntityMut`, but you need `EntityMut`.
pub fn reborrow(&mut self) -> EntityMut<'_> { pub fn reborrow(&mut self) -> EntityMut<'_> {
// SAFETY: We have exclusive access to the entire entity and its components. // SAFETY: We have exclusive access to the entire entity and its components.
unsafe { Self::new(self.0) } unsafe { Self::new(self.cell) }
}
/// Consumes `self` and returns read-only access to all of the entity's
/// components, with the world `'w` lifetime.
pub fn into_readonly(self) -> EntityRef<'w> {
EntityRef::from(self)
} }
/// Gets read-only access to all of the entity's components. /// Gets read-only access to all of the entity's components.
@ -463,19 +474,19 @@ impl<'w> EntityMut<'w> {
#[inline] #[inline]
#[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."] #[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."]
pub fn id(&self) -> Entity { pub fn id(&self) -> Entity {
self.0.id() self.cell.id()
} }
/// Gets metadata indicating the location where the current entity is stored. /// Gets metadata indicating the location where the current entity is stored.
#[inline] #[inline]
pub fn location(&self) -> EntityLocation { pub fn location(&self) -> EntityLocation {
self.0.location() self.cell.location()
} }
/// Returns the archetype that the current entity belongs to. /// Returns the archetype that the current entity belongs to.
#[inline] #[inline]
pub fn archetype(&self) -> &Archetype { pub fn archetype(&self) -> &Archetype {
self.0.archetype() self.cell.archetype()
} }
/// Returns `true` if the current entity has a component of type `T`. /// Returns `true` if the current entity has a component of type `T`.
@ -500,7 +511,7 @@ impl<'w> EntityMut<'w> {
/// [`Self::contains_type_id`]. /// [`Self::contains_type_id`].
#[inline] #[inline]
pub fn contains_id(&self, component_id: ComponentId) -> bool { pub fn contains_id(&self, component_id: ComponentId) -> bool {
self.0.contains_id(component_id) self.cell.contains_id(component_id)
} }
/// Returns `true` if the current entity has a component with the type identified by `type_id`. /// Returns `true` if the current entity has a component with the type identified by `type_id`.
@ -512,7 +523,7 @@ impl<'w> EntityMut<'w> {
/// - If you have a [`ComponentId`] instead of a [`TypeId`], consider using [`Self::contains_id`]. /// - If you have a [`ComponentId`] instead of a [`TypeId`], consider using [`Self::contains_id`].
#[inline] #[inline]
pub fn contains_type_id(&self, type_id: TypeId) -> bool { pub fn contains_type_id(&self, type_id: TypeId) -> bool {
self.0.contains_type_id(type_id) self.cell.contains_type_id(type_id)
} }
/// Gets access to the component of type `T` for the current entity. /// Gets access to the component of type `T` for the current entity.
@ -528,14 +539,13 @@ impl<'w> EntityMut<'w> {
/// ///
/// If the entity does not have the components required by the query `Q`. /// If the entity does not have the components required by the query `Q`.
pub fn components<Q: ReadOnlyQueryData>(&self) -> Q::Item<'_> { pub fn components<Q: ReadOnlyQueryData>(&self) -> Q::Item<'_> {
self.get_components::<Q>().expect(QUERY_MISMATCH_ERROR) self.as_readonly().components::<Q>()
} }
/// Returns read-only components for the current entity that match the query `Q`, /// Returns read-only components for the current entity that match the query `Q`,
/// or `None` if the entity does not have the components required by the query `Q`. /// or `None` if the entity does not have the components required by the query `Q`.
pub fn get_components<Q: ReadOnlyQueryData>(&self) -> Option<Q::Item<'_>> { pub fn get_components<Q: ReadOnlyQueryData>(&self) -> Option<Q::Item<'_>> {
// SAFETY: We have read-only access to all components of this entity. self.as_readonly().get_components::<Q>()
unsafe { self.0.get_components::<Q>() }
} }
/// Consumes `self` and gets access to the component of type `T` with the /// Consumes `self` and gets access to the component of type `T` with the
@ -544,8 +554,7 @@ impl<'w> EntityMut<'w> {
/// Returns `None` if the entity does not have a component of type `T`. /// Returns `None` if the entity does not have a component of type `T`.
#[inline] #[inline]
pub fn into_borrow<T: Component>(self) -> Option<&'w T> { pub fn into_borrow<T: Component>(self) -> Option<&'w T> {
// SAFETY: consuming `self` implies exclusive access self.into_readonly().get()
unsafe { self.0.get() }
} }
/// Gets access to the component of type `T` for the current entity, /// Gets access to the component of type `T` for the current entity,
@ -564,8 +573,7 @@ impl<'w> EntityMut<'w> {
/// Returns `None` if the entity does not have a component of type `T`. /// Returns `None` if the entity does not have a component of type `T`.
#[inline] #[inline]
pub fn into_ref<T: Component>(self) -> Option<Ref<'w, T>> { pub fn into_ref<T: Component>(self) -> Option<Ref<'w, T>> {
// SAFETY: consuming `self` implies exclusive access self.into_readonly().get_ref()
unsafe { self.0.get_ref() }
} }
/// Gets mutable access to the component of type `T` for the current entity. /// Gets mutable access to the component of type `T` for the current entity.
@ -573,7 +581,7 @@ impl<'w> EntityMut<'w> {
#[inline] #[inline]
pub fn get_mut<T: Component<Mutability = Mutable>>(&mut self) -> Option<Mut<'_, T>> { pub fn get_mut<T: Component<Mutability = Mutable>>(&mut self) -> Option<Mut<'_, T>> {
// SAFETY: &mut self implies exclusive access for duration of returned value // SAFETY: &mut self implies exclusive access for duration of returned value
unsafe { self.0.get_mut() } unsafe { self.cell.get_mut() }
} }
/// Gets mutable access to the component of type `T` for the current entity. /// Gets mutable access to the component of type `T` for the current entity.
@ -584,8 +592,10 @@ impl<'w> EntityMut<'w> {
/// - `T` must be a mutable component /// - `T` must be a mutable component
#[inline] #[inline]
pub unsafe fn get_mut_assume_mutable<T: Component>(&mut self) -> Option<Mut<'_, T>> { pub unsafe fn get_mut_assume_mutable<T: Component>(&mut self) -> Option<Mut<'_, T>> {
// SAFETY: &mut self implies exclusive access for duration of returned value // SAFETY:
unsafe { self.0.get_mut_assume_mutable() } // - &mut self implies exclusive access for duration of returned value
// - Caller ensures `T` is a mutable component
unsafe { self.cell.get_mut_assume_mutable() }
} }
/// Consumes self and gets mutable access to the component of type `T` /// Consumes self and gets mutable access to the component of type `T`
@ -594,7 +604,21 @@ impl<'w> EntityMut<'w> {
#[inline] #[inline]
pub fn into_mut<T: Component<Mutability = Mutable>>(self) -> Option<Mut<'w, T>> { pub fn into_mut<T: Component<Mutability = Mutable>>(self) -> Option<Mut<'w, T>> {
// SAFETY: consuming `self` implies exclusive access // SAFETY: consuming `self` implies exclusive access
unsafe { self.0.get_mut() } unsafe { self.cell.get_mut() }
}
/// Gets mutable access to the component of type `T` for the current entity.
/// Returns `None` if the entity does not have a component of type `T`.
///
/// # Safety
///
/// - `T` must be a mutable component
#[inline]
pub unsafe fn into_mut_assume_mutable<T: Component>(self) -> Option<Mut<'w, T>> {
// SAFETY:
// - Consuming `self` implies exclusive access
// - Caller ensures `T` is a mutable component
unsafe { self.cell.get_mut_assume_mutable() }
} }
/// Retrieves the change ticks for the given component. This can be useful for implementing change /// Retrieves the change ticks for the given component. This can be useful for implementing change
@ -667,10 +691,7 @@ impl<'w> EntityMut<'w> {
self, self,
component_ids: F, component_ids: F,
) -> Result<F::Ref<'w>, EntityComponentError> { ) -> Result<F::Ref<'w>, EntityComponentError> {
// SAFETY: self.into_readonly().get_by_id(component_ids)
// - We have read-only access to all components of this entity.
// - consuming `self` ensures that no references exist to this entity's components.
unsafe { component_ids.fetch_ref(self.0) }
} }
/// Returns [untyped mutable reference(s)](MutUntyped) to component(s) for /// Returns [untyped mutable reference(s)](MutUntyped) to component(s) for
@ -794,7 +815,7 @@ impl<'w> EntityMut<'w> {
// SAFETY: // SAFETY:
// - `&mut self` ensures that no references exist to this entity's components. // - `&mut self` ensures that no references exist to this entity's components.
// - We have exclusive access to all components of this entity. // - We have exclusive access to all components of this entity.
unsafe { component_ids.fetch_mut(self.0) } unsafe { component_ids.fetch_mut(self.cell) }
} }
/// Returns [untyped mutable reference](MutUntyped) to component for /// Returns [untyped mutable reference](MutUntyped) to component for
@ -822,7 +843,7 @@ impl<'w> EntityMut<'w> {
// SAFETY: // SAFETY:
// - The caller must ensure simultaneous access is limited // - The caller must ensure simultaneous access is limited
// - to components that are mutually independent. // - to components that are mutually independent.
unsafe { component_ids.fetch_mut(self.0) } unsafe { component_ids.fetch_mut(self.cell) }
} }
/// Consumes `self` and returns [untyped mutable reference(s)](MutUntyped) /// Consumes `self` and returns [untyped mutable reference(s)](MutUntyped)
@ -855,47 +876,47 @@ impl<'w> EntityMut<'w> {
// SAFETY: // SAFETY:
// - consuming `self` ensures that no references exist to this entity's components. // - consuming `self` ensures that no references exist to this entity's components.
// - We have exclusive access to all components of this entity. // - We have exclusive access to all components of this entity.
unsafe { component_ids.fetch_mut(self.0) } unsafe { component_ids.fetch_mut(self.cell) }
} }
/// Returns the source code location from which this entity has been spawned. /// Returns the source code location from which this entity has been spawned.
#[cfg(feature = "track_location")] #[cfg(feature = "track_location")]
pub fn spawned_by(&self) -> &'static Location<'static> { pub fn spawned_by(&self) -> &'static Location<'static> {
self.0.spawned_by() self.cell.spawned_by()
} }
} }
impl<'w> From<&'w mut EntityMut<'_>> for EntityMut<'w> { impl<'w> From<&'w mut EntityMut<'_>> for EntityMut<'w> {
fn from(value: &'w mut EntityMut<'_>) -> Self { fn from(entity: &'w mut EntityMut<'_>) -> Self {
value.reborrow() entity.reborrow()
} }
} }
impl<'w> From<EntityWorldMut<'w>> for EntityMut<'w> { impl<'w> From<EntityWorldMut<'w>> for EntityMut<'w> {
fn from(value: EntityWorldMut<'w>) -> Self { fn from(entity: EntityWorldMut<'w>) -> Self {
// SAFETY: `EntityWorldMut` guarantees exclusive access to the entire world. // SAFETY: `EntityWorldMut` guarantees exclusive access to the entire world.
unsafe { EntityMut::new(value.into_unsafe_entity_cell()) } unsafe { EntityMut::new(entity.into_unsafe_entity_cell()) }
} }
} }
impl<'a> From<&'a mut EntityWorldMut<'_>> for EntityMut<'a> { impl<'a> From<&'a mut EntityWorldMut<'_>> for EntityMut<'a> {
fn from(value: &'a mut EntityWorldMut<'_>) -> Self { fn from(entity: &'a mut EntityWorldMut<'_>) -> Self {
// SAFETY: `EntityWorldMut` guarantees exclusive access to the entire world. // SAFETY: `EntityWorldMut` guarantees exclusive access to the entire world.
unsafe { EntityMut::new(value.as_unsafe_entity_cell()) } unsafe { EntityMut::new(entity.as_unsafe_entity_cell()) }
} }
} }
impl<'a> TryFrom<FilteredEntityMut<'a>> for EntityMut<'a> { impl<'a> TryFrom<FilteredEntityMut<'a>> for EntityMut<'a> {
type Error = TryFromFilteredError; type Error = TryFromFilteredError;
fn try_from(value: FilteredEntityMut<'a>) -> Result<Self, Self::Error> { fn try_from(entity: FilteredEntityMut<'a>) -> Result<Self, Self::Error> {
if !value.access.has_read_all() { if !entity.access.has_read_all() {
Err(TryFromFilteredError::MissingReadAllAccess) Err(TryFromFilteredError::MissingReadAllAccess)
} else if !value.access.has_write_all() { } else if !entity.access.has_write_all() {
Err(TryFromFilteredError::MissingWriteAllAccess) Err(TryFromFilteredError::MissingWriteAllAccess)
} else { } else {
// SAFETY: check above guarantees exclusive access to all components of the entity. // SAFETY: check above guarantees exclusive access to all components of the entity.
Ok(unsafe { EntityMut::new(value.entity) }) Ok(unsafe { EntityMut::new(entity.entity) })
} }
} }
} }
@ -903,14 +924,14 @@ impl<'a> TryFrom<FilteredEntityMut<'a>> for EntityMut<'a> {
impl<'a> TryFrom<&'a mut FilteredEntityMut<'_>> for EntityMut<'a> { impl<'a> TryFrom<&'a mut FilteredEntityMut<'_>> for EntityMut<'a> {
type Error = TryFromFilteredError; type Error = TryFromFilteredError;
fn try_from(value: &'a mut FilteredEntityMut<'_>) -> Result<Self, Self::Error> { fn try_from(entity: &'a mut FilteredEntityMut<'_>) -> Result<Self, Self::Error> {
if !value.access.has_read_all() { if !entity.access.has_read_all() {
Err(TryFromFilteredError::MissingReadAllAccess) Err(TryFromFilteredError::MissingReadAllAccess)
} else if !value.access.has_write_all() { } else if !entity.access.has_write_all() {
Err(TryFromFilteredError::MissingWriteAllAccess) Err(TryFromFilteredError::MissingWriteAllAccess)
} else { } else {
// SAFETY: check above guarantees exclusive access to all components of the entity. // SAFETY: check above guarantees exclusive access to all components of the entity.
Ok(unsafe { EntityMut::new(value.entity) }) Ok(unsafe { EntityMut::new(entity.entity) })
} }
} }
} }
@ -1039,6 +1060,28 @@ impl<'w> EntityWorldMut<'w> {
} }
} }
/// Consumes `self` and returns read-only access to all of the entity's
/// components, with the world `'w` lifetime.
pub fn into_readonly(self) -> EntityRef<'w> {
EntityRef::from(self)
}
/// Gets read-only access to all of the entity's components.
pub fn as_readonly(&self) -> EntityRef<'_> {
EntityRef::from(self)
}
/// Consumes `self` and returns non-structural mutable access to all of the
/// entity's components, with the world `'w` lifetime.
pub fn into_mutable(self) -> EntityMut<'w> {
EntityMut::from(self)
}
/// Gets non-structural mutable access to all of the entity's components.
pub fn as_mutable(&mut self) -> EntityMut<'_> {
EntityMut::from(self)
}
/// Returns the [ID](Entity) of the current entity. /// Returns the [ID](Entity) of the current entity.
#[inline] #[inline]
#[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."] #[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."]
@ -1127,7 +1170,7 @@ impl<'w> EntityWorldMut<'w> {
/// If the entity has been despawned while this `EntityWorldMut` is still alive. /// If the entity has been despawned while this `EntityWorldMut` is still alive.
#[inline] #[inline]
pub fn get<T: Component>(&self) -> Option<&'_ T> { pub fn get<T: Component>(&self) -> Option<&'_ T> {
EntityRef::from(self).get() self.as_readonly().get()
} }
/// Returns read-only components for the current entity that match the query `Q`. /// Returns read-only components for the current entity that match the query `Q`.
@ -1138,7 +1181,7 @@ impl<'w> EntityWorldMut<'w> {
/// has been despawned while this `EntityWorldMut` is still alive. /// has been despawned while this `EntityWorldMut` is still alive.
#[inline] #[inline]
pub fn components<Q: ReadOnlyQueryData>(&self) -> Q::Item<'_> { pub fn components<Q: ReadOnlyQueryData>(&self) -> Q::Item<'_> {
EntityRef::from(self).components::<Q>() self.as_readonly().components::<Q>()
} }
/// Returns read-only components for the current entity that match the query `Q`, /// Returns read-only components for the current entity that match the query `Q`,
@ -1149,7 +1192,7 @@ impl<'w> EntityWorldMut<'w> {
/// If the entity has been despawned while this `EntityWorldMut` is still alive. /// If the entity has been despawned while this `EntityWorldMut` is still alive.
#[inline] #[inline]
pub fn get_components<Q: ReadOnlyQueryData>(&self) -> Option<Q::Item<'_>> { pub fn get_components<Q: ReadOnlyQueryData>(&self) -> Option<Q::Item<'_>> {
EntityRef::from(self).get_components::<Q>() self.as_readonly().get_components::<Q>()
} }
/// Consumes `self` and gets access to the component of type `T` with /// Consumes `self` and gets access to the component of type `T` with
@ -1161,8 +1204,7 @@ impl<'w> EntityWorldMut<'w> {
/// If the entity has been despawned while this `EntityWorldMut` is still alive. /// If the entity has been despawned while this `EntityWorldMut` is still alive.
#[inline] #[inline]
pub fn into_borrow<T: Component>(self) -> Option<&'w T> { pub fn into_borrow<T: Component>(self) -> Option<&'w T> {
// SAFETY: consuming `self` implies exclusive access self.into_readonly().get()
unsafe { self.into_unsafe_entity_cell().get() }
} }
/// Gets access to the component of type `T` for the current entity, /// Gets access to the component of type `T` for the current entity,
@ -1175,7 +1217,7 @@ impl<'w> EntityWorldMut<'w> {
/// If the entity has been despawned while this `EntityWorldMut` is still alive. /// If the entity has been despawned while this `EntityWorldMut` is still alive.
#[inline] #[inline]
pub fn get_ref<T: Component>(&self) -> Option<Ref<'_, T>> { pub fn get_ref<T: Component>(&self) -> Option<Ref<'_, T>> {
EntityRef::from(self).get_ref() self.as_readonly().get_ref()
} }
/// Consumes `self` and gets access to the component of type `T` /// Consumes `self` and gets access to the component of type `T`
@ -1189,7 +1231,7 @@ impl<'w> EntityWorldMut<'w> {
/// If the entity has been despawned while this `EntityWorldMut` is still alive. /// If the entity has been despawned while this `EntityWorldMut` is still alive.
#[inline] #[inline]
pub fn into_ref<T: Component>(self) -> Option<Ref<'w, T>> { pub fn into_ref<T: Component>(self) -> Option<Ref<'w, T>> {
EntityRef::from(self).get_ref() self.into_readonly().get_ref()
} }
/// Gets mutable access to the component of type `T` for the current entity. /// Gets mutable access to the component of type `T` for the current entity.
@ -1200,8 +1242,7 @@ impl<'w> EntityWorldMut<'w> {
/// If the entity has been despawned while this `EntityWorldMut` is still alive. /// If the entity has been despawned while this `EntityWorldMut` is still alive.
#[inline] #[inline]
pub fn get_mut<T: Component<Mutability = Mutable>>(&mut self) -> Option<Mut<'_, T>> { pub fn get_mut<T: Component<Mutability = Mutable>>(&mut self) -> Option<Mut<'_, T>> {
// SAFETY: trait bound `Mutability = Mutable` ensures `T` is mutable self.as_mutable().into_mut()
unsafe { self.get_mut_assume_mutable() }
} }
/// Temporarily removes a [`Component`] `T` from this [`Entity`] and runs the /// Temporarily removes a [`Component`] `T` from this [`Entity`] and runs the
@ -1265,10 +1306,7 @@ impl<'w> EntityWorldMut<'w> {
/// - `T` must be a mutable component /// - `T` must be a mutable component
#[inline] #[inline]
pub unsafe fn get_mut_assume_mutable<T: Component>(&mut self) -> Option<Mut<'_, T>> { pub unsafe fn get_mut_assume_mutable<T: Component>(&mut self) -> Option<Mut<'_, T>> {
// SAFETY: self.as_mutable().into_mut_assume_mutable()
// - &mut self implies exclusive access for duration of returned value
// - caller ensures T is mutable
unsafe { self.as_unsafe_entity_cell().get_mut_assume_mutable() }
} }
/// Consumes `self` and gets mutable access to the component of type `T` /// Consumes `self` and gets mutable access to the component of type `T`
@ -1292,7 +1330,7 @@ impl<'w> EntityWorldMut<'w> {
/// If the entity has been despawned while this `EntityWorldMut` is still alive. /// If the entity has been despawned while this `EntityWorldMut` is still alive.
#[inline] #[inline]
pub fn get_change_ticks<T: Component>(&self) -> Option<ComponentTicks> { pub fn get_change_ticks<T: Component>(&self) -> Option<ComponentTicks> {
EntityRef::from(self).get_change_ticks::<T>() self.as_readonly().get_change_ticks::<T>()
} }
/// Retrieves the change ticks for the given [`ComponentId`]. This can be useful for implementing change /// Retrieves the change ticks for the given [`ComponentId`]. This can be useful for implementing change
@ -1307,7 +1345,7 @@ impl<'w> EntityWorldMut<'w> {
/// If the entity has been despawned while this `EntityWorldMut` is still alive. /// If the entity has been despawned while this `EntityWorldMut` is still alive.
#[inline] #[inline]
pub fn get_change_ticks_by_id(&self, component_id: ComponentId) -> Option<ComponentTicks> { pub fn get_change_ticks_by_id(&self, component_id: ComponentId) -> Option<ComponentTicks> {
EntityRef::from(self).get_change_ticks_by_id(component_id) self.as_readonly().get_change_ticks_by_id(component_id)
} }
/// Returns [untyped read-only reference(s)](Ptr) to component(s) for the /// Returns [untyped read-only reference(s)](Ptr) to component(s) for the
@ -1338,7 +1376,7 @@ impl<'w> EntityWorldMut<'w> {
&self, &self,
component_ids: F, component_ids: F,
) -> Result<F::Ref<'_>, EntityComponentError> { ) -> Result<F::Ref<'_>, EntityComponentError> {
EntityRef::from(self).get_by_id(component_ids) self.as_readonly().get_by_id(component_ids)
} }
/// Consumes `self` and returns [untyped read-only reference(s)](Ptr) to /// Consumes `self` and returns [untyped read-only reference(s)](Ptr) to
@ -1370,10 +1408,7 @@ impl<'w> EntityWorldMut<'w> {
self, self,
component_ids: F, component_ids: F,
) -> Result<F::Ref<'w>, EntityComponentError> { ) -> Result<F::Ref<'w>, EntityComponentError> {
// SAFETY: self.into_readonly().get_by_id(component_ids)
// - We have read-only access to all components of this entity.
// - consuming `self` ensures that no references exist to this entity's components.
unsafe { component_ids.fetch_ref(self.into_unsafe_entity_cell()) }
} }
/// Returns [untyped mutable reference(s)](MutUntyped) to component(s) for /// Returns [untyped mutable reference(s)](MutUntyped) to component(s) for
@ -1406,10 +1441,7 @@ impl<'w> EntityWorldMut<'w> {
&mut self, &mut self,
component_ids: F, component_ids: F,
) -> Result<F::Mut<'_>, EntityComponentError> { ) -> Result<F::Mut<'_>, EntityComponentError> {
// SAFETY: self.as_mutable().into_mut_by_id(component_ids)
// - `&mut self` ensures that no references exist to this entity's components.
// - We have exclusive access to all components of this entity.
unsafe { component_ids.fetch_mut(self.as_unsafe_entity_cell()) }
} }
/// Consumes `self` and returns [untyped mutable reference(s)](MutUntyped) /// Consumes `self` and returns [untyped mutable reference(s)](MutUntyped)
@ -1443,10 +1475,7 @@ impl<'w> EntityWorldMut<'w> {
self, self,
component_ids: F, component_ids: F,
) -> Result<F::Mut<'w>, EntityComponentError> { ) -> Result<F::Mut<'w>, EntityComponentError> {
// SAFETY: self.into_mutable().into_mut_by_id(component_ids)
// - consuming `self` ensures that no references exist to this entity's components.
// - We have exclusive access to all components of this entity.
unsafe { component_ids.fetch_mut(self.into_unsafe_entity_cell()) }
} }
/// Adds a [`Bundle`] of components to the entity. /// Adds a [`Bundle`] of components to the entity.
@ -2499,8 +2528,6 @@ unsafe fn trigger_on_replace_and_on_remove_hooks_and_observers(
deferred_world.trigger_on_remove(archetype, entity, bundle_info.iter_explicit_components()); deferred_world.trigger_on_remove(archetype, entity, bundle_info.iter_explicit_components());
} }
const QUERY_MISMATCH_ERROR: &str = "Query does not match the current entity";
/// A view into a single entity and component in a world, which may either be vacant or occupied. /// A view into a single entity and component in a world, which may either be vacant or occupied.
/// ///
/// This `enum` can only be constructed from the [`entry`] method on [`EntityWorldMut`]. /// This `enum` can only be constructed from the [`entry`] method on [`EntityWorldMut`].
@ -3018,19 +3045,19 @@ impl<'w> FilteredEntityRef<'w> {
impl<'w> From<FilteredEntityMut<'w>> for FilteredEntityRef<'w> { impl<'w> From<FilteredEntityMut<'w>> for FilteredEntityRef<'w> {
#[inline] #[inline]
fn from(entity_mut: FilteredEntityMut<'w>) -> Self { fn from(entity: FilteredEntityMut<'w>) -> Self {
// SAFETY: // SAFETY:
// - `FilteredEntityMut` guarantees exclusive access to all components in the new `FilteredEntityRef`. // - `FilteredEntityMut` guarantees exclusive access to all components in the new `FilteredEntityRef`.
unsafe { FilteredEntityRef::new(entity_mut.entity, entity_mut.access) } unsafe { FilteredEntityRef::new(entity.entity, entity.access) }
} }
} }
impl<'a> From<&'a FilteredEntityMut<'_>> for FilteredEntityRef<'a> { impl<'a> From<&'a FilteredEntityMut<'_>> for FilteredEntityRef<'a> {
#[inline] #[inline]
fn from(entity_mut: &'a FilteredEntityMut<'_>) -> Self { fn from(entity: &'a FilteredEntityMut<'_>) -> Self {
// SAFETY: // SAFETY:
// - `FilteredEntityMut` guarantees exclusive access to all components in the new `FilteredEntityRef`. // - `FilteredEntityMut` guarantees exclusive access to all components in the new `FilteredEntityRef`.
unsafe { FilteredEntityRef::new(entity_mut.entity, entity_mut.access.clone()) } unsafe { FilteredEntityRef::new(entity.entity, entity.access.clone()) }
} }
} }
@ -3041,7 +3068,7 @@ impl<'a> From<EntityRef<'a>> for FilteredEntityRef<'a> {
unsafe { unsafe {
let mut access = Access::default(); let mut access = Access::default();
access.read_all(); access.read_all();
FilteredEntityRef::new(entity.0, access) FilteredEntityRef::new(entity.cell, access)
} }
} }
} }
@ -3053,7 +3080,7 @@ impl<'a> From<&'a EntityRef<'_>> for FilteredEntityRef<'a> {
unsafe { unsafe {
let mut access = Access::default(); let mut access = Access::default();
access.read_all(); access.read_all();
FilteredEntityRef::new(entity.0, access) FilteredEntityRef::new(entity.cell, access)
} }
} }
} }
@ -3065,7 +3092,7 @@ impl<'a> From<EntityMut<'a>> for FilteredEntityRef<'a> {
unsafe { unsafe {
let mut access = Access::default(); let mut access = Access::default();
access.read_all(); access.read_all();
FilteredEntityRef::new(entity.0, access) FilteredEntityRef::new(entity.cell, access)
} }
} }
} }
@ -3077,7 +3104,7 @@ impl<'a> From<&'a EntityMut<'_>> for FilteredEntityRef<'a> {
unsafe { unsafe {
let mut access = Access::default(); let mut access = Access::default();
access.read_all(); access.read_all();
FilteredEntityRef::new(entity.0, access) FilteredEntityRef::new(entity.cell, access)
} }
} }
} }
@ -3389,7 +3416,7 @@ impl<'a> From<EntityMut<'a>> for FilteredEntityMut<'a> {
let mut access = Access::default(); let mut access = Access::default();
access.read_all(); access.read_all();
access.write_all(); access.write_all();
FilteredEntityMut::new(entity.0, access) FilteredEntityMut::new(entity.cell, access)
} }
} }
} }
@ -3402,7 +3429,7 @@ impl<'a> From<&'a mut EntityMut<'_>> for FilteredEntityMut<'a> {
let mut access = Access::default(); let mut access = Access::default();
access.read_all(); access.read_all();
access.write_all(); access.write_all();
FilteredEntityMut::new(entity.0, access) FilteredEntityMut::new(entity.cell, access)
} }
} }
} }
@ -3566,10 +3593,10 @@ impl<'a, B> From<&'a EntityMutExcept<'_, B>> for EntityRefExcept<'a, B>
where where
B: Bundle, B: Bundle,
{ {
fn from(entity_mut: &'a EntityMutExcept<'_, B>) -> Self { fn from(entity: &'a EntityMutExcept<'_, 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_mut.entity) } unsafe { EntityRefExcept::new(entity.entity) }
} }
} }