From 2e3e0e304d573571603f87ee5f15028f07084f6d Mon Sep 17 00:00:00 2001 From: Mike Hsu Date: Fri, 19 Dec 2025 14:45:41 -0800 Subject: [PATCH 1/2] nonnull pointer deref safety --- crates/bevy_ecs/src/bundle/insert.rs | 31 +++++++-- crates/bevy_ecs/src/bundle/remove.rs | 98 ++++++++++++++++++++------- crates/bevy_ecs/src/bundle/spawner.rs | 20 ++++-- 3 files changed, 114 insertions(+), 35 deletions(-) diff --git a/crates/bevy_ecs/src/bundle/insert.rs b/crates/bevy_ecs/src/bundle/insert.rs index 116480694913b..cd9bffa3226f7 100644 --- a/crates/bevy_ecs/src/bundle/insert.rs +++ b/crates/bevy_ecs/src/bundle/insert.rs @@ -166,6 +166,10 @@ impl<'w> BundleInserter<'w> { let mut deferred_world = world.into_deferred(); if insert_mode == InsertMode::Replace { + // SAFETY: + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` let archetype = archetype.as_ref(); if archetype.has_replace_observer() { // SAFETY: the REPLACE event_key corresponds to the Replace event's type @@ -188,11 +192,19 @@ impl<'w> BundleInserter<'w> { } } - let table = table.as_mut(); + // SAFETY: + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` + let table = unsafe { table.as_mut() }; - // SAFETY: Archetype gets borrowed when running the on_replace observers above, + // SAFETY: + // * Archetype gets borrowed when running the on_replace observers above, // so this reference can only be promoted from shared to &mut down here, after they have been ran - let archetype = archetype.as_mut(); + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` + let archetype = unsafe { archetype.as_mut() }; match archetype_move_type { ArchetypeMoveType::SameArchetype => { @@ -343,7 +355,11 @@ impl<'w> BundleInserter<'w> { caller: MaybeLocation, relationship_hook_mode: RelationshipHookMode, ) -> EntityLocation { - let archetype_after_insert = self.archetype_after_insert.as_ref(); + // SAFETY: + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` + let archetype_after_insert = unsafe { self.archetype_after_insert.as_ref() }; let (new_archetype, new_location) = { // Non-generic prelude extracted to improve compile time by minimizing monomorphized code. @@ -360,7 +376,12 @@ impl<'w> BundleInserter<'w> { &mut self.archetype_move_type, ); - self.bundle_info.as_ref().write_components( + // SAFETY: + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` + let bundle_info = unsafe { self.bundle_info.as_ref() }; + bundle_info.write_components( table, sparse_sets, archetype_after_insert, diff --git a/crates/bevy_ecs/src/bundle/remove.rs b/crates/bevy_ecs/src/bundle/remove.rs index 5063abaf36ce9..54119597de0a4 100644 --- a/crates/bevy_ecs/src/bundle/remove.rs +++ b/crates/bevy_ecs/src/bundle/remove.rs @@ -142,11 +142,20 @@ impl<'w> BundleRemover<'w> { // SAFETY: We only keep access to archetype/bundle data. let mut deferred_world = self.world.into_deferred(); let bundle_components_in_archetype = || { - self.bundle_info - .as_ref() + // SAFETY: + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` + let (bundle_info, old_archetype) = + (self.bundle_info.as_ref(), self.old_archetype.as_ref()); + bundle_info .iter_explicit_components() - .filter(|component_id| self.old_archetype.as_ref().contains(*component_id)) + .filter(|component_id| old_archetype.contains(*component_id)) }; + // SAFETY: + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` if self.old_archetype.as_ref().has_replace_observer() { let components = bundle_components_in_archetype().collect::>(); // SAFETY: the REPLACE event_key corresponds to the Replace event's type @@ -160,12 +169,20 @@ impl<'w> BundleRemover<'w> { ); } deferred_world.trigger_on_replace( + // SAFETY: + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` self.old_archetype.as_ref(), entity, bundle_components_in_archetype(), caller, self.relationship_hook_mode, ); + // SAFETY: + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` if self.old_archetype.as_ref().has_remove_observer() { let components = bundle_components_in_archetype().collect::>(); // SAFETY: the REMOVE event_key corresponds to the Remove event's type @@ -179,6 +196,10 @@ impl<'w> BundleRemover<'w> { ); } deferred_world.trigger_on_remove( + // SAFETY: + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` self.old_archetype.as_ref(), entity, bundle_components_in_archetype(), @@ -196,18 +217,34 @@ impl<'w> BundleRemover<'w> { // SAFETY: There is no conflicting access for this scope. .map(|(old, _)| unsafe { &mut *old.as_ptr() }), &world.components, - self.bundle_info.as_ref().explicit_components(), + // SAFETY: + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` + unsafe { self.bundle_info.as_ref() }.explicit_components(), ); // Handle sparse set removes - for component_id in self.bundle_info.as_ref().iter_explicit_components() { - if self.old_archetype.as_ref().contains(component_id) { + // SAFETY: + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` + for component_id in unsafe { self.bundle_info.as_ref() }.iter_explicit_components() { + // SAFETY: + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` + if unsafe { self.old_archetype.as_ref() }.contains(component_id) { world.removed_components.write(component_id, entity); // Make sure to drop components stored in sparse sets. // Dense components are dropped later in `move_to_and_drop_missing_unchecked`. if let Some(StorageType::SparseSet) = - self.old_archetype.as_ref().get_storage_type(component_id) + // SAFETY: + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` + unsafe { self.old_archetype.as_ref() }.get_storage_type(component_id) { world .storages @@ -222,10 +259,12 @@ impl<'w> BundleRemover<'w> { } // Handle archetype change - let remove_result = self - .old_archetype - .as_mut() - .swap_remove(location.archetype_row); + let remove_result = + // SAFETY: + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` + unsafe { self.old_archetype.as_mut() }.swap_remove(location.archetype_row); // if an entity was moved into this entity's archetype row, update its archetype row if let Some(swapped_entity) = remove_result.swapped_entity { let swapped_location = world.entities.get_spawned(swapped_entity).unwrap(); @@ -244,28 +283,36 @@ impl<'w> BundleRemover<'w> { // Handle table change let new_location = if let Some((mut old_table, mut new_table)) = self.old_and_new_table { let move_result = if needs_drop { + // SAFETY: + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` + let old_table = unsafe { old_table.as_mut() }; + // SAFETY: old_table_row exists unsafe { old_table - .as_mut() .move_to_and_drop_missing_unchecked(location.table_row, new_table.as_mut()) } } else { + // SAFETY: + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` + let (old_table, new_table) = unsafe { (old_table.as_mut(), new_table.as_mut()) }; // SAFETY: old_table_row exists unsafe { - old_table.as_mut().move_to_and_forget_missing_unchecked( - location.table_row, - new_table.as_mut(), - ) + old_table.move_to_and_forget_missing_unchecked(location.table_row, new_table) } }; + // SAFETY: + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` + let new_archetype = unsafe { self.new_archetype.as_mut() }; // SAFETY: move_result.new_row is a valid position in new_archetype's table - let new_location = unsafe { - self.new_archetype - .as_mut() - .allocate(entity, move_result.new_row) - }; + let new_location = unsafe { new_archetype.allocate(entity, move_result.new_row) }; // if an entity was moved into this entity's table row, update its table row if let Some(swapped_entity) = move_result.swapped_entity { @@ -286,10 +333,13 @@ impl<'w> BundleRemover<'w> { new_location } else { + // SAFETY: + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` + let new_archetype = unsafe { self.new_archetype.as_mut() }; // The tables are the same - self.new_archetype - .as_mut() - .allocate(entity, location.table_row) + new_archetype.allocate(entity, location.table_row) }; // SAFETY: The entity is valid and has been moved to the new location already. diff --git a/crates/bevy_ecs/src/bundle/spawner.rs b/crates/bevy_ecs/src/bundle/spawner.rs index b471d8735fd39..c9050e77bd8fd 100644 --- a/crates/bevy_ecs/src/bundle/spawner.rs +++ b/crates/bevy_ecs/src/bundle/spawner.rs @@ -94,11 +94,17 @@ impl<'w> BundleSpawner<'w> { bundle: MovingPtr<'_, T>, caller: MaybeLocation, ) -> EntityLocation { - // SAFETY: We do not make any structural changes to the archetype graph through self.world so these pointers always remain valid - let bundle_info = self.bundle_info.as_ref(); + // SAFETY: + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` + let bundle_info = unsafe { self.bundle_info.as_ref() }; let location = { - let table = self.table.as_mut(); - let archetype = self.archetype.as_mut(); + // SAFETY: + // * Pointers are dereferencable because they were created from a reference in `Self::new_with_id`. + // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural + // changes to the world, so the data is valid for the lifetime of `Self` + let (table, archetype) = unsafe { (self.table.as_mut(), self.archetype.as_mut()) }; // SAFETY: Mutable references do not alias and will be dropped after this block let (sparse_sets, entities) = { @@ -126,8 +132,10 @@ impl<'w> BundleSpawner<'w> { // SAFETY: We have no outstanding mutable references to world as they were dropped let mut deferred_world = unsafe { self.world.into_deferred() }; - // SAFETY: `DeferredWorld` cannot provide mutable access to `Archetypes`. - let archetype = self.archetype.as_ref(); + // SAFETY: + // * Dereferencable because it was created from an exclusive reference in `Self::new_with_id`. + // * `DeferredWorld` does not provide mutable access to `Archetypes`, so it is safe to hold a reference to an archetype. + let archetype = unsafe { self.archetype.as_ref() }; // SAFETY: All components in the bundle are guaranteed to exist in the World // as they must be initialized before creating the BundleInfo. unsafe { From 435ab24724c066d66e75d481d5c25e1fb2444dfd Mon Sep 17 00:00:00 2001 From: Mike Hsu Date: Fri, 19 Dec 2025 17:15:11 -0800 Subject: [PATCH 2/2] spell the weird word correctly --- crates/bevy_ecs/src/bundle/insert.rs | 10 +++++----- crates/bevy_ecs/src/bundle/remove.rs | 28 +++++++++++++-------------- crates/bevy_ecs/src/bundle/spawner.rs | 6 +++--- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/crates/bevy_ecs/src/bundle/insert.rs b/crates/bevy_ecs/src/bundle/insert.rs index cd9bffa3226f7..b15e959c265b2 100644 --- a/crates/bevy_ecs/src/bundle/insert.rs +++ b/crates/bevy_ecs/src/bundle/insert.rs @@ -167,7 +167,7 @@ impl<'w> BundleInserter<'w> { if insert_mode == InsertMode::Replace { // SAFETY: - // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferenceable`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` let archetype = archetype.as_ref(); @@ -193,7 +193,7 @@ impl<'w> BundleInserter<'w> { } // SAFETY: - // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferenceable`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` let table = unsafe { table.as_mut() }; @@ -201,7 +201,7 @@ impl<'w> BundleInserter<'w> { // SAFETY: // * Archetype gets borrowed when running the on_replace observers above, // so this reference can only be promoted from shared to &mut down here, after they have been ran - // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferenceable`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` let archetype = unsafe { archetype.as_mut() }; @@ -356,7 +356,7 @@ impl<'w> BundleInserter<'w> { relationship_hook_mode: RelationshipHookMode, ) -> EntityLocation { // SAFETY: - // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferenceable`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` let archetype_after_insert = unsafe { self.archetype_after_insert.as_ref() }; @@ -377,7 +377,7 @@ impl<'w> BundleInserter<'w> { ); // SAFETY: - // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferenceable`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` let bundle_info = unsafe { self.bundle_info.as_ref() }; diff --git a/crates/bevy_ecs/src/bundle/remove.rs b/crates/bevy_ecs/src/bundle/remove.rs index 54119597de0a4..58af57541f03b 100644 --- a/crates/bevy_ecs/src/bundle/remove.rs +++ b/crates/bevy_ecs/src/bundle/remove.rs @@ -143,7 +143,7 @@ impl<'w> BundleRemover<'w> { let mut deferred_world = self.world.into_deferred(); let bundle_components_in_archetype = || { // SAFETY: - // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferenceable`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` let (bundle_info, old_archetype) = @@ -153,7 +153,7 @@ impl<'w> BundleRemover<'w> { .filter(|component_id| old_archetype.contains(*component_id)) }; // SAFETY: - // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferenceable`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` if self.old_archetype.as_ref().has_replace_observer() { @@ -170,7 +170,7 @@ impl<'w> BundleRemover<'w> { } deferred_world.trigger_on_replace( // SAFETY: - // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferenceable`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` self.old_archetype.as_ref(), @@ -180,7 +180,7 @@ impl<'w> BundleRemover<'w> { self.relationship_hook_mode, ); // SAFETY: - // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferenceable`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` if self.old_archetype.as_ref().has_remove_observer() { @@ -197,7 +197,7 @@ impl<'w> BundleRemover<'w> { } deferred_world.trigger_on_remove( // SAFETY: - // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferenceable`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` self.old_archetype.as_ref(), @@ -218,7 +218,7 @@ impl<'w> BundleRemover<'w> { .map(|(old, _)| unsafe { &mut *old.as_ptr() }), &world.components, // SAFETY: - // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferenceable`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` unsafe { self.bundle_info.as_ref() }.explicit_components(), @@ -226,12 +226,12 @@ impl<'w> BundleRemover<'w> { // Handle sparse set removes // SAFETY: - // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferenceable`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` for component_id in unsafe { self.bundle_info.as_ref() }.iter_explicit_components() { // SAFETY: - // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferenceable`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` if unsafe { self.old_archetype.as_ref() }.contains(component_id) { @@ -241,7 +241,7 @@ impl<'w> BundleRemover<'w> { // Dense components are dropped later in `move_to_and_drop_missing_unchecked`. if let Some(StorageType::SparseSet) = // SAFETY: - // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferenceable`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` unsafe { self.old_archetype.as_ref() }.get_storage_type(component_id) @@ -261,7 +261,7 @@ impl<'w> BundleRemover<'w> { // Handle archetype change let remove_result = // SAFETY: - // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferenceable`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` unsafe { self.old_archetype.as_mut() }.swap_remove(location.archetype_row); @@ -284,7 +284,7 @@ impl<'w> BundleRemover<'w> { let new_location = if let Some((mut old_table, mut new_table)) = self.old_and_new_table { let move_result = if needs_drop { // SAFETY: - // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferenceable`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` let old_table = unsafe { old_table.as_mut() }; @@ -296,7 +296,7 @@ impl<'w> BundleRemover<'w> { } } else { // SAFETY: - // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferenceable`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` let (old_table, new_table) = unsafe { (old_table.as_mut(), new_table.as_mut()) }; @@ -307,7 +307,7 @@ impl<'w> BundleRemover<'w> { }; // SAFETY: - // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferenceable`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` let new_archetype = unsafe { self.new_archetype.as_mut() }; @@ -334,7 +334,7 @@ impl<'w> BundleRemover<'w> { new_location } else { // SAFETY: - // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferenceable`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` let new_archetype = unsafe { self.new_archetype.as_mut() }; diff --git a/crates/bevy_ecs/src/bundle/spawner.rs b/crates/bevy_ecs/src/bundle/spawner.rs index c9050e77bd8fd..730dbf869a3f2 100644 --- a/crates/bevy_ecs/src/bundle/spawner.rs +++ b/crates/bevy_ecs/src/bundle/spawner.rs @@ -95,13 +95,13 @@ impl<'w> BundleSpawner<'w> { caller: MaybeLocation, ) -> EntityLocation { // SAFETY: - // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferencable`. + // * Pointer was created from a reference in `Self::new_with_id` and so is `dereferenceable`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` let bundle_info = unsafe { self.bundle_info.as_ref() }; let location = { // SAFETY: - // * Pointers are dereferencable because they were created from a reference in `Self::new_with_id`. + // * Pointers are dereferenceable because they were created from a reference in `Self::new_with_id`. // * `Self`'s lifetime is tied to an exclusive reference to `World` and it does not make structural // changes to the world, so the data is valid for the lifetime of `Self` let (table, archetype) = unsafe { (self.table.as_mut(), self.archetype.as_mut()) }; @@ -133,7 +133,7 @@ impl<'w> BundleSpawner<'w> { // SAFETY: We have no outstanding mutable references to world as they were dropped let mut deferred_world = unsafe { self.world.into_deferred() }; // SAFETY: - // * Dereferencable because it was created from an exclusive reference in `Self::new_with_id`. + // * dereferenceable because it was created from an exclusive reference in `Self::new_with_id`. // * `DeferredWorld` does not provide mutable access to `Archetypes`, so it is safe to hold a reference to an archetype. let archetype = unsafe { self.archetype.as_ref() }; // SAFETY: All components in the bundle are guaranteed to exist in the World