Skip to content

Commit d0a8c6c

Browse files
committed
Rewrite required components
1 parent e81670a commit d0a8c6c

File tree

8 files changed

+503
-491
lines changed

8 files changed

+503
-491
lines changed

crates/bevy_ecs/macros/src/component.rs

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -237,38 +237,17 @@ pub fn derive_component(input: TokenStream) -> TokenStream {
237237

238238
let requires = &attrs.requires;
239239
let mut register_required = Vec::with_capacity(attrs.requires.iter().len());
240-
let mut register_recursive_requires = Vec::with_capacity(attrs.requires.iter().len());
241240
if let Some(requires) = requires {
242241
for require in requires {
243242
let ident = &require.path;
244-
register_recursive_requires.push(quote! {
245-
<#ident as #bevy_ecs_path::component::Component>::register_required_components(
246-
requiree,
247-
components,
248-
required_components,
249-
inheritance_depth + 1
250-
);
243+
let constructor = match &require.func {
244+
Some(func) => quote! { || { let x: #ident = (#func)().into(); x } },
245+
None => quote! { <#ident as Default>::default },
246+
};
247+
register_required.push(quote! {
248+
// SAFETY: we registered all components with the same instance of components.
249+
unsafe { required_components.register::<#ident>(components, #constructor) };
251250
});
252-
match &require.func {
253-
Some(func) => {
254-
register_required.push(quote! {
255-
components.register_required_components_manual::<Self, #ident>(
256-
required_components,
257-
|| { let x: #ident = (#func)().into(); x },
258-
inheritance_depth
259-
);
260-
});
261-
}
262-
None => {
263-
register_required.push(quote! {
264-
components.register_required_components_manual::<Self, #ident>(
265-
required_components,
266-
<#ident as Default>::default,
267-
inheritance_depth
268-
);
269-
});
270-
}
271-
}
272251
}
273252
}
274253
let struct_name = &ast.ident;
@@ -308,14 +287,12 @@ pub fn derive_component(input: TokenStream) -> TokenStream {
308287
impl #impl_generics #bevy_ecs_path::component::Component for #struct_name #type_generics #where_clause {
309288
const STORAGE_TYPE: #bevy_ecs_path::component::StorageType = #storage;
310289
type Mutability = #mutable_type;
311-
fn register_required_components(
290+
unsafe fn register_required_components(
312291
_requiree: #bevy_ecs_path::component::ComponentId,
313292
components: &mut #bevy_ecs_path::component::ComponentsRegistrator,
314293
required_components: &mut #bevy_ecs_path::component::RequiredComponents,
315-
inheritance_depth: u16,
316294
) {
317295
#(#register_required)*
318-
#(#register_recursive_requires)*
319296
}
320297

321298
#on_add

crates/bevy_ecs/src/bundle/info.rs

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ use bevy_platform::collections::{HashMap, HashSet};
33
use bevy_ptr::OwningPtr;
44
use bevy_utils::TypeIdMap;
55
use core::{any::TypeId, ptr::NonNull};
6+
use indexmap::{IndexMap, IndexSet};
67

78
use crate::{
89
archetype::{Archetype, BundleComponentStatus, ComponentStatus},
910
bundle::{Bundle, DynamicBundle},
1011
change_detection::MaybeLocation,
1112
component::{
12-
ComponentId, Components, ComponentsRegistrator, RequiredComponentConstructor,
13-
RequiredComponents, StorageType, Tick,
13+
ComponentId, Components, ComponentsRegistrator, RequiredComponentConstructor, StorageType,
14+
Tick,
1415
},
1516
entity::Entity,
1617
query::DebugCheckedUnwrap as _,
@@ -59,6 +60,7 @@ pub enum InsertMode {
5960
/// [`World`]: crate::world::World
6061
pub struct BundleInfo {
6162
pub(super) id: BundleId,
63+
6264
/// The list of all components contributed by the bundle (including Required Components). This is in
6365
/// the order `[EXPLICIT_COMPONENTS][REQUIRED_COMPONENTS]`
6466
///
@@ -67,9 +69,10 @@ pub struct BundleInfo {
6769
/// must have its storage initialized (i.e. columns created in tables, sparse set created),
6870
/// and the range (0..`explicit_components_len`) must be in the same order as the source bundle
6971
/// type writes its components in.
70-
pub(super) component_ids: Vec<ComponentId>,
71-
pub(super) required_components: Vec<RequiredComponentConstructor>,
72-
pub(super) explicit_components_len: usize,
72+
pub(super) contributed_components: Vec<ComponentId>,
73+
74+
/// The list of constructors for all required components indirectly contributed by this bundle.
75+
pub(super) required_component_constructors: Vec<RequiredComponentConstructor>,
7376
}
7477

7578
impl BundleInfo {
@@ -86,11 +89,10 @@ impl BundleInfo {
8689
mut component_ids: Vec<ComponentId>,
8790
id: BundleId,
8891
) -> BundleInfo {
92+
let explicit_component_ids = component_ids.iter().copied().collect::<IndexSet<_>>();
93+
8994
// check for duplicates
90-
let mut deduped = component_ids.clone();
91-
deduped.sort_unstable();
92-
deduped.dedup();
93-
if deduped.len() != component_ids.len() {
95+
if explicit_component_ids.len() != component_ids.len() {
9496
// TODO: Replace with `Vec::partition_dedup` once https://github.com/rust-lang/rust/issues/54279 is stabilized
9597
let mut seen = <HashSet<_>>::default();
9698
let mut dups = Vec::new();
@@ -111,41 +113,39 @@ impl BundleInfo {
111113
panic!("Bundle {bundle_type_name} has duplicate components: {names:?}");
112114
}
113115

114-
// handle explicit components
115-
let explicit_components_len = component_ids.len();
116-
let mut required_components = RequiredComponents::default();
117-
for component_id in component_ids.iter().copied() {
116+
let mut depth_first_components = IndexMap::new();
117+
for &component_id in &component_ids {
118118
// SAFETY: caller has verified that all ids are valid
119119
let info = unsafe { components.get_info_unchecked(component_id) };
120-
required_components.merge(info.required_components());
120+
121+
for (&required_id, required_component) in &info.required_components().all {
122+
depth_first_components
123+
.entry(required_id)
124+
.or_insert_with(|| required_component.clone());
125+
}
126+
121127
storages.prepare_component(info);
122128
}
123-
required_components.remove_explicit_components(&component_ids);
124-
125-
// handle required components
126-
let required_components = required_components
127-
.0
128-
.into_iter()
129-
.map(|(component_id, v)| {
130-
// Safety: These ids came out of the passed `components`, so they must be valid.
131-
let info = unsafe { components.get_info_unchecked(component_id) };
132-
storages.prepare_component(info);
133-
// This adds required components to the component_ids list _after_ using that list to remove explicitly provided
134-
// components. This ordering is important!
135-
component_ids.push(component_id);
136-
v.constructor
129+
130+
let required_components = depth_first_components
131+
.iter()
132+
.filter(|&(required_id, _)| !explicit_component_ids.contains(required_id))
133+
.inspect(|&(&required_id, _)| {
134+
// SAFETY: These ids came out of the passed `components`, so they must be valid.
135+
storages.prepare_component(unsafe { components.get_info_unchecked(required_id) });
136+
component_ids.push(required_id);
137137
})
138-
.collect();
138+
.map(|(_, required_component)| required_component.constructor.clone())
139+
.collect::<Vec<_>>();
139140

140141
// SAFETY: The caller ensures that component_ids:
141142
// - is valid for the associated world
142143
// - has had its storage initialized
143144
// - is in the same order as the source bundle type
144145
BundleInfo {
145146
id,
146-
component_ids,
147-
required_components,
148-
explicit_components_len,
147+
contributed_components: component_ids,
148+
required_component_constructors: required_components,
149149
}
150150
}
151151

@@ -155,27 +155,32 @@ impl BundleInfo {
155155
self.id
156156
}
157157

158+
/// Returns the length of the explicit components part of the [contributed_components](Self::contributed_components) list.
159+
pub(super) fn explicit_components_len(&self) -> usize {
160+
self.contributed_components.len() - self.required_component_constructors.len()
161+
}
162+
158163
/// Returns the [ID](ComponentId) of each component explicitly defined in this bundle (ex: Required Components are excluded).
159164
///
160165
/// For all components contributed by this bundle (including Required Components), see [`BundleInfo::contributed_components`]
161166
#[inline]
162167
pub fn explicit_components(&self) -> &[ComponentId] {
163-
&self.component_ids[0..self.explicit_components_len]
168+
&self.contributed_components[0..self.explicit_components_len()]
164169
}
165170

166171
/// Returns the [ID](ComponentId) of each Required Component needed by this bundle. This _does not include_ Required Components that are
167172
/// explicitly provided by the bundle.
168173
#[inline]
169174
pub fn required_components(&self) -> &[ComponentId] {
170-
&self.component_ids[self.explicit_components_len..]
175+
&self.contributed_components[self.explicit_components_len()..]
171176
}
172177

173178
/// Returns the [ID](ComponentId) of each component contributed by this bundle. This includes Required Components.
174179
///
175180
/// For only components explicitly defined in this bundle, see [`BundleInfo::explicit_components`]
176181
#[inline]
177182
pub fn contributed_components(&self) -> &[ComponentId] {
178-
&self.component_ids
183+
&self.contributed_components
179184
}
180185

181186
/// 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 {
190195
/// To iterate only components explicitly defined in this bundle, see [`BundleInfo::iter_explicit_components`]
191196
#[inline]
192197
pub fn iter_contributed_components(&self) -> impl Iterator<Item = ComponentId> + Clone + '_ {
193-
self.component_ids.iter().copied()
198+
self.contributed_components().iter().copied()
194199
}
195200

196201
/// 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 {
236241
// bundle_info.component_ids are also in "bundle order"
237242
let mut bundle_component = 0;
238243
let after_effect = bundle.get_components(&mut |storage_type, component_ptr| {
239-
let component_id = *self.component_ids.get_unchecked(bundle_component);
244+
let component_id = *self.contributed_components.get_unchecked(bundle_component);
240245
// SAFETY: bundle_component is a valid index for this bundle
241246
let status = unsafe { bundle_component_status.get_status(bundle_component) };
242247
match storage_type {

crates/bevy_ecs/src/bundle/insert.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ impl BundleInfo {
433433
}
434434
let mut new_table_components = Vec::new();
435435
let mut new_sparse_set_components = Vec::new();
436-
let mut bundle_status = Vec::with_capacity(self.explicit_components_len);
436+
let mut bundle_status = Vec::with_capacity(self.explicit_components_len());
437437
let mut added_required_components = Vec::new();
438438
let mut added = Vec::new();
439439
let mut existing = Vec::new();
@@ -457,7 +457,7 @@ impl BundleInfo {
457457

458458
for (index, component_id) in self.iter_required_components().enumerate() {
459459
if !current_archetype.contains(component_id) {
460-
added_required_components.push(self.required_components[index].clone());
460+
added_required_components.push(self.required_component_constructors[index].clone());
461461
added.push(component_id);
462462
// SAFETY: component_id exists
463463
let component_info = unsafe { components.get_info_unchecked(component_id) };

crates/bevy_ecs/src/bundle/spawner.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ impl<'w> BundleSpawner<'w> {
108108
table,
109109
sparse_sets,
110110
&SpawnBundleStatus,
111-
bundle_info.required_components.iter(),
111+
bundle_info.required_component_constructors.iter(),
112112
entity,
113113
table_row,
114114
self.change_tick,

crates/bevy_ecs/src/component/info.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use alloc::{borrow::Cow, vec::Vec};
2-
use bevy_platform::{collections::HashSet, sync::PoisonError};
2+
use bevy_platform::sync::PoisonError;
33
use bevy_ptr::OwningPtr;
44
#[cfg(feature = "bevy_reflect")]
55
use bevy_reflect::Reflect;
@@ -10,6 +10,7 @@ use core::{
1010
fmt::Debug,
1111
mem::needs_drop,
1212
};
13+
use indexmap::IndexSet;
1314

1415
use crate::{
1516
archetype::ArchetypeFlags,
@@ -30,7 +31,10 @@ pub struct ComponentInfo {
3031
pub(super) descriptor: ComponentDescriptor,
3132
pub(super) hooks: ComponentHooks,
3233
pub(super) required_components: RequiredComponents,
33-
pub(super) required_by: HashSet<ComponentId>,
34+
/// The set of components that require this components.
35+
/// Invariant: this is stored in a depth-first order, that is components are stored after the components
36+
/// that they depend on.
37+
pub(super) required_by: IndexSet<ComponentId>,
3438
}
3539

3640
impl ComponentInfo {
@@ -505,6 +509,13 @@ impl Components {
505509
.and_then(|info| info.as_mut().map(|info| &mut info.hooks))
506510
}
507511

512+
#[inline]
513+
pub(crate) fn get_required_components(&self, id: ComponentId) -> Option<&RequiredComponents> {
514+
self.components
515+
.get(id.0)
516+
.and_then(|info| info.as_ref().map(|info| &info.required_components))
517+
}
518+
508519
#[inline]
509520
pub(crate) fn get_required_components_mut(
510521
&mut self,
@@ -516,7 +527,7 @@ impl Components {
516527
}
517528

518529
#[inline]
519-
pub(crate) fn get_required_by(&self, id: ComponentId) -> Option<&HashSet<ComponentId>> {
530+
pub(crate) fn get_required_by(&self, id: ComponentId) -> Option<&IndexSet<ComponentId>> {
520531
self.components
521532
.get(id.0)
522533
.and_then(|info| info.as_ref().map(|info| &info.required_by))
@@ -526,7 +537,7 @@ impl Components {
526537
pub(crate) fn get_required_by_mut(
527538
&mut self,
528539
id: ComponentId,
529-
) -> Option<&mut HashSet<ComponentId>> {
540+
) -> Option<&mut IndexSet<ComponentId>> {
530541
self.components
531542
.get_mut(id.0)
532543
.and_then(|info| info.as_mut().map(|info| &mut info.required_by))

crates/bevy_ecs/src/component/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -522,11 +522,14 @@ pub trait Component: Send + Sync + 'static {
522522
}
523523

524524
/// Registers required components.
525-
fn register_required_components(
525+
///
526+
/// # Safety
527+
///
528+
/// - `_required_components` must only contain components valid in `_components`.
529+
unsafe fn register_required_components(
526530
_component_id: ComponentId,
527531
_components: &mut ComponentsRegistrator,
528532
_required_components: &mut RequiredComponents,
529-
_inheritance_depth: u16,
530533
) {
531534
}
532535

crates/bevy_ecs/src/component/register.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use core::any::Any;
55
use core::ops::DerefMut;
66
use core::{any::TypeId, fmt::Debug, ops::Deref};
77

8+
use crate::component::enforce_no_required_components_recursion;
89
use crate::query::DebugCheckedUnwrap as _;
910
use crate::{
1011
component::{
@@ -189,8 +190,9 @@ impl<'w> ComponentsRegistrator<'w> {
189190
#[inline]
190191
pub(super) fn register_component_checked<T: Component>(&mut self) -> ComponentId {
191192
let type_id = TypeId::of::<T>();
192-
if let Some(id) = self.indices.get(&type_id) {
193-
return *id;
193+
if let Some(&id) = self.indices.get(&type_id) {
194+
enforce_no_required_components_recursion(self, &self.recursion_check_stack, id);
195+
return id;
194196
}
195197

196198
if let Some(registrator) = self
@@ -229,8 +231,15 @@ impl<'w> ComponentsRegistrator<'w> {
229231

230232
self.recursion_check_stack.push(id);
231233
let mut required_components = RequiredComponents::default();
232-
T::register_required_components(id, self, &mut required_components, 0);
234+
// SAFETY: `required_components` is empty
235+
unsafe { T::register_required_components(id, self, &mut required_components) };
236+
// SAFETY:
237+
// - `id` was just registered in `self`
238+
// - `register_required_components` have been given `self` to register components in
239+
// (TODO: this is not really true... but the alternative would be making `Component` `unsafe`...)
240+
unsafe { self.register_required_by(id, &required_components) };
233241
self.recursion_check_stack.pop();
242+
234243
// SAFETY: we just inserted it in `register_component_inner`
235244
let info = unsafe {
236245
&mut self

0 commit comments

Comments
 (0)