# EntityPtrs and where to find them Author(s): @doot @bushRAT @Victoron Contributor(s): @quartermeister @Diddykonga ## Working Group Goals - Reduce code duplication within the "Entity pointer" APIs - Minimize breaking changes where possible (these are heavily used APIs) - Ensure the main entity pointer types and the filtered variants provide consistent access to operations on an entity pointer. - Current APIs are missing various operations for the filtered variants that are present on the main ones. ## Unresolved Questions - [ ] Should `Shared`/`Exclusive` capabilities be renamed? - [ ] Should `EntityPtr` be renamed to `EntityCell`? - [ ] What performance regressions (if any) do we encounter by switching `&mut World` to `UnsafeWorldCell` for `EntityWorldMut`? - [ ] Do we see any performance hits with `Full` and `Global` when calling `Scope::can_read/can_write`? They *should* inline into a no-op, but we should check. - [ ] Should we remove `UnsafeEntityCell` and inline its logic into `EntityPtr`? - [ ] Additionally, should we introduce a new `Unsafe` capability as a replacement? It would be a `Copy`able pointer that can (unsafely) give out mutable references. - [ ] Should the `Capability` be stored directly on the `EntityPtr`, as opposed to `PhantomData`? This would enable a `EntityPtr::new(cell, capability, scope`) style constructor. - [ ] Should `EntityRef`/`EntityMut`'s scope type parameter be un-defaulted and aliases added for `Full`: `FullEntityRef`/`FullEntityMut`? - [ ] Should we remove the following functions from `World`, given they have equivalents through entity references? `World::get`, `World::get_mut`, `World::get_by_id`, `World::get_mut_by_id`, `World::inspect_entity`, `World::despawn`, `World::try_despawn`. - [ ] Should we keep `EntityWorldMut` as a separate type? If we unify it, we will likely need to add a function to the `Scope` trait to update the location for all `EntityPtr` functions. For non-global `Scope`s, this would be implemented as a no-op. - [ ] Should `World::get_entity` family of functions return `EntityWorldRef`s instead of `EntityRef`s? - [ ] Since `EntityFetcher` now exists, should we add a scope for "can access itself and all other entities"? This would be a smaller scope than `Global`'s "can access itself and the whole world". - [ ] Should we add an `And<(A, B, ...)>` scope combinator that performs boolean AND on all of the contained scopes? - [ ] Should we rename the `Full` scope to `All`? ## Capabilities Capabilities describe what you can _do_ to data referenced by an `EntityPtr`. The `Shared` capability allows for shared, or "read-only", access. This is analagous to Rust's `&T` reference type. Following from this, the `Exclusive` capability allows for exclusive, or "mutable", access. Again, analogous to Rust's `&mut T` reference type. ## Scopes Scopes describe _what_ you can access with an `EntityPtr`. The typical scope for an `EntityPtr` is `Full`, permitting visibility over all components owned by this entity. `Global` is a wider scope, allowing visibility over the entire `World` that this entity lives in. In the opposite direction, `Except`, `Only`, and `Partial` give subsets of `Full` access. `Except` is `Full` scope, _except_ a given `Bundle` `B`. `Only` is the inverse of `Except`, providing access _only_ to a given `Bundle` `B`. Finally, `Partial` is a more complex subset of `Full`, where the exact items you have scope over is controlled at runtime via an `Access<ComponentId>`. ### Q: Why is `World` access a scope and not a capability? If `World` access were a `Capability`, it would interact weirdly with filters (which are scopes). For example, if you have world capability, but you're filtered to only access `Foo`, then you could access the component `Bar` by getting a world reference and said entity directly. So there's no reason to give out a `EntityPtr<Global, Only<Bundle>>` or make it constructible in the first place. In Rust terms, we can say that Capabilities define what *type* of borrow an entity pointer is, while Scopes define how *big or small* the borrow is: from just a few specific components, to the whole entity, or the whole `World`. ## Scopes vs Capabilities If we were to map out how scopes and capabilities fit into the types that exist in Bevy today, it would follow as such: - `EntityRef` is a `Shared` pointer with `Full` access to the entity's components. - `EntityMut` is an `Exclusive` pointer with `Full` access to the entity's components. - `EntityWorldMut` is an `Exclusive` pointer with `Global` access to the entity's components and the `World` at large. - `FilteredEntityRef` is a `Shared` pointer with `Partial` access to the entity's components, as defined by an `Access<ComponentId>`. - `FilteredEntityMut` likewise is an `Exclusive` pointer with `Partial` access to the entity's components. - `EntityRefExcept<B>` is a `Shared` pointer with access to all of the entity's components `Except` the ones included in the `Bundle` `B`. - `EntityMutExcept<B>` likewise is an `Exclusive` pointer with access to all of the entity's components `Except` the ones included in the `Bundle` `B`. A table is provided below to see the different types altogether. Scopes are across the top, while Capabilities are along the left-hand side. | | Full | Global | Except | Only | Partial | |-----------|-----------|----------------|-----------------|---------------|-------------------| | Shared | EntityRef | EntityWorldRef | EntityRefExcept | EntityRefOnly | FilteredEntityRef | | Exclusive | EntityMut | EntityWorldMut | EntityMutExcept | EntityMutOnly | FilteredEntityMut | ## Proposed breaking changes - `EntityRef::get` and related functions now return references with lifetime `'_` instead of `'w`. Use the `into_x` family of functions instead if `'w` data is required. - *(optional)* Rename `EntityWorldMut` -> `EntityMutWorld`. - Reason: `World` is now more like a "scope" rather than an access level, so would be more aptly named Entity(Capability)(Scope). Note that `Full` is considered the "default" scope. ## Public API Definition ```rust /// A pointer to an [`Entity`] with access to some or all of its components, /// as determined by the [`Scope`] `S`. The operations available to the /// user are determined by the [`Capability`] `C`. (i.e. whether the /// entity is read-only or mutable). /// /// # Capabilities /// /// Capabilities describe what you can _do_ to data referenced by an entity /// pointer. The [`Shared`] capability allows for shared, or "read-only", /// access. This is analagous to Rust's `&T` reference type. Following from /// this, the [`Exclusive`] capability allows for exclusive, or "mutable", /// access. Again, analogous to Rust's `&mut T` reference type. /// /// # Scopes /// /// Scopes describe _what_ you can access with an entity pointer. The typical /// scope for an entity pointer is [`Full`], permitting visibility over all /// components owned by this entity. [`Global`] is a wider scope, allowing /// visibility over the entire [`World`] that this entity lives in. /// /// In the opposite direction, [`Except`], [`Only`], and [`Partial`] give /// subsets of [`Full`] access: /// /// - [`Except`] provides access to all components _except_ those given in /// the [`Bundle`] `B`. /// - [`Only`] is the inverse of [`Except`], providing access _only_ to a /// given [`Bundle`] `B`. /// - [`Partial`] is a more complex subset of [`Full`], where the exact items /// available are defined at runtime via an [`Access<ComponentId>`]. /// /// # Table of Scopes vs Capabilities /// /// Scopes are across the top, while Capabilities are along the left-hand side. /// /// | | Full | Global | Except | Only | Partial | /// |-----------|-----------|----------------|-----------------|---------------|-------------------| /// | Shared | EntityRef | EntityWorldRef | EntityRefExcept | EntityRefOnly | FilteredEntityRef | /// | Exclusive | EntityMut | EntityWorldMut | EntityMutExcept | EntityMutOnly | FilteredEntityMut | pub struct EntityPtr<'w, C: Capability, S: Scope = Full> { cell: UnsafeEntityCell<'w>, scope: S, _capability: PhantomData<C>, } impl<'w, C: Capability, S: Scope> EntityPtr<'w, C, S> { pub fn as_readonly(&self) -> EntityPtr<'_, Shared, &S>; pub fn into_readonly(self) -> EntityPtr<'w, Shared, S>; pub fn scope(&self) -> &S; pub fn into_scope(self) -> S; 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: 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: 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<'_>>; pub fn into_borrow<T: Component>(self) -> Option<&'w T>; pub fn into_ref<T: Component>(self) -> Option<Ref<'w, T>>; pub fn into_borrow_by_id<F: DynamicComponentFetch>(self, component_ids: F) -> Result<F::Ref<'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, S: Scope> EntityPtr<'w, Shared, S> { pub(crate) unsafe fn new_shared(cell: UnsafeEntityCell<'w>, scope: S) -> Self; } impl<'w, S: Scope> EntityPtr<'w, Exclusive, S> { pub(crate) unsafe fn new_exclusive(cell: UnsafeEntityCell<'w>, scope: S) -> Self; pub fn reborrow(&mut self) -> EntityPtr<'_, Exclusive, &S>; pub fn get_mut<T: Component>(&mut self) -> Option<Mut<'_, T>>; 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<T: Component>(self) -> Option<Mut<'w, T>>; pub fn into_mut_by_id<F: DynamicComponentFetch>(self, component_ids: F) -> Result<F::Mut<'w>, EntityComponentError>; } /// Both [`Shared`] and [`Exclusive`] capabilities have access to these /// functions. impl<'w, C: Capability> EntityPtr<'w, C, Global> { pub fn world(&self) -> &World; pub fn into_world(self) -> &'w World; pub fn downgrade(&self) -> EntityPtr<'_, C, Full>; pub fn downgrade_into(self) -> EntityPtr<'w, C, Full>; } impl<'w> EntityPtr<'w, Exclusive, Global> { 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 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 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, C: Capability> EntityPtr<'w, C, Full> { pub fn split<B: Bundle>(self) -> (EntityPtr<'w, C, Only<B>>, EntityPtr<'w, C, Except<B>>); pub fn split_by(self, access: Access<ComponentId>) -> (EntityPtr<'w, C, Partial>, EntityPtr<'w, C, Partial>); } impl<'w, C: Capability, B: Bundle> EntityPtr<'w, C, Except<B>> { pub fn split<C: Bundle>(self) -> (EntityPtr<'w, C, Only<C>>, EntityPtr<'w, C, Except<(B, C)>); } /// [`EntityPtr`]s with a [`Clone`]able [`Scope`] that only have permission /// to read components can be [`Clone`]d. impl<S: Scope + Clone> Clone for EntityPtr<'_, Shared, S> { fn clone(&self) -> Self { Self { cell: self.cell, scope: self.scope.clone(), _access: PhantomData, } } } /// [`EntityPtr`]s with a [`Copy`]able [`Scope`] that only have permission /// to read components can be [`Copy`]'d. impl<S: Scope + Copy> Copy for EntityPtr<'_, Shared, S> {} /// An [`Exclusive`] entity pointer within any [`Scope`] can always be downgraded /// into a [`Shared`] pointer in the same [`Scope`]. impl<'w, S: Scope> From<EntityPtr<'w, Exclusive, S>> for EntityPtr<'w, Shared, S> {} impl<'w, C: Capability> TryFrom<EntityPtr<'w, C, Partial>> for EntityPtr<'w, Shared, Full> {} impl<'a, C: Capability, S: Scope> From<&'a EntityPtr<'_, C, S>> for EntityPtr<'a, Shared, &S> {} impl<'a, C: Capability> From<&'a EntityPtr<'_, C, Global>> for EntityPtr<'a, Shared, Full> {} impl<'a, S: Scope> From<&'a mut EntityPtr<'_, Exclusive, S>> for EntityPtr<'a, Exclusive, &S> {} impl<'a> From<&'a mut EntityPtr<'_, Exclusive, Global>> for EntityPtr<'a, Exclusive, Full> {} /// An [`EntityPtr`] variant with read access to all components on an entity. /// /// See [`EntityPtr`] for details. pub type EntityRef<'w> = EntityPtr<'w, Shared, Full>; /// An [`EntityPtr`] variant with mutable access to all components on an /// entity. /// /// See [`EntityPtr`] for details. pub type EntityMut<'w> = EntityPtr<'w, Exclusive, Full>; /// This [`EntityPtr`] variant provides the maximum permissions over an /// entity, its components, and the world: /// - The entity's components can be read and mutated. /// - New components can be inserted onto the entity. /// - Components can be removed from the entity. /// - The entity can be despawned entirely. /// - The World attached to the entity can have its command queue flushed. /// /// See [`EntityPtr`] for further details. pub type EntityWorldMut<'w> = EntityPtr<'w, Exclusive, Global>; /// An [`EntityPtr`] variant with read access to some components on an /// entity. The set of available components is determined by an /// [`Access<ComponentId>`]. /// /// See [`EntityPtr`] for further details. pub type FilteredEntityRef<'w> = EntityPtr<'w, Shared, Partial>; /// An [`EntityPtr`] variant with mutable access to some components on an /// entity. The set of available components is determined by an /// [`Access<ComponentId>`]. /// /// See [`EntityPtr`] for further details. pub type FilteredEntityMut<'w> = EntityPtr<'w, Exclusive, Partial>; /// An [`EntityPtr`] variant with read access to some components on an /// entity. The set of available components are the ones included in the /// [`Bundle`]. /// /// See [`EntityRefExcept`] for the inverted form of this type. /// See [`EntityPtr`] for further details. pub type EntityRefOnly<'w, Bundle> = EntityPtr<'w, Shared, Only<Bundle>>; /// An [`EntityPtr`] variant with mutable access to some components on an /// entity. The set of available components are the ones included in the /// [`Bundle`]. /// /// See [`EntityMutExcept`] for the inverted form of this type. /// See [`EntityPtr`] for further details. pub type EntityMutOnly<'w, Bundle> = EntityPtr<'w, Exclusive, Only<Bundle>>; /// An [`EntityPtr`] variant with read access to some components on an /// entity. The set of available components are the ones **NOT** included in /// the [`Bundle`]. /// /// See [`EntityRefOnly`] for the inverted form of this type. /// See [`EntityPtr`] for further details. pub type EntityRefExcept<'w, Bundle> = EntityPtr<'w, Shared, Except<Bundle>>; /// An [`EntityPtr`] variant with mutable access to some components on an /// entity. The set of available components are the ones **NOT** included in /// the [`Bundle`]. /// /// See [`EntityMutOnly`] for the inverted form of this type. /// See [`EntityPtr`] for further details. pub type EntityMutExcept<'w, Bundle> = EntityPtr<'w, Exclusive, Except<Bundle>>; // TODO: DOCS pub trait Capability: sealed::Capability {} /// [`EntityPtr`] [`Capability`] used to denote that the pointer has read /// access to an entity's components. pub struct Shared; impl Capability for Shared {} /// [`EntityPtr`] [`Capability`] used to denote that it has /// mutable access to an entity's components. pub struct Exclusive; impl Capability for Exclusive {} /// TODO: DOCS pub trait Scope: sealed::Scope { /// Returns `true` if the given [`Component`] can be read by /// a certain [`EntityPtr`]. fn can_read(&self, component: ComponentId) -> bool; /// Returns `true` if the given [`Component`] can be mutated by /// a certain [`EntityPtr`]. fn can_write(&self, component: ComponentId) -> bool; } impl<S: Scope> Scope for &S { fn can_read(&self, component: ComponentId) -> bool { (**self).can_read(component) } fn can_write(&self, component: ComponentId) -> bool { (**self).can_write(component) } } /// [`EntityPtr`] [`Scope`] that provides full access to an entity's components. /// /// See [`EntityRef`] and [`EntityMut`] which operate in this scope. #[derive(Clone, Copy)] pub struct Full; impl Scope for Full { fn can_read(&self, component: ComponentId) -> bool { true } fn can_write(&self, component: ComponentId) -> bool { true } } /// [`EntityPtr`] [`Scope`] that provides full access to an entity's components /// and the [`World`] that the entity is contained in. /// /// See [`EntityWorldMut`] which operates in this scope. #[derive(Clone, Copy)] pub struct Global; impl Scope for Global { fn can_read(&self, component: ComponentId) -> bool { true } fn can_write(&self, component: ComponentId) -> bool { true } } /// [`Scope`] that filters an [`EntityPtr`]'s access to its components /// based on a provided [`Access<ComponentId>`]. /// /// See [`FilteredEntityRef`] and [`FilteredEntityMut`] which operate in this /// scope. #[derive(Clone)] pub struct Partial(pub Access<ComponentId>); impl Scope for Partial { fn can_read(&self, component: ComponentId) -> bool { self.0.has_component_read(component) } fn can_write(&self, component: ComponentId) -> bool { self.0.has_component_write(component) } } /// [`Scope`] that allows an [`EntityPtr`] access to *only* the components /// which are included in the [`Bundle`] `B`. /// /// See [`EntityRefOnly`] and [`EntityMutOnly`] which operate in this scope. #[derive(Clone, Copy)] pub struct Only<B: Bundle>(PhantomData<B>); impl<B: Bundle> Scope for Only<B> { // TODO } /// [`Scope`] that allows an [`EntityPtr`] access to all of its components, /// *except* those included in the [`Bundle`] `B`. /// /// See [`EntityRefExcept`] and [`EntityMutExcept`] which operate in this /// scope. #[derive(Clone, Copy)] pub struct Except<B: Bundle>(PhantomData<B>); impl<B: Bundle> Scope for Except<B> { // TODO } mod sealed { pub trait Capability {} impl Capability for super::Shared {} impl Capability for super::Exclusive {} pub trait Scope {} impl Scope for super::Full {} impl Scope for super::Global {} impl Scope for super::Partial {} impl<B: Bundle> Scope for super::Only<B> {} impl<B: Bundle> Scope for super::Except<B> {} } ``` ## Order of PRs 1. Add `EntityPtr` type and turn `EntityRef` and `EntityMut` into type aliases. 2. Change `EntityWorldMut` to hold an `UnsafeEntityCell` instead of `(&mut World, EntityLocation, Entity)`. 3. Change `EntityWorldMut` into a type alias and add `Global` scope. 4. Turn `FilteredEntityRef` and `FilteredEntityMut` into type aliases and add `Partial` scope. 5. Turn `EntityRefExcept` and `EntityMutExcept` into type aliases and add `Except` scope. 6. Add `EntityRefOnly` and `EntityMutOnly` type aliases and `Only` scope. 7. Add `EntityPtr::split` functions to split access over a single entity pointer. # What if we used references instead? Instead of modeling access levels with generics on `EntityPtr`, they could be modeled with references to an `EntityView` instead. We can use them directly, no need to How We can avoid a lot of cognitive load on the user/complexity budget this way. Instead of representing scope with a generic, we let the lifetime of the respective `EntityAccess` type constrain the lifetime of any access. This works, even in the presence of `*Ref` clones and copies. ```rust #[derive(Clone, Copy)] pub struct EntityView<'w>(UnsafeEntityCell<'w>); impl<'w> EntityView { // ... EntityView-specific methods, separated by &self/&mut self as needed // ... if desired style-wise, they can be in separate impl blocks } // Due to lifetime elision rules, the inner 'w lifetime // will be constrained by the &self lifetime in `Clone`/`Copy`! #[derive(Clone, Copy)] pub struct EntityRef<'w>(EntityView<'w>); impl<'w> Deref for EntityRef<'w> { type Target = EntityView<'w> // ... } // derefs to EntityRef via &mut -> & coercion pub type EntityMut<'w>(EntityView<'w>); impl<'w> Deref for EntityMut<'w> { type Target = EntityView<'w> // ... } impl<'w> DerefMut for EntityMut<'w>{ // ... } ``` The Clone/Copy impl split remains even when derefed! These used to be direct trait aliases to references, but were changed to newtypes to allow for the `QueryData` impl. Instead, each newtype now derefs to its matching reference type. ```rust // derefs to EntityRef, mutably derefs to EntityMut pub struct EntityWorldMut<'w>(EntityView<'w>); impl<'w> EntityWorldMut<'w> { //.. EntityWorldMut-specific methods } impl<'w> Deref for EntityWorldMut<'w> { type Target = EntityView<'w> // ... } impl<'w> DerefMut for EntityWorldMut<'w> { // ... } ``` Given that immutable access to world can be granted via a `world(&self) -> &World` method, an `EntityWorldRef` is not necessary. (Immutable access with sole focus on an entity would just be `EntityRef`, which is covered by the `Deref` impl) However, if a `ÈntityWorldRef` is still desired, it could also be added, with `Deref` into `EntityRef`. ```rust #[derive(Clone, Copy)] pub struct FilteredEntityView<'w>{ entity: UnsafeEntityCell<'w>, access: ComponentId } // if desired style-wise, they can be in separate impl blocks impl<'w> FilteredEntityView { // ... FilteredEntityView-specific methods, separated by &self/&mut self as needed // fn as_readonly(&self) -> Self; } #[derive(Clone, Copy)] pub struct FilteredEntityRef<'w>(FilteredEntityView<'w>); impl<'w> Deref for FilteredEntityRef<'w> { type Target = FilteredEntityView<'w> // ... } pub struct FilteredEntityMut<'w>(FilteredEntityView<'w>); impl<'w> Deref for FilteredEntityMut<'w> { type Target = FilteredEntityView<'w> // ... } impl<'w> DerefMut for FilteredEntityMut<'w>{ // ... } ``` The Filtered and Except variants follow he same schema. ```rust #[derive(Clone, Copy)] pub struct EntityViewExcept<'w, B>(UnsafeEntityCell<'w>, PhantomData<B>); // if desired style-wise, they can be in separate impl blocks impl<'w> EntityViewExcept { // ... EntityViewExcept-specific methods, separated by &self/&mut self as needed } #[derive(Clone, Copy)] pub struct EntityRefExcept<'w, B>(EntityViewExcept<'w, B>); impl<'w> Deref for EntityRefExcept<'w> { type Target = EntityViewExcept<'w> // ... } pub struct EntityMutExcept<'w, B>(EntityViewExcept<'w, B>); impl<'w> Deref for EntityMutExcept<'w> { type Target = EntityViewExcept<'w> // ... } impl<'w> DerefMut for EntityMutExcept<'w>{ // ... } ``` While all of the above conceptually share functionality, a pair of traits is provided to abstract over it. While the underlying implementations all use `UnsafeEntityCell`, we don't want to expose a deref/trait impl to it from the various views, since correctness is no longer guaranteed without abstraction. ```rust pub trait EntityAccess { // shared methods for all the immutable entity pointers in one place! // ... fn reborrow(&mut self) -> Self; fn id(&self) -> Entity; fn location(&self) -> EntityLocation fn archetype(&self) -> &Archetype; fn contains<T: Component>(&self) -> bool; fn contains_id(&self, component_id: ComponentId) -> bool; fn contains_type_id(&self, type_id: TypeId) -> bool; fn get<T: Component>(&self) -> Option<&T>; fn get_components<Q: ReadOnlyQueryData>(&self) -> Option<Q::Item<'_>>; fn into_borrow<T: Component>(self) -> Option<&'w T>; fn get_ref<T>(&self) -> Option<Ref<'_, T>>; fn into_ref<T: Component>(self) -> Option<Ref<'w, T>>; fn get_change_ticks<T: Component>(&self) -> Option<ComponentTicks>; fn get_change_ticks_by_id( &self, component_id: ComponentId, ) -> Option<ComponentTicks>; fn get_by_id<F: DynamicComponentFetch>( &self, component_ids: F, ) -> Result<F::Ref<'_>, EntityComponentError>; fn into_borrow_by_id<F: DynamicComponentFetch>( self, component_ids: F, ) -> Result<F::Ref<'w>, EntityComponentError>; } // Due to the nature of &/&mut `as_readonly` has ceased to exist! pub trait EntityAccessMut: EntityAccess { // shared methods for all the mutable entity pointers in one place! // ... fn get_mut<T: Component>(&mut self) -> Option<Mut<'_, T>>; fn into_mut<T: Component>(self) -> Option<Mut<'w, T>>; fn get_mut_by_id<F: DynamicComponentFetch>( &mut self, component_ids: F, ) -> Result<F::Mut<'_>, EntityComponentError>; unsafe fn get_mut_by_id_unchecked<F: DynamicComponentFetch>( &self, component_ids: F, ) -> Result<F::Mut<'_>, EntityComponentError>; fn into_mut_by_id<F: DynamicComponentFetch>( self, component_ids: F, ) -> Result<F::Mut<'w>, EntityComponentError>; } // There are a lot of implementation here, but the user only has two unified traits to think about! // Plus, a lot of this ultimately forwards. impl EntityAccess for EntityWorldMut { /* ... */ } impl EntityAccess for &EntityView { /* ... */ } impl EntityAccess for &FilteredEntityView { /* ... */ } impl EntityAccess for EntityRefExcept { /* ... */ } impl EntityAccess for &EntityView { /* ... */ } impl EntityAccess for &FilteredEntityView { /* ... */ } impl EntityAccess for &EntityViewExcept { /* ... */ } // This impl just forwards all methods to &T impl<'a, T> EntityAccess for &'a mut T where &'a T: EntityAccess { /* ... */ } impl EntityAccessMut for EntityWorldMut { /* ... */ } impl EntityAccessMut for &mut EntityView { /* ... */ } impl EntityAccessMut for &mut FilteredEntityView { /* ... */ } impl EntityAccessMut for &mut EntityViewExcept { /* ... */ } // TODO: Deref ladders dont work for consuming methods, and `Deref<Target: EntityAccess>` is not a nice bound, impl the trrait for the newtypes as well? ```