# Entity Pointer Dereference
Authors: @doot
Contributors: @bushRAT @quartermeister @Diddykonga @Victoron
> This document details an alternative design to [Unified EntityPtr Types](/8m_dGybhTCy7SrMPtwGbiQ).
We have a few types within Bevy ECS that allow access to an Entity's metadata and components:
- `EntityRef`: provides read-only access.
- `EntityMut`: provides mutable access.
- `EntityWorldMut`: provides structurally mutable access, like adding/removing components or despawning.
However, we incur API duplication because these are unique types even though they only differ in semantics (they are essentially layout and alignment-compatible). If we can either 1. safely treat them as a single type for certain operations, or 2. eliminate the need for explicit conversions, we can reduce this duplication. This document attempts #2.
## New type: `EntityView`
To reduce API duplication we can try to implement a Deref "ladder" following: `EntityWorldMut` -> `EntityMut` -> `EntityRef`. However, that creates a soundness issue that we'll describe below:
```rust
#[derive(Copy, Clone)] // Remember that we can currently copy around EntityRefs
pub struct EntityRef<'w>(UnsafeEntityCell<'w>);
pub struct EntityMut<'w>(UnsafeEntityCell<'w>);
// We can deref from &'a EntityMut<'w> to &'a EntityRef<'w>
// So if we then clone the EntityRef we would now have an owned EntityRef<'w>.
// This would untie the lifetime of the EntityRef from the EntityMut,
// which means we could still mess with the EntityMut mutably while reading
// from the EntityRef. That is aliased mutability aka Undefined Behavior (UB)!
impl<'w> Deref for EntityMut<'w> {
type Target = EntityRef<'w>;
fn deref(&self) -> &Self::Target;
}
```
So, enter `EntityView`:
```rust
pub struct EntityView<'w>(UnsafeEntityCell<'w>);
impl<'w> EntityView<'w> {
// Only read operations are allowed, no mutations
pub fn id(&self) -> Entity;
pub fn contains<T: Component>(&self) -> bool;
pub fn get<T: Component>(&self) -> Option<&'_ T>;
pub fn components<Q: ReadOnlyQueryData>(&self) -> Q::Item<'_>;
// ...
}
```
It's *almost* exactly what `EntityRef` currently is *except* it doesn't impl `Clone` or `Copy`, which means we can deref `EntityMut` into it without causing UB. To keep things simple we'll also deref `EntityRef` into it, which leaves us with two separate `Deref` "ladders":
- `EntityWorldMut` -> `EntityMut` -> `EntityView`
- `EntityRef` -> `EntityView`
And if users want to go from `EntityMut` -> `EntityRef` or `EntityRef` <-> `EntityView`, we'll still provide `From`/`Into` implementations for those conversions. However, those follow a `&'a EntityMut<'w>` -> `EntityRef<'a>` conversion (i.e. following the current lifetime shortening we use) so we don't introduce any UB. See the [Public API Definition](#Public-API-Definition) below for a more complete look.
## Public API Definition
The TL;DR is that `impl<'w> Deref for EntityMut<'w> { type Target = EntityRef<'w>; }` is unsound because `impl Clone for EntityRef` so we need a new type that's like `EntityRef` but doesn't implement `Clone` or `Copy`.
```rust
#[repr(transparent)]
pub struct EntityView<'w>(UnsafeEntityCell<'w>);
impl<'w> EntityView<'w> {
pub fn id(&self) -> Entity;
pub fn location(&self) -> EntityLocation;
pub fn archetype(&self) -> &Archetype;
pub fn contains<T: Component>(&self) -> bool;
pub fn contains_id(&self, component_id: ComponentId) -> bool;
pub fn contains_type_id(&self, type_id: TypeId) -> bool;
pub fn get<T: Component>(&self) -> Option<&'_ T>;
pub fn get_ref<T: Component>(&self) -> Option<Ref<'_, T>>;
pub fn get_change_ticks<T: Component>(&self) -> Option<ComponentTicks>;
pub fn get_change_ticks_by_id(&self, component_id: ComponentId) -> Option<ComponentTicks>;
pub fn get_by_id<F: DynamicComponentFetch>(&self, component_ids: F) -> Result<F::Ref<'_>, EntityComponentError>;
pub fn components<Q: ReadOnlyQueryData>(&self) -> Q::Item<'_>;
pub fn get_components<Q: ReadOnlyQueryData>(&self) -> Option<Q::Item<'_>>;
}
impl<'w> From<EntityRef<'w>> for EntityView<'w> {}
impl<'w> From<EntityMut<'w>> for EntityView<'w> {}
impl<'w> From<EntityWorldMut<'w>> for EntityView<'w> {}
impl<'a> From<&'a EntityView<'_>> for EntityView<'a> {}
impl<'a> From<&'a EntityRef<'_>> for EntityView<'a> {}
impl<'a> From<&'a EntityMut<'_>> for EntityView<'a> {}
impl<'a> From<&'a EntityWorldMut<'w>> for EntityView<'a> {}
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct EntityRef<'w>(UnsafeEntityCell<'w>);
impl<'w> EntityRef<'w> {
pub fn get<T: Component>(&self) -> Option<&'w T>;
pub fn get_ref<T: Component>(&self) -> Option<Ref<'w, T>>;
pub fn get_by_id<F: DynamicComponentFetch>(&self, component_ids: F) -> Result<F::Ref<'w>, EntityComponentError>;
pub fn components<Q: ReadOnlyQueryData>(&self) -> Q::Item<'w>;
pub fn get_components<Q: ReadOnlyQueryData>(&self) -> Option<Q::Item<'w>>;
}
impl<'w> Deref for EntityRef<'w> {
type Target = EntityView<'w>;
fn deref(&self) -> &Self::Target;
}
impl<'w> From<EntityView<'w>> for EntityRef<'w> {}
impl<'w> From<EntityMut<'w>> for EntityRef<'w> {}
impl<'w> From<EntityWorldMut<'w>> for EntityRef<'w> {}
impl<'w> From<&'a EntityView<'_>> for EntityRef<'a> {}
impl<'w> From<&'a EntityRef<'_>> for EntityRef<'a> {}
impl<'a> From<&'a EntityMut<'_>> for EntityRef<'a> {}
impl<'a> From<&'a EntityWorldMut<'w>> for EntityRef<'a> {}
#[repr(transparent)]
pub struct EntityMut<'w>(UnsafeEntityCell<'w>);
impl<'w> EntityMut<'w> {
pub fn reborrow(&mut self) -> EntityMut<'_>;
pub fn as_readonly(&self) -> EntityRef<'_>;
pub fn into_borrow<T: Component>(self) -> Option<&'w T>;
pub fn into_ref<T: Component>(self) -> Option<Ref<'w, T>>;
pub fn get_mut<T: Component>(&mut self) -> Option<Mut<'_, T>>;
pub fn into_mut<T: Component>(self) -> Option<Mut<'w, T>>;
pub fn into_borrow_by_id<F: DynamicComponentFetch>(self, component_ids: F) -> Result<F::Ref<'w>, EntityComponentError>;
pub fn get_mut_by_id<F: DynamicComponentFetch>(&mut self, component_ids: F) -> Result<F::Mut<'_>, EntityComponentError>;
pub unsafe fn get_mut_by_id_unchecked<F: DynamicComponentFetch>(&self, component_ids: F) -> Result<F::Mut<'_>, EntityComponentError>;
pub fn into_mut_by_id<F: DynamicComponentFetch>(self, component_ids: F) -> Result<F::Mut<'w>, EntityComponentError>;
pub fn into_components<Q: ReadOnlyQueryData>(self) -> Q::Item<'w>;
pub fn try_into_components<Q: ReadOnlyQueryData>(self) -> Option<Q::Item<'w>>;
}
impl<'w> Deref for EntityMut<'w> {
type Target = EntityView<'w>;
fn deref(&self) -> &Self::Target;
}
impl<'w> From<EntityWorldMut<'w>> for EntityMut<'w> {}
impl<'a> From<&'a mut EntityMut<'_>> for EntityMut<'a> {}
impl<'a> From<&'a mut EntityWorldMut<'_>> for EntityMut<'a> {}
#[repr(transparent)]
pub struct EntityWorldMut<'w>(UnsafeEntityCell<'w>);
impl<'w> EntityWorldMut<'w> {
pub fn insert<T: Bundle>(&mut self, bundle: T);
pub fn insert_if_new<T: Bundle>(&mut self, bundle: T) -> &mut Self;
pub unsafe fn insert_by_id(&mut self, component_id: ComponentId, component: OwningPtr<'_>) -> &mut Self;
pub unsafe fn insert_by_ids<'a, I: Iterator<Item = OwningPtr<'a>>>(&mut self, component_ids: &[ComponentId], iter_components: I) -> &mut Self;
pub fn take<T: Bundle>(&mut self) -> Option<T>;
pub fn remove<T: Bundle>(&mut self) -> &mut Self;
pub fn remove_with_requires<T: Bundle>(&mut self) -> &mut Self;
pub fn retain<T: Bundle>(&mut self) -> &mut Self;
pub fn remove_by_id(&mut self, component_id: ComponentId) -> &mut Self;
pub fn clear(&mut self) -> &mut Self;
pub fn despawn(self);
pub fn flush(self) -> Entity;
pub fn world(&self) -> &World;
pub unsafe fn world_mut(&mut self) -> &mut World;
pub fn into_world_mut(self) -> &'w mut World;
pub fn world_scope<U>(&mut self, f: impl FnOnce(&mut World) -> U) -> U;
pub fn update_location(&mut self);
pub fn entry<'a, T: Component>(&'a mut self) -> Entry<'w, 'a, T>;
pub fn trigger(&mut self, event: impl Event) -> &mut Self;
pub fn observe<E: Event, B: Bundle, M>(&mut self, observer: impl IntoObserverSystem<E, B, M>) -> &mut Self;
}
impl<'w> Deref for EntityWorldMut<'w> {
type Target = EntityMut<'w>;
fn deref(&self) -> &Self::Target;
}
impl<'w> DerefMut for EntityWorldMut<'w> {
fn deref_mut(&mut self) -> &mut Self::Target;
}
```