bevy_ecs/world/
unsafe_world_cell.rs

1//! Contains types that allow disjoint mutable access to a [`World`].
2
3use super::{Mut, Ref, World, WorldId};
4use crate::{
5    archetype::{Archetype, Archetypes},
6    bundle::Bundles,
7    change_detection::{MaybeLocation, MutUntyped, Ticks, TicksMut},
8    component::{ComponentId, ComponentTicks, Components, Mutable, StorageType, Tick, TickCells},
9    entity::{ContainsEntity, Entities, Entity, EntityDoesNotExistError, EntityLocation},
10    observer::Observers,
11    prelude::Component,
12    query::{DebugCheckedUnwrap, ReadOnlyQueryData},
13    removal_detection::RemovedComponentEvents,
14    resource::Resource,
15    storage::{ComponentSparseSet, Storages, Table},
16    world::RawCommandQueue,
17};
18use bevy_platform::sync::atomic::Ordering;
19use bevy_ptr::{Ptr, UnsafeCellDeref};
20use core::{any::TypeId, cell::UnsafeCell, fmt::Debug, marker::PhantomData, panic::Location, ptr};
21use thiserror::Error;
22
23/// Variant of the [`World`] where resource and component accesses take `&self`, and the responsibility to avoid
24/// aliasing violations are given to the caller instead of being checked at compile-time by rust's unique XOR shared rule.
25///
26/// ### Rationale
27/// In rust, having a `&mut World` means that there are absolutely no other references to the safe world alive at the same time,
28/// without exceptions. Not even unsafe code can change this.
29///
30/// But there are situations where careful shared mutable access through a type is possible and safe. For this, rust provides the [`UnsafeCell`]
31/// escape hatch, which allows you to get a `*mut T` from a `&UnsafeCell<T>` and around which safe abstractions can be built.
32///
33/// Access to resources and components can be done uniquely using [`World::resource_mut`] and [`World::entity_mut`], and shared using [`World::resource`] and [`World::entity`].
34/// These methods use lifetimes to check at compile time that no aliasing rules are being broken.
35///
36/// This alone is not enough to implement bevy systems where multiple systems can access *disjoint* parts of the world concurrently. For this, bevy stores all values of
37/// resources and components (and [`ComponentTicks`]) in [`UnsafeCell`]s, and carefully validates disjoint access patterns using
38/// APIs like [`System::component_access`](crate::system::System::component_access).
39///
40/// A system then can be executed using [`System::run_unsafe`](crate::system::System::run_unsafe) with a `&World` and use methods with interior mutability to access resource values.
41///
42/// ### Example Usage
43///
44/// [`UnsafeWorldCell`] can be used as a building block for writing APIs that safely allow disjoint access into the world.
45/// In the following example, the world is split into a resource access half and a component access half, where each one can
46/// safely hand out mutable references.
47///
48/// ```
49/// use bevy_ecs::world::World;
50/// use bevy_ecs::change_detection::Mut;
51/// use bevy_ecs::resource::Resource;
52/// use bevy_ecs::world::unsafe_world_cell::UnsafeWorldCell;
53///
54/// // INVARIANT: existence of this struct means that users of it are the only ones being able to access resources in the world
55/// struct OnlyResourceAccessWorld<'w>(UnsafeWorldCell<'w>);
56/// // INVARIANT: existence of this struct means that users of it are the only ones being able to access components in the world
57/// struct OnlyComponentAccessWorld<'w>(UnsafeWorldCell<'w>);
58///
59/// impl<'w> OnlyResourceAccessWorld<'w> {
60///     fn get_resource_mut<T: Resource>(&mut self) -> Option<Mut<'_, T>> {
61///         // SAFETY: resource access is allowed through this UnsafeWorldCell
62///         unsafe { self.0.get_resource_mut::<T>() }
63///     }
64/// }
65/// // impl<'w> OnlyComponentAccessWorld<'w> {
66/// //     ...
67/// // }
68///
69/// // the two `UnsafeWorldCell`s borrow from the `&mut World`, so it cannot be accessed while they are live
70/// fn split_world_access(world: &mut World) -> (OnlyResourceAccessWorld<'_>, OnlyComponentAccessWorld<'_>) {
71///     let unsafe_world_cell = world.as_unsafe_world_cell();
72///     let resource_access = OnlyResourceAccessWorld(unsafe_world_cell);
73///     let component_access = OnlyComponentAccessWorld(unsafe_world_cell);
74///     (resource_access, component_access)
75/// }
76/// ```
77#[derive(Copy, Clone)]
78pub struct UnsafeWorldCell<'w> {
79    ptr: *mut World,
80    #[cfg(debug_assertions)]
81    allows_mutable_access: bool,
82    _marker: PhantomData<(&'w World, &'w UnsafeCell<World>)>,
83}
84
85// SAFETY: `&World` and `&mut World` are both `Send`
86unsafe impl Send for UnsafeWorldCell<'_> {}
87// SAFETY: `&World` and `&mut World` are both `Sync`
88unsafe impl Sync for UnsafeWorldCell<'_> {}
89
90impl<'w> From<&'w mut World> for UnsafeWorldCell<'w> {
91    fn from(value: &'w mut World) -> Self {
92        value.as_unsafe_world_cell()
93    }
94}
95
96impl<'w> From<&'w World> for UnsafeWorldCell<'w> {
97    fn from(value: &'w World) -> Self {
98        value.as_unsafe_world_cell_readonly()
99    }
100}
101
102impl<'w> UnsafeWorldCell<'w> {
103    /// Creates a [`UnsafeWorldCell`] that can be used to access everything immutably
104    #[inline]
105    pub(crate) fn new_readonly(world: &'w World) -> Self {
106        Self {
107            ptr: ptr::from_ref(world).cast_mut(),
108            #[cfg(debug_assertions)]
109            allows_mutable_access: false,
110            _marker: PhantomData,
111        }
112    }
113
114    /// Creates [`UnsafeWorldCell`] that can be used to access everything mutably
115    #[inline]
116    pub(crate) fn new_mutable(world: &'w mut World) -> Self {
117        Self {
118            ptr: ptr::from_mut(world),
119            #[cfg(debug_assertions)]
120            allows_mutable_access: true,
121            _marker: PhantomData,
122        }
123    }
124
125    #[cfg_attr(debug_assertions, inline(never), track_caller)]
126    #[cfg_attr(not(debug_assertions), inline(always))]
127    pub(crate) fn assert_allows_mutable_access(self) {
128        // This annotation is needed because the
129        // allows_mutable_access field doesn't exist otherwise.
130        // Kinda weird, since debug_assert would never be called,
131        // but CI complained in https://github.com/bevyengine/bevy/pull/17393
132        #[cfg(debug_assertions)]
133        debug_assert!(
134            self.allows_mutable_access,
135            "mutating world data via `World::as_unsafe_world_cell_readonly` is forbidden"
136        );
137    }
138
139    /// Gets a mutable reference to the [`World`] this [`UnsafeWorldCell`] belongs to.
140    /// This is an incredibly error-prone operation and is only valid in a small number of circumstances.
141    ///
142    /// Calling this method implies mutable access to the *whole* world (see first point on safety section
143    /// below), which includes all entities, components, and resources. Notably, calling this on
144    /// [`WorldQuery::init_fetch`](crate::query::WorldQuery::init_fetch) and
145    /// [`SystemParam::get_param`](crate::system::SystemParam::get_param) are most likely *unsound* unless
146    /// you can prove that the underlying [`World`] is exclusive, which in normal circumstances is not.
147    ///
148    /// # Safety
149    /// - `self` must have been obtained from a call to [`World::as_unsafe_world_cell`]
150    ///   (*not* `as_unsafe_world_cell_readonly` or any other method of construction that
151    ///   does not provide mutable access to the entire world).
152    ///   - This means that if you have an `UnsafeWorldCell` that you didn't create yourself,
153    ///     it is likely *unsound* to call this method.
154    /// - The returned `&mut World` *must* be unique: it must never be allowed to exist
155    ///   at the same time as any other borrows of the world or any accesses to its data.
156    ///   This includes safe ways of accessing world data, such as [`UnsafeWorldCell::archetypes`].
157    ///   - Note that the `&mut World` *may* exist at the same time as instances of `UnsafeWorldCell`,
158    ///     so long as none of those instances are used to access world data in any way
159    ///     while the mutable borrow is active.
160    ///
161    /// [//]: # (This test fails miri.)
162    /// ```no_run
163    /// # use bevy_ecs::prelude::*;
164    /// # #[derive(Component)] struct Player;
165    /// # fn store_but_dont_use<T>(_: T) {}
166    /// # let mut world = World::new();
167    /// // Make an UnsafeWorldCell.
168    /// let world_cell = world.as_unsafe_world_cell();
169    ///
170    /// // SAFETY: `world_cell` was originally created from `&mut World`.
171    /// // We must be sure not to access any world data while `world_mut` is active.
172    /// let world_mut = unsafe { world_cell.world_mut() };
173    ///
174    /// // We can still use `world_cell` so long as we don't access the world with it.
175    /// store_but_dont_use(world_cell);
176    ///
177    /// // !!This is unsound!! Even though this method is safe, we cannot call it until
178    /// // `world_mut` is no longer active.
179    /// let tick = world_cell.change_tick();
180    ///
181    /// // Use mutable access to spawn an entity.
182    /// world_mut.spawn(Player);
183    ///
184    /// // Since we never use `world_mut` after this, the borrow is released
185    /// // and we are once again allowed to access the world using `world_cell`.
186    /// let archetypes = world_cell.archetypes();
187    /// ```
188    #[inline]
189    pub unsafe fn world_mut(self) -> &'w mut World {
190        self.assert_allows_mutable_access();
191        // SAFETY:
192        // - caller ensures the created `&mut World` is the only borrow of world
193        unsafe { &mut *self.ptr }
194    }
195
196    /// Gets a reference to the [`&World`](World) this [`UnsafeWorldCell`] belongs to.
197    /// This can be used for arbitrary shared/readonly access.
198    ///
199    /// # Safety
200    /// - must have permission to access the whole world immutably
201    /// - there must be no live exclusive borrows on world data
202    /// - there must be no live exclusive borrow of world
203    #[inline]
204    pub unsafe fn world(self) -> &'w World {
205        // SAFETY:
206        // - caller ensures there is no `&mut World` this makes it okay to make a `&World`
207        // - caller ensures there is no mutable borrows of world data, this means the caller cannot
208        //   misuse the returned `&World`
209        unsafe { self.unsafe_world() }
210    }
211
212    /// Gets a reference to the [`World`] this [`UnsafeWorldCell`] belong to.
213    /// This can be used for arbitrary read only access of world metadata
214    ///
215    /// You should attempt to use various safe methods on [`UnsafeWorldCell`] for
216    /// metadata access before using this method.
217    ///
218    /// # Safety
219    /// - must only be used to access world metadata
220    #[inline]
221    pub unsafe fn world_metadata(self) -> &'w World {
222        // SAFETY: caller ensures that returned reference is not used to violate aliasing rules
223        unsafe { self.unsafe_world() }
224    }
225
226    /// Variant on [`UnsafeWorldCell::world`] solely used for implementing this type's methods.
227    /// It allows having an `&World` even with live mutable borrows of components and resources
228    /// so the returned `&World` should not be handed out to safe code and care should be taken
229    /// when working with it.
230    ///
231    /// Deliberately private as the correct way to access data in a [`World`] that may have existing
232    /// mutable borrows of data inside it, is to use [`UnsafeWorldCell`].
233    ///
234    /// # Safety
235    /// - must not be used in a way that would conflict with any
236    ///   live exclusive borrows on world data
237    #[inline]
238    unsafe fn unsafe_world(self) -> &'w World {
239        // SAFETY:
240        // - caller ensures that the returned `&World` is not used in a way that would conflict
241        //   with any existing mutable borrows of world data
242        unsafe { &*self.ptr }
243    }
244
245    /// Retrieves this world's unique [ID](WorldId).
246    #[inline]
247    pub fn id(self) -> WorldId {
248        // SAFETY:
249        // - we only access world metadata
250        unsafe { self.world_metadata() }.id()
251    }
252
253    /// Retrieves this world's [`Entities`] collection.
254    #[inline]
255    pub fn entities(self) -> &'w Entities {
256        // SAFETY:
257        // - we only access world metadata
258        &unsafe { self.world_metadata() }.entities
259    }
260
261    /// Retrieves this world's [`Archetypes`] collection.
262    #[inline]
263    pub fn archetypes(self) -> &'w Archetypes {
264        // SAFETY:
265        // - we only access world metadata
266        &unsafe { self.world_metadata() }.archetypes
267    }
268
269    /// Retrieves this world's [`Components`] collection.
270    #[inline]
271    pub fn components(self) -> &'w Components {
272        // SAFETY:
273        // - we only access world metadata
274        &unsafe { self.world_metadata() }.components
275    }
276
277    /// Retrieves this world's collection of [removed components](RemovedComponentEvents).
278    pub fn removed_components(self) -> &'w RemovedComponentEvents {
279        // SAFETY:
280        // - we only access world metadata
281        &unsafe { self.world_metadata() }.removed_components
282    }
283
284    /// Retrieves this world's [`Observers`] collection.
285    pub(crate) fn observers(self) -> &'w Observers {
286        // SAFETY:
287        // - we only access world metadata
288        &unsafe { self.world_metadata() }.observers
289    }
290
291    /// Retrieves this world's [`Bundles`] collection.
292    #[inline]
293    pub fn bundles(self) -> &'w Bundles {
294        // SAFETY:
295        // - we only access world metadata
296        &unsafe { self.world_metadata() }.bundles
297    }
298
299    /// Gets the current change tick of this world.
300    #[inline]
301    pub fn change_tick(self) -> Tick {
302        // SAFETY:
303        // - we only access world metadata
304        unsafe { self.world_metadata() }.read_change_tick()
305    }
306
307    /// Returns the id of the last ECS event that was fired.
308    /// Used internally to ensure observers don't trigger multiple times for the same event.
309    #[inline]
310    pub fn last_trigger_id(&self) -> u32 {
311        // SAFETY:
312        // - we only access world metadata
313        unsafe { self.world_metadata() }.last_trigger_id()
314    }
315
316    /// Returns the [`Tick`] indicating the last time that [`World::clear_trackers`] was called.
317    ///
318    /// If this `UnsafeWorldCell` was created from inside of an exclusive system (a [`System`] that
319    /// takes `&mut World` as its first parameter), this will instead return the `Tick` indicating
320    /// the last time the system was run.
321    ///
322    /// See [`World::last_change_tick()`].
323    ///
324    /// [`System`]: crate::system::System
325    #[inline]
326    pub fn last_change_tick(self) -> Tick {
327        // SAFETY:
328        // - we only access world metadata
329        unsafe { self.world_metadata() }.last_change_tick()
330    }
331
332    /// Increments the world's current change tick and returns the old value.
333    #[inline]
334    pub fn increment_change_tick(self) -> Tick {
335        // SAFETY:
336        // - we only access world metadata
337        let change_tick = unsafe { &self.world_metadata().change_tick };
338        // NOTE: We can used a relaxed memory ordering here, since nothing
339        // other than the atomic value itself is relying on atomic synchronization
340        Tick::new(change_tick.fetch_add(1, Ordering::Relaxed))
341    }
342
343    /// Provides unchecked access to the internal data stores of the [`World`].
344    ///
345    /// # Safety
346    ///
347    /// The caller must ensure that this is only used to access world data
348    /// that this [`UnsafeWorldCell`] is allowed to.
349    /// As always, any mutable access to a component must not exist at the same
350    /// time as any other accesses to that same component.
351    #[inline]
352    pub unsafe fn storages(self) -> &'w Storages {
353        // SAFETY: The caller promises to only access world data allowed by this instance.
354        &unsafe { self.unsafe_world() }.storages
355    }
356
357    /// Retrieves an [`UnsafeEntityCell`] that exposes read and write operations for the given `entity`.
358    /// Similar to the [`UnsafeWorldCell`], you are in charge of making sure that no aliasing rules are violated.
359    #[inline]
360    pub fn get_entity(
361        self,
362        entity: Entity,
363    ) -> Result<UnsafeEntityCell<'w>, EntityDoesNotExistError> {
364        let location = self
365            .entities()
366            .get(entity)
367            .ok_or(EntityDoesNotExistError::new(entity, self.entities()))?;
368        Ok(UnsafeEntityCell::new(self, entity, location))
369    }
370
371    /// Gets a reference to the resource of the given type if it exists
372    ///
373    /// # Safety
374    /// It is the callers responsibility to ensure that
375    /// - the [`UnsafeWorldCell`] has permission to access the resource
376    /// - no mutable reference to the resource exists at the same time
377    #[inline]
378    pub unsafe fn get_resource<R: Resource>(self) -> Option<&'w R> {
379        let component_id = self.components().get_resource_id(TypeId::of::<R>())?;
380        // SAFETY: caller ensures `self` has permission to access the resource
381        //  caller also ensure that no mutable reference to the resource exists
382        unsafe {
383            self.get_resource_by_id(component_id)
384                // SAFETY: `component_id` was obtained from the type ID of `R`.
385                .map(|ptr| ptr.deref::<R>())
386        }
387    }
388
389    /// Gets a reference including change detection to the resource of the given type if it exists.
390    ///
391    /// # Safety
392    /// It is the callers responsibility to ensure that
393    /// - the [`UnsafeWorldCell`] has permission to access the resource
394    /// - no mutable reference to the resource exists at the same time
395    #[inline]
396    pub unsafe fn get_resource_ref<R: Resource>(self) -> Option<Ref<'w, R>> {
397        let component_id = self.components().get_resource_id(TypeId::of::<R>())?;
398
399        // SAFETY: caller ensures `self` has permission to access the resource
400        // caller also ensure that no mutable reference to the resource exists
401        let (ptr, ticks, caller) = unsafe { self.get_resource_with_ticks(component_id)? };
402
403        // SAFETY: `component_id` was obtained from the type ID of `R`
404        let value = unsafe { ptr.deref::<R>() };
405
406        // SAFETY: caller ensures that no mutable reference to the resource exists
407        let ticks =
408            unsafe { Ticks::from_tick_cells(ticks, self.last_change_tick(), self.change_tick()) };
409
410        // SAFETY: caller ensures that no mutable reference to the resource exists
411        let caller = caller.map(|caller| unsafe { caller.deref() });
412
413        Some(Ref {
414            value,
415            ticks,
416            changed_by: caller,
417        })
418    }
419
420    /// Gets a pointer to the resource with the id [`ComponentId`] if it exists.
421    /// The returned pointer must not be used to modify the resource, and must not be
422    /// dereferenced after the borrow of the [`World`] ends.
423    ///
424    /// **You should prefer to use the typed API [`UnsafeWorldCell::get_resource`] where possible and only
425    /// use this in cases where the actual types are not known at compile time.**
426    ///
427    /// # Safety
428    /// It is the callers responsibility to ensure that
429    /// - the [`UnsafeWorldCell`] has permission to access the resource
430    /// - no mutable reference to the resource exists at the same time
431    #[inline]
432    pub unsafe fn get_resource_by_id(self, component_id: ComponentId) -> Option<Ptr<'w>> {
433        // SAFETY: caller ensures that `self` has permission to access `R`
434        //  caller ensures that no mutable reference exists to `R`
435        unsafe { self.storages() }
436            .resources
437            .get(component_id)?
438            .get_data()
439    }
440
441    /// Gets a reference to the non-send resource of the given type if it exists
442    ///
443    /// # Safety
444    /// It is the callers responsibility to ensure that
445    /// - the [`UnsafeWorldCell`] has permission to access the resource
446    /// - no mutable reference to the resource exists at the same time
447    #[inline]
448    pub unsafe fn get_non_send_resource<R: 'static>(self) -> Option<&'w R> {
449        let component_id = self.components().get_resource_id(TypeId::of::<R>())?;
450        // SAFETY: caller ensures that `self` has permission to access `R`
451        //  caller ensures that no mutable reference exists to `R`
452        unsafe {
453            self.get_non_send_resource_by_id(component_id)
454                // SAFETY: `component_id` was obtained from `TypeId::of::<R>()`
455                .map(|ptr| ptr.deref::<R>())
456        }
457    }
458
459    /// Gets a `!Send` resource to the resource with the id [`ComponentId`] if it exists.
460    /// The returned pointer must not be used to modify the resource, and must not be
461    /// dereferenced after the immutable borrow of the [`World`] ends.
462    ///
463    /// **You should prefer to use the typed API [`UnsafeWorldCell::get_non_send_resource`] where possible and only
464    /// use this in cases where the actual types are not known at compile time.**
465    ///
466    /// # Panics
467    /// This function will panic if it isn't called from the same thread that the resource was inserted from.
468    ///
469    /// # Safety
470    /// It is the callers responsibility to ensure that
471    /// - the [`UnsafeWorldCell`] has permission to access the resource
472    /// - no mutable reference to the resource exists at the same time
473    #[inline]
474    pub unsafe fn get_non_send_resource_by_id(self, component_id: ComponentId) -> Option<Ptr<'w>> {
475        // SAFETY: we only access data on world that the caller has ensured is unaliased and we have
476        //  permission to access.
477        unsafe { self.storages() }
478            .non_send_resources
479            .get(component_id)?
480            .get_data()
481    }
482
483    /// Gets a mutable reference to the resource of the given type if it exists
484    ///
485    /// # Safety
486    /// It is the callers responsibility to ensure that
487    /// - the [`UnsafeWorldCell`] has permission to access the resource mutably
488    /// - no other references to the resource exist at the same time
489    #[inline]
490    pub unsafe fn get_resource_mut<R: Resource>(self) -> Option<Mut<'w, R>> {
491        self.assert_allows_mutable_access();
492        let component_id = self.components().get_resource_id(TypeId::of::<R>())?;
493        // SAFETY:
494        // - caller ensures `self` has permission to access the resource mutably
495        // - caller ensures no other references to the resource exist
496        unsafe {
497            self.get_resource_mut_by_id(component_id)
498                // `component_id` was gotten from `TypeId::of::<R>()`
499                .map(|ptr| ptr.with_type::<R>())
500        }
501    }
502
503    /// Gets a pointer to the resource with the id [`ComponentId`] if it exists.
504    /// The returned pointer may be used to modify the resource, as long as the mutable borrow
505    /// of the [`UnsafeWorldCell`] is still valid.
506    ///
507    /// **You should prefer to use the typed API [`UnsafeWorldCell::get_resource_mut`] where possible and only
508    /// use this in cases where the actual types are not known at compile time.**
509    ///
510    /// # Safety
511    /// It is the callers responsibility to ensure that
512    /// - the [`UnsafeWorldCell`] has permission to access the resource mutably
513    /// - no other references to the resource exist at the same time
514    #[inline]
515    pub unsafe fn get_resource_mut_by_id(
516        self,
517        component_id: ComponentId,
518    ) -> Option<MutUntyped<'w>> {
519        self.assert_allows_mutable_access();
520        // SAFETY: we only access data that the caller has ensured is unaliased and `self`
521        //  has permission to access.
522        let (ptr, ticks, caller) = unsafe { self.storages() }
523            .resources
524            .get(component_id)?
525            .get_with_ticks()?;
526
527        // SAFETY:
528        // - index is in-bounds because the column is initialized and non-empty
529        // - the caller promises that no other reference to the ticks of the same row can exist at the same time
530        let ticks = unsafe {
531            TicksMut::from_tick_cells(ticks, self.last_change_tick(), self.change_tick())
532        };
533
534        Some(MutUntyped {
535            // SAFETY:
536            // - caller ensures that `self` has permission to access the resource
537            // - caller ensures that the resource is unaliased
538            value: unsafe { ptr.assert_unique() },
539            ticks,
540            // SAFETY:
541            // - caller ensures that `self` has permission to access the resource
542            // - caller ensures that the resource is unaliased
543            changed_by: unsafe { caller.map(|caller| caller.deref_mut()) },
544        })
545    }
546
547    /// Gets a mutable reference to the non-send resource of the given type if it exists
548    ///
549    /// # Safety
550    /// It is the callers responsibility to ensure that
551    /// - the [`UnsafeWorldCell`] has permission to access the resource mutably
552    /// - no other references to the resource exist at the same time
553    #[inline]
554    pub unsafe fn get_non_send_resource_mut<R: 'static>(self) -> Option<Mut<'w, R>> {
555        self.assert_allows_mutable_access();
556        let component_id = self.components().get_resource_id(TypeId::of::<R>())?;
557        // SAFETY:
558        // - caller ensures that `self` has permission to access the resource
559        // - caller ensures that the resource is unaliased
560        unsafe {
561            self.get_non_send_resource_mut_by_id(component_id)
562                // SAFETY: `component_id` was gotten by `TypeId::of::<R>()`
563                .map(|ptr| ptr.with_type::<R>())
564        }
565    }
566
567    /// Gets a `!Send` resource to the resource with the id [`ComponentId`] if it exists.
568    /// The returned pointer may be used to modify the resource, as long as the mutable borrow
569    /// of the [`World`] is still valid.
570    ///
571    /// **You should prefer to use the typed API [`UnsafeWorldCell::get_non_send_resource_mut`] where possible and only
572    /// use this in cases where the actual types are not known at compile time.**
573    ///
574    /// # Panics
575    /// This function will panic if it isn't called from the same thread that the resource was inserted from.
576    ///
577    /// # Safety
578    /// It is the callers responsibility to ensure that
579    /// - the [`UnsafeWorldCell`] has permission to access the resource mutably
580    /// - no other references to the resource exist at the same time
581    #[inline]
582    pub unsafe fn get_non_send_resource_mut_by_id(
583        self,
584        component_id: ComponentId,
585    ) -> Option<MutUntyped<'w>> {
586        self.assert_allows_mutable_access();
587        let change_tick = self.change_tick();
588        // SAFETY: we only access data that the caller has ensured is unaliased and `self`
589        //  has permission to access.
590        let (ptr, ticks, caller) = unsafe { self.storages() }
591            .non_send_resources
592            .get(component_id)?
593            .get_with_ticks()?;
594
595        let ticks =
596            // SAFETY: This function has exclusive access to the world so nothing aliases `ticks`.
597            // - index is in-bounds because the column is initialized and non-empty
598            // - no other reference to the ticks of the same row can exist at the same time
599            unsafe { TicksMut::from_tick_cells(ticks, self.last_change_tick(), change_tick) };
600
601        Some(MutUntyped {
602            // SAFETY: This function has exclusive access to the world so nothing aliases `ptr`.
603            value: unsafe { ptr.assert_unique() },
604            ticks,
605            // SAFETY: This function has exclusive access to the world
606            changed_by: unsafe { caller.map(|caller| caller.deref_mut()) },
607        })
608    }
609
610    // Shorthand helper function for getting the data and change ticks for a resource.
611    /// # Safety
612    /// It is the callers responsibility to ensure that
613    /// - the [`UnsafeWorldCell`] has permission to access the resource mutably
614    /// - no mutable references to the resource exist at the same time
615    #[inline]
616    pub(crate) unsafe fn get_resource_with_ticks(
617        self,
618        component_id: ComponentId,
619    ) -> Option<(
620        Ptr<'w>,
621        TickCells<'w>,
622        MaybeLocation<&'w UnsafeCell<&'static Location<'static>>>,
623    )> {
624        // SAFETY:
625        // - caller ensures there is no `&mut World`
626        // - caller ensures there are no mutable borrows of this resource
627        // - caller ensures that we have permission to access this resource
628        unsafe { self.storages() }
629            .resources
630            .get(component_id)?
631            .get_with_ticks()
632    }
633
634    // Shorthand helper function for getting the data and change ticks for a resource.
635    /// # Panics
636    /// This function will panic if it isn't called from the same thread that the resource was inserted from.
637    ///
638    /// # Safety
639    /// It is the callers responsibility to ensure that
640    /// - the [`UnsafeWorldCell`] has permission to access the resource mutably
641    /// - no mutable references to the resource exist at the same time
642    #[inline]
643    pub(crate) unsafe fn get_non_send_with_ticks(
644        self,
645        component_id: ComponentId,
646    ) -> Option<(
647        Ptr<'w>,
648        TickCells<'w>,
649        MaybeLocation<&'w UnsafeCell<&'static Location<'static>>>,
650    )> {
651        // SAFETY:
652        // - caller ensures there is no `&mut World`
653        // - caller ensures there are no mutable borrows of this resource
654        // - caller ensures that we have permission to access this resource
655        unsafe { self.storages() }
656            .non_send_resources
657            .get(component_id)?
658            .get_with_ticks()
659    }
660
661    // Returns a mutable reference to the underlying world's [`CommandQueue`].
662    /// # Safety
663    /// It is the callers responsibility to ensure that
664    /// - the [`UnsafeWorldCell`] has permission to access the queue mutably
665    /// - no mutable references to the queue exist at the same time
666    pub(crate) unsafe fn get_raw_command_queue(self) -> RawCommandQueue {
667        self.assert_allows_mutable_access();
668        // SAFETY:
669        // - caller ensures there are no existing mutable references
670        // - caller ensures that we have permission to access the queue
671        unsafe { (*self.ptr).command_queue.clone() }
672    }
673
674    /// # Safety
675    /// It is the callers responsibility to ensure that there are no outstanding
676    /// references to `last_trigger_id`.
677    pub(crate) unsafe fn increment_trigger_id(self) {
678        self.assert_allows_mutable_access();
679        // SAFETY: Caller ensure there are no outstanding references
680        unsafe {
681            (*self.ptr).last_trigger_id = (*self.ptr).last_trigger_id.wrapping_add(1);
682        }
683    }
684}
685
686impl Debug for UnsafeWorldCell<'_> {
687    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
688        // SAFETY: World's Debug implementation only accesses metadata.
689        Debug::fmt(unsafe { self.world_metadata() }, f)
690    }
691}
692
693/// A interior-mutable reference to a particular [`Entity`] and all of its components
694#[derive(Copy, Clone)]
695pub struct UnsafeEntityCell<'w> {
696    world: UnsafeWorldCell<'w>,
697    entity: Entity,
698    location: EntityLocation,
699}
700
701impl<'w> UnsafeEntityCell<'w> {
702    #[inline]
703    pub(crate) fn new(
704        world: UnsafeWorldCell<'w>,
705        entity: Entity,
706        location: EntityLocation,
707    ) -> Self {
708        UnsafeEntityCell {
709            world,
710            entity,
711            location,
712        }
713    }
714
715    /// Returns the [ID](Entity) of the current entity.
716    #[inline]
717    #[must_use = "Omit the .id() call if you do not need to store the `Entity` identifier."]
718    pub fn id(self) -> Entity {
719        self.entity
720    }
721
722    /// Gets metadata indicating the location where the current entity is stored.
723    #[inline]
724    pub fn location(self) -> EntityLocation {
725        self.location
726    }
727
728    /// Returns the archetype that the current entity belongs to.
729    #[inline]
730    pub fn archetype(self) -> &'w Archetype {
731        &self.world.archetypes()[self.location.archetype_id]
732    }
733
734    /// Gets the world that the current entity belongs to.
735    #[inline]
736    pub fn world(self) -> UnsafeWorldCell<'w> {
737        self.world
738    }
739
740    /// Returns `true` if the current entity has a component of type `T`.
741    /// Otherwise, this returns `false`.
742    ///
743    /// ## Notes
744    ///
745    /// If you do not know the concrete type of a component, consider using
746    /// [`Self::contains_id`] or [`Self::contains_type_id`].
747    #[inline]
748    pub fn contains<T: Component>(self) -> bool {
749        self.contains_type_id(TypeId::of::<T>())
750    }
751
752    /// Returns `true` if the current entity has a component identified by `component_id`.
753    /// Otherwise, this returns false.
754    ///
755    /// ## Notes
756    ///
757    /// - If you know the concrete type of the component, you should prefer [`Self::contains`].
758    /// - If you know the component's [`TypeId`] but not its [`ComponentId`], consider using
759    ///   [`Self::contains_type_id`].
760    #[inline]
761    pub fn contains_id(self, component_id: ComponentId) -> bool {
762        self.archetype().contains(component_id)
763    }
764
765    /// Returns `true` if the current entity has a component with the type identified by `type_id`.
766    /// Otherwise, this returns false.
767    ///
768    /// ## Notes
769    ///
770    /// - If you know the concrete type of the component, you should prefer [`Self::contains`].
771    /// - If you have a [`ComponentId`] instead of a [`TypeId`], consider using [`Self::contains_id`].
772    #[inline]
773    pub fn contains_type_id(self, type_id: TypeId) -> bool {
774        let Some(id) = self.world.components().get_id(type_id) else {
775            return false;
776        };
777        self.contains_id(id)
778    }
779
780    /// # Safety
781    /// It is the callers responsibility to ensure that
782    /// - the [`UnsafeEntityCell`] has permission to access the component
783    /// - no other mutable references to the component exist at the same time
784    #[inline]
785    pub unsafe fn get<T: Component>(self) -> Option<&'w T> {
786        let component_id = self.world.components().get_id(TypeId::of::<T>())?;
787        // SAFETY:
788        // - `storage_type` is correct (T component_id + T::STORAGE_TYPE)
789        // - `location` is valid
790        // - proper aliasing is promised by caller
791        unsafe {
792            get_component(
793                self.world,
794                component_id,
795                T::STORAGE_TYPE,
796                self.entity,
797                self.location,
798            )
799            // SAFETY: returned component is of type T
800            .map(|value| value.deref::<T>())
801        }
802    }
803
804    /// # Safety
805    /// It is the callers responsibility to ensure that
806    /// - the [`UnsafeEntityCell`] has permission to access the component
807    /// - no other mutable references to the component exist at the same time
808    #[inline]
809    pub unsafe fn get_ref<T: Component>(self) -> Option<Ref<'w, T>> {
810        let last_change_tick = self.world.last_change_tick();
811        let change_tick = self.world.change_tick();
812        let component_id = self.world.components().get_id(TypeId::of::<T>())?;
813
814        // SAFETY:
815        // - `storage_type` is correct (T component_id + T::STORAGE_TYPE)
816        // - `location` is valid
817        // - proper aliasing is promised by caller
818        unsafe {
819            get_component_and_ticks(
820                self.world,
821                component_id,
822                T::STORAGE_TYPE,
823                self.entity,
824                self.location,
825            )
826            .map(|(value, cells, caller)| Ref {
827                // SAFETY: returned component is of type T
828                value: value.deref::<T>(),
829                ticks: Ticks::from_tick_cells(cells, last_change_tick, change_tick),
830                changed_by: caller.map(|caller| caller.deref()),
831            })
832        }
833    }
834
835    /// Retrieves the change ticks for the given component. This can be useful for implementing change
836    /// detection in custom runtimes.
837    ///
838    /// # Safety
839    /// It is the callers responsibility to ensure that
840    /// - the [`UnsafeEntityCell`] has permission to access the component
841    /// - no other mutable references to the component exist at the same time
842    #[inline]
843    pub unsafe fn get_change_ticks<T: Component>(self) -> Option<ComponentTicks> {
844        let component_id = self.world.components().get_id(TypeId::of::<T>())?;
845
846        // SAFETY:
847        // - entity location is valid
848        // - proper world access is promised by caller
849        unsafe {
850            get_ticks(
851                self.world,
852                component_id,
853                T::STORAGE_TYPE,
854                self.entity,
855                self.location,
856            )
857        }
858    }
859
860    /// Retrieves the change ticks for the given [`ComponentId`]. This can be useful for implementing change
861    /// detection in custom runtimes.
862    ///
863    /// **You should prefer to use the typed API [`UnsafeEntityCell::get_change_ticks`] where possible and only
864    /// use this in cases where the actual component types are not known at
865    /// compile time.**
866    ///
867    /// # Safety
868    /// It is the callers responsibility to ensure that
869    /// - the [`UnsafeEntityCell`] has permission to access the component
870    /// - no other mutable references to the component exist at the same time
871    #[inline]
872    pub unsafe fn get_change_ticks_by_id(
873        &self,
874        component_id: ComponentId,
875    ) -> Option<ComponentTicks> {
876        let info = self.world.components().get_info(component_id)?;
877        // SAFETY:
878        // - entity location and entity is valid
879        // - world access is immutable, lifetime tied to `&self`
880        // - the storage type provided is correct for T
881        unsafe {
882            get_ticks(
883                self.world,
884                component_id,
885                info.storage_type(),
886                self.entity,
887                self.location,
888            )
889        }
890    }
891
892    /// # Safety
893    /// It is the callers responsibility to ensure that
894    /// - the [`UnsafeEntityCell`] has permission to access the component mutably
895    /// - no other references to the component exist at the same time
896    #[inline]
897    pub unsafe fn get_mut<T: Component<Mutability = Mutable>>(self) -> Option<Mut<'w, T>> {
898        // SAFETY:
899        // - trait bound `T: Component<Mutability = Mutable>` ensures component is mutable
900        // - same safety requirements
901        unsafe { self.get_mut_assume_mutable() }
902    }
903
904    /// # Safety
905    /// It is the callers responsibility to ensure that
906    /// - the [`UnsafeEntityCell`] has permission to access the component mutably
907    /// - no other references to the component exist at the same time
908    /// - the component `T` is mutable
909    #[inline]
910    pub unsafe fn get_mut_assume_mutable<T: Component>(self) -> Option<Mut<'w, T>> {
911        // SAFETY: same safety requirements
912        unsafe {
913            self.get_mut_using_ticks_assume_mutable(
914                self.world.last_change_tick(),
915                self.world.change_tick(),
916            )
917        }
918    }
919
920    /// # Safety
921    /// It is the callers responsibility to ensure that
922    /// - the [`UnsafeEntityCell`] has permission to access the component mutably
923    /// - no other references to the component exist at the same time
924    /// - The component `T` is mutable
925    #[inline]
926    pub(crate) unsafe fn get_mut_using_ticks_assume_mutable<T: Component>(
927        &self,
928        last_change_tick: Tick,
929        change_tick: Tick,
930    ) -> Option<Mut<'w, T>> {
931        self.world.assert_allows_mutable_access();
932
933        let component_id = self.world.components().get_id(TypeId::of::<T>())?;
934
935        // SAFETY:
936        // - `storage_type` is correct
937        // - `location` is valid
938        // - aliasing rules are ensured by caller
939        unsafe {
940            get_component_and_ticks(
941                self.world,
942                component_id,
943                T::STORAGE_TYPE,
944                self.entity,
945                self.location,
946            )
947            .map(|(value, cells, caller)| Mut {
948                // SAFETY: returned component is of type T
949                value: value.assert_unique().deref_mut::<T>(),
950                ticks: TicksMut::from_tick_cells(cells, last_change_tick, change_tick),
951                changed_by: caller.map(|caller| caller.deref_mut()),
952            })
953        }
954    }
955
956    /// Returns read-only components for the current entity that match the query `Q`,
957    /// or `None` if the entity does not have the components required by the query `Q`.
958    ///
959    /// # Safety
960    /// It is the callers responsibility to ensure that
961    /// - the [`UnsafeEntityCell`] has permission to access the queried data immutably
962    /// - no mutable references to the queried data exist at the same time
963    pub(crate) unsafe fn get_components<Q: ReadOnlyQueryData>(&self) -> Option<Q::Item<'w>> {
964        // SAFETY: World is only used to access query data and initialize query state
965        let state = unsafe {
966            let world = self.world().world();
967            Q::get_state(world.components())?
968        };
969        let location = self.location();
970        // SAFETY: Location is guaranteed to exist
971        let archetype = unsafe {
972            self.world
973                .archetypes()
974                .get(location.archetype_id)
975                .debug_checked_unwrap()
976        };
977        if Q::matches_component_set(&state, &|id| archetype.contains(id)) {
978            // SAFETY: state was initialized above using the world passed into this function
979            let mut fetch = unsafe {
980                Q::init_fetch(
981                    self.world,
982                    &state,
983                    self.world.last_change_tick(),
984                    self.world.change_tick(),
985                )
986            };
987            // SAFETY: Table is guaranteed to exist
988            let table = unsafe {
989                self.world
990                    .storages()
991                    .tables
992                    .get(location.table_id)
993                    .debug_checked_unwrap()
994            };
995            // SAFETY: Archetype and table are from the same world used to initialize state and fetch.
996            // Table corresponds to archetype. State is the same state used to init fetch above.
997            unsafe { Q::set_archetype(&mut fetch, &state, archetype, table) }
998            // SAFETY: Called after set_archetype above. Entity and location are guaranteed to exist.
999            unsafe { Some(Q::fetch(&mut fetch, self.id(), location.table_row)) }
1000        } else {
1001            None
1002        }
1003    }
1004
1005    /// Gets the component of the given [`ComponentId`] from the entity.
1006    ///
1007    /// **You should prefer to use the typed API where possible and only
1008    /// use this in cases where the actual component types are not known at
1009    /// compile time.**
1010    ///
1011    /// Unlike [`UnsafeEntityCell::get`], this returns a raw pointer to the component,
1012    /// which is only valid while the `'w` borrow of the lifetime is active.
1013    ///
1014    /// # Safety
1015    /// It is the callers responsibility to ensure that
1016    /// - the [`UnsafeEntityCell`] has permission to access the component
1017    /// - no other mutable references to the component exist at the same time
1018    #[inline]
1019    pub unsafe fn get_by_id(self, component_id: ComponentId) -> Option<Ptr<'w>> {
1020        let info = self.world.components().get_info(component_id)?;
1021        // SAFETY: entity_location is valid, component_id is valid as checked by the line above
1022        unsafe {
1023            get_component(
1024                self.world,
1025                component_id,
1026                info.storage_type(),
1027                self.entity,
1028                self.location,
1029            )
1030        }
1031    }
1032
1033    /// Retrieves a mutable untyped reference to the given `entity`'s [`Component`] of the given [`ComponentId`].
1034    /// Returns `None` if the `entity` does not have a [`Component`] of the given type.
1035    ///
1036    /// **You should prefer to use the typed API [`UnsafeEntityCell::get_mut`] where possible and only
1037    /// use this in cases where the actual types are not known at compile time.**
1038    ///
1039    /// # Safety
1040    /// It is the callers responsibility to ensure that
1041    /// - the [`UnsafeEntityCell`] has permission to access the component mutably
1042    /// - no other references to the component exist at the same time
1043    #[inline]
1044    pub unsafe fn get_mut_by_id(
1045        self,
1046        component_id: ComponentId,
1047    ) -> Result<MutUntyped<'w>, GetEntityMutByIdError> {
1048        self.world.assert_allows_mutable_access();
1049
1050        let info = self
1051            .world
1052            .components()
1053            .get_info(component_id)
1054            .ok_or(GetEntityMutByIdError::InfoNotFound)?;
1055
1056        // If a component is immutable then a mutable reference to it doesn't exist
1057        if !info.mutable() {
1058            return Err(GetEntityMutByIdError::ComponentIsImmutable);
1059        }
1060
1061        // SAFETY: entity_location is valid, component_id is valid as checked by the line above
1062        unsafe {
1063            get_component_and_ticks(
1064                self.world,
1065                component_id,
1066                info.storage_type(),
1067                self.entity,
1068                self.location,
1069            )
1070            .map(|(value, cells, caller)| MutUntyped {
1071                // SAFETY: world access validated by caller and ties world lifetime to `MutUntyped` lifetime
1072                value: value.assert_unique(),
1073                ticks: TicksMut::from_tick_cells(
1074                    cells,
1075                    self.world.last_change_tick(),
1076                    self.world.change_tick(),
1077                ),
1078                changed_by: caller.map(|caller| caller.deref_mut()),
1079            })
1080            .ok_or(GetEntityMutByIdError::ComponentNotFound)
1081        }
1082    }
1083
1084    /// Retrieves a mutable untyped reference to the given `entity`'s [`Component`] of the given [`ComponentId`].
1085    /// Returns `None` if the `entity` does not have a [`Component`] of the given type.
1086    /// This method assumes the [`Component`] is mutable, skipping that check.
1087    ///
1088    /// **You should prefer to use the typed API [`UnsafeEntityCell::get_mut_assume_mutable`] where possible and only
1089    /// use this in cases where the actual types are not known at compile time.**
1090    ///
1091    /// # Safety
1092    /// It is the callers responsibility to ensure that
1093    /// - the [`UnsafeEntityCell`] has permission to access the component mutably
1094    /// - no other references to the component exist at the same time
1095    /// - the component `T` is mutable
1096    #[inline]
1097    pub unsafe fn get_mut_assume_mutable_by_id(
1098        self,
1099        component_id: ComponentId,
1100    ) -> Result<MutUntyped<'w>, GetEntityMutByIdError> {
1101        self.world.assert_allows_mutable_access();
1102
1103        let info = self
1104            .world
1105            .components()
1106            .get_info(component_id)
1107            .ok_or(GetEntityMutByIdError::InfoNotFound)?;
1108
1109        // SAFETY: entity_location is valid, component_id is valid as checked by the line above
1110        unsafe {
1111            get_component_and_ticks(
1112                self.world,
1113                component_id,
1114                info.storage_type(),
1115                self.entity,
1116                self.location,
1117            )
1118            .map(|(value, cells, caller)| MutUntyped {
1119                // SAFETY: world access validated by caller and ties world lifetime to `MutUntyped` lifetime
1120                value: value.assert_unique(),
1121                ticks: TicksMut::from_tick_cells(
1122                    cells,
1123                    self.world.last_change_tick(),
1124                    self.world.change_tick(),
1125                ),
1126                changed_by: caller.map(|caller| caller.deref_mut()),
1127            })
1128            .ok_or(GetEntityMutByIdError::ComponentNotFound)
1129        }
1130    }
1131
1132    /// Returns the source code location from which this entity has been spawned.
1133    pub fn spawned_by(self) -> MaybeLocation {
1134        self.world()
1135            .entities()
1136            .entity_get_spawned_or_despawned_by(self.entity)
1137            .map(|o| o.unwrap())
1138    }
1139}
1140
1141/// Error that may be returned when calling [`UnsafeEntityCell::get_mut_by_id`].
1142#[derive(Debug, Clone, Copy, PartialEq, Eq, Error)]
1143pub enum GetEntityMutByIdError {
1144    /// The [`ComponentInfo`](crate::component::ComponentInfo) could not be found.
1145    #[error("the `ComponentInfo` could not be found")]
1146    InfoNotFound,
1147    /// The [`Component`] is immutable. Creating a mutable reference violates its
1148    /// invariants.
1149    #[error("the `Component` is immutable")]
1150    ComponentIsImmutable,
1151    /// This [`Entity`] does not have the desired [`Component`].
1152    #[error("the `Component` could not be found")]
1153    ComponentNotFound,
1154}
1155
1156impl<'w> UnsafeWorldCell<'w> {
1157    #[inline]
1158    /// # Safety
1159    /// - the returned `Table` is only used in ways that this [`UnsafeWorldCell`] has permission for.
1160    /// - the returned `Table` is only used in ways that would not conflict with any existing borrows of world data.
1161    unsafe fn fetch_table(self, location: EntityLocation) -> Option<&'w Table> {
1162        // SAFETY:
1163        // - caller ensures returned data is not misused and we have not created any borrows of component/resource data
1164        // - `location` contains a valid `TableId`, so getting the table won't fail
1165        unsafe { self.storages().tables.get(location.table_id) }
1166    }
1167
1168    #[inline]
1169    /// # Safety
1170    /// - the returned `ComponentSparseSet` is only used in ways that this [`UnsafeWorldCell`] has permission for.
1171    /// - the returned `ComponentSparseSet` is only used in ways that would not conflict with any existing
1172    ///   borrows of world data.
1173    unsafe fn fetch_sparse_set(self, component_id: ComponentId) -> Option<&'w ComponentSparseSet> {
1174        // SAFETY: caller ensures returned data is not misused and we have not created any borrows
1175        // of component/resource data
1176        unsafe { self.storages() }.sparse_sets.get(component_id)
1177    }
1178}
1179
1180/// Get an untyped pointer to a particular [`Component`] on a particular [`Entity`] in the provided [`World`].
1181///
1182/// # Safety
1183/// - `location` must refer to an archetype that contains `entity`
1184///   the archetype
1185/// - `component_id` must be valid
1186/// - `storage_type` must accurately reflect where the components for `component_id` are stored.
1187/// - the caller must ensure that no aliasing rules are violated
1188#[inline]
1189unsafe fn get_component(
1190    world: UnsafeWorldCell<'_>,
1191    component_id: ComponentId,
1192    storage_type: StorageType,
1193    entity: Entity,
1194    location: EntityLocation,
1195) -> Option<Ptr<'_>> {
1196    // SAFETY: component_id exists and is therefore valid
1197    match storage_type {
1198        StorageType::Table => {
1199            let table = world.fetch_table(location)?;
1200            // SAFETY: archetypes only store valid table_rows and caller ensure aliasing rules
1201            table.get_component(component_id, location.table_row)
1202        }
1203        StorageType::SparseSet => world.fetch_sparse_set(component_id)?.get(entity),
1204    }
1205}
1206
1207/// Get an untyped pointer to a particular [`Component`] and its [`ComponentTicks`]
1208///
1209/// # Safety
1210/// - `location` must refer to an archetype that contains `entity`
1211/// - `component_id` must be valid
1212/// - `storage_type` must accurately reflect where the components for `component_id` are stored.
1213/// - the caller must ensure that no aliasing rules are violated
1214#[inline]
1215unsafe fn get_component_and_ticks(
1216    world: UnsafeWorldCell<'_>,
1217    component_id: ComponentId,
1218    storage_type: StorageType,
1219    entity: Entity,
1220    location: EntityLocation,
1221) -> Option<(
1222    Ptr<'_>,
1223    TickCells<'_>,
1224    MaybeLocation<&UnsafeCell<&'static Location<'static>>>,
1225)> {
1226    match storage_type {
1227        StorageType::Table => {
1228            let table = world.fetch_table(location)?;
1229
1230            // SAFETY: archetypes only store valid table_rows and caller ensure aliasing rules
1231            Some((
1232                table.get_component(component_id, location.table_row)?,
1233                TickCells {
1234                    added: table
1235                        .get_added_tick(component_id, location.table_row)
1236                        .debug_checked_unwrap(),
1237                    changed: table
1238                        .get_changed_tick(component_id, location.table_row)
1239                        .debug_checked_unwrap(),
1240                },
1241                table
1242                    .get_changed_by(component_id, location.table_row)
1243                    .map(|changed_by| changed_by.debug_checked_unwrap()),
1244            ))
1245        }
1246        StorageType::SparseSet => world.fetch_sparse_set(component_id)?.get_with_ticks(entity),
1247    }
1248}
1249
1250/// Get an untyped pointer to the [`ComponentTicks`] on a particular [`Entity`]
1251///
1252/// # Safety
1253/// - `location` must refer to an archetype that contains `entity`
1254///   the archetype
1255/// - `component_id` must be valid
1256/// - `storage_type` must accurately reflect where the components for `component_id` are stored.
1257/// - the caller must ensure that no aliasing rules are violated
1258#[inline]
1259unsafe fn get_ticks(
1260    world: UnsafeWorldCell<'_>,
1261    component_id: ComponentId,
1262    storage_type: StorageType,
1263    entity: Entity,
1264    location: EntityLocation,
1265) -> Option<ComponentTicks> {
1266    match storage_type {
1267        StorageType::Table => {
1268            let table = world.fetch_table(location)?;
1269            // SAFETY: archetypes only store valid table_rows and caller ensure aliasing rules
1270            table.get_ticks_unchecked(component_id, location.table_row)
1271        }
1272        StorageType::SparseSet => world.fetch_sparse_set(component_id)?.get_ticks(entity),
1273    }
1274}
1275
1276impl ContainsEntity for UnsafeEntityCell<'_> {
1277    fn entity(&self) -> Entity {
1278        self.id()
1279    }
1280}
1281
1282#[cfg(test)]
1283mod tests {
1284    use super::*;
1285
1286    #[test]
1287    #[should_panic = "is forbidden"]
1288    fn as_unsafe_world_cell_readonly_world_mut_forbidden() {
1289        let world = World::new();
1290        let world_cell = world.as_unsafe_world_cell_readonly();
1291        // SAFETY: this invalid usage will be caught by a runtime panic.
1292        let _ = unsafe { world_cell.world_mut() };
1293    }
1294
1295    #[derive(Resource)]
1296    struct R;
1297
1298    #[test]
1299    #[should_panic = "is forbidden"]
1300    fn as_unsafe_world_cell_readonly_resource_mut_forbidden() {
1301        let mut world = World::new();
1302        world.insert_resource(R);
1303        let world_cell = world.as_unsafe_world_cell_readonly();
1304        // SAFETY: this invalid usage will be caught by a runtime panic.
1305        let _ = unsafe { world_cell.get_resource_mut::<R>() };
1306    }
1307
1308    #[derive(Component)]
1309    struct C;
1310
1311    #[test]
1312    #[should_panic = "is forbidden"]
1313    fn as_unsafe_world_cell_readonly_component_mut_forbidden() {
1314        let mut world = World::new();
1315        let entity = world.spawn(C).id();
1316        let world_cell = world.as_unsafe_world_cell_readonly();
1317        let entity_cell = world_cell.get_entity(entity).unwrap();
1318        // SAFETY: this invalid usage will be caught by a runtime panic.
1319        let _ = unsafe { entity_cell.get_mut::<C>() };
1320    }
1321}