# 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; } ```