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}