Update safety comment for bundle removal (#12657)

# Objective

- Tiny PR to clarify that `self.world.bundles.init_info::<T>` must have
been called so that the BundleInfo is present in the World

---------

Co-authored-by: James Liu <contact@jamessliu.com>
This commit is contained in:
Charles Bournhonesque 2024-03-23 18:07:08 -04:00 committed by GitHub
parent 85b488b73d
commit 944fc71eb1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 11 additions and 6 deletions

View File

@ -977,6 +977,8 @@ impl Bundles {
} }
/// Initializes a new [`BundleInfo`] for a statically known type. /// Initializes a new [`BundleInfo`] for a statically known type.
///
/// Also initializes all the components in the bundle.
pub(crate) fn init_info<T: Bundle>( pub(crate) fn init_info<T: Bundle>(
&mut self, &mut self,
components: &mut Components, components: &mut Components,
@ -999,6 +1001,8 @@ impl Bundles {
id id
} }
/// # Safety
/// A `BundleInfo` with the given `BundleId` must have been initialized for this instance of `Bundles`.
pub(crate) unsafe fn get_unchecked(&self, id: BundleId) -> &BundleInfo { pub(crate) unsafe fn get_unchecked(&self, id: BundleId) -> &BundleInfo {
self.bundle_infos.get_unchecked(id.0) self.bundle_infos.get_unchecked(id.0)
} }

View File

@ -1031,22 +1031,25 @@ impl<'w> EntityWorldMut<'w> {
/// Remove the components of `bundle` from `entity`. /// Remove the components of `bundle` from `entity`.
/// ///
/// SAFETY: The components in `bundle_info` must exist. /// SAFETY:
/// - A `BundleInfo` with the corresponding `BundleId` must have been initialized.
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
unsafe fn remove_bundle(&mut self, bundle: BundleId) -> EntityLocation { unsafe fn remove_bundle(&mut self, bundle: BundleId) -> EntityLocation {
let entity = self.entity; let entity = self.entity;
let world = &mut self.world; let world = &mut self.world;
let location = self.location; let location = self.location;
// SAFETY: the caller guarantees that the BundleInfo for this id has been initialized.
let bundle_info = world.bundles.get_unchecked(bundle); let bundle_info = world.bundles.get_unchecked(bundle);
// SAFETY: `archetype_id` exists because it is referenced in `location` which is valid // SAFETY: `archetype_id` exists because it is referenced in `location` which is valid
// and components in `bundle_info` must exist due to this functions safety invariants. // and components in `bundle_info` must exist due to this function's safety invariants.
let new_archetype_id = remove_bundle_from_archetype( let new_archetype_id = remove_bundle_from_archetype(
&mut world.archetypes, &mut world.archetypes,
&mut world.storages, &mut world.storages,
&world.components, &world.components,
location.archetype_id, location.archetype_id,
bundle_info, bundle_info,
// components from the bundle that are not present on the entity are ignored
true, true,
) )
.expect("intersections should always return a result"); .expect("intersections should always return a result");
@ -1117,8 +1120,7 @@ impl<'w> EntityWorldMut<'w> {
let components = &mut self.world.components; let components = &mut self.world.components;
let bundle_info = self.world.bundles.init_info::<T>(components, storages); let bundle_info = self.world.bundles.init_info::<T>(components, storages);
// SAFETY: Components exist in `bundle_info` because `Bundles::init_info` // SAFETY: the `BundleInfo` is initialized above
// initializes a: EntityLocation `BundleInfo` containing all components of the bundle type `T`.
self.location = unsafe { self.remove_bundle(bundle_info) }; self.location = unsafe { self.remove_bundle(bundle_info) };
self self
@ -1144,8 +1146,7 @@ impl<'w> EntityWorldMut<'w> {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let remove_bundle = self.world.bundles.init_dynamic_info(components, to_remove); let remove_bundle = self.world.bundles.init_dynamic_info(components, to_remove);
// SAFETY: Components exist in `remove_bundle` because `Bundles::init_dynamic_info` // SAFETY: the `BundleInfo` for the components to remove is initialized above
// initializes a `BundleInfo` containing all components in the to_remove Bundle.
self.location = unsafe { self.remove_bundle(remove_bundle) }; self.location = unsafe { self.remove_bundle(remove_bundle) };
self self
} }