From 07a85676b3051a41c545c8ed0296449865f55591 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 11 Jun 2024 15:54:42 -0700 Subject: [PATCH] =?UTF-8?q?Revert=20"constrain=20WorldQuery::init=5Fstate?= =?UTF-8?q?=20argument=20to=20ComponentInitial=E2=80=A6=20(#13804)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …izer (#13442)" This reverts commit 5cfb063d4ae4b6abb40c3e7d2c7752a68ab5eb3d. - This PR broke bevy-trait-query, which needs to be able to write a resource in init_state. See #13798 for more details. - Note this doesn't fix everything as transmutes for bevy-trait-query will still be broken,. But the current usage in that crate is UB, so we need to find another solution. --- crates/bevy_ecs/macros/src/world_query.rs | 4 +- crates/bevy_ecs/src/component.rs | 70 ----------------------- crates/bevy_ecs/src/query/builder.rs | 14 ++--- crates/bevy_ecs/src/query/fetch.rs | 54 ++++++++--------- crates/bevy_ecs/src/query/filter.rs | 24 ++++---- crates/bevy_ecs/src/query/state.rs | 10 ++-- crates/bevy_ecs/src/query/world_query.rs | 14 ++--- crates/bevy_ecs/src/world/mod.rs | 11 +--- 8 files changed, 59 insertions(+), 142 deletions(-) diff --git a/crates/bevy_ecs/macros/src/world_query.rs b/crates/bevy_ecs/macros/src/world_query.rs index ee38f37317383..8675458cdf06b 100644 --- a/crates/bevy_ecs/macros/src/world_query.rs +++ b/crates/bevy_ecs/macros/src/world_query.rs @@ -164,9 +164,9 @@ pub(crate) fn world_query_impl( #( <#field_types>::update_component_access(&state.#named_field_idents, _access); )* } - fn init_state(initializer: &mut #path::component::ComponentInitializer) -> #state_struct_name #user_ty_generics { + fn init_state(world: &mut #path::world::World) -> #state_struct_name #user_ty_generics { #state_struct_name { - #(#named_field_idents: <#field_types>::init_state(initializer),)* + #(#named_field_idents: <#field_types>::init_state(world),)* } } diff --git a/crates/bevy_ecs/src/component.rs b/crates/bevy_ecs/src/component.rs index 4b23bf7e022f1..28582d20dbc66 100644 --- a/crates/bevy_ecs/src/component.rs +++ b/crates/bevy_ecs/src/component.rs @@ -21,7 +21,6 @@ use std::{ borrow::Cow, marker::PhantomData, mem::needs_drop, - ops::Deref, }; /// A data type that can be used to store data for an [entity]. @@ -838,75 +837,6 @@ impl Components { } } -/// A wrapper over a mutable [`Components`] reference that allows for state initialization. -/// This can be obtained with [`World::component_initializer`]. -pub struct ComponentInitializer<'w> { - pub(crate) components: &'w mut Components, - pub(crate) storages: &'w mut Storages, -} - -impl<'w> Deref for ComponentInitializer<'w> { - type Target = Components; - - fn deref(&self) -> &Components { - self.components - } -} - -impl<'w> ComponentInitializer<'w> { - /// Initializes a component of type `T` with this instance. - /// If a component of this type has already been initialized, this will return - /// the ID of the pre-existing component. - /// - /// # See also - /// - /// * [`Components::component_id()`] - /// * [`Components::init_component_with_descriptor()`] - #[inline] - pub fn init_component(&mut self) -> ComponentId { - self.components.init_component::(self.storages) - } - - /// Initializes a component described by `descriptor`. - /// - /// ## Note - /// - /// If this method is called multiple times with identical descriptors, a distinct `ComponentId` - /// will be created for each one. - /// - /// # See also - /// - /// * [`Components::component_id()`] - /// * [`Components::init_component()`] - pub fn init_component_with_descriptor( - &mut self, - descriptor: ComponentDescriptor, - ) -> ComponentId { - self.components - .init_component_with_descriptor(self.storages, descriptor) - } - - /// Initializes a [`Resource`] of type `T` with this instance. - /// If a resource of this type has already been initialized, this will return - /// the ID of the pre-existing resource. - /// - /// # See also - /// - /// * [`Components::resource_id()`] - #[inline] - pub fn init_resource(&mut self) -> ComponentId { - self.components.init_resource::() - } - - /// Initializes a [non-send resource](crate::system::NonSend) of type `T` with this instance. - /// If a resource of this type has already been initialized, this will return - /// the ID of the pre-existing resource. - #[inline] - pub fn init_non_send(&mut self) -> ComponentId { - self.components.init_non_send::() - } -} - /// A value that tracks when a system ran relative to other systems. /// This is used to power change detection. /// diff --git a/crates/bevy_ecs/src/query/builder.rs b/crates/bevy_ecs/src/query/builder.rs index bcc9b58b126ed..101371d00400f 100644 --- a/crates/bevy_ecs/src/query/builder.rs +++ b/crates/bevy_ecs/src/query/builder.rs @@ -43,9 +43,8 @@ pub struct QueryBuilder<'w, D: QueryData = (), F: QueryFilter = ()> { impl<'w, D: QueryData, F: QueryFilter> QueryBuilder<'w, D, F> { /// Creates a new builder with the accesses required for `Q` and `F` pub fn new(world: &'w mut World) -> Self { - let initializer = &mut world.component_initializer(); - let fetch_state = D::init_state(initializer); - let filter_state = F::init_state(initializer); + let fetch_state = D::init_state(world); + let filter_state = F::init_state(world); let mut access = FilteredAccess::default(); D::update_component_access(&fetch_state, &mut access); @@ -96,7 +95,7 @@ impl<'w, D: QueryData, F: QueryFilter> QueryBuilder<'w, D, F> { /// Adds accesses required for `T` to self. pub fn data(&mut self) -> &mut Self { - let state = T::init_state(&mut self.world.component_initializer()); + let state = T::init_state(self.world); let mut access = FilteredAccess::default(); T::update_component_access(&state, &mut access); self.extend_access(access); @@ -105,7 +104,7 @@ impl<'w, D: QueryData, F: QueryFilter> QueryBuilder<'w, D, F> { /// Adds filter from `T` to self. pub fn filter(&mut self) -> &mut Self { - let state = T::init_state(&mut self.world.component_initializer()); + let state = T::init_state(self.world); let mut access = FilteredAccess::default(); T::update_component_access(&state, &mut access); self.extend_access(access); @@ -223,9 +222,8 @@ impl<'w, D: QueryData, F: QueryFilter> QueryBuilder<'w, D, F> { pub fn transmute_filtered( &mut self, ) -> &mut QueryBuilder<'w, NewD, NewF> { - let initializer = &mut self.world.component_initializer(); - let mut fetch_state = NewD::init_state(initializer); - let filter_state = NewF::init_state(initializer); + let mut fetch_state = NewD::init_state(self.world); + let filter_state = NewF::init_state(self.world); NewD::set_access(&mut fetch_state, &self.access); diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index e611ad92e4428..2ebf95cdea787 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -1,20 +1,20 @@ use crate::{ archetype::{Archetype, Archetypes}, change_detection::{Ticks, TicksMut}, - component::{Component, ComponentId, ComponentInitializer, Components, StorageType, Tick}, + component::{Component, ComponentId, Components, StorageType, Tick}, entity::{Entities, Entity, EntityLocation}, query::{Access, DebugCheckedUnwrap, FilteredAccess, WorldQuery}, storage::{ComponentSparseSet, Table, TableRow}, world::{ unsafe_world_cell::UnsafeWorldCell, EntityMut, EntityRef, FilteredEntityMut, - FilteredEntityRef, Mut, Ref, + FilteredEntityRef, Mut, Ref, World, }, }; use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref}; use bevy_utils::all_tuples; use std::{cell::UnsafeCell, marker::PhantomData}; -/// Types that can be fetched from a [`World`](crate::world::World) using a [`Query`]. +/// Types that can be fetched from a [`World`] using a [`Query`]. /// /// There are many types that natively implement this trait: /// @@ -335,7 +335,7 @@ unsafe impl WorldQuery for Entity { fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {} - fn init_state(_initializer: &mut ComponentInitializer) {} + fn init_state(_world: &mut World) {} fn get_state(_components: &Components) -> Option<()> { Some(()) @@ -407,7 +407,7 @@ unsafe impl WorldQuery for EntityLocation { fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {} - fn init_state(_initializer: &mut ComponentInitializer) {} + fn init_state(_world: &mut World) {} fn get_state(_components: &Components) -> Option<()> { Some(()) @@ -486,7 +486,7 @@ unsafe impl<'a> WorldQuery for EntityRef<'a> { access.read_all(); } - fn init_state(_initializer: &mut ComponentInitializer) {} + fn init_state(_world: &mut World) {} fn get_state(_components: &Components) -> Option<()> { Some(()) @@ -562,7 +562,7 @@ unsafe impl<'a> WorldQuery for EntityMut<'a> { access.write_all(); } - fn init_state(_initializer: &mut ComponentInitializer) {} + fn init_state(_world: &mut World) {} fn get_state(_components: &Components) -> Option<()> { Some(()) @@ -660,7 +660,7 @@ unsafe impl<'a> WorldQuery for FilteredEntityRef<'a> { filtered_access.access.extend(&state.access); } - fn init_state(_initializer: &mut ComponentInitializer) -> Self::State { + fn init_state(_world: &mut World) -> Self::State { FilteredAccess::default() } @@ -772,7 +772,7 @@ unsafe impl<'a> WorldQuery for FilteredEntityMut<'a> { filtered_access.access.extend(&state.access); } - fn init_state(_initializer: &mut ComponentInitializer) -> Self::State { + fn init_state(_world: &mut World) -> Self::State { FilteredAccess::default() } @@ -846,7 +846,7 @@ unsafe impl WorldQuery for &Archetype { fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {} - fn init_state(_initializer: &mut ComponentInitializer) {} + fn init_state(_world: &mut World) {} fn get_state(_components: &Components) -> Option<()> { Some(()) @@ -995,8 +995,8 @@ unsafe impl WorldQuery for &T { access.add_read(component_id); } - fn init_state(initializer: &mut ComponentInitializer) -> ComponentId { - initializer.init_component::() + fn init_state(world: &mut World) -> ComponentId { + world.init_component::() } fn get_state(components: &Components) -> Option { @@ -1178,8 +1178,8 @@ unsafe impl<'__w, T: Component> WorldQuery for Ref<'__w, T> { access.add_read(component_id); } - fn init_state(initializer: &mut ComponentInitializer<'_>) -> ComponentId { - initializer.init_component::() + fn init_state(world: &mut World) -> ComponentId { + world.init_component::() } fn get_state(components: &Components) -> Option { @@ -1361,8 +1361,8 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T { access.add_write(component_id); } - fn init_state(initializer: &mut ComponentInitializer<'_>) -> ComponentId { - initializer.init_component::() + fn init_state(world: &mut World) -> ComponentId { + world.init_component::() } fn get_state(components: &Components) -> Option { @@ -1460,8 +1460,8 @@ unsafe impl<'__w, T: Component> WorldQuery for Mut<'__w, T> { } // Forwarded to `&mut T` - fn init_state(initializer: &mut ComponentInitializer) -> ComponentId { - <&mut T as WorldQuery>::init_state(initializer) + fn init_state(world: &mut World) -> ComponentId { + <&mut T as WorldQuery>::init_state(world) } // Forwarded to `&mut T` @@ -1581,8 +1581,8 @@ unsafe impl WorldQuery for Option { access.extend_access(&intermediate); } - fn init_state(initializer: &mut ComponentInitializer) -> T::State { - T::init_state(initializer) + fn init_state(world: &mut World) -> T::State { + T::init_state(world) } fn get_state(components: &Components) -> Option { @@ -1736,8 +1736,8 @@ unsafe impl WorldQuery for Has { access.access_mut().add_archetypal(component_id); } - fn init_state(initializer: &mut ComponentInitializer) -> ComponentId { - initializer.init_component::() + fn init_state(world: &mut World) -> ComponentId { + world.init_component::() } fn get_state(components: &Components) -> Option { @@ -1882,8 +1882,8 @@ macro_rules! impl_anytuple_fetch { *_access = _new_access; } #[allow(unused_variables)] - fn init_state(initializer: &mut ComponentInitializer) -> Self::State { - ($($name::init_state(initializer),)*) + fn init_state(world: &mut World) -> Self::State { + ($($name::init_state(world),)*) } #[allow(unused_variables)] fn get_state(components: &Components) -> Option { @@ -1959,8 +1959,8 @@ unsafe impl WorldQuery for NopWorldQuery { fn update_component_access(_state: &D::State, _access: &mut FilteredAccess) {} - fn init_state(initializer: &mut ComponentInitializer) -> Self::State { - D::init_state(initializer) + fn init_state(world: &mut World) -> Self::State { + D::init_state(world) } fn get_state(components: &Components) -> Option { @@ -2026,7 +2026,7 @@ unsafe impl WorldQuery for PhantomData { fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {} - fn init_state(_initializer: &mut ComponentInitializer) -> Self::State {} + fn init_state(_world: &mut World) -> Self::State {} fn get_state(_components: &Components) -> Option { Some(()) diff --git a/crates/bevy_ecs/src/query/filter.rs b/crates/bevy_ecs/src/query/filter.rs index 75fbf681563b5..316aed862bc44 100644 --- a/crates/bevy_ecs/src/query/filter.rs +++ b/crates/bevy_ecs/src/query/filter.rs @@ -1,10 +1,10 @@ use crate::{ archetype::Archetype, - component::{Component, ComponentId, ComponentInitializer, Components, StorageType, Tick}, + component::{Component, ComponentId, Components, StorageType, Tick}, entity::Entity, query::{DebugCheckedUnwrap, FilteredAccess, WorldQuery}, storage::{Column, ComponentSparseSet, Table, TableRow}, - world::unsafe_world_cell::UnsafeWorldCell, + world::{unsafe_world_cell::UnsafeWorldCell, World}, }; use bevy_ptr::{ThinSlicePtr, UnsafeCellDeref}; use bevy_utils::all_tuples; @@ -183,8 +183,8 @@ unsafe impl WorldQuery for With { access.and_with(id); } - fn init_state(initializer: &mut ComponentInitializer) -> ComponentId { - initializer.init_component::() + fn init_state(world: &mut World) -> ComponentId { + world.init_component::() } fn get_state(components: &Components) -> Option { @@ -291,8 +291,8 @@ unsafe impl WorldQuery for Without { access.and_without(id); } - fn init_state(initializer: &mut ComponentInitializer) -> ComponentId { - initializer.init_component::() + fn init_state(world: &mut World) -> ComponentId { + world.init_component::() } fn get_state(components: &Components) -> Option { @@ -461,8 +461,8 @@ macro_rules! impl_or_query_filter { *access = _new_access; } - fn init_state(initializer: &mut ComponentInitializer) -> Self::State { - ($($filter::init_state(initializer),)*) + fn init_state(world: &mut World) -> Self::State { + ($($filter::init_state(world),)*) } fn get_state(components: &Components) -> Option { @@ -693,8 +693,8 @@ unsafe impl WorldQuery for Added { access.add_read(id); } - fn init_state(initializer: &mut ComponentInitializer) -> ComponentId { - initializer.init_component::() + fn init_state(world: &mut World) -> ComponentId { + world.init_component::() } fn get_state(components: &Components) -> Option { @@ -904,8 +904,8 @@ unsafe impl WorldQuery for Changed { access.add_read(id); } - fn init_state(initializer: &mut ComponentInitializer) -> ComponentId { - initializer.init_component::() + fn init_state(world: &mut World) -> ComponentId { + world.init_component::() } fn get_state(components: &Components) -> Option { diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index 1fe5a88d2d5c9..b59822ef1a1c7 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -178,9 +178,8 @@ impl QueryState { /// `new_archetype` and its variants must be called on all of the World's archetypes before the /// state can return valid query results. fn new_uninitialized(world: &mut World) -> Self { - let initializer = &mut world.component_initializer(); - let fetch_state = D::init_state(initializer); - let filter_state = F::init_state(initializer); + let fetch_state = D::init_state(world); + let filter_state = F::init_state(world); let mut component_access = FilteredAccess::default(); D::update_component_access(&fetch_state, &mut component_access); @@ -215,9 +214,8 @@ impl QueryState { /// Creates a new [`QueryState`] from a given [`QueryBuilder`] and inherits its [`FilteredAccess`]. pub fn from_builder(builder: &mut QueryBuilder) -> Self { - let initializer = &mut builder.world_mut().component_initializer(); - let mut fetch_state = D::init_state(initializer); - let filter_state = F::init_state(initializer); + let mut fetch_state = D::init_state(builder.world_mut()); + let filter_state = F::init_state(builder.world_mut()); D::set_access(&mut fetch_state, builder.access()); let mut state = Self { diff --git a/crates/bevy_ecs/src/query/world_query.rs b/crates/bevy_ecs/src/query/world_query.rs index ab3444f6d981f..7c8283cbfe196 100644 --- a/crates/bevy_ecs/src/query/world_query.rs +++ b/crates/bevy_ecs/src/query/world_query.rs @@ -1,10 +1,10 @@ use crate::{ archetype::Archetype, - component::{ComponentId, ComponentInitializer, Components, Tick}, + component::{ComponentId, Components, Tick}, entity::Entity, query::FilteredAccess, storage::{Table, TableRow}, - world::unsafe_world_cell::UnsafeWorldCell, + world::{unsafe_world_cell::UnsafeWorldCell, World}, }; use bevy_utils::all_tuples; @@ -79,7 +79,7 @@ pub unsafe trait WorldQuery { /// /// # Safety /// - /// - `archetype` and `tables` must be from the same [`World`](crate::world::World) that [`WorldQuery::init_state`] was called on. + /// - `archetype` and `tables` must be from the same [`World`] that [`WorldQuery::init_state`] was called on. /// - `table` must correspond to `archetype`. /// - `state` must be the [`State`](Self::State) that `fetch` was initialized with. unsafe fn set_archetype<'w>( @@ -94,7 +94,7 @@ pub unsafe trait WorldQuery { /// /// # Safety /// - /// - `table` must be from the same [`World`](crate::world::World) that [`WorldQuery::init_state`] was called on. + /// - `table` must be from the same [`World`] that [`WorldQuery::init_state`] was called on. /// - `state` must be the [`State`](Self::State) that `fetch` was initialized with. unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table); @@ -127,7 +127,7 @@ pub unsafe trait WorldQuery { fn update_component_access(state: &Self::State, access: &mut FilteredAccess); /// Creates and initializes a [`State`](WorldQuery::State) for this [`WorldQuery`] type. - fn init_state(initializer: &mut ComponentInitializer) -> Self::State; + fn init_state(world: &mut World) -> Self::State; /// Attempts to initialize a [`State`](WorldQuery::State) for this [`WorldQuery`] type using read-only /// access to [`Components`]. @@ -213,8 +213,8 @@ macro_rules! impl_tuple_world_query { $($name::update_component_access($name, _access);)* } #[allow(unused_variables)] - fn init_state(initializer: &mut ComponentInitializer) -> Self::State { - ($($name::init_state(initializer),)*) + fn init_state(world: &mut World) -> Self::State { + ($($name::init_state(world),)*) } #[allow(unused_variables)] fn get_state(components: &Components) -> Option { diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index 354da63ea88eb..099534a4272fe 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -8,8 +8,8 @@ mod spawn_batch; pub mod unsafe_world_cell; pub use crate::change_detection::{Mut, Ref, CHECK_TICK_THRESHOLD}; +use crate::entity::EntityHashSet; pub use crate::world::command_queue::CommandQueue; -use crate::{component::ComponentInitializer, entity::EntityHashSet}; pub use deferred_world::DeferredWorld; pub use entity_ref::{ EntityMut, EntityRef, EntityWorldMut, Entry, FilteredEntityMut, FilteredEntityRef, @@ -219,15 +219,6 @@ impl World { &self.bundles } - /// Creates a [`ComponentInitializer`] for this world. - #[inline] - pub fn component_initializer(&mut self) -> ComponentInitializer { - ComponentInitializer { - components: &mut self.components, - storages: &mut self.storages, - } - } - /// Retrieves this world's [`RemovedComponentEvents`] collection #[inline] pub fn removed_components(&self) -> &RemovedComponentEvents {