From dc2befe9af091e8a58773ea7ebc11d9848bde133 Mon Sep 17 00:00:00 2001 From: Giacomo Stevanato Date: Wed, 9 Jul 2025 18:09:50 +0200 Subject: [PATCH] Extract required components related items from components --- crates/bevy_ecs/src/component/mod.rs | 535 +-------------------- crates/bevy_ecs/src/component/required.rs | 536 ++++++++++++++++++++++ 2 files changed, 542 insertions(+), 529 deletions(-) create mode 100644 crates/bevy_ecs/src/component/required.rs diff --git a/crates/bevy_ecs/src/component/mod.rs b/crates/bevy_ecs/src/component/mod.rs index e643894196..c61feb2455 100644 --- a/crates/bevy_ecs/src/component/mod.rs +++ b/crates/bevy_ecs/src/component/mod.rs @@ -2,31 +2,27 @@ mod clone; mod queued_registration; +mod required; mod tick; pub use clone::*; pub use queued_registration::*; +pub use required::*; pub use tick::*; use crate::{ archetype::ArchetypeFlags, - bundle::BundleInfo, - change_detection::MaybeLocation, - entity::{Entity, EntityMapper}, + entity::EntityMapper, lifecycle::{ComponentHook, ComponentHooks}, query::DebugCheckedUnwrap, resource::Resource, - storage::{SparseSetIndex, SparseSets, Table, TableRow}, + storage::SparseSetIndex, system::{Local, SystemParam}, world::{FromWorld, World}, }; -use alloc::{borrow::Cow, format, vec::Vec}; +use alloc::{borrow::Cow, vec::Vec}; pub use bevy_ecs_macros::Component; -use bevy_platform::sync::Arc; -use bevy_platform::{ - collections::{HashMap, HashSet}, - sync::PoisonError, -}; +use bevy_platform::{collections::HashSet, sync::PoisonError}; use bevy_ptr::OwningPtr; #[cfg(feature = "bevy_reflect")] use bevy_reflect::Reflect; @@ -39,8 +35,6 @@ use core::{ mem::needs_drop, ops::{Deref, DerefMut}, }; -use smallvec::SmallVec; -use thiserror::Error; /// A data type that can be used to store data for an [entity]. /// @@ -1304,48 +1298,6 @@ impl<'w> ComponentsRegistrator<'w> { id } - // NOTE: This should maybe be private, but it is currently public so that `bevy_ecs_macros` can use it. - // We can't directly move this there either, because this uses `Components::get_required_by_mut`, - // which is private, and could be equally risky to expose to users. - /// Registers the given component `R` and [required components] inherited from it as required by `T`, - /// and adds `T` to their lists of requirees. - /// - /// The given `inheritance_depth` determines how many levels of inheritance deep the requirement is. - /// A direct requirement has a depth of `0`, and each level of inheritance increases the depth by `1`. - /// Lower depths are more specific requirements, and can override existing less specific registrations. - /// - /// The `recursion_check_stack` allows checking whether this component tried to register itself as its - /// own (indirect) required component. - /// - /// This method does *not* register any components as required by components that require `T`. - /// - /// Only use this method if you know what you are doing. In most cases, you should instead use [`World::register_required_components`], - /// or the equivalent method in `bevy_app::App`. - /// - /// [required component]: Component#required-components - #[doc(hidden)] - pub fn register_required_components_manual( - &mut self, - required_components: &mut RequiredComponents, - constructor: fn() -> R, - inheritance_depth: u16, - recursion_check_stack: &mut Vec, - ) { - let requiree = self.register_component_checked::(recursion_check_stack); - let required = self.register_component_checked::(recursion_check_stack); - - // SAFETY: We just created the components. - unsafe { - self.register_required_components_manual_unchecked::( - requiree, - required, - required_components, - constructor, - inheritance_depth, - ); - } - } - /// Registers a [`Resource`] of type `T` with this instance. /// If a resource of this type has already been registered, this will return /// the ID of the pre-existing resource. @@ -1613,210 +1565,6 @@ impl Components { .and_then(|info| info.as_mut().map(|info| &mut info.required_components)) } - /// Registers the given component `R` and [required components] inherited from it as required by `T`. - /// - /// When `T` is added to an entity, `R` will also be added if it was not already provided. - /// The given `constructor` will be used for the creation of `R`. - /// - /// [required components]: Component#required-components - /// - /// # Safety - /// - /// The given component IDs `required` and `requiree` must be valid. - /// - /// # Errors - /// - /// Returns a [`RequiredComponentsError`] if the `required` component is already a directly required component for the `requiree`. - /// - /// Indirect requirements through other components are allowed. In those cases, the more specific - /// registration will be used. - pub(crate) unsafe fn register_required_components( - &mut self, - requiree: ComponentId, - required: ComponentId, - constructor: fn() -> R, - ) -> Result<(), RequiredComponentsError> { - // SAFETY: The caller ensures that the `requiree` is valid. - let required_components = unsafe { - self.get_required_components_mut(requiree) - .debug_checked_unwrap() - }; - - // Cannot directly require the same component twice. - if required_components - .0 - .get(&required) - .is_some_and(|c| c.inheritance_depth == 0) - { - return Err(RequiredComponentsError::DuplicateRegistration( - requiree, required, - )); - } - - // Register the required component for the requiree. - // This is a direct requirement with a depth of `0`. - required_components.register_by_id(required, constructor, 0); - - // Add the requiree to the list of components that require the required component. - // SAFETY: The component is in the list of required components, so it must exist already. - let required_by = unsafe { self.get_required_by_mut(required).debug_checked_unwrap() }; - required_by.insert(requiree); - - let mut required_components_tmp = RequiredComponents::default(); - // SAFETY: The caller ensures that the `requiree` and `required` components are valid. - let inherited_requirements = unsafe { - self.register_inherited_required_components( - requiree, - required, - &mut required_components_tmp, - ) - }; - - // SAFETY: The caller ensures that the `requiree` is valid. - let required_components = unsafe { - self.get_required_components_mut(requiree) - .debug_checked_unwrap() - }; - required_components.0.extend(required_components_tmp.0); - - // Propagate the new required components up the chain to all components that require the requiree. - if let Some(required_by) = self - .get_required_by(requiree) - .map(|set| set.iter().copied().collect::>()) - { - // `required` is now required by anything that `requiree` was required by. - self.get_required_by_mut(required) - .unwrap() - .extend(required_by.iter().copied()); - for &required_by_id in required_by.iter() { - // SAFETY: The component is in the list of required components, so it must exist already. - let required_components = unsafe { - self.get_required_components_mut(required_by_id) - .debug_checked_unwrap() - }; - - // Register the original required component in the "parent" of the requiree. - // The inheritance depth is 1 deeper than the `requiree` wrt `required_by_id`. - let depth = required_components.0.get(&requiree).expect("requiree is required by required_by_id, so its required_components must include requiree").inheritance_depth; - required_components.register_by_id(required, constructor, depth + 1); - - for (component_id, component) in inherited_requirements.iter() { - // Register the required component. - // The inheritance depth of inherited components is whatever the requiree's - // depth is relative to `required_by_id`, plus the inheritance depth of the - // inherited component relative to the requiree, plus 1 to account for the - // requiree in between. - // SAFETY: Component ID and constructor match the ones on the original requiree. - // The original requiree is responsible for making sure the registration is safe. - unsafe { - required_components.register_dynamic_with( - *component_id, - component.inheritance_depth + depth + 1, - || component.constructor.clone(), - ); - }; - } - } - } - - Ok(()) - } - - /// Registers the components inherited from `required` for the given `requiree`, - /// returning the requirements in a list. - /// - /// # Safety - /// - /// The given component IDs `requiree` and `required` must be valid. - unsafe fn register_inherited_required_components( - &mut self, - requiree: ComponentId, - required: ComponentId, - required_components: &mut RequiredComponents, - ) -> Vec<(ComponentId, RequiredComponent)> { - // Get required components inherited from the `required` component. - // SAFETY: The caller ensures that the `required` component is valid. - let required_component_info = unsafe { self.get_info(required).debug_checked_unwrap() }; - let inherited_requirements: Vec<(ComponentId, RequiredComponent)> = required_component_info - .required_components() - .0 - .iter() - .map(|(component_id, required_component)| { - ( - *component_id, - RequiredComponent { - constructor: required_component.constructor.clone(), - // Add `1` to the inheritance depth since this will be registered - // for the component that requires `required`. - inheritance_depth: required_component.inheritance_depth + 1, - }, - ) - }) - .collect(); - - // Register the new required components. - for (component_id, component) in inherited_requirements.iter() { - // Register the required component for the requiree. - // SAFETY: Component ID and constructor match the ones on the original requiree. - unsafe { - required_components.register_dynamic_with( - *component_id, - component.inheritance_depth, - || component.constructor.clone(), - ); - }; - - // Add the requiree to the list of components that require the required component. - // SAFETY: The caller ensures that the required components are valid. - let required_by = unsafe { - self.get_required_by_mut(*component_id) - .debug_checked_unwrap() - }; - required_by.insert(requiree); - } - - inherited_requirements - } - - /// Registers the given component `R` and [required components] inherited from it as required by `T`, - /// and adds `T` to their lists of requirees. - /// - /// The given `inheritance_depth` determines how many levels of inheritance deep the requirement is. - /// A direct requirement has a depth of `0`, and each level of inheritance increases the depth by `1`. - /// Lower depths are more specific requirements, and can override existing less specific registrations. - /// - /// This method does *not* register any components as required by components that require `T`. - /// - /// [required component]: Component#required-components - /// - /// # Safety - /// - /// The given component IDs `required` and `requiree` must be valid. - pub(crate) unsafe fn register_required_components_manual_unchecked( - &mut self, - requiree: ComponentId, - required: ComponentId, - required_components: &mut RequiredComponents, - constructor: fn() -> R, - inheritance_depth: u16, - ) { - // Components cannot require themselves. - if required == requiree { - return; - } - - // Register the required component `R` for the requiree. - required_components.register_by_id(required, constructor, inheritance_depth); - - // Add the requiree to the list of components that require `R`. - // SAFETY: The caller ensures that the component ID is valid. - // Assuming it is valid, the component is in the list of required components, so it must exist already. - let required_by = unsafe { self.get_required_by_mut(required).debug_checked_unwrap() }; - required_by.insert(requiree); - - self.register_inherited_required_components(requiree, required, required_components); - } - #[inline] pub(crate) fn get_required_by(&self, id: ComponentId) -> Option<&HashSet> { self.components @@ -2071,274 +1819,3 @@ impl FromWorld for InitComponentId { } } } - -/// An error returned when the registration of a required component fails. -#[derive(Error, Debug)] -#[non_exhaustive] -pub enum RequiredComponentsError { - /// The component is already a directly required component for the requiree. - #[error("Component {0:?} already directly requires component {1:?}")] - DuplicateRegistration(ComponentId, ComponentId), - /// An archetype with the component that requires other components already exists - #[error("An archetype with the component {0:?} that requires other components already exists")] - ArchetypeExists(ComponentId), -} - -/// A Required Component constructor. See [`Component`] for details. -#[derive(Clone)] -pub struct RequiredComponentConstructor( - pub Arc, -); - -impl RequiredComponentConstructor { - /// # Safety - /// This is intended to only be called in the context of [`BundleInfo::write_components`] to initialized required components. - /// Calling it _anywhere else_ should be considered unsafe. - /// - /// `table_row` and `entity` must correspond to a valid entity that currently needs a component initialized via the constructor stored - /// on this [`RequiredComponentConstructor`]. The stored constructor must correspond to a component on `entity` that needs initialization. - /// `table` and `sparse_sets` must correspond to storages on a world where `entity` needs this required component initialized. - /// - /// Again, don't call this anywhere but [`BundleInfo::write_components`]. - pub(crate) unsafe fn initialize( - &self, - table: &mut Table, - sparse_sets: &mut SparseSets, - change_tick: Tick, - table_row: TableRow, - entity: Entity, - caller: MaybeLocation, - ) { - (self.0)(table, sparse_sets, change_tick, table_row, entity, caller); - } -} - -/// Metadata associated with a required component. See [`Component`] for details. -#[derive(Clone)] -pub struct RequiredComponent { - /// The constructor used for the required component. - pub constructor: RequiredComponentConstructor, - - /// The depth of the component requirement in the requirement hierarchy for this component. - /// This is used for determining which constructor is used in cases where there are duplicate requires. - /// - /// For example, consider the inheritance tree `X -> Y -> Z`, where `->` indicates a requirement. - /// `X -> Y` and `Y -> Z` are direct requirements with a depth of 0, while `Z` is only indirectly - /// required for `X` with a depth of `1`. - /// - /// In cases where there are multiple conflicting requirements with the same depth, a higher priority - /// will be given to components listed earlier in the `require` attribute, or to the latest added requirement - /// if registered at runtime. - pub inheritance_depth: u16, -} - -/// The collection of metadata for components that are required for a given component. -/// -/// For more information, see the "Required Components" section of [`Component`]. -#[derive(Default, Clone)] -pub struct RequiredComponents(pub(crate) HashMap); - -impl Debug for RequiredComponents { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - f.debug_tuple("RequiredComponents") - .field(&self.0.keys()) - .finish() - } -} - -impl RequiredComponents { - /// Registers a required component. - /// - /// If the component is already registered, it will be overwritten if the given inheritance depth - /// is smaller than the depth of the existing registration. Otherwise, the new registration will be ignored. - /// - /// # Safety - /// - /// `component_id` must match the type initialized by `constructor`. - /// `constructor` _must_ initialize a component for `component_id` in such a way that - /// matches the storage type of the component. It must only use the given `table_row` or `Entity` to - /// initialize the storage for `component_id` corresponding to the given entity. - pub unsafe fn register_dynamic_with( - &mut self, - component_id: ComponentId, - inheritance_depth: u16, - constructor: impl FnOnce() -> RequiredComponentConstructor, - ) { - let entry = self.0.entry(component_id); - match entry { - bevy_platform::collections::hash_map::Entry::Occupied(mut occupied) => { - let current = occupied.get_mut(); - if current.inheritance_depth > inheritance_depth { - *current = RequiredComponent { - constructor: constructor(), - inheritance_depth, - } - } - } - bevy_platform::collections::hash_map::Entry::Vacant(vacant) => { - vacant.insert(RequiredComponent { - constructor: constructor(), - inheritance_depth, - }); - } - } - } - - /// Registers a required component. - /// - /// If the component is already registered, it will be overwritten if the given inheritance depth - /// is smaller than the depth of the existing registration. Otherwise, the new registration will be ignored. - pub fn register( - &mut self, - components: &mut ComponentsRegistrator, - constructor: fn() -> C, - inheritance_depth: u16, - ) { - let component_id = components.register_component::(); - self.register_by_id(component_id, constructor, inheritance_depth); - } - - /// Registers the [`Component`] with the given ID as required if it exists. - /// - /// If the component is already registered, it will be overwritten if the given inheritance depth - /// is smaller than the depth of the existing registration. Otherwise, the new registration will be ignored. - pub fn register_by_id( - &mut self, - component_id: ComponentId, - constructor: fn() -> C, - inheritance_depth: u16, - ) { - let erased = || { - RequiredComponentConstructor({ - // `portable-atomic-util` `Arc` is not able to coerce an unsized - // type like `std::sync::Arc` can. Creating a `Box` first does the - // coercion. - // - // This would be resolved by https://github.com/rust-lang/rust/issues/123430 - - #[cfg(not(target_has_atomic = "ptr"))] - use alloc::boxed::Box; - - type Constructor = dyn for<'a, 'b> Fn( - &'a mut Table, - &'b mut SparseSets, - Tick, - TableRow, - Entity, - MaybeLocation, - ); - - #[cfg(not(target_has_atomic = "ptr"))] - type Intermediate = Box; - - #[cfg(target_has_atomic = "ptr")] - type Intermediate = Arc; - - let boxed: Intermediate = Intermediate::new( - move |table, sparse_sets, change_tick, table_row, entity, caller| { - OwningPtr::make(constructor(), |ptr| { - // SAFETY: This will only be called in the context of `BundleInfo::write_components`, which will - // pass in a valid table_row and entity requiring a C constructor - // C::STORAGE_TYPE is the storage type associated with `component_id` / `C` - // `ptr` points to valid `C` data, which matches the type associated with `component_id` - unsafe { - BundleInfo::initialize_required_component( - table, - sparse_sets, - change_tick, - table_row, - entity, - component_id, - C::STORAGE_TYPE, - ptr, - caller, - ); - } - }); - }, - ); - - Arc::from(boxed) - }) - }; - - // SAFETY: - // `component_id` matches the type initialized by the `erased` constructor above. - // `erased` initializes a component for `component_id` in such a way that - // matches the storage type of the component. It only uses the given `table_row` or `Entity` to - // initialize the storage corresponding to the given entity. - unsafe { self.register_dynamic_with(component_id, inheritance_depth, erased) }; - } - - /// Iterates the ids of all required components. This includes recursive required components. - pub fn iter_ids(&self) -> impl Iterator + '_ { - self.0.keys().copied() - } - - /// Removes components that are explicitly provided in a given [`Bundle`]. These components should - /// be logically treated as normal components, not "required components". - /// - /// [`Bundle`]: crate::bundle::Bundle - pub(crate) fn remove_explicit_components(&mut self, components: &[ComponentId]) { - for component in components { - self.0.remove(component); - } - } - - /// Merges `required_components` into this collection. This only inserts a required component - /// if it _did not already exist_ *or* if the required component is more specific than the existing one - /// (in other words, if the inheritance depth is smaller). - /// - /// See [`register_dynamic_with`](Self::register_dynamic_with) for details. - pub(crate) fn merge(&mut self, required_components: &RequiredComponents) { - for ( - component_id, - RequiredComponent { - constructor, - inheritance_depth, - }, - ) in required_components.0.iter() - { - // SAFETY: This exact registration must have been done on `required_components`, so safety is ensured by that caller. - unsafe { - self.register_dynamic_with(*component_id, *inheritance_depth, || { - constructor.clone() - }); - } - } - } -} - -// NOTE: This should maybe be private, but it is currently public so that `bevy_ecs_macros` can use it. -// This exists as a standalone function instead of being inlined into the component derive macro so as -// to reduce the amount of generated code. -#[doc(hidden)] -pub fn enforce_no_required_components_recursion( - components: &Components, - recursion_check_stack: &[ComponentId], -) { - if let Some((&requiree, check)) = recursion_check_stack.split_last() { - if let Some(direct_recursion) = check - .iter() - .position(|&id| id == requiree) - .map(|index| index == check.len() - 1) - { - panic!( - "Recursive required components detected: {}\nhelp: {}", - recursion_check_stack - .iter() - .map(|id| format!("{}", components.get_name(*id).unwrap().shortname())) - .collect::>() - .join(" → "), - if direct_recursion { - format!( - "Remove require({}).", - components.get_name(requiree).unwrap().shortname() - ) - } else { - "If this is intentional, consider merging the components.".into() - } - ); - } - } -} diff --git a/crates/bevy_ecs/src/component/required.rs b/crates/bevy_ecs/src/component/required.rs new file mode 100644 index 0000000000..d46b6b61ce --- /dev/null +++ b/crates/bevy_ecs/src/component/required.rs @@ -0,0 +1,536 @@ +use alloc::{format, vec::Vec}; +use bevy_platform::{collections::HashMap, sync::Arc}; +use bevy_ptr::OwningPtr; +use core::fmt::Debug; +use smallvec::SmallVec; +use thiserror::Error; + +use crate::{ + bundle::BundleInfo, + change_detection::MaybeLocation, + component::{Component, ComponentId, Components, ComponentsRegistrator, Tick}, + entity::Entity, + query::DebugCheckedUnwrap as _, + storage::{SparseSets, Table, TableRow}, +}; + +impl Components { + /// Registers the given component `R` and [required components] inherited from it as required by `T`. + /// + /// When `T` is added to an entity, `R` will also be added if it was not already provided. + /// The given `constructor` will be used for the creation of `R`. + /// + /// [required components]: Component#required-components + /// + /// # Safety + /// + /// The given component IDs `required` and `requiree` must be valid. + /// + /// # Errors + /// + /// Returns a [`RequiredComponentsError`] if the `required` component is already a directly required component for the `requiree`. + /// + /// Indirect requirements through other components are allowed. In those cases, the more specific + /// registration will be used. + pub(crate) unsafe fn register_required_components( + &mut self, + requiree: ComponentId, + required: ComponentId, + constructor: fn() -> R, + ) -> Result<(), RequiredComponentsError> { + // SAFETY: The caller ensures that the `requiree` is valid. + let required_components = unsafe { + self.get_required_components_mut(requiree) + .debug_checked_unwrap() + }; + + // Cannot directly require the same component twice. + if required_components + .0 + .get(&required) + .is_some_and(|c| c.inheritance_depth == 0) + { + return Err(RequiredComponentsError::DuplicateRegistration( + requiree, required, + )); + } + + // Register the required component for the requiree. + // This is a direct requirement with a depth of `0`. + required_components.register_by_id(required, constructor, 0); + + // Add the requiree to the list of components that require the required component. + // SAFETY: The component is in the list of required components, so it must exist already. + let required_by = unsafe { self.get_required_by_mut(required).debug_checked_unwrap() }; + required_by.insert(requiree); + + let mut required_components_tmp = RequiredComponents::default(); + // SAFETY: The caller ensures that the `requiree` and `required` components are valid. + let inherited_requirements = unsafe { + self.register_inherited_required_components( + requiree, + required, + &mut required_components_tmp, + ) + }; + + // SAFETY: The caller ensures that the `requiree` is valid. + let required_components = unsafe { + self.get_required_components_mut(requiree) + .debug_checked_unwrap() + }; + required_components.0.extend(required_components_tmp.0); + + // Propagate the new required components up the chain to all components that require the requiree. + if let Some(required_by) = self + .get_required_by(requiree) + .map(|set| set.iter().copied().collect::>()) + { + // `required` is now required by anything that `requiree` was required by. + self.get_required_by_mut(required) + .unwrap() + .extend(required_by.iter().copied()); + for &required_by_id in required_by.iter() { + // SAFETY: The component is in the list of required components, so it must exist already. + let required_components = unsafe { + self.get_required_components_mut(required_by_id) + .debug_checked_unwrap() + }; + + // Register the original required component in the "parent" of the requiree. + // The inheritance depth is 1 deeper than the `requiree` wrt `required_by_id`. + let depth = required_components.0.get(&requiree).expect("requiree is required by required_by_id, so its required_components must include requiree").inheritance_depth; + required_components.register_by_id(required, constructor, depth + 1); + + for (component_id, component) in inherited_requirements.iter() { + // Register the required component. + // The inheritance depth of inherited components is whatever the requiree's + // depth is relative to `required_by_id`, plus the inheritance depth of the + // inherited component relative to the requiree, plus 1 to account for the + // requiree in between. + // SAFETY: Component ID and constructor match the ones on the original requiree. + // The original requiree is responsible for making sure the registration is safe. + unsafe { + required_components.register_dynamic_with( + *component_id, + component.inheritance_depth + depth + 1, + || component.constructor.clone(), + ); + }; + } + } + } + + Ok(()) + } + + /// Registers the components inherited from `required` for the given `requiree`, + /// returning the requirements in a list. + /// + /// # Safety + /// + /// The given component IDs `requiree` and `required` must be valid. + unsafe fn register_inherited_required_components( + &mut self, + requiree: ComponentId, + required: ComponentId, + required_components: &mut RequiredComponents, + ) -> Vec<(ComponentId, RequiredComponent)> { + // Get required components inherited from the `required` component. + // SAFETY: The caller ensures that the `required` component is valid. + let required_component_info = unsafe { self.get_info(required).debug_checked_unwrap() }; + let inherited_requirements: Vec<(ComponentId, RequiredComponent)> = required_component_info + .required_components() + .0 + .iter() + .map(|(component_id, required_component)| { + ( + *component_id, + RequiredComponent { + constructor: required_component.constructor.clone(), + // Add `1` to the inheritance depth since this will be registered + // for the component that requires `required`. + inheritance_depth: required_component.inheritance_depth + 1, + }, + ) + }) + .collect(); + + // Register the new required components. + for (component_id, component) in inherited_requirements.iter() { + // Register the required component for the requiree. + // SAFETY: Component ID and constructor match the ones on the original requiree. + unsafe { + required_components.register_dynamic_with( + *component_id, + component.inheritance_depth, + || component.constructor.clone(), + ); + }; + + // Add the requiree to the list of components that require the required component. + // SAFETY: The caller ensures that the required components are valid. + let required_by = unsafe { + self.get_required_by_mut(*component_id) + .debug_checked_unwrap() + }; + required_by.insert(requiree); + } + + inherited_requirements + } + + /// Registers the given component `R` and [required components] inherited from it as required by `T`, + /// and adds `T` to their lists of requirees. + /// + /// The given `inheritance_depth` determines how many levels of inheritance deep the requirement is. + /// A direct requirement has a depth of `0`, and each level of inheritance increases the depth by `1`. + /// Lower depths are more specific requirements, and can override existing less specific registrations. + /// + /// This method does *not* register any components as required by components that require `T`. + /// + /// [required component]: Component#required-components + /// + /// # Safety + /// + /// The given component IDs `required` and `requiree` must be valid. + pub(crate) unsafe fn register_required_components_manual_unchecked( + &mut self, + requiree: ComponentId, + required: ComponentId, + required_components: &mut RequiredComponents, + constructor: fn() -> R, + inheritance_depth: u16, + ) { + // Components cannot require themselves. + if required == requiree { + return; + } + + // Register the required component `R` for the requiree. + required_components.register_by_id(required, constructor, inheritance_depth); + + // Add the requiree to the list of components that require `R`. + // SAFETY: The caller ensures that the component ID is valid. + // Assuming it is valid, the component is in the list of required components, so it must exist already. + let required_by = unsafe { self.get_required_by_mut(required).debug_checked_unwrap() }; + required_by.insert(requiree); + + self.register_inherited_required_components(requiree, required, required_components); + } +} + +impl<'w> ComponentsRegistrator<'w> { + // NOTE: This should maybe be private, but it is currently public so that `bevy_ecs_macros` can use it. + // We can't directly move this there either, because this uses `Components::get_required_by_mut`, + // which is private, and could be equally risky to expose to users. + /// Registers the given component `R` and [required components] inherited from it as required by `T`, + /// and adds `T` to their lists of requirees. + /// + /// The given `inheritance_depth` determines how many levels of inheritance deep the requirement is. + /// A direct requirement has a depth of `0`, and each level of inheritance increases the depth by `1`. + /// Lower depths are more specific requirements, and can override existing less specific registrations. + /// + /// The `recursion_check_stack` allows checking whether this component tried to register itself as its + /// own (indirect) required component. + /// + /// This method does *not* register any components as required by components that require `T`. + /// + /// Only use this method if you know what you are doing. In most cases, you should instead use [`World::register_required_components`], + /// or the equivalent method in `bevy_app::App`. + /// + /// [required component]: Component#required-components + #[doc(hidden)] + pub fn register_required_components_manual( + &mut self, + required_components: &mut RequiredComponents, + constructor: fn() -> R, + inheritance_depth: u16, + recursion_check_stack: &mut Vec, + ) { + let requiree = self.register_component_checked::(recursion_check_stack); + let required = self.register_component_checked::(recursion_check_stack); + + // SAFETY: We just created the components. + unsafe { + self.register_required_components_manual_unchecked::( + requiree, + required, + required_components, + constructor, + inheritance_depth, + ); + } + } +} + +/// An error returned when the registration of a required component fails. +#[derive(Error, Debug)] +#[non_exhaustive] +pub enum RequiredComponentsError { + /// The component is already a directly required component for the requiree. + #[error("Component {0:?} already directly requires component {1:?}")] + DuplicateRegistration(ComponentId, ComponentId), + /// An archetype with the component that requires other components already exists + #[error("An archetype with the component {0:?} that requires other components already exists")] + ArchetypeExists(ComponentId), +} + +/// A Required Component constructor. See [`Component`] for details. +#[derive(Clone)] +pub struct RequiredComponentConstructor( + pub Arc, +); + +impl RequiredComponentConstructor { + /// # Safety + /// This is intended to only be called in the context of [`BundleInfo::write_components`] to initialized required components. + /// Calling it _anywhere else_ should be considered unsafe. + /// + /// `table_row` and `entity` must correspond to a valid entity that currently needs a component initialized via the constructor stored + /// on this [`RequiredComponentConstructor`]. The stored constructor must correspond to a component on `entity` that needs initialization. + /// `table` and `sparse_sets` must correspond to storages on a world where `entity` needs this required component initialized. + /// + /// Again, don't call this anywhere but [`BundleInfo::write_components`]. + pub(crate) unsafe fn initialize( + &self, + table: &mut Table, + sparse_sets: &mut SparseSets, + change_tick: Tick, + table_row: TableRow, + entity: Entity, + caller: MaybeLocation, + ) { + (self.0)(table, sparse_sets, change_tick, table_row, entity, caller); + } +} + +/// Metadata associated with a required component. See [`Component`] for details. +#[derive(Clone)] +pub struct RequiredComponent { + /// The constructor used for the required component. + pub constructor: RequiredComponentConstructor, + + /// The depth of the component requirement in the requirement hierarchy for this component. + /// This is used for determining which constructor is used in cases where there are duplicate requires. + /// + /// For example, consider the inheritance tree `X -> Y -> Z`, where `->` indicates a requirement. + /// `X -> Y` and `Y -> Z` are direct requirements with a depth of 0, while `Z` is only indirectly + /// required for `X` with a depth of `1`. + /// + /// In cases where there are multiple conflicting requirements with the same depth, a higher priority + /// will be given to components listed earlier in the `require` attribute, or to the latest added requirement + /// if registered at runtime. + pub inheritance_depth: u16, +} + +/// The collection of metadata for components that are required for a given component. +/// +/// For more information, see the "Required Components" section of [`Component`]. +#[derive(Default, Clone)] +pub struct RequiredComponents(pub(crate) HashMap); + +impl Debug for RequiredComponents { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_tuple("RequiredComponents") + .field(&self.0.keys()) + .finish() + } +} + +impl RequiredComponents { + /// Registers a required component. + /// + /// If the component is already registered, it will be overwritten if the given inheritance depth + /// is smaller than the depth of the existing registration. Otherwise, the new registration will be ignored. + /// + /// # Safety + /// + /// `component_id` must match the type initialized by `constructor`. + /// `constructor` _must_ initialize a component for `component_id` in such a way that + /// matches the storage type of the component. It must only use the given `table_row` or `Entity` to + /// initialize the storage for `component_id` corresponding to the given entity. + pub unsafe fn register_dynamic_with( + &mut self, + component_id: ComponentId, + inheritance_depth: u16, + constructor: impl FnOnce() -> RequiredComponentConstructor, + ) { + let entry = self.0.entry(component_id); + match entry { + bevy_platform::collections::hash_map::Entry::Occupied(mut occupied) => { + let current = occupied.get_mut(); + if current.inheritance_depth > inheritance_depth { + *current = RequiredComponent { + constructor: constructor(), + inheritance_depth, + } + } + } + bevy_platform::collections::hash_map::Entry::Vacant(vacant) => { + vacant.insert(RequiredComponent { + constructor: constructor(), + inheritance_depth, + }); + } + } + } + + /// Registers a required component. + /// + /// If the component is already registered, it will be overwritten if the given inheritance depth + /// is smaller than the depth of the existing registration. Otherwise, the new registration will be ignored. + pub fn register( + &mut self, + components: &mut ComponentsRegistrator, + constructor: fn() -> C, + inheritance_depth: u16, + ) { + let component_id = components.register_component::(); + self.register_by_id(component_id, constructor, inheritance_depth); + } + + /// Registers the [`Component`] with the given ID as required if it exists. + /// + /// If the component is already registered, it will be overwritten if the given inheritance depth + /// is smaller than the depth of the existing registration. Otherwise, the new registration will be ignored. + pub fn register_by_id( + &mut self, + component_id: ComponentId, + constructor: fn() -> C, + inheritance_depth: u16, + ) { + let erased = || { + RequiredComponentConstructor({ + // `portable-atomic-util` `Arc` is not able to coerce an unsized + // type like `std::sync::Arc` can. Creating a `Box` first does the + // coercion. + // + // This would be resolved by https://github.com/rust-lang/rust/issues/123430 + + #[cfg(not(target_has_atomic = "ptr"))] + use alloc::boxed::Box; + + type Constructor = dyn for<'a, 'b> Fn( + &'a mut Table, + &'b mut SparseSets, + Tick, + TableRow, + Entity, + MaybeLocation, + ); + + #[cfg(not(target_has_atomic = "ptr"))] + type Intermediate = Box; + + #[cfg(target_has_atomic = "ptr")] + type Intermediate = Arc; + + let boxed: Intermediate = Intermediate::new( + move |table, sparse_sets, change_tick, table_row, entity, caller| { + OwningPtr::make(constructor(), |ptr| { + // SAFETY: This will only be called in the context of `BundleInfo::write_components`, which will + // pass in a valid table_row and entity requiring a C constructor + // C::STORAGE_TYPE is the storage type associated with `component_id` / `C` + // `ptr` points to valid `C` data, which matches the type associated with `component_id` + unsafe { + BundleInfo::initialize_required_component( + table, + sparse_sets, + change_tick, + table_row, + entity, + component_id, + C::STORAGE_TYPE, + ptr, + caller, + ); + } + }); + }, + ); + + Arc::from(boxed) + }) + }; + + // SAFETY: + // `component_id` matches the type initialized by the `erased` constructor above. + // `erased` initializes a component for `component_id` in such a way that + // matches the storage type of the component. It only uses the given `table_row` or `Entity` to + // initialize the storage corresponding to the given entity. + unsafe { self.register_dynamic_with(component_id, inheritance_depth, erased) }; + } + + /// Iterates the ids of all required components. This includes recursive required components. + pub fn iter_ids(&self) -> impl Iterator + '_ { + self.0.keys().copied() + } + + /// Removes components that are explicitly provided in a given [`Bundle`]. These components should + /// be logically treated as normal components, not "required components". + /// + /// [`Bundle`]: crate::bundle::Bundle + pub(crate) fn remove_explicit_components(&mut self, components: &[ComponentId]) { + for component in components { + self.0.remove(component); + } + } + + /// Merges `required_components` into this collection. This only inserts a required component + /// if it _did not already exist_ *or* if the required component is more specific than the existing one + /// (in other words, if the inheritance depth is smaller). + /// + /// See [`register_dynamic_with`](Self::register_dynamic_with) for details. + pub(crate) fn merge(&mut self, required_components: &RequiredComponents) { + for ( + component_id, + RequiredComponent { + constructor, + inheritance_depth, + }, + ) in required_components.0.iter() + { + // SAFETY: This exact registration must have been done on `required_components`, so safety is ensured by that caller. + unsafe { + self.register_dynamic_with(*component_id, *inheritance_depth, || { + constructor.clone() + }); + } + } + } +} + +// NOTE: This should maybe be private, but it is currently public so that `bevy_ecs_macros` can use it. +// This exists as a standalone function instead of being inlined into the component derive macro so as +// to reduce the amount of generated code. +#[doc(hidden)] +pub fn enforce_no_required_components_recursion( + components: &Components, + recursion_check_stack: &[ComponentId], +) { + if let Some((&requiree, check)) = recursion_check_stack.split_last() { + if let Some(direct_recursion) = check + .iter() + .position(|&id| id == requiree) + .map(|index| index == check.len() - 1) + { + panic!( + "Recursive required components detected: {}\nhelp: {}", + recursion_check_stack + .iter() + .map(|id| format!("{}", components.get_name(*id).unwrap().shortname())) + .collect::>() + .join(" → "), + if direct_recursion { + format!( + "Remove require({}).", + components.get_name(requiree).unwrap().shortname() + ) + } else { + "If this is intentional, consider merging the components.".into() + } + ); + } + } +}