Rewrite required components

This commit is contained in:
Giacomo Stevanato 2025-07-13 15:28:37 +02:00
parent c182932618
commit e335244112
No known key found for this signature in database
8 changed files with 508 additions and 496 deletions

View File

@ -237,38 +237,17 @@ pub fn derive_component(input: TokenStream) -> TokenStream {
let requires = &attrs.requires;
let mut register_required = Vec::with_capacity(attrs.requires.iter().len());
let mut register_recursive_requires = Vec::with_capacity(attrs.requires.iter().len());
if let Some(requires) = requires {
for require in requires {
let ident = &require.path;
register_recursive_requires.push(quote! {
<#ident as #bevy_ecs_path::component::Component>::register_required_components(
requiree,
components,
required_components,
inheritance_depth + 1
);
let constructor = match &require.func {
Some(func) => quote! { || { let x: #ident = (#func)().into(); x } },
None => quote! { <#ident as Default>::default },
};
register_required.push(quote! {
// SAFETY: we registered all components with the same instance of components.
unsafe { required_components.register::<#ident>(components, #constructor) };
});
match &require.func {
Some(func) => {
register_required.push(quote! {
components.register_required_components_manual::<Self, #ident>(
required_components,
|| { let x: #ident = (#func)().into(); x },
inheritance_depth
);
});
}
None => {
register_required.push(quote! {
components.register_required_components_manual::<Self, #ident>(
required_components,
<#ident as Default>::default,
inheritance_depth
);
});
}
}
}
}
let struct_name = &ast.ident;
@ -308,14 +287,12 @@ pub fn derive_component(input: TokenStream) -> TokenStream {
impl #impl_generics #bevy_ecs_path::component::Component for #struct_name #type_generics #where_clause {
const STORAGE_TYPE: #bevy_ecs_path::component::StorageType = #storage;
type Mutability = #mutable_type;
fn register_required_components(
unsafe fn register_required_components(
_requiree: #bevy_ecs_path::component::ComponentId,
components: &mut #bevy_ecs_path::component::ComponentsRegistrator,
required_components: &mut #bevy_ecs_path::component::RequiredComponents,
inheritance_depth: u16,
) {
#(#register_required)*
#(#register_recursive_requires)*
}
#on_add

View File

@ -3,14 +3,15 @@ use bevy_platform::collections::{HashMap, HashSet};
use bevy_ptr::OwningPtr;
use bevy_utils::TypeIdMap;
use core::{any::TypeId, ptr::NonNull};
use indexmap::{IndexMap, IndexSet};
use crate::{
archetype::{Archetype, BundleComponentStatus, ComponentStatus},
bundle::{Bundle, DynamicBundle},
change_detection::MaybeLocation,
component::{
ComponentId, Components, ComponentsRegistrator, RequiredComponentConstructor,
RequiredComponents, StorageType, Tick,
ComponentId, Components, ComponentsRegistrator, RequiredComponentConstructor, StorageType,
Tick,
},
entity::Entity,
query::DebugCheckedUnwrap as _,
@ -59,6 +60,7 @@ pub enum InsertMode {
/// [`World`]: crate::world::World
pub struct BundleInfo {
pub(super) id: BundleId,
/// The list of all components contributed by the bundle (including Required Components). This is in
/// the order `[EXPLICIT_COMPONENTS][REQUIRED_COMPONENTS]`
///
@ -67,9 +69,10 @@ pub struct BundleInfo {
/// must have its storage initialized (i.e. columns created in tables, sparse set created),
/// and the range (0..`explicit_components_len`) must be in the same order as the source bundle
/// type writes its components in.
pub(super) component_ids: Vec<ComponentId>,
pub(super) required_components: Vec<RequiredComponentConstructor>,
pub(super) explicit_components_len: usize,
pub(super) contributed_components: Vec<ComponentId>,
/// The list of constructors for all required components indirectly contributed by this bundle.
pub(super) required_component_constructors: Vec<RequiredComponentConstructor>,
}
impl BundleInfo {
@ -86,11 +89,10 @@ impl BundleInfo {
mut component_ids: Vec<ComponentId>,
id: BundleId,
) -> BundleInfo {
let explicit_component_ids = component_ids.iter().copied().collect::<IndexSet<_>>();
// check for duplicates
let mut deduped = component_ids.clone();
deduped.sort_unstable();
deduped.dedup();
if deduped.len() != component_ids.len() {
if explicit_component_ids.len() != component_ids.len() {
// TODO: Replace with `Vec::partition_dedup` once https://github.com/rust-lang/rust/issues/54279 is stabilized
let mut seen = <HashSet<_>>::default();
let mut dups = Vec::new();
@ -111,31 +113,30 @@ impl BundleInfo {
panic!("Bundle {bundle_type_name} has duplicate components: {names:?}");
}
// handle explicit components
let explicit_components_len = component_ids.len();
let mut required_components = RequiredComponents::default();
for component_id in component_ids.iter().copied() {
let mut depth_first_components = IndexMap::new();
for &component_id in &component_ids {
// SAFETY: caller has verified that all ids are valid
let info = unsafe { components.get_info_unchecked(component_id) };
required_components.merge(info.required_components());
for (&required_id, required_component) in &info.required_components().all {
depth_first_components
.entry(required_id)
.or_insert_with(|| required_component.clone());
}
storages.prepare_component(info);
}
required_components.remove_explicit_components(&component_ids);
// handle required components
let required_components = required_components
.0
.into_iter()
.map(|(component_id, v)| {
// Safety: These ids came out of the passed `components`, so they must be valid.
let info = unsafe { components.get_info_unchecked(component_id) };
storages.prepare_component(info);
// This adds required components to the component_ids list _after_ using that list to remove explicitly provided
// components. This ordering is important!
component_ids.push(component_id);
v.constructor
let required_components = depth_first_components
.iter()
.filter(|&(required_id, _)| !explicit_component_ids.contains(required_id))
.inspect(|&(&required_id, _)| {
// SAFETY: These ids came out of the passed `components`, so they must be valid.
storages.prepare_component(unsafe { components.get_info_unchecked(required_id) });
component_ids.push(required_id);
})
.collect();
.map(|(_, required_component)| required_component.constructor.clone())
.collect::<Vec<_>>();
// SAFETY: The caller ensures that component_ids:
// - is valid for the associated world
@ -143,9 +144,8 @@ impl BundleInfo {
// - is in the same order as the source bundle type
BundleInfo {
id,
component_ids,
required_components,
explicit_components_len,
contributed_components: component_ids,
required_component_constructors: required_components,
}
}
@ -155,19 +155,24 @@ impl BundleInfo {
self.id
}
/// Returns the length of the explicit components part of the [contributed_components](Self::contributed_components) list.
pub(super) fn explicit_components_len(&self) -> usize {
self.contributed_components.len() - self.required_component_constructors.len()
}
/// Returns the [ID](ComponentId) of each component explicitly defined in this bundle (ex: Required Components are excluded).
///
/// For all components contributed by this bundle (including Required Components), see [`BundleInfo::contributed_components`]
#[inline]
pub fn explicit_components(&self) -> &[ComponentId] {
&self.component_ids[0..self.explicit_components_len]
&self.contributed_components[0..self.explicit_components_len()]
}
/// Returns the [ID](ComponentId) of each Required Component needed by this bundle. This _does not include_ Required Components that are
/// explicitly provided by the bundle.
#[inline]
pub fn required_components(&self) -> &[ComponentId] {
&self.component_ids[self.explicit_components_len..]
&self.contributed_components[self.explicit_components_len()..]
}
/// Returns the [ID](ComponentId) of each component contributed by this bundle. This includes Required Components.
@ -175,7 +180,7 @@ impl BundleInfo {
/// For only components explicitly defined in this bundle, see [`BundleInfo::explicit_components`]
#[inline]
pub fn contributed_components(&self) -> &[ComponentId] {
&self.component_ids
&self.contributed_components
}
/// Returns an iterator over the [ID](ComponentId) of each component explicitly defined in this bundle (ex: this excludes Required Components).
@ -190,7 +195,7 @@ impl BundleInfo {
/// To iterate only components explicitly defined in this bundle, see [`BundleInfo::iter_explicit_components`]
#[inline]
pub fn iter_contributed_components(&self) -> impl Iterator<Item = ComponentId> + Clone + '_ {
self.component_ids.iter().copied()
self.contributed_components().iter().copied()
}
/// Returns an iterator over the [ID](ComponentId) of each Required Component needed by this bundle. This _does not include_ Required Components that are
@ -236,7 +241,7 @@ impl BundleInfo {
// bundle_info.component_ids are also in "bundle order"
let mut bundle_component = 0;
let after_effect = bundle.get_components(&mut |storage_type, component_ptr| {
let component_id = *self.component_ids.get_unchecked(bundle_component);
let component_id = *self.contributed_components.get_unchecked(bundle_component);
// SAFETY: bundle_component is a valid index for this bundle
let status = unsafe { bundle_component_status.get_status(bundle_component) };
match storage_type {

View File

@ -433,7 +433,7 @@ impl BundleInfo {
}
let mut new_table_components = Vec::new();
let mut new_sparse_set_components = Vec::new();
let mut bundle_status = Vec::with_capacity(self.explicit_components_len);
let mut bundle_status = Vec::with_capacity(self.explicit_components_len());
let mut added_required_components = Vec::new();
let mut added = Vec::new();
let mut existing = Vec::new();
@ -457,7 +457,7 @@ impl BundleInfo {
for (index, component_id) in self.iter_required_components().enumerate() {
if !current_archetype.contains(component_id) {
added_required_components.push(self.required_components[index].clone());
added_required_components.push(self.required_component_constructors[index].clone());
added.push(component_id);
// SAFETY: component_id exists
let component_info = unsafe { components.get_info_unchecked(component_id) };

View File

@ -108,7 +108,7 @@ impl<'w> BundleSpawner<'w> {
table,
sparse_sets,
&SpawnBundleStatus,
bundle_info.required_components.iter(),
bundle_info.required_component_constructors.iter(),
entity,
table_row,
self.change_tick,

View File

@ -1,5 +1,5 @@
use alloc::{borrow::Cow, vec::Vec};
use bevy_platform::{collections::HashSet, sync::PoisonError};
use bevy_platform::sync::PoisonError;
use bevy_ptr::OwningPtr;
#[cfg(feature = "bevy_reflect")]
use bevy_reflect::Reflect;
@ -10,6 +10,7 @@ use core::{
fmt::Debug,
mem::needs_drop,
};
use indexmap::IndexSet;
use crate::{
archetype::ArchetypeFlags,
@ -30,7 +31,10 @@ pub struct ComponentInfo {
pub(super) descriptor: ComponentDescriptor,
pub(super) hooks: ComponentHooks,
pub(super) required_components: RequiredComponents,
pub(super) required_by: HashSet<ComponentId>,
/// The set of components that require this components.
/// Invariant: this is stored in a depth-first order, that is components are stored after the components
/// that they depend on.
pub(super) required_by: IndexSet<ComponentId>,
}
impl ComponentInfo {
@ -505,6 +509,13 @@ impl Components {
.and_then(|info| info.as_mut().map(|info| &mut info.hooks))
}
#[inline]
pub(crate) fn get_required_components(&self, id: ComponentId) -> Option<&RequiredComponents> {
self.components
.get(id.0)
.and_then(|info| info.as_ref().map(|info| &info.required_components))
}
#[inline]
pub(crate) fn get_required_components_mut(
&mut self,
@ -516,7 +527,7 @@ impl Components {
}
#[inline]
pub(crate) fn get_required_by(&self, id: ComponentId) -> Option<&HashSet<ComponentId>> {
pub(crate) fn get_required_by(&self, id: ComponentId) -> Option<&IndexSet<ComponentId>> {
self.components
.get(id.0)
.and_then(|info| info.as_ref().map(|info| &info.required_by))
@ -526,7 +537,7 @@ impl Components {
pub(crate) fn get_required_by_mut(
&mut self,
id: ComponentId,
) -> Option<&mut HashSet<ComponentId>> {
) -> Option<&mut IndexSet<ComponentId>> {
self.components
.get_mut(id.0)
.and_then(|info| info.as_mut().map(|info| &mut info.required_by))

View File

@ -522,11 +522,14 @@ pub trait Component: Send + Sync + 'static {
}
/// Registers required components.
fn register_required_components(
///
/// # Safety
///
/// - `_required_components` must only contain components valid in `_components`.
unsafe fn register_required_components(
_component_id: ComponentId,
_components: &mut ComponentsRegistrator,
_required_components: &mut RequiredComponents,
_inheritance_depth: u16,
) {
}

View File

@ -5,6 +5,7 @@ use core::any::Any;
use core::ops::DerefMut;
use core::{any::TypeId, fmt::Debug, ops::Deref};
use crate::component::enforce_no_required_components_recursion;
use crate::query::DebugCheckedUnwrap as _;
use crate::{
component::{
@ -189,8 +190,9 @@ impl<'w> ComponentsRegistrator<'w> {
#[inline]
pub(super) fn register_component_checked<T: Component>(&mut self) -> ComponentId {
let type_id = TypeId::of::<T>();
if let Some(id) = self.indices.get(&type_id) {
return *id;
if let Some(&id) = self.indices.get(&type_id) {
enforce_no_required_components_recursion(self, &self.recursion_check_stack, id);
return id;
}
if let Some(registrator) = self
@ -229,8 +231,15 @@ impl<'w> ComponentsRegistrator<'w> {
self.recursion_check_stack.push(id);
let mut required_components = RequiredComponents::default();
T::register_required_components(id, self, &mut required_components, 0);
// SAFETY: `required_components` is empty
unsafe { T::register_required_components(id, self, &mut required_components) };
// SAFETY:
// - `id` was just registered in `self`
// - `register_required_components` have been given `self` to register components in
// (TODO: this is not really true... but the alternative would be making `Component` `unsafe`...)
unsafe { self.register_required_by(id, &required_components) };
self.recursion_check_stack.pop();
// SAFETY: we just inserted it in `register_component_inner`
let info = unsafe {
&mut self

View File

@ -1,8 +1,8 @@
use alloc::{format, vec::Vec};
use bevy_platform::{collections::HashMap, sync::Arc};
use bevy_platform::sync::Arc;
use bevy_ptr::OwningPtr;
use core::fmt::Debug;
use smallvec::SmallVec;
use indexmap::{IndexMap, IndexSet};
use thiserror::Error;
use crate::{
@ -14,273 +14,80 @@ use crate::{
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<R: Component>(
&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::<SmallVec<[ComponentId; 8]>>())
{
// `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<R: Component>(
&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.
///
/// 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<T: Component, R: Component>(
&mut self,
required_components: &mut RequiredComponents,
constructor: fn() -> R,
inheritance_depth: u16,
) {
let requiree = self.register_component_checked::<T>();
let required = self.register_component_checked::<R>();
enforce_no_required_components_recursion(self, &self.recursion_check_stack, required);
// SAFETY: We just created the components.
unsafe {
self.register_required_components_manual_unchecked::<R>(
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),
/// 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,
}
/// A Required Component constructor. See [`Component`] for details.
#[derive(Clone)]
pub struct RequiredComponentConstructor(
pub Arc<dyn Fn(&mut Table, &mut SparseSets, Tick, TableRow, Entity, MaybeLocation)>,
// Note: this function makes `unsafe` assumptions, so it cannot be public.
Arc<dyn Fn(&mut Table, &mut SparseSets, Tick, TableRow, Entity, MaybeLocation)>,
);
impl RequiredComponentConstructor {
/// Creates a new instance of `RequiredComponentConstructor` for the given type
///
/// # Safety
///
/// - `component_id` must be a valid component for type `C`.
pub unsafe fn new<C: Component>(component_id: ComponentId, constructor: fn() -> C) -> Self {
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<T> = Box<T>;
#[cfg(target_has_atomic = "ptr")]
type Intermediate<T> = Arc<T>;
let boxed: Intermediate<Constructor> = 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
/// 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.
@ -303,203 +110,403 @@ impl RequiredComponentConstructor {
}
}
/// 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<ComponentId, RequiredComponent>);
pub struct RequiredComponents {
/// The components that are directly required (i.e. excluding inherited ones), in the order of their precedence.
///
/// # Safety
/// The [`RequiredComponent`] instance associated to each ID must be valid for its component.
pub(crate) direct: IndexMap<ComponentId, RequiredComponent>,
/// All the components that are required (i.e. including inherited ones), in depth-first order. Most importantly,
/// components in this list always appear after all the components that they require.
///
/// Note that the direct components are not necessarily at the end of this list, for example if A and C are directly
/// requires, and A requires B requires C, then `all` will hold [C, B, A].
///
/// # Safety
/// The [`RequiredComponent`] instance associated to each ID must be valid for its component.
pub(crate) all: IndexMap<ComponentId, RequiredComponent>,
}
impl Debug for RequiredComponents {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("RequiredComponents")
.field(&self.0.keys())
f.debug_struct("RequiredComponents")
.field("direct", &self.direct.keys())
.field("all", &self.all.keys())
.finish()
}
}
impl RequiredComponents {
/// Registers a required component.
/// Registers the [`Component`] `C` as an explicitly 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.
/// If the component was not already registered as an explicit required component then it is added
/// as one, potentially overriding the constructor of a inherited required component, and `true` is returned.
/// Otherwise `false` is returned.
///
/// # 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.
/// - all other components in this [`RequiredComponents`] instance must have been registrated in `components`.
pub unsafe fn register<C: Component>(
&mut self,
components: &mut ComponentsRegistrator<'_>,
constructor: fn() -> C,
) -> bool {
let id = components.register_component::<C>();
// SAFETY:
// - `id` was just registered in `components`;
// - the caller guarantees all other components were registered in `components`.
unsafe { self.register_by_id::<C>(id, components, constructor) }
}
/// Registers the [`Component`] with the given `component_id` ID as an explicitly required component.
///
/// If the component was not already registered as an explicit required component then it is added
/// as one, potentially overriding the constructor of a inherited required component, and `true` is returned.
/// Otherwise `false` is returned.
///
/// # Safety
///
/// - `component_id` must be a valid component in `components` for the type `C`;
/// - all other components in this [`RequiredComponents`] instance must have been registrated in `components`.
pub unsafe fn register_by_id<C: Component>(
&mut self,
component_id: ComponentId,
components: &Components,
constructor: fn() -> C,
) -> bool {
// SAFETY: the caller guarantees that `component_id` is valid for the type `C`.
let constructor =
|| unsafe { RequiredComponentConstructor::new(component_id, constructor) };
// SAFETY:
// - the caller guarantees that `component_id` is valid in `components`
// - the caller guarantees all other components were registered in `components`;
// - constructor is guaranteed to create a valid constructor for the component with id `component_id`.
unsafe { self.register_dynamic_with(component_id, components, constructor) }
}
/// Registers the [`Component`] with the given `component_id` ID as an explicitly required component.
///
/// If the component was not already registered as an explicit required component then it is added
/// as one, potentially overriding the constructor of a inherited required component, and `true` is returned.
/// Otherwise `false` is returned.
///
/// # Safety
///
/// - `component_id` must be a valid component in `components`;
/// - all other components in this [`RequiredComponents`] instance must have been registrated in `components`;
/// - `constructor` must return a [`RequiredComponentConstructor`] that constructs a valid instance for the
/// component with ID `component_id`.
pub unsafe fn register_dynamic_with(
&mut self,
component_id: ComponentId,
inheritance_depth: u16,
components: &Components,
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,
});
) -> bool {
// If already registered as a direct required component then bail.
let entry = match self.direct.entry(component_id) {
indexmap::map::Entry::Vacant(entry) => entry,
indexmap::map::Entry::Occupied(_) => return false,
};
// Insert into `direct`.
let constructor = constructor();
let required_component = RequiredComponent { constructor };
entry.insert(required_component.clone());
// Register inherited required components.
unsafe {
Self::register_inherited_required_components_unchecked(
&mut self.all,
component_id,
required_component,
components,
)
};
true
}
/// Rebuild the `all` list
///
/// # Safety
///
/// - all components in this [`RequiredComponents`] instance must have been registrated in `components`.
unsafe fn rebuild_inherited_required_components(&mut self, components: &Components) {
// Clear `all`, we are re-initializing it.
self.all.clear();
// Register all inherited components as if we just registered all components in `direct` one-by-one.
for (&required_id, required_component) in &self.direct {
// SAFETY:
// - the caller guarantees that all components in this instance have been registered in `components`,
// meaning both `all` and `required_id` have been registered in `components`;
// - `required_component` was associated to `required_id`, so it must hold a constructor valid for it.
unsafe {
Self::register_inherited_required_components_unchecked(
&mut self.all,
required_id,
required_component.clone(),
components,
)
}
}
}
/// Registers a required component.
/// Registers all the inherited required components from `required_id`.
///
/// 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<C: Component>(
&mut self,
components: &mut ComponentsRegistrator,
constructor: fn() -> C,
inheritance_depth: u16,
/// # Safety
///
/// - all components in `all` must have been registered in `components`;
/// - `required_id` must have been registered in `components`;
/// - `required_component` must hold a valid constructor for the component with id `required_id`.
unsafe fn register_inherited_required_components_unchecked(
all: &mut IndexMap<ComponentId, RequiredComponent>,
required_id: ComponentId,
required_component: RequiredComponent,
components: &Components,
) {
let component_id = components.register_component::<C>();
self.register_by_id(component_id, constructor, inheritance_depth);
}
// SAFETY: the caller guarantees that `required_id` is valid in `components`.
let info = unsafe { components.get_info(required_id).debug_checked_unwrap() };
/// 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<C: Component>(
&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.
// Now we need to "recursively" register the
// Small optimization: if the current required component was already required recursively
// by an earlier direct required component then all its inherited components have all already
// been inserted, so let's not try to reinsert them.
if !all.contains_key(&required_id) {
for (&inherited_id, inherited_required) in &info.required_components().all {
// This is an inherited required component: insert it only if not already present.
// By the invariants of `RequiredComponents`, `info.required_components().all` holds the required
// components in a depth-first order, and this makes us store teh components in `self.all` also
// in depth-first order, as long as we don't overwrite existing ones.
//
// This would be resolved by https://github.com/rust-lang/rust/issues/123430
// SAFETY:
// `inherited_required` was associated to `inherited_id`, so it must have been valid for its component.
all.entry(inherited_id)
.or_insert_with(|| inherited_required.clone());
}
}
#[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<T> = Box<T>;
#[cfg(target_has_atomic = "ptr")]
type Intermediate<T> = Arc<T>;
let boxed: Intermediate<Constructor> = 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) };
// For direct required components:
// - insert them after inherited components to follow the depth-first order;
// - insert them unconditionally in order to make their constructor the one that's used.
// Note that `insert` does not change the order of components, meaning `component_id` will still appear
// before any other component that requires it.
//
// SAFETY: the caller guaranees that `required_component` is valid for the component with ID `required_id`.
all.insert(required_id, required_component);
}
/// Iterates the ids of all required components. This includes recursive required components.
pub fn iter_ids(&self) -> impl Iterator<Item = ComponentId> + '_ {
self.0.keys().copied()
self.all.keys().copied()
}
}
/// Removes components that are explicitly provided in a given [`Bundle`]. These components should
/// be logically treated as normal components, not "required components".
impl Components {
/// Registers the components in `required_components` as required by `requiree`.
///
/// [`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).
/// # Safety
///
/// 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()
});
}
/// - `requiree` must have been registered in `self`
/// - all components in `required_components` must have been registered in `self`.
pub(crate) unsafe fn register_required_by(
&mut self,
requiree: ComponentId,
required_components: &RequiredComponents,
) {
for &required in required_components.all.keys() {
// SAFETY: the caller guarantees that all components in `required_components` have been registered in `self`.
let required_by = unsafe { self.get_required_by_mut(required).debug_checked_unwrap() };
required_by.insert(requiree);
}
}
}
fn enforce_no_required_components_recursion(
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 in `self`;
/// - the given component ID `required` must be valid for the component type `R`.
///
///
/// # Errors
///
/// Returns a [`RequiredComponentsError`] if either of these are true:
/// - 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.
/// - the `requiree` component is already a (possibly indirect) required component for the `required` component.
pub(crate) unsafe fn register_required_components<R: Component>(
&mut self,
requiree: ComponentId,
required: ComponentId,
constructor: fn() -> R,
) -> Result<(), RequiredComponentsError> {
// First step: validate inputs and return errors.
// SAFETY: The caller ensures that the `required` is valid.
let required_required_components = unsafe {
self.get_required_components(required)
.debug_checked_unwrap()
};
// Cannot create cyclic requirements.
if required_required_components.all.contains_key(&requiree) {
return Err(RequiredComponentsError::CyclicRequirement(
requiree, required,
));
}
// 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.direct.contains_key(&required) {
return Err(RequiredComponentsError::DuplicateRegistration(
requiree, required,
));
}
// Second step: register the single requirement requiree->required
// Store the old count of (all) required components. This will help determine which ones are new.
let old_required_count = required_components.all.len();
// SAFETY: the caller guarantees that `requiree` and `required` are valid in `self`, with `required` valid for R.
unsafe { self.register_required_component_single(requiree, required, constructor) };
// Third step: update the required components and required_by of all the indirect requirements/requirees.
// Borrow again otherwise it conflicts with the `self.register_required_component_single` call.
// SAFETY: The caller ensures that the `requiree` is valid.
let required_components = unsafe {
self.get_required_components_mut(requiree)
.debug_checked_unwrap()
};
// Optimization: get all the new required components, i.e. those that were appended.
// Other components that might be inherited when requiring `required` can be safely ignored because
// any component requiring `requiree` will already transitively require them.
// Note: the only small exception is for `required` itself, for which we cannot ignore the value of the
// constructor. But for simplicity we will rebuild any `RequiredComponents`
let new_required_components = required_components.all[old_required_count..]
.keys()
.copied()
.collect::<IndexSet<_>>();
// Get all the new requiree components, i.e. `requiree` and all the components that `requiree` is required by.
// SAFETY: The caller ensures that the `requiree` is valid.
let new_requiree_components =
unsafe { self.get_required_by(requiree).debug_checked_unwrap() }.clone();
// We now need to update the required and required_by components of all the components
// directly or indirectly involved.
// Important: we need to be careful about the order we do these operations in.
// Since computing the required components of some component depends on the required components of
// other components, and while we do this operations not all required components are up-to-date, we need
// to ensure we update components in such a way that we update a component after the components it depends on.
// Luckily this is exactly the depth-first order, which is guaranteed to be the order of `new_requiree_components`.
// Update the inherited required components of all requiree components (directly or indirectly).
for &indirect_requiree in &new_requiree_components {
// Extract the required components to avoid conflicting borrows. Remember to put this back before continuing!
// SAFETY: `indirect_requiree` comes from `self`, so it must be valid.
let mut required_components = std::mem::take(unsafe {
self.get_required_components_mut(indirect_requiree)
.debug_checked_unwrap()
});
// Rebuild the inherited required components.
// SAFETY: `required_components` comes from `self`, so all its components must have be valid in `self`.
unsafe { required_components.rebuild_inherited_required_components(self) };
// Let's not forget to put back `required_components`!
// SAFETY: `indirect_requiree` comes from `self`, so it must be valid.
*unsafe {
self.get_required_components_mut(indirect_requiree)
.debug_checked_unwrap()
} = required_components;
}
// Update the `required_by` of all the components that were newly required (directly or indirectly).
for &indirect_required in &new_required_components {
// SAFETY: `indirect_required` comes from `self`, so it must be valid.
let required_by = unsafe {
self.get_required_by_mut(indirect_required)
.debug_checked_unwrap()
};
for &requiree in [&requiree].into_iter().chain(&new_requiree_components) {
required_by.insert_before(required_by.len(), requiree);
}
}
Ok(())
}
/// Register the `required` as a required component in the [`RequiredComponents`] for `requiree`.
/// This function does not update any other metadata, such as required components of components requiring `requiree`.
///
/// # Safety
///
/// - `requiree` and `required` must be defined in `self`.
/// - `required` must be a valid component ID for the type `R`.
unsafe fn register_required_component_single<R: Component>(
&mut self,
requiree: ComponentId,
required: ComponentId,
constructor: fn() -> R,
) {
// Extract the required components to avoid conflicting borrows. Remember to put this back before returning!
// SAFETY: The caller ensures that the `requiree` is valid.
let mut required_components = std::mem::take(unsafe {
self.get_required_components_mut(requiree)
.debug_checked_unwrap()
});
// Register the required component for the requiree.
required_components.register_by_id(required, self, constructor);
// Let's not forget to put back `required_components`!
// SAFETY: The caller ensures that the `requiree` is valid.
*unsafe {
self.get_required_components_mut(requiree)
.debug_checked_unwrap()
} = required_components;
}
}
/// 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),
/// Adding the given requirement would create a cycle.
#[error("Cyclic requirement found: the requiree component {0:?} is required by the required component {1:?}")]
CyclicRequirement(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),
}
pub(super) fn enforce_no_required_components_recursion(
components: &Components,
recursion_check_stack: &[ComponentId],
required: ComponentId,