From e99a0c14870f12d912207c6538b0c4b9863a34b6 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Wed, 18 Sep 2024 10:31:14 -0400 Subject: [PATCH 01/18] Don't obtain two NameOrEntity items at once from QueryState::get(). That takes a mutable borrow of the QueryState, which will conflict once query items may borrow the state. --- crates/bevy_core/src/name.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_core/src/name.rs b/crates/bevy_core/src/name.rs index 9f858cf96e09c..0d7c7a39d5048 100644 --- a/crates/bevy_core/src/name.rs +++ b/crates/bevy_core/src/name.rs @@ -229,9 +229,9 @@ mod tests { let e2 = world.spawn(name.clone()).id(); let mut query = world.query::(); let d1 = query.get(&world, e1).unwrap(); - let d2 = query.get(&world, e2).unwrap(); // NameOrEntity Display for entities without a Name should be {index}v{generation} assert_eq!(d1.to_string(), "0v1"); + let d2 = query.get(&world, e2).unwrap(); // NameOrEntity Display for entities with a Name should be the Name assert_eq!(d2.to_string(), "MyName"); } From f29562442f74d212e2da099c2cf66d651671675e Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Sun, 22 Sep 2024 13:28:13 -0400 Subject: [PATCH 02/18] Introduce a ReleaseStateQueryData trait that will release borrows on the QueryState. --- crates/bevy_ecs/src/query/fetch.rs | 95 ++++++++++++++++++- crates/bevy_ecs/src/query/iter.rs | 32 ++++--- crates/bevy_ecs/src/world/entity_ref.rs | 20 ++-- .../bevy_ecs/src/world/unsafe_world_cell.rs | 9 +- 4 files changed, 127 insertions(+), 29 deletions(-) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 311ddcc9aaaaa..1cb97aafca2fa 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -291,6 +291,12 @@ pub type QueryItem<'w, Q> = ::Item<'w>; /// The read-only variant of the item type returned when a [`QueryData`] is iterated over immutably pub type ROQueryItem<'w, D> = QueryItem<'w, ::ReadOnly>; +/// A [`QueryData`] that does not borrow from its [`QueryState`](crate::query::QueryState). +pub trait ReleaseStateQueryData: QueryData { + /// Releases the borrow from the query state by converting an item to have a `'static` state lifetime. + fn release_state(item: Self::Item<'_>) -> Self::Item<'_>; +} + /// SAFETY: /// `update_component_access` and `update_archetype_component_access` do nothing. /// This is sound because `fetch` does not access components. @@ -361,6 +367,12 @@ unsafe impl QueryData for Entity { /// SAFETY: access is read only unsafe impl ReadOnlyQueryData for Entity {} +impl ReleaseStateQueryData for Entity { + fn release_state(item: Self::Item<'_>) -> Self::Item<'_> { + item + } +} + /// SAFETY: /// `update_component_access` and `update_archetype_component_access` do nothing. /// This is sound because `fetch` does not access components. @@ -437,6 +449,12 @@ unsafe impl QueryData for EntityLocation { /// SAFETY: access is read only unsafe impl ReadOnlyQueryData for EntityLocation {} +impl ReleaseStateQueryData for EntityLocation { + fn release_state(item: Self::Item<'_>) -> Self::Item<'_> { + item + } +} + /// SAFETY: /// `fetch` accesses all components in a readonly way. /// This is sound because `update_component_access` and `update_archetype_component_access` set read access for all components and panic when appropriate. @@ -520,6 +538,12 @@ unsafe impl<'a> QueryData for EntityRef<'a> { /// SAFETY: access is read only unsafe impl ReadOnlyQueryData for EntityRef<'_> {} +impl ReleaseStateQueryData for EntityRef<'_> { + fn release_state(item: Self::Item<'_>) -> Self::Item<'_> { + item + } +} + /// SAFETY: The accesses of `Self::ReadOnly` are a subset of the accesses of `Self` unsafe impl<'a> WorldQuery for EntityMut<'a> { type Item<'w> = EntityMut<'w>; @@ -597,6 +621,12 @@ unsafe impl<'a> QueryData for EntityMut<'a> { type ReadOnly = EntityRef<'a>; } +impl ReleaseStateQueryData for EntityMut<'_> { + fn release_state(item: Self::Item<'_>) -> Self::Item<'_> { + item + } +} + /// SAFETY: The accesses of `Self::ReadOnly` are a subset of the accesses of `Self` unsafe impl<'a> WorldQuery for FilteredEntityRef<'a> { type Fetch<'w> = (UnsafeWorldCell<'w>, Access); @@ -1057,6 +1087,12 @@ unsafe impl QueryData for &Archetype { /// SAFETY: access is read only unsafe impl ReadOnlyQueryData for &Archetype {} +impl ReleaseStateQueryData for &Archetype { + fn release_state(item: Self::Item<'_>) -> Self::Item<'_> { + item + } +} + #[doc(hidden)] pub struct ReadFetch<'w, T> { // T::STORAGE_TYPE = StorageType::Table @@ -1211,6 +1247,12 @@ unsafe impl QueryData for &T { /// SAFETY: access is read only unsafe impl ReadOnlyQueryData for &T {} +impl ReleaseStateQueryData for &T { + fn release_state(item: Self::Item<'_>) -> Self::Item<'_> { + item + } +} + #[doc(hidden)] pub struct RefFetch<'w, T> { // T::STORAGE_TYPE = StorageType::Table @@ -1410,6 +1452,12 @@ unsafe impl<'__w, T: Component> QueryData for Ref<'__w, T> { /// SAFETY: access is read only unsafe impl<'__w, T: Component> ReadOnlyQueryData for Ref<'__w, T> {} +impl ReleaseStateQueryData for Ref<'_, T> { + fn release_state(item: Self::Item<'_>) -> Self::Item<'_> { + item + } +} + #[doc(hidden)] pub struct WriteFetch<'w, T> { // T::STORAGE_TYPE = StorageType::Table @@ -1606,6 +1654,12 @@ unsafe impl<'__w, T: Component> QueryData for &'__w mut T { type ReadOnly = &'__w T; } +impl ReleaseStateQueryData for &mut T { + fn release_state(item: Self::Item<'_>) -> Self::Item<'_> { + item + } +} + /// When `Mut` is used in a query, it will be converted to `Ref` when transformed into its read-only form, providing access to change detection methods. /// /// By contrast `&mut T` will result in a `Mut` item in mutable form to record mutations, but result in a bare `&T` in read-only form. @@ -1711,6 +1765,12 @@ unsafe impl<'__w, T: Component> QueryData for Mut<'__w, T> { type ReadOnly = Ref<'__w, T>; } +impl ReleaseStateQueryData for Mut<'_, T> { + fn release_state(item: Self::Item<'_>) -> Self::Item<'_> { + item + } +} + #[doc(hidden)] pub struct OptionFetch<'w, T: WorldQuery> { fetch: T::Fetch<'w>, @@ -2000,6 +2060,12 @@ unsafe impl QueryData for Has { /// SAFETY: [`Has`] is read only unsafe impl ReadOnlyQueryData for Has {} +impl ReleaseStateQueryData for Has { + fn release_state(item: Self::Item<'_>) -> Self::Item<'_> { + item + } +} + /// The `AnyOf` query parameter fetches entities with any of the component types included in T. /// /// `Query>` is equivalent to `Query<(Option<&A>, Option<&B>, Option<&mut C>), Or<(With, With, With)>>`. @@ -2008,7 +2074,7 @@ unsafe impl ReadOnlyQueryData for Has {} pub struct AnyOf(PhantomData); macro_rules! impl_tuple_query_data { - ($(#[$meta:meta])* $(($name: ident, $state: ident)),*) => { + ($(#[$meta:meta])* $(($name: ident, $item: ident)),*) => { #[allow(non_snake_case)] #[allow(clippy::unused_unit)] @@ -2021,11 +2087,17 @@ macro_rules! impl_tuple_query_data { /// SAFETY: each item in the tuple is read only unsafe impl<$($name: ReadOnlyQueryData),*> ReadOnlyQueryData for ($($name,)*) {} + #[allow(clippy::unused_unit)] + impl<$($name: ReleaseStateQueryData),*> ReleaseStateQueryData for ($($name,)*) { + fn release_state(($($item,)*): Self::Item<'_>) -> Self::Item<'_> { + ($($name::release_state($item),)*) + } + } }; } macro_rules! impl_anytuple_fetch { - ($(($name: ident, $state: ident)),*) => { + ($(($name: ident, $state: ident, $item: ident)),*) => { #[allow(non_snake_case)] #[allow(clippy::unused_unit)] @@ -2157,6 +2229,13 @@ macro_rules! impl_anytuple_fetch { /// SAFETY: each item in the tuple is read only unsafe impl<$($name: ReadOnlyQueryData),*> ReadOnlyQueryData for AnyOf<($($name,)*)> {} + + #[allow(clippy::unused_unit)] + impl<$($name: ReleaseStateQueryData),*> ReleaseStateQueryData for AnyOf<($($name,)*)> { + fn release_state(($($item,)*): Self::Item<'_>) -> Self::Item<'_> { + ($($item.map(|$item| $name::release_state($item)),)*) + } + } }; } @@ -2166,9 +2245,9 @@ all_tuples!( 0, 15, F, - S + i ); -all_tuples!(impl_anytuple_fetch, 0, 15, F, S); +all_tuples!(impl_anytuple_fetch, 0, 15, F, S, i); /// [`WorldQuery`] used to nullify queries by turning `Query` into `Query>` /// @@ -2244,6 +2323,10 @@ unsafe impl QueryData for NopWorldQuery { /// SAFETY: `NopFetch` never accesses any data unsafe impl ReadOnlyQueryData for NopWorldQuery {} +impl ReleaseStateQueryData for NopWorldQuery { + fn release_state(_item: Self::Item<'_>) -> Self::Item<'_> {} +} + /// SAFETY: /// `update_component_access` and `update_archetype_component_access` do nothing. /// This is sound because `fetch` does not access components. @@ -2312,6 +2395,10 @@ unsafe impl QueryData for PhantomData { /// SAFETY: `PhantomData` never accesses any world data. unsafe impl ReadOnlyQueryData for PhantomData {} +impl ReleaseStateQueryData for PhantomData { + fn release_state(_item: Self::Item<'_>) -> Self::Item<'_> {} +} + #[cfg(test)] mod tests { use bevy_ecs_macros::QueryData; diff --git a/crates/bevy_ecs/src/query/iter.rs b/crates/bevy_ecs/src/query/iter.rs index 6522a1b2372ba..ff5bfd7a07f62 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -15,7 +15,7 @@ use std::{ ops::Range, }; -use super::{QueryData, QueryFilter, ReadOnlyQueryData}; +use super::{QueryData, QueryFilter, ReadOnlyQueryData, ReleaseStateQueryData}; /// An [`Iterator`] over query results of a [`Query`](crate::system::Query). /// @@ -484,7 +484,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// # schedule.add_systems((system_1, system_2, system_3)); /// # schedule.run(&mut world); /// ``` - pub fn sort: Ord> + 'w>( + pub fn sort: Ord> + ReleaseStateQueryData + 'w>( self, ) -> QuerySortedIter< 'w, @@ -516,7 +516,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { ) }; let mut keyed_query: Vec<_> = query_lens - .map(|(key, entity)| (key, NeutralOrd(entity))) + .map(|(key, entity)| (L::release_state(key), NeutralOrd(entity))) .collect(); keyed_query.sort(); let entity_iter = keyed_query.into_iter().map(|(.., entity)| entity.0); @@ -576,7 +576,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// # schedule.add_systems((system_1)); /// # schedule.run(&mut world); /// ``` - pub fn sort_unstable: Ord> + 'w>( + pub fn sort_unstable< + L: ReadOnlyQueryData: Ord> + ReleaseStateQueryData + 'w, + >( self, ) -> QuerySortedIter< 'w, @@ -608,7 +610,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { ) }; let mut keyed_query: Vec<_> = query_lens - .map(|(key, entity)| (key, NeutralOrd(entity))) + .map(|(key, entity)| (L::release_state(key), NeutralOrd(entity))) .collect(); keyed_query.sort_unstable(); let entity_iter = keyed_query.into_iter().map(|(.., entity)| entity.0); @@ -675,7 +677,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// # schedule.add_systems((system_1)); /// # schedule.run(&mut world); /// ``` - pub fn sort_by( + pub fn sort_by( self, mut compare: impl FnMut(&L::Item<'w>, &L::Item<'w>) -> Ordering, ) -> QuerySortedIter< @@ -707,7 +709,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { world.change_tick(), ) }; - let mut keyed_query: Vec<_> = query_lens.collect(); + let mut keyed_query: Vec<_> = query_lens.map(<(L, Entity)>::release_state).collect(); keyed_query.sort_by(|(key_1, _), (key_2, _)| compare(key_1, key_2)); let entity_iter = keyed_query.into_iter().map(|(.., entity)| entity); // SAFETY: @@ -741,7 +743,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// # Panics /// /// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty. - pub fn sort_unstable_by( + pub fn sort_unstable_by( self, mut compare: impl FnMut(&L::Item<'w>, &L::Item<'w>) -> Ordering, ) -> QuerySortedIter< @@ -773,7 +775,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { world.change_tick(), ) }; - let mut keyed_query: Vec<_> = query_lens.collect(); + let mut keyed_query: Vec<_> = query_lens.map(<(L, Entity)>::release_state).collect(); keyed_query.sort_by(|(key_1, _), (key_2, _)| compare(key_1, key_2)); let entity_iter = keyed_query.into_iter().map(|(.., entity)| entity); // SAFETY: @@ -867,7 +869,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// # schedule.add_systems((system_1, system_2)); /// # schedule.run(&mut world); /// ``` - pub fn sort_by_key( + pub fn sort_by_key( self, mut f: impl FnMut(&L::Item<'w>) -> K, ) -> QuerySortedIter< @@ -902,7 +904,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { world.change_tick(), ) }; - let mut keyed_query: Vec<_> = query_lens.collect(); + let mut keyed_query: Vec<_> = query_lens.map(<(L, Entity)>::release_state).collect(); keyed_query.sort_by_key(|(lens, _)| f(lens)); let entity_iter = keyed_query.into_iter().map(|(.., entity)| entity); // SAFETY: @@ -936,7 +938,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// # Panics /// /// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty. - pub fn sort_unstable_by_key( + pub fn sort_unstable_by_key( self, mut f: impl FnMut(&L::Item<'w>) -> K, ) -> QuerySortedIter< @@ -971,7 +973,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { world.change_tick(), ) }; - let mut keyed_query: Vec<_> = query_lens.collect(); + let mut keyed_query: Vec<_> = query_lens.map(<(L, Entity)>::release_state).collect(); keyed_query.sort_unstable_by_key(|(lens, _)| f(lens)); let entity_iter = keyed_query.into_iter().map(|(.., entity)| entity); // SAFETY: @@ -1006,7 +1008,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// /// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty. /// - pub fn sort_by_cached_key( + pub fn sort_by_cached_key( self, mut f: impl FnMut(&L::Item<'w>) -> K, ) -> QuerySortedIter< @@ -1041,7 +1043,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { world.change_tick(), ) }; - let mut keyed_query: Vec<_> = query_lens.collect(); + let mut keyed_query: Vec<_> = query_lens.map(<(L, Entity)>::release_state).collect(); keyed_query.sort_by_cached_key(|(lens, _)| f(lens)); let entity_iter = keyed_query.into_iter().map(|(.., entity)| entity); // SAFETY: diff --git a/crates/bevy_ecs/src/world/entity_ref.rs b/crates/bevy_ecs/src/world/entity_ref.rs index c91885469c766..4ac5731c6a7ae 100644 --- a/crates/bevy_ecs/src/world/entity_ref.rs +++ b/crates/bevy_ecs/src/world/entity_ref.rs @@ -6,7 +6,7 @@ use crate::{ entity::{Entities, Entity, EntityLocation}, event::Event, observer::{Observer, Observers}, - query::{Access, ReadOnlyQueryData}, + query::{Access, ReadOnlyQueryData, ReleaseStateQueryData}, removal_detection::RemovedComponentEvents, storage::Storages, system::IntoObserverSystem, @@ -162,13 +162,15 @@ impl<'w> EntityRef<'w> { /// # Panics /// /// If the entity does not have the components required by the query `Q`. - pub fn components(&self) -> Q::Item<'w> { + pub fn components(&self) -> Q::Item<'w> { self.get_components::().expect(QUERY_MISMATCH_ERROR) } /// Returns read-only components for the current entity that match the query `Q`, /// or `None` if the entity does not have the components required by the query `Q`. - pub fn get_components(&self) -> Option> { + pub fn get_components( + &self, + ) -> Option> { // SAFETY: We have read-only access to all components of this entity. unsafe { self.0.get_components::() } } @@ -372,13 +374,15 @@ impl<'w> EntityMut<'w> { /// # Panics /// /// If the entity does not have the components required by the query `Q`. - pub fn components(&self) -> Q::Item<'_> { + pub fn components(&self) -> Q::Item<'_> { self.get_components::().expect(QUERY_MISMATCH_ERROR) } /// Returns read-only components for the current entity that match the query `Q`, /// or `None` if the entity does not have the components required by the query `Q`. - pub fn get_components(&self) -> Option> { + pub fn get_components( + &self, + ) -> Option> { // SAFETY: We have read-only access to all components of this entity. unsafe { self.0.get_components::() } } @@ -686,14 +690,16 @@ impl<'w> EntityWorldMut<'w> { /// /// If the entity does not have the components required by the query `Q`. #[inline] - pub fn components(&self) -> Q::Item<'_> { + pub fn components(&self) -> Q::Item<'_> { EntityRef::from(self).components::() } /// Returns read-only components for the current entity that match the query `Q`, /// or `None` if the entity does not have the components required by the query `Q`. #[inline] - pub fn get_components(&self) -> Option> { + pub fn get_components( + &self, + ) -> Option> { EntityRef::from(self).get_components::() } diff --git a/crates/bevy_ecs/src/world/unsafe_world_cell.rs b/crates/bevy_ecs/src/world/unsafe_world_cell.rs index 7aac53742d458..d1ce0ce8c97cb 100644 --- a/crates/bevy_ecs/src/world/unsafe_world_cell.rs +++ b/crates/bevy_ecs/src/world/unsafe_world_cell.rs @@ -11,7 +11,7 @@ use crate::{ entity::{Entities, Entity, EntityLocation}, observer::Observers, prelude::Component, - query::{DebugCheckedUnwrap, ReadOnlyQueryData}, + query::{DebugCheckedUnwrap, ReadOnlyQueryData, ReleaseStateQueryData}, removal_detection::RemovedComponentEvents, storage::{ComponentSparseSet, Storages, Table}, system::Resource, @@ -891,7 +891,9 @@ impl<'w> UnsafeEntityCell<'w> { /// It is the callers responsibility to ensure that /// - the [`UnsafeEntityCell`] has permission to access the queried data immutably /// - no mutable references to the queried data exist at the same time - pub(crate) unsafe fn get_components(&self) -> Option> { + pub(crate) unsafe fn get_components( + &self, + ) -> Option> { // SAFETY: World is only used to access query data and initialize query state let state = unsafe { let world = self.world().world(); @@ -927,7 +929,8 @@ impl<'w> UnsafeEntityCell<'w> { // Table corresponds to archetype. State is the same state used to init fetch above. unsafe { Q::set_archetype(&mut fetch, &state, archetype, table) } // SAFETY: Called after set_archetype above. Entity and location are guaranteed to exist. - unsafe { Some(Q::fetch(&mut fetch, self.id(), location.table_row)) } + let item = unsafe { Q::fetch(&mut fetch, self.id(), location.table_row) }; + Some(Q::release_state(item)) } else { None } From 648eb3184606b52b67bf755223a0aec12aa7813f Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Sun, 22 Sep 2024 13:33:26 -0400 Subject: [PATCH 03/18] Add a 'state lifetime to query items and fetches. This allows them to borrow from the query state, which can avoid expensive clones in some cases. --- crates/bevy_core/src/name.rs | 2 +- .../bevy_core_pipeline/src/bloom/settings.rs | 2 +- .../src/core_2d/main_opaque_pass_2d_node.rs | 2 +- .../core_2d/main_transparent_pass_2d_node.rs | 2 +- .../src/core_3d/main_opaque_pass_3d_node.rs | 2 +- .../bevy_core_pipeline/src/deferred/node.rs | 6 +- crates/bevy_core_pipeline/src/dof/mod.rs | 2 +- .../bevy_core_pipeline/src/msaa_writeback.rs | 2 +- .../src/post_process/mod.rs | 4 +- crates/bevy_core_pipeline/src/prepass/node.rs | 2 +- crates/bevy_core_pipeline/src/skybox/mod.rs | 4 +- crates/bevy_core_pipeline/src/smaa/mod.rs | 2 +- crates/bevy_ecs/macros/src/query_data.rs | 1 + crates/bevy_ecs/macros/src/query_filter.rs | 5 +- crates/bevy_ecs/macros/src/world_query.rs | 54 +- crates/bevy_ecs/src/query/fetch.rs | 594 +++++++++++------- crates/bevy_ecs/src/query/filter.rs | 160 ++--- crates/bevy_ecs/src/query/iter.rs | 64 +- crates/bevy_ecs/src/query/par_iter.rs | 4 +- crates/bevy_ecs/src/query/state.rs | 36 +- crates/bevy_ecs/src/query/world_query.rs | 60 +- crates/bevy_ecs/src/system/query.rs | 31 +- crates/bevy_ecs/src/world/entity_ref.rs | 12 +- .../bevy_ecs/src/world/unsafe_world_cell.rs | 2 +- crates/bevy_gizmos/src/lib.rs | 12 +- crates/bevy_hierarchy/src/query_extension.rs | 20 +- .../src/light_probe/environment_map.rs | 2 +- crates/bevy_pbr/src/render/mesh.rs | 2 +- crates/bevy_pbr/src/ssr/mod.rs | 4 +- crates/bevy_pbr/src/volumetric_fog/render.rs | 2 +- .../macros/src/extract_component.rs | 2 +- crates/bevy_render/src/extract_component.rs | 4 +- crates/bevy_render/src/extract_instances.rs | 4 +- crates/bevy_render/src/render_graph/node.rs | 2 +- crates/bevy_render/src/render_phase/draw.rs | 8 +- crates/bevy_sprite/src/lib.rs | 2 +- crates/bevy_sprite/src/mesh2d/mesh.rs | 2 +- crates/bevy_sprite/src/render/mod.rs | 2 +- .../src/render/ui_material_pipeline.rs | 2 +- examples/ecs/custom_query_param.rs | 4 +- examples/shader/custom_phase_item.rs | 4 +- examples/shader/shader_instancing.rs | 2 +- 42 files changed, 643 insertions(+), 492 deletions(-) diff --git a/crates/bevy_core/src/name.rs b/crates/bevy_core/src/name.rs index 0d7c7a39d5048..016e08ca6934b 100644 --- a/crates/bevy_core/src/name.rs +++ b/crates/bevy_core/src/name.rs @@ -131,7 +131,7 @@ pub struct NameOrEntity { pub entity: Entity, } -impl<'a> std::fmt::Display for NameOrEntityItem<'a> { +impl<'w, 's> std::fmt::Display for NameOrEntityItem<'w, 's> { #[inline(always)] fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self.name { diff --git a/crates/bevy_core_pipeline/src/bloom/settings.rs b/crates/bevy_core_pipeline/src/bloom/settings.rs index 3fc35dc4d5105..d41530eda512c 100644 --- a/crates/bevy_core_pipeline/src/bloom/settings.rs +++ b/crates/bevy_core_pipeline/src/bloom/settings.rs @@ -218,7 +218,7 @@ impl ExtractComponent for Bloom { type QueryFilter = (); type Out = (Self, BloomUniforms); - fn extract_component((bloom, camera): QueryItem<'_, Self::QueryData>) -> Option { + fn extract_component((bloom, camera): QueryItem<'_, '_, Self::QueryData>) -> Option { match ( camera.physical_viewport_rect(), camera.physical_viewport_size(), diff --git a/crates/bevy_core_pipeline/src/core_2d/main_opaque_pass_2d_node.rs b/crates/bevy_core_pipeline/src/core_2d/main_opaque_pass_2d_node.rs index 91093d0da5c94..e85fe7b2d5d14 100644 --- a/crates/bevy_core_pipeline/src/core_2d/main_opaque_pass_2d_node.rs +++ b/crates/bevy_core_pipeline/src/core_2d/main_opaque_pass_2d_node.rs @@ -30,7 +30,7 @@ impl ViewNode for MainOpaquePass2dNode { &self, graph: &mut RenderGraphContext, render_context: &mut RenderContext<'w>, - (camera, target, depth): QueryItem<'w, Self::ViewQuery>, + (camera, target, depth): QueryItem<'w, '_, Self::ViewQuery>, world: &'w World, ) -> Result<(), NodeRunError> { let (Some(opaque_phases), Some(alpha_mask_phases)) = ( diff --git a/crates/bevy_core_pipeline/src/core_2d/main_transparent_pass_2d_node.rs b/crates/bevy_core_pipeline/src/core_2d/main_transparent_pass_2d_node.rs index e365be954775b..3307c7960d9ee 100644 --- a/crates/bevy_core_pipeline/src/core_2d/main_transparent_pass_2d_node.rs +++ b/crates/bevy_core_pipeline/src/core_2d/main_transparent_pass_2d_node.rs @@ -27,7 +27,7 @@ impl ViewNode for MainTransparentPass2dNode { &self, graph: &mut RenderGraphContext, render_context: &mut RenderContext<'w>, - (camera, target, depth): bevy_ecs::query::QueryItem<'w, Self::ViewQuery>, + (camera, target, depth): bevy_ecs::query::QueryItem<'w, '_, Self::ViewQuery>, world: &'w World, ) -> Result<(), NodeRunError> { let Some(transparent_phases) = diff --git a/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs b/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs index b51f36354340a..4b3e631db9232 100644 --- a/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs +++ b/crates/bevy_core_pipeline/src/core_3d/main_opaque_pass_3d_node.rs @@ -45,7 +45,7 @@ impl ViewNode for MainOpaquePass3dNode { skybox_pipeline, skybox_bind_group, view_uniform_offset, - ): QueryItem<'w, Self::ViewQuery>, + ): QueryItem<'w, '_, Self::ViewQuery>, world: &'w World, ) -> Result<(), NodeRunError> { let (Some(opaque_phases), Some(alpha_mask_phases)) = ( diff --git a/crates/bevy_core_pipeline/src/deferred/node.rs b/crates/bevy_core_pipeline/src/deferred/node.rs index 44895aaeb8cd2..7f780207ae286 100644 --- a/crates/bevy_core_pipeline/src/deferred/node.rs +++ b/crates/bevy_core_pipeline/src/deferred/node.rs @@ -37,7 +37,11 @@ impl ViewNode for DeferredGBufferPrepassNode { &self, graph: &mut RenderGraphContext, render_context: &mut RenderContext<'w>, - (view, camera, view_depth_texture, view_prepass_textures): QueryItem<'w, Self::ViewQuery>, + (view, camera, view_depth_texture, view_prepass_textures): QueryItem< + 'w, + '_, + Self::ViewQuery, + >, world: &'w World, ) -> Result<(), NodeRunError> { let (Some(opaque_deferred_phases), Some(alpha_mask_deferred_phases)) = ( diff --git a/crates/bevy_core_pipeline/src/dof/mod.rs b/crates/bevy_core_pipeline/src/dof/mod.rs index ba31dfb279653..7089fa5b884e7 100644 --- a/crates/bevy_core_pipeline/src/dof/mod.rs +++ b/crates/bevy_core_pipeline/src/dof/mod.rs @@ -348,7 +348,7 @@ impl ViewNode for DepthOfFieldNode { view_bind_group_layouts, depth_of_field_uniform_index, auxiliary_dof_texture, - ): QueryItem<'w, Self::ViewQuery>, + ): QueryItem<'w, '_, Self::ViewQuery>, world: &'w World, ) -> Result<(), NodeRunError> { let pipeline_cache = world.resource::(); diff --git a/crates/bevy_core_pipeline/src/msaa_writeback.rs b/crates/bevy_core_pipeline/src/msaa_writeback.rs index 01f579a0e1404..0a1e541c7f7fb 100644 --- a/crates/bevy_core_pipeline/src/msaa_writeback.rs +++ b/crates/bevy_core_pipeline/src/msaa_writeback.rs @@ -63,7 +63,7 @@ impl ViewNode for MsaaWritebackNode { &self, _graph: &mut RenderGraphContext, render_context: &mut RenderContext<'w>, - (target, blit_pipeline_id, msaa): QueryItem<'w, Self::ViewQuery>, + (target, blit_pipeline_id, msaa): QueryItem<'w, '_, Self::ViewQuery>, world: &'w World, ) -> Result<(), NodeRunError> { if *msaa == Msaa::Off { diff --git a/crates/bevy_core_pipeline/src/post_process/mod.rs b/crates/bevy_core_pipeline/src/post_process/mod.rs index 79c41f990b33c..5b5949979cb33 100644 --- a/crates/bevy_core_pipeline/src/post_process/mod.rs +++ b/crates/bevy_core_pipeline/src/post_process/mod.rs @@ -360,7 +360,7 @@ impl ViewNode for PostProcessingNode { &self, _: &mut RenderGraphContext, render_context: &mut RenderContext<'w>, - (view_target, pipeline_id, chromatic_aberration, post_processing_uniform_buffer_offsets): QueryItem<'w, Self::ViewQuery>, + (view_target, pipeline_id, chromatic_aberration, post_processing_uniform_buffer_offsets): QueryItem<'w, '_, Self::ViewQuery>, world: &'w World, ) -> Result<(), NodeRunError> { let pipeline_cache = world.resource::(); @@ -493,7 +493,7 @@ impl ExtractComponent for ChromaticAberration { type Out = ChromaticAberration; fn extract_component( - chromatic_aberration: QueryItem<'_, Self::QueryData>, + chromatic_aberration: QueryItem<'_, '_, Self::QueryData>, ) -> Option { // Skip the postprocessing phase entirely if the intensity is zero. if chromatic_aberration.intensity > 0.0 { diff --git a/crates/bevy_core_pipeline/src/prepass/node.rs b/crates/bevy_core_pipeline/src/prepass/node.rs index d362c36f6c21f..fec1311f73a92 100644 --- a/crates/bevy_core_pipeline/src/prepass/node.rs +++ b/crates/bevy_core_pipeline/src/prepass/node.rs @@ -53,7 +53,7 @@ impl ViewNode for PrepassNode { skybox_prepass_pipeline, skybox_prepass_bind_group, view_prev_uniform_offset, - ): QueryItem<'w, Self::ViewQuery>, + ): QueryItem<'w, '_, Self::ViewQuery>, world: &'w World, ) -> Result<(), NodeRunError> { let (Some(opaque_prepass_phases), Some(alpha_mask_prepass_phases)) = ( diff --git a/crates/bevy_core_pipeline/src/skybox/mod.rs b/crates/bevy_core_pipeline/src/skybox/mod.rs index 59cfa908863c2..0014e5db52165 100644 --- a/crates/bevy_core_pipeline/src/skybox/mod.rs +++ b/crates/bevy_core_pipeline/src/skybox/mod.rs @@ -114,7 +114,9 @@ impl ExtractComponent for Skybox { type QueryFilter = (); type Out = (Self, SkyboxUniforms); - fn extract_component((skybox, exposure): QueryItem<'_, Self::QueryData>) -> Option { + fn extract_component( + (skybox, exposure): QueryItem<'_, '_, Self::QueryData>, + ) -> Option { let exposure = exposure .map(Exposure::exposure) .unwrap_or_else(|| Exposure::default().exposure()); diff --git a/crates/bevy_core_pipeline/src/smaa/mod.rs b/crates/bevy_core_pipeline/src/smaa/mod.rs index a41a77c806844..9ad199be0ee7c 100644 --- a/crates/bevy_core_pipeline/src/smaa/mod.rs +++ b/crates/bevy_core_pipeline/src/smaa/mod.rs @@ -845,7 +845,7 @@ impl ViewNode for SmaaNode { view_smaa_uniform_offset, smaa_textures, view_smaa_bind_groups, - ): QueryItem<'w, Self::ViewQuery>, + ): QueryItem<'w, '_, Self::ViewQuery>, world: &'w World, ) -> Result<(), NodeRunError> { let pipeline_cache = world.resource::(); diff --git a/crates/bevy_ecs/macros/src/query_data.rs b/crates/bevy_ecs/macros/src/query_data.rs index 0a78b705a062e..54512af8aaada 100644 --- a/crates/bevy_ecs/macros/src/query_data.rs +++ b/crates/bevy_ecs/macros/src/query_data.rs @@ -95,6 +95,7 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream { let user_generics_with_world = { let mut generics = ast.generics; generics.params.insert(0, parse_quote!('__w)); + generics.params.insert(0, parse_quote!('__s)); generics }; let (user_impl_generics_with_world, user_ty_generics_with_world, user_where_clauses_with_world) = diff --git a/crates/bevy_ecs/macros/src/query_filter.rs b/crates/bevy_ecs/macros/src/query_filter.rs index 378e26df101a7..fb06422576fe2 100644 --- a/crates/bevy_ecs/macros/src/query_filter.rs +++ b/crates/bevy_ecs/macros/src/query_filter.rs @@ -26,6 +26,7 @@ pub fn derive_query_filter_impl(input: TokenStream) -> TokenStream { let user_generics_with_world = { let mut generics = ast.generics; generics.params.insert(0, parse_quote!('__w)); + generics.params.insert(0, parse_quote!('__s)); generics }; let (user_impl_generics_with_world, user_ty_generics_with_world, user_where_clauses_with_world) = @@ -127,8 +128,8 @@ pub fn derive_query_filter_impl(input: TokenStream) -> TokenStream { #[allow(unused_variables)] #[inline(always)] - unsafe fn filter_fetch<'__w>( - _fetch: &mut ::Fetch<'__w>, + unsafe fn filter_fetch<'__w, '__s>( + _fetch: &mut ::Fetch<'__w, '__s>, _entity: #path::entity::Entity, _table_row: #path::storage::TableRow, ) -> bool { diff --git a/crates/bevy_ecs/macros/src/world_query.rs b/crates/bevy_ecs/macros/src/world_query.rs index 9d97f185dede9..e667f79a67be8 100644 --- a/crates/bevy_ecs/macros/src/world_query.rs +++ b/crates/bevy_ecs/macros/src/world_query.rs @@ -38,14 +38,14 @@ pub(crate) fn item_struct( #derive_macro_call #item_attrs #visibility struct #item_struct_name #user_impl_generics_with_world #user_where_clauses_with_world { - #(#(#field_attrs)* #field_visibilities #field_idents: <#field_types as #path::query::WorldQuery>::Item<'__w>,)* + #(#(#field_attrs)* #field_visibilities #field_idents: <#field_types as #path::query::WorldQuery>::Item<'__w, '__s>,)* } }, Fields::Unnamed(_) => quote! { #derive_macro_call #item_attrs #visibility struct #item_struct_name #user_impl_generics_with_world #user_where_clauses_with_world( - #( #field_visibilities <#field_types as #path::query::WorldQuery>::Item<'__w>, )* + #( #field_visibilities <#field_types as #path::query::WorldQuery>::Item<'__w, '__s>, )* ); }, Fields::Unit => quote! { @@ -88,8 +88,8 @@ pub(crate) fn world_query_impl( )] #[automatically_derived] #visibility struct #fetch_struct_name #user_impl_generics_with_world #user_where_clauses_with_world { - #(#named_field_idents: <#field_types as #path::query::WorldQuery>::Fetch<'__w>,)* - #marker_name: &'__w (), + #(#named_field_idents: <#field_types as #path::query::WorldQuery>::Fetch<'__w, '__s>,)* + #marker_name: (&'__w(), &'__s()), } impl #user_impl_generics_with_world Clone for #fetch_struct_name #user_ty_generics_with_world @@ -97,7 +97,7 @@ pub(crate) fn world_query_impl( fn clone(&self) -> Self { Self { #(#named_field_idents: self.#named_field_idents.clone(),)* - #marker_name: &(), + #marker_name: (&(), &()), } } } @@ -106,13 +106,13 @@ pub(crate) fn world_query_impl( unsafe impl #user_impl_generics #path::query::WorldQuery for #struct_name #user_ty_generics #user_where_clauses { - type Item<'__w> = #item_struct_name #user_ty_generics_with_world; - type Fetch<'__w> = #fetch_struct_name #user_ty_generics_with_world; + type Item<'__w, '__s> = #item_struct_name #user_ty_generics_with_world; + type Fetch<'__w, '__s> = #fetch_struct_name #user_ty_generics_with_world; type State = #state_struct_name #user_ty_generics; - fn shrink<'__wlong: '__wshort, '__wshort>( - item: <#struct_name #user_ty_generics as #path::query::WorldQuery>::Item<'__wlong> - ) -> <#struct_name #user_ty_generics as #path::query::WorldQuery>::Item<'__wshort> { + fn shrink<'__wlong: '__wshort, '__wshort, '__s>( + item: <#struct_name #user_ty_generics as #path::query::WorldQuery>::Item<'__wlong, '__s> + ) -> <#struct_name #user_ty_generics as #path::query::WorldQuery>::Item<'__wshort, '__s> { #item_struct_name { #( #field_idents: <#field_types>::shrink(item.#field_idents), @@ -120,23 +120,23 @@ pub(crate) fn world_query_impl( } } - fn shrink_fetch<'__wlong: '__wshort, '__wshort>( - fetch: <#struct_name #user_ty_generics as #path::query::WorldQuery>::Fetch<'__wlong> - ) -> <#struct_name #user_ty_generics as #path::query::WorldQuery>::Fetch<'__wshort> { + fn shrink_fetch<'__wlong: '__wshort, '__wshort, '__s>( + fetch: <#struct_name #user_ty_generics as #path::query::WorldQuery>::Fetch<'__wlong, '__s> + ) -> <#struct_name #user_ty_generics as #path::query::WorldQuery>::Fetch<'__wshort, '__s> { #fetch_struct_name { #( #named_field_idents: <#field_types>::shrink_fetch(fetch.#named_field_idents), )* - #marker_name: &(), + #marker_name: (&(), &()), } } - unsafe fn init_fetch<'__w>( + unsafe fn init_fetch<'__w, '__s>( _world: #path::world::unsafe_world_cell::UnsafeWorldCell<'__w>, - state: &Self::State, + state: &'__s Self::State, _last_run: #path::component::Tick, _this_run: #path::component::Tick, - ) -> ::Fetch<'__w> { + ) -> ::Fetch<'__w, '__s> { #fetch_struct_name { #(#named_field_idents: <#field_types>::init_fetch( @@ -146,7 +146,7 @@ pub(crate) fn world_query_impl( _this_run, ), )* - #marker_name: &(), + #marker_name: (&(), &()), } } @@ -154,9 +154,9 @@ pub(crate) fn world_query_impl( /// SAFETY: we call `set_archetype` for each member that implements `Fetch` #[inline] - unsafe fn set_archetype<'__w>( - _fetch: &mut ::Fetch<'__w>, - _state: &Self::State, + unsafe fn set_archetype<'__w, '__s>( + _fetch: &mut ::Fetch<'__w, '__s>, + _state: &'__s Self::State, _archetype: &'__w #path::archetype::Archetype, _table: &'__w #path::storage::Table ) { @@ -165,9 +165,9 @@ pub(crate) fn world_query_impl( /// SAFETY: we call `set_table` for each member that implements `Fetch` #[inline] - unsafe fn set_table<'__w>( - _fetch: &mut ::Fetch<'__w>, - _state: &Self::State, + unsafe fn set_table<'__w, '__s>( + _fetch: &mut ::Fetch<'__w, '__s>, + _state: &'__s Self::State, _table: &'__w #path::storage::Table ) { #(<#field_types>::set_table(&mut _fetch.#named_field_idents, &_state.#named_field_idents, _table);)* @@ -175,11 +175,11 @@ pub(crate) fn world_query_impl( /// SAFETY: we call `fetch` for each member that implements `Fetch`. #[inline(always)] - unsafe fn fetch<'__w>( - _fetch: &mut ::Fetch<'__w>, + unsafe fn fetch<'__w, '__s>( + _fetch: &mut ::Fetch<'__w, '__s>, _entity: #path::entity::Entity, _table_row: #path::storage::TableRow, - ) -> ::Item<'__w> { + ) -> ::Item<'__w, '__s> { Self::Item { #(#field_idents: <#field_types>::fetch(&mut _fetch.#named_field_idents, _entity, _table_row),)* } diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 1cb97aafca2fa..0e5aabf16890c 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -159,7 +159,7 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// } /// /// // `HealthQueryItem` is only available when accessing the query with mutable methods. -/// impl<'w> HealthQueryItem<'w> { +/// impl<'w, 's> HealthQueryItem<'w, 's> { /// fn damage(&mut self, value: f32) { /// self.health.0 -= value; /// } @@ -170,7 +170,7 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// } /// /// // `HealthQueryReadOnlyItem` is only available when accessing the query with immutable methods. -/// impl<'w> HealthQueryReadOnlyItem<'w> { +/// impl<'w, 's> HealthQueryReadOnlyItem<'w, 's> { /// fn total(&self) -> f32 { /// self.health.0 + self.buff.map_or(0.0, |Buff(buff)| *buff) /// } @@ -287,59 +287,68 @@ pub unsafe trait QueryData: WorldQuery { pub unsafe trait ReadOnlyQueryData: QueryData {} /// The item type returned when a [`WorldQuery`] is iterated over -pub type QueryItem<'w, Q> = ::Item<'w>; +pub type QueryItem<'w, 's, Q> = ::Item<'w, 's>; /// The read-only variant of the item type returned when a [`QueryData`] is iterated over immutably -pub type ROQueryItem<'w, D> = QueryItem<'w, ::ReadOnly>; +pub type ROQueryItem<'w, 's, D> = QueryItem<'w, 's, ::ReadOnly>; /// A [`QueryData`] that does not borrow from its [`QueryState`](crate::query::QueryState). pub trait ReleaseStateQueryData: QueryData { /// Releases the borrow from the query state by converting an item to have a `'static` state lifetime. - fn release_state(item: Self::Item<'_>) -> Self::Item<'_>; + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static>; } /// SAFETY: /// `update_component_access` and `update_archetype_component_access` do nothing. /// This is sound because `fetch` does not access components. unsafe impl WorldQuery for Entity { - type Item<'w> = Entity; - type Fetch<'w> = (); + type Item<'w, 's> = Entity; + type Fetch<'w, 's> = (); type State = (); - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { item } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {} + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + _: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { + } - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( _world: UnsafeWorldCell<'w>, - _state: &Self::State, + _state: &'s Self::State, _last_run: Tick, _this_run: Tick, - ) -> Self::Fetch<'w> { + ) -> Self::Fetch<'w, 's> { } const IS_DENSE: bool = true; #[inline] - unsafe fn set_archetype<'w>( - _fetch: &mut Self::Fetch<'w>, - _state: &Self::State, + unsafe fn set_archetype<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, _archetype: &'w Archetype, _table: &Table, ) { } #[inline] - unsafe fn set_table<'w>(_fetch: &mut Self::Fetch<'w>, _state: &Self::State, _table: &'w Table) { + unsafe fn set_table<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, + _table: &'w Table, + ) { } #[inline(always)] - unsafe fn fetch<'w>( - _fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, entity: Entity, _table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { entity } @@ -368,7 +377,7 @@ unsafe impl QueryData for Entity { unsafe impl ReadOnlyQueryData for Entity {} impl ReleaseStateQueryData for Entity { - fn release_state(item: Self::Item<'_>) -> Self::Item<'_> { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { item } } @@ -377,24 +386,28 @@ impl ReleaseStateQueryData for Entity { /// `update_component_access` and `update_archetype_component_access` do nothing. /// This is sound because `fetch` does not access components. unsafe impl WorldQuery for EntityLocation { - type Item<'w> = EntityLocation; - type Fetch<'w> = &'w Entities; + type Item<'w, 's> = EntityLocation; + type Fetch<'w, 's> = &'w Entities; type State = (); - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { item } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { fetch } - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, - _state: &Self::State, + _state: &'s Self::State, _last_run: Tick, _this_run: Tick, - ) -> Self::Fetch<'w> { + ) -> Self::Fetch<'w, 's> { world.entities() } @@ -403,24 +416,28 @@ unsafe impl WorldQuery for EntityLocation { const IS_DENSE: bool = true; #[inline] - unsafe fn set_archetype<'w>( - _fetch: &mut Self::Fetch<'w>, - _state: &Self::State, + unsafe fn set_archetype<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, _archetype: &'w Archetype, _table: &Table, ) { } #[inline] - unsafe fn set_table<'w>(_fetch: &mut Self::Fetch<'w>, _state: &Self::State, _table: &'w Table) { + unsafe fn set_table<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, + _table: &'w Table, + ) { } #[inline(always)] - unsafe fn fetch<'w>( - fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, entity: Entity, _table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { // SAFETY: `fetch` must be called with an entity that exists in the world unsafe { fetch.get(entity).debug_checked_unwrap() } } @@ -450,7 +467,7 @@ unsafe impl QueryData for EntityLocation { unsafe impl ReadOnlyQueryData for EntityLocation {} impl ReleaseStateQueryData for EntityLocation { - fn release_state(item: Self::Item<'_>) -> Self::Item<'_> { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { item } } @@ -460,48 +477,56 @@ impl ReleaseStateQueryData for EntityLocation { /// This is sound because `update_component_access` and `update_archetype_component_access` set read access for all components and panic when appropriate. /// Filters are unchanged. unsafe impl<'a> WorldQuery for EntityRef<'a> { - type Item<'w> = EntityRef<'w>; - type Fetch<'w> = UnsafeWorldCell<'w>; + type Item<'w, 's> = EntityRef<'w>; + type Fetch<'w, 's> = UnsafeWorldCell<'w>; type State = (); - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { item } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { fetch } - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, - _state: &Self::State, + _state: &'s Self::State, _last_run: Tick, _this_run: Tick, - ) -> Self::Fetch<'w> { + ) -> Self::Fetch<'w, 's> { world } const IS_DENSE: bool = true; #[inline] - unsafe fn set_archetype<'w>( - _fetch: &mut Self::Fetch<'w>, - _state: &Self::State, + unsafe fn set_archetype<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, _archetype: &'w Archetype, _table: &Table, ) { } #[inline] - unsafe fn set_table<'w>(_fetch: &mut Self::Fetch<'w>, _state: &Self::State, _table: &'w Table) { + unsafe fn set_table<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, + _table: &'w Table, + ) { } #[inline(always)] - unsafe fn fetch<'w>( - world: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + world: &mut Self::Fetch<'w, 's>, entity: Entity, _table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { // SAFETY: `fetch` must be called with an entity that exists in the world let cell = unsafe { world.get_entity(entity).debug_checked_unwrap() }; // SAFETY: Read-only access to every component has been registered. @@ -539,55 +564,63 @@ unsafe impl<'a> QueryData for EntityRef<'a> { unsafe impl ReadOnlyQueryData for EntityRef<'_> {} impl ReleaseStateQueryData for EntityRef<'_> { - fn release_state(item: Self::Item<'_>) -> Self::Item<'_> { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { item } } /// SAFETY: The accesses of `Self::ReadOnly` are a subset of the accesses of `Self` unsafe impl<'a> WorldQuery for EntityMut<'a> { - type Item<'w> = EntityMut<'w>; - type Fetch<'w> = UnsafeWorldCell<'w>; + type Item<'w, 's> = EntityMut<'w>; + type Fetch<'w, 's> = UnsafeWorldCell<'w>; type State = (); - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { item } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { fetch } - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, - _state: &Self::State, + _state: &'s Self::State, _last_run: Tick, _this_run: Tick, - ) -> Self::Fetch<'w> { + ) -> Self::Fetch<'w, 's> { world } const IS_DENSE: bool = true; #[inline] - unsafe fn set_archetype<'w>( - _fetch: &mut Self::Fetch<'w>, - _state: &Self::State, + unsafe fn set_archetype<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, _archetype: &'w Archetype, _table: &Table, ) { } #[inline] - unsafe fn set_table<'w>(_fetch: &mut Self::Fetch<'w>, _state: &Self::State, _table: &'w Table) { + unsafe fn set_table<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, + _table: &'w Table, + ) { } #[inline(always)] - unsafe fn fetch<'w>( - world: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + world: &mut Self::Fetch<'w, 's>, entity: Entity, _table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { // SAFETY: `fetch` must be called with an entity that exists in the world let cell = unsafe { world.get_entity(entity).debug_checked_unwrap() }; // SAFETY: mutable access to every component has been registered. @@ -622,42 +655,46 @@ unsafe impl<'a> QueryData for EntityMut<'a> { } impl ReleaseStateQueryData for EntityMut<'_> { - fn release_state(item: Self::Item<'_>) -> Self::Item<'_> { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { item } } /// SAFETY: The accesses of `Self::ReadOnly` are a subset of the accesses of `Self` unsafe impl<'a> WorldQuery for FilteredEntityRef<'a> { - type Fetch<'w> = (UnsafeWorldCell<'w>, Access); - type Item<'w> = FilteredEntityRef<'w>; + type Fetch<'w, 's> = (UnsafeWorldCell<'w>, Access); + type Item<'w, 's> = FilteredEntityRef<'w>; type State = FilteredAccess; - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { item } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { fetch } const IS_DENSE: bool = false; - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, - _state: &Self::State, + _state: &'s Self::State, _last_run: Tick, _this_run: Tick, - ) -> Self::Fetch<'w> { + ) -> Self::Fetch<'w, 's> { let mut access = Access::default(); access.read_all_components(); (world, access) } #[inline] - unsafe fn set_archetype<'w>( - fetch: &mut Self::Fetch<'w>, - state: &Self::State, + unsafe fn set_archetype<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, + state: &'s Self::State, _: &'w Archetype, _table: &Table, ) { @@ -665,7 +702,11 @@ unsafe impl<'a> WorldQuery for FilteredEntityRef<'a> { } #[inline] - unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, _: &'w Table) { + unsafe fn set_table<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, + state: &'s Self::State, + _: &'w Table, + ) { fetch.1.clone_from(&state.access); } @@ -676,11 +717,11 @@ unsafe impl<'a> WorldQuery for FilteredEntityRef<'a> { } #[inline(always)] - unsafe fn fetch<'w>( - (world, access): &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + (world, access): &mut Self::Fetch<'w, 's>, entity: Entity, _table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { // SAFETY: `fetch` must be called with an entity that exists in the world let cell = unsafe { world.get_entity(entity).debug_checked_unwrap() }; // SAFETY: mutable access to every component has been registered. @@ -724,35 +765,39 @@ unsafe impl ReadOnlyQueryData for FilteredEntityRef<'_> {} /// SAFETY: The accesses of `Self::ReadOnly` are a subset of the accesses of `Self` unsafe impl<'a> WorldQuery for FilteredEntityMut<'a> { - type Fetch<'w> = (UnsafeWorldCell<'w>, Access); - type Item<'w> = FilteredEntityMut<'w>; + type Fetch<'w, 's> = (UnsafeWorldCell<'w>, Access); + type Item<'w, 's> = FilteredEntityMut<'w>; type State = FilteredAccess; - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { item } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { fetch } const IS_DENSE: bool = false; - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, - _state: &Self::State, + _state: &'s Self::State, _last_run: Tick, _this_run: Tick, - ) -> Self::Fetch<'w> { + ) -> Self::Fetch<'w, 's> { let mut access = Access::default(); access.write_all_components(); (world, access) } #[inline] - unsafe fn set_archetype<'w>( - fetch: &mut Self::Fetch<'w>, - state: &Self::State, + unsafe fn set_archetype<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, + state: &'s Self::State, _: &'w Archetype, _table: &Table, ) { @@ -760,7 +805,11 @@ unsafe impl<'a> WorldQuery for FilteredEntityMut<'a> { } #[inline] - unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, _: &'w Table) { + unsafe fn set_table<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, + state: &'s Self::State, + _: &'w Table, + ) { fetch.1.clone_from(&state.access); } @@ -770,11 +819,11 @@ unsafe impl<'a> WorldQuery for FilteredEntityMut<'a> { } #[inline(always)] - unsafe fn fetch<'w>( - (world, access): &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + (world, access): &mut Self::Fetch<'w, 's>, entity: Entity, _table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { // SAFETY: `fetch` must be called with an entity that exists in the world let cell = unsafe { world.get_entity(entity).debug_checked_unwrap() }; // SAFETY: mutable access to every component has been registered. @@ -820,44 +869,48 @@ unsafe impl<'a, B> WorldQuery for EntityRefExcept<'a, B> where B: Bundle, { - type Fetch<'w> = UnsafeWorldCell<'w>; - type Item<'w> = EntityRefExcept<'w, B>; + type Fetch<'w, 's> = UnsafeWorldCell<'w>; + type Item<'w, 's> = EntityRefExcept<'w, B>; type State = SmallVec<[ComponentId; 4]>; - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { item } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { fetch } - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, - _: &Self::State, + _: &'s Self::State, _: Tick, _: Tick, - ) -> Self::Fetch<'w> { + ) -> Self::Fetch<'w, 's> { world } const IS_DENSE: bool = true; - unsafe fn set_archetype<'w>( - _: &mut Self::Fetch<'w>, - _: &Self::State, + unsafe fn set_archetype<'w, 's>( + _: &mut Self::Fetch<'w, 's>, + _: &'s Self::State, _: &'w Archetype, _: &'w Table, ) { } - unsafe fn set_table<'w>(_: &mut Self::Fetch<'w>, _: &Self::State, _: &'w Table) {} + unsafe fn set_table<'w, 's>(_: &mut Self::Fetch<'w, 's>, _: &'s Self::State, _: &'w Table) {} - unsafe fn fetch<'w>( - world: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + world: &mut Self::Fetch<'w, 's>, entity: Entity, _: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { let cell = world.get_entity(entity).unwrap(); EntityRefExcept::new(cell) } @@ -919,44 +972,48 @@ unsafe impl<'a, B> WorldQuery for EntityMutExcept<'a, B> where B: Bundle, { - type Fetch<'w> = UnsafeWorldCell<'w>; - type Item<'w> = EntityMutExcept<'w, B>; + type Fetch<'w, 's> = UnsafeWorldCell<'w>; + type Item<'w, 's> = EntityMutExcept<'w, B>; type State = SmallVec<[ComponentId; 4]>; - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { item } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { fetch } - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, - _: &Self::State, + _: &'s Self::State, _: Tick, _: Tick, - ) -> Self::Fetch<'w> { + ) -> Self::Fetch<'w, 's> { world } const IS_DENSE: bool = true; - unsafe fn set_archetype<'w>( - _: &mut Self::Fetch<'w>, - _: &Self::State, + unsafe fn set_archetype<'w, 's>( + _: &mut Self::Fetch<'w, 's>, + _: &'s Self::State, _: &'w Archetype, _: &'w Table, ) { } - unsafe fn set_table<'w>(_: &mut Self::Fetch<'w>, _: &Self::State, _: &'w Table) {} + unsafe fn set_table<'w, 's>(_: &mut Self::Fetch<'w, 's>, _: &'s Self::State, _: &'w Table) {} - unsafe fn fetch<'w>( - world: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + world: &mut Self::Fetch<'w, 's>, entity: Entity, _: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { let cell = world.get_entity(entity).unwrap(); EntityMutExcept::new(cell) } @@ -1012,24 +1069,28 @@ where /// `update_component_access` and `update_archetype_component_access` do nothing. /// This is sound because `fetch` does not access components. unsafe impl WorldQuery for &Archetype { - type Item<'w> = &'w Archetype; - type Fetch<'w> = (&'w Entities, &'w Archetypes); + type Item<'w, 's> = &'w Archetype; + type Fetch<'w, 's> = (&'w Entities, &'w Archetypes); type State = (); - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { item } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { fetch } - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, - _state: &Self::State, + _state: &'s Self::State, _last_run: Tick, _this_run: Tick, - ) -> Self::Fetch<'w> { + ) -> Self::Fetch<'w, 's> { (world.entities(), world.archetypes()) } @@ -1038,24 +1099,28 @@ unsafe impl WorldQuery for &Archetype { const IS_DENSE: bool = true; #[inline] - unsafe fn set_archetype<'w>( - _fetch: &mut Self::Fetch<'w>, - _state: &Self::State, + unsafe fn set_archetype<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, _archetype: &'w Archetype, _table: &Table, ) { } #[inline] - unsafe fn set_table<'w>(_fetch: &mut Self::Fetch<'w>, _state: &Self::State, _table: &'w Table) { + unsafe fn set_table<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, + _table: &'w Table, + ) { } #[inline(always)] - unsafe fn fetch<'w>( - fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, entity: Entity, _table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { let (entities, archetypes) = *fetch; // SAFETY: `fetch` must be called with an entity that exists in the world let location = unsafe { entities.get(entity).debug_checked_unwrap() }; @@ -1088,7 +1153,7 @@ unsafe impl QueryData for &Archetype { unsafe impl ReadOnlyQueryData for &Archetype {} impl ReleaseStateQueryData for &Archetype { - fn release_state(item: Self::Item<'_>) -> Self::Item<'_> { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { item } } @@ -1114,20 +1179,24 @@ impl Copy for ReadFetch<'_, T> {} /// `update_component_access` adds a `With` filter for a component. /// This is sound because `matches_component_set` returns whether the set contains that component. unsafe impl WorldQuery for &T { - type Item<'w> = &'w T; - type Fetch<'w> = ReadFetch<'w, T>; + type Item<'w, 's> = &'w T; + type Fetch<'w, 's> = ReadFetch<'w, T>; type State = ComponentId; - fn shrink<'wlong: 'wshort, 'wshort>(item: &'wlong T) -> &'wshort T { + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { item } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { fetch } #[inline] - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, &component_id: &ComponentId, _last_run: Tick, @@ -1188,11 +1257,11 @@ unsafe impl WorldQuery for &T { } #[inline(always)] - unsafe fn fetch<'w>( - fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, entity: Entity, table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { match T::STORAGE_TYPE { StorageType::Table => { // SAFETY: STORAGE_TYPE = Table @@ -1248,7 +1317,7 @@ unsafe impl QueryData for &T { unsafe impl ReadOnlyQueryData for &T {} impl ReleaseStateQueryData for &T { - fn release_state(item: Self::Item<'_>) -> Self::Item<'_> { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { item } } @@ -1282,20 +1351,24 @@ impl Copy for RefFetch<'_, T> {} /// `update_component_access` adds a `With` filter for a component. /// This is sound because `matches_component_set` returns whether the set contains that component. unsafe impl<'__w, T: Component> WorldQuery for Ref<'__w, T> { - type Item<'w> = Ref<'w, T>; - type Fetch<'w> = RefFetch<'w, T>; + type Item<'w, 's> = Ref<'w, T>; + type Fetch<'w, 's> = RefFetch<'w, T>; type State = ComponentId; - fn shrink<'wlong: 'wshort, 'wshort>(item: Ref<'wlong, T>) -> Ref<'wshort, T> { + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { item } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { fetch } #[inline] - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, &component_id: &ComponentId, last_run: Tick, @@ -1362,11 +1435,11 @@ unsafe impl<'__w, T: Component> WorldQuery for Ref<'__w, T> { } #[inline(always)] - unsafe fn fetch<'w>( - fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, entity: Entity, table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { match T::STORAGE_TYPE { StorageType::Table => { // SAFETY: STORAGE_TYPE = Table @@ -1453,7 +1526,7 @@ unsafe impl<'__w, T: Component> QueryData for Ref<'__w, T> { unsafe impl<'__w, T: Component> ReadOnlyQueryData for Ref<'__w, T> {} impl ReleaseStateQueryData for Ref<'_, T> { - fn release_state(item: Self::Item<'_>) -> Self::Item<'_> { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { item } } @@ -1487,20 +1560,24 @@ impl Copy for WriteFetch<'_, T> {} /// `update_component_access` adds a `With` filter for a component. /// This is sound because `matches_component_set` returns whether the set contains that component. unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T { - type Item<'w> = Mut<'w, T>; - type Fetch<'w> = WriteFetch<'w, T>; + type Item<'w, 's> = Mut<'w, T>; + type Fetch<'w, 's> = WriteFetch<'w, T>; type State = ComponentId; - fn shrink<'wlong: 'wshort, 'wshort>(item: Mut<'wlong, T>) -> Mut<'wshort, T> { + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { item } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { fetch } #[inline] - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, &component_id: &ComponentId, last_run: Tick, @@ -1567,11 +1644,11 @@ unsafe impl<'__w, T: Component> WorldQuery for &'__w mut T { } #[inline(always)] - unsafe fn fetch<'w>( - fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, entity: Entity, table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { match T::STORAGE_TYPE { StorageType::Table => { // SAFETY: STORAGE_TYPE = Table @@ -1655,7 +1732,7 @@ unsafe impl<'__w, T: Component> QueryData for &'__w mut T { } impl ReleaseStateQueryData for &mut T { - fn release_state(item: Self::Item<'_>) -> Self::Item<'_> { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { item } } @@ -1670,22 +1747,26 @@ impl ReleaseStateQueryData for &mut T { /// `update_component_access` adds a `With` filter for a component. /// This is sound because `matches_component_set` returns whether the set contains that component. unsafe impl<'__w, T: Component> WorldQuery for Mut<'__w, T> { - type Item<'w> = Mut<'w, T>; - type Fetch<'w> = WriteFetch<'w, T>; + type Item<'w, 's> = Mut<'w, T>; + type Fetch<'w, 's> = WriteFetch<'w, T>; type State = ComponentId; // Forwarded to `&mut T` - fn shrink<'wlong: 'wshort, 'wshort>(item: Mut<'wlong, T>) -> Mut<'wshort, T> { + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { <&mut T as WorldQuery>::shrink(item) } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { fetch } #[inline] // Forwarded to `&mut T` - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, state: &ComponentId, last_run: Tick, @@ -1716,13 +1797,13 @@ unsafe impl<'__w, T: Component> WorldQuery for Mut<'__w, T> { #[inline(always)] // Forwarded to `&mut T` - unsafe fn fetch<'w>( + unsafe fn fetch<'w, 's>( // Rust complains about lifetime bounds not matching the trait if I directly use `WriteFetch<'w, T>` right here. // But it complains nowhere else in the entire trait implementation. - fetch: &mut Self::Fetch<'w>, + fetch: &mut Self::Fetch<'w, 's>, entity: Entity, table_row: TableRow, - ) -> Mut<'w, T> { + ) -> Self::Item<'w, 's> { <&mut T as WorldQuery>::fetch(fetch, entity, table_row) } @@ -1766,18 +1847,18 @@ unsafe impl<'__w, T: Component> QueryData for Mut<'__w, T> { } impl ReleaseStateQueryData for Mut<'_, T> { - fn release_state(item: Self::Item<'_>) -> Self::Item<'_> { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { item } } #[doc(hidden)] -pub struct OptionFetch<'w, T: WorldQuery> { - fetch: T::Fetch<'w>, +pub struct OptionFetch<'w, 's, T: WorldQuery> { + fetch: T::Fetch<'w, 's>, matches: bool, } -impl Clone for OptionFetch<'_, T> { +impl Clone for OptionFetch<'_, '_, T> { fn clone(&self) -> Self { Self { fetch: self.fetch.clone(), @@ -1791,15 +1872,19 @@ impl Clone for OptionFetch<'_, T> { /// This is sound because `update_component_access` and `update_archetype_component_access` add the same accesses as `T`. /// Filters are unchanged. unsafe impl WorldQuery for Option { - type Item<'w> = Option>; - type Fetch<'w> = OptionFetch<'w, T>; + type Item<'w, 's> = Option>; + type Fetch<'w, 's> = OptionFetch<'w, 's, T>; type State = T::State; - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { item.map(T::shrink) } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { OptionFetch { fetch: T::shrink_fetch(fetch.fetch), matches: fetch.matches, @@ -1807,12 +1892,12 @@ unsafe impl WorldQuery for Option { } #[inline] - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, - state: &T::State, + state: &'s T::State, last_run: Tick, this_run: Tick, - ) -> OptionFetch<'w, T> { + ) -> OptionFetch<'w, 's, T> { OptionFetch { // SAFETY: The invariants are uphold by the caller. fetch: unsafe { T::init_fetch(world, state, last_run, this_run) }, @@ -1823,9 +1908,9 @@ unsafe impl WorldQuery for Option { const IS_DENSE: bool = T::IS_DENSE; #[inline] - unsafe fn set_archetype<'w>( - fetch: &mut OptionFetch<'w, T>, - state: &T::State, + unsafe fn set_archetype<'w, 's>( + fetch: &mut OptionFetch<'w, 's, T>, + state: &'s T::State, archetype: &'w Archetype, table: &'w Table, ) { @@ -1839,7 +1924,11 @@ unsafe impl WorldQuery for Option { } #[inline] - unsafe fn set_table<'w>(fetch: &mut OptionFetch<'w, T>, state: &T::State, table: &'w Table) { + unsafe fn set_table<'w, 's>( + fetch: &mut OptionFetch<'w, 's, T>, + state: &'s T::State, + table: &'w Table, + ) { fetch.matches = T::matches_component_set(state, &|id| table.has_column(id)); if fetch.matches { // SAFETY: The invariants are uphold by the caller. @@ -1850,11 +1939,11 @@ unsafe impl WorldQuery for Option { } #[inline(always)] - unsafe fn fetch<'w>( - fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, entity: Entity, table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { fetch .matches // SAFETY: The invariants are uphold by the caller. @@ -1975,25 +2064,29 @@ impl std::fmt::Debug for Has { /// `update_component_access` and `update_archetype_component_access` do nothing. /// This is sound because `fetch` does not access components. unsafe impl WorldQuery for Has { - type Item<'w> = bool; - type Fetch<'w> = bool; + type Item<'w, 's> = bool; + type Fetch<'w, 's> = bool; type State = ComponentId; - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { item } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { fetch } #[inline] - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( _world: UnsafeWorldCell<'w>, - _state: &Self::State, + _state: &'s Self::State, _last_run: Tick, _this_run: Tick, - ) -> Self::Fetch<'w> { + ) -> Self::Fetch<'w, 's> { false } @@ -2005,9 +2098,9 @@ unsafe impl WorldQuery for Has { }; #[inline] - unsafe fn set_archetype<'w>( - fetch: &mut Self::Fetch<'w>, - state: &Self::State, + unsafe fn set_archetype<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, + state: &'s Self::State, archetype: &'w Archetype, _table: &Table, ) { @@ -2015,16 +2108,20 @@ unsafe impl WorldQuery for Has { } #[inline] - unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table) { + unsafe fn set_table<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, + state: &'s Self::State, + table: &'w Table, + ) { *fetch = table.has_column(*state); } #[inline(always)] - unsafe fn fetch<'w>( - fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, _entity: Entity, _table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { *fetch } @@ -2061,7 +2158,7 @@ unsafe impl QueryData for Has { unsafe impl ReadOnlyQueryData for Has {} impl ReleaseStateQueryData for Has { - fn release_state(item: Self::Item<'_>) -> Self::Item<'_> { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { item } } @@ -2089,7 +2186,7 @@ macro_rules! impl_tuple_query_data { #[allow(clippy::unused_unit)] impl<$($name: ReleaseStateQueryData),*> ReleaseStateQueryData for ($($name,)*) { - fn release_state(($($item,)*): Self::Item<'_>) -> Self::Item<'_> { + fn release_state<'w>(($($item,)*): Self::Item<'w, '_>) -> Self::Item<'w, 'static> { ($($name::release_state($item),)*) } } @@ -2107,17 +2204,17 @@ macro_rules! impl_anytuple_fetch { /// `update_component_access` replaces the filters with a disjunction where every element is a conjunction of the previous filters and the filters of one of the subqueries. /// This is sound because `matches_component_set` returns a disjunction of the results of the subqueries' implementations. unsafe impl<$($name: WorldQuery),*> WorldQuery for AnyOf<($($name,)*)> { - type Fetch<'w> = ($(($name::Fetch<'w>, bool),)*); - type Item<'w> = ($(Option<$name::Item<'w>>,)*); + type Fetch<'w, 's> = ($(($name::Fetch<'w, 's>, bool),)*); + type Item<'w, 's> = ($(Option<$name::Item<'w, 's>>,)*); type State = ($($name::State,)*); - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + fn shrink<'wlong: 'wshort, 'wshort, 's>(item: Self::Item<'wlong, 's>) -> Self::Item<'wshort, 's> { let ($($name,)*) = item; ($( $name.map($name::shrink), )*) } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(fetch: Self::Fetch<'wlong, 's>) -> Self::Fetch<'wshort, 's> { let ($($name,)*) = fetch; ($( ($name::shrink_fetch($name.0), $name.1), @@ -2126,7 +2223,7 @@ macro_rules! impl_anytuple_fetch { #[inline] #[allow(clippy::unused_unit)] - unsafe fn init_fetch<'w>(_world: UnsafeWorldCell<'w>, state: &Self::State, _last_run: Tick, _this_run: Tick) -> Self::Fetch<'w> { + unsafe fn init_fetch<'w, 's>(_world: UnsafeWorldCell<'w>, state: &'s Self::State, _last_run: Tick, _this_run: Tick) -> Self::Fetch<'w, 's> { let ($($name,)*) = state; // SAFETY: The invariants are uphold by the caller. ($(( unsafe { $name::init_fetch(_world, $name, _last_run, _this_run) }, false),)*) @@ -2135,9 +2232,9 @@ macro_rules! impl_anytuple_fetch { const IS_DENSE: bool = true $(&& $name::IS_DENSE)*; #[inline] - unsafe fn set_archetype<'w>( - _fetch: &mut Self::Fetch<'w>, - _state: &Self::State, + unsafe fn set_archetype<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, _archetype: &'w Archetype, _table: &'w Table ) { @@ -2153,7 +2250,7 @@ macro_rules! impl_anytuple_fetch { } #[inline] - unsafe fn set_table<'w>(_fetch: &mut Self::Fetch<'w>, _state: &Self::State, _table: &'w Table) { + unsafe fn set_table<'w, 's>(_fetch: &mut Self::Fetch<'w, 's>, _state: &'s Self::State, _table: &'w Table) { let ($($name,)*) = _fetch; let ($($state,)*) = _state; $( @@ -2167,11 +2264,11 @@ macro_rules! impl_anytuple_fetch { #[inline(always)] #[allow(clippy::unused_unit)] - unsafe fn fetch<'w>( - _fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, _entity: Entity, _table_row: TableRow - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { let ($($name,)*) = _fetch; ($( // SAFETY: The invariants are required to be upheld by the caller. @@ -2232,7 +2329,7 @@ macro_rules! impl_anytuple_fetch { #[allow(clippy::unused_unit)] impl<$($name: ReleaseStateQueryData),*> ReleaseStateQueryData for AnyOf<($($name,)*)> { - fn release_state(($($item,)*): Self::Item<'_>) -> Self::Item<'_> { + fn release_state<'w>(($($item,)*): Self::Item<'w, '_>) -> Self::Item<'w, 'static> { ($($item.map(|$item| $name::release_state($item)),)*) } } @@ -2258,13 +2355,19 @@ pub(crate) struct NopWorldQuery(PhantomData); /// `update_component_access` and `update_archetype_component_access` do nothing. /// This is sound because `fetch` does not access components. unsafe impl WorldQuery for NopWorldQuery { - type Item<'w> = (); - type Fetch<'w> = (); + type Item<'w, 's> = (); + type Fetch<'w, 's> = (); type State = D::State; - fn shrink<'wlong: 'wshort, 'wshort>(_: ()) {} + fn shrink<'wlong: 'wshort, 'wshort, 's>( + _item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { + } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: ()) {} + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + _fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { + } #[inline(always)] unsafe fn init_fetch( @@ -2290,11 +2393,11 @@ unsafe impl WorldQuery for NopWorldQuery { unsafe fn set_table<'w>(_fetch: &mut (), _state: &D::State, _table: &Table) {} #[inline(always)] - unsafe fn fetch<'w>( - _fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, _entity: Entity, _table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { } fn update_component_access(_state: &D::State, _access: &mut FilteredAccess) {} @@ -2324,51 +2427,60 @@ unsafe impl QueryData for NopWorldQuery { unsafe impl ReadOnlyQueryData for NopWorldQuery {} impl ReleaseStateQueryData for NopWorldQuery { - fn release_state(_item: Self::Item<'_>) -> Self::Item<'_> {} + fn release_state<'w>(_item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {} } /// SAFETY: /// `update_component_access` and `update_archetype_component_access` do nothing. /// This is sound because `fetch` does not access components. unsafe impl WorldQuery for PhantomData { - type Item<'a> = (); - type Fetch<'a> = (); + type Item<'w, 's> = (); + type Fetch<'w, 's> = (); type State = (); - fn shrink<'wlong: 'wshort, 'wshort>(_item: Self::Item<'wlong>) -> Self::Item<'wshort> {} + fn shrink<'wlong: 'wshort, 'wshort, 's>( + _item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { + } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(_fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + _fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { } - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( _world: UnsafeWorldCell<'w>, - _state: &Self::State, + _state: &'s Self::State, _last_run: Tick, _this_run: Tick, - ) -> Self::Fetch<'w> { + ) -> Self::Fetch<'w, 's> { } // `PhantomData` does not match any components, so all components it matches // are stored in a Table (vacuous truth). const IS_DENSE: bool = true; - unsafe fn set_archetype<'w>( - _fetch: &mut Self::Fetch<'w>, - _state: &Self::State, + unsafe fn set_archetype<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, _archetype: &'w Archetype, _table: &'w Table, ) { } - unsafe fn set_table<'w>(_fetch: &mut Self::Fetch<'w>, _state: &Self::State, _table: &'w Table) { + unsafe fn set_table<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, + _table: &'w Table, + ) { } - unsafe fn fetch<'w>( - _fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, _entity: Entity, _table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { } fn update_component_access(_state: &Self::State, _access: &mut FilteredAccess) {} @@ -2396,7 +2508,7 @@ unsafe impl QueryData for PhantomData { unsafe impl ReadOnlyQueryData for PhantomData {} impl ReleaseStateQueryData for PhantomData { - fn release_state(_item: Self::Item<'_>) -> Self::Item<'_> {} + fn release_state<'w>(_item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> {} } #[cfg(test)] diff --git a/crates/bevy_ecs/src/query/filter.rs b/crates/bevy_ecs/src/query/filter.rs index ee447ec99bc42..72b4060aaa335 100644 --- a/crates/bevy_ecs/src/query/filter.rs +++ b/crates/bevy_ecs/src/query/filter.rs @@ -100,7 +100,7 @@ pub unsafe trait QueryFilter: WorldQuery { /// `table_row` must be in the range of the current table and archetype. #[allow(unused_variables)] unsafe fn filter_fetch( - fetch: &mut Self::Fetch<'_>, + fetch: &mut Self::Fetch<'_, '_>, entity: Entity, table_row: TableRow, ) -> bool; @@ -141,13 +141,19 @@ pub struct With(PhantomData); /// `update_component_access` adds a `With` filter for `T`. /// This is sound because `matches_component_set` returns whether the set contains the component. unsafe impl WorldQuery for With { - type Item<'w> = (); - type Fetch<'w> = (); + type Item<'w, 's> = (); + type Fetch<'w, 's> = (); type State = ComponentId; - fn shrink<'wlong: 'wshort, 'wshort>(_: Self::Item<'wlong>) -> Self::Item<'wshort> {} + fn shrink<'wlong: 'wshort, 'wshort, 's>( + _item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { + } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {} + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + _: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { + } #[inline] unsafe fn init_fetch( @@ -178,11 +184,11 @@ unsafe impl WorldQuery for With { unsafe fn set_table(_fetch: &mut (), _state: &ComponentId, _table: &Table) {} #[inline(always)] - unsafe fn fetch<'w>( - _fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, _entity: Entity, _table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { } #[inline] @@ -212,7 +218,7 @@ unsafe impl QueryFilter for With { #[inline(always)] unsafe fn filter_fetch( - _fetch: &mut Self::Fetch<'_>, + _fetch: &mut Self::Fetch<'_, '_>, _entity: Entity, _table_row: TableRow, ) -> bool { @@ -252,13 +258,19 @@ pub struct Without(PhantomData); /// `update_component_access` adds a `Without` filter for `T`. /// This is sound because `matches_component_set` returns whether the set does not contain the component. unsafe impl WorldQuery for Without { - type Item<'w> = (); - type Fetch<'w> = (); + type Item<'w, 's> = (); + type Fetch<'w, 's> = (); type State = ComponentId; - fn shrink<'wlong: 'wshort, 'wshort>(_: Self::Item<'wlong>) -> Self::Item<'wshort> {} + fn shrink<'wlong: 'wshort, 'wshort, 's>( + _item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { + } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {} + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + _: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { + } #[inline] unsafe fn init_fetch( @@ -289,11 +301,11 @@ unsafe impl WorldQuery for Without { unsafe fn set_table(_fetch: &mut (), _state: &Self::State, _table: &Table) {} #[inline(always)] - unsafe fn fetch<'w>( - _fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, _entity: Entity, _table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { } #[inline] @@ -323,7 +335,7 @@ unsafe impl QueryFilter for Without { #[inline(always)] unsafe fn filter_fetch( - _fetch: &mut Self::Fetch<'_>, + _fetch: &mut Self::Fetch<'_, '_>, _entity: Entity, _table_row: TableRow, ) -> bool { @@ -364,12 +376,12 @@ unsafe impl QueryFilter for Without { pub struct Or(PhantomData); #[doc(hidden)] -pub struct OrFetch<'w, T: WorldQuery> { - fetch: T::Fetch<'w>, +pub struct OrFetch<'w, 's, T: WorldQuery> { + fetch: T::Fetch<'w, 's>, matches: bool, } -impl Clone for OrFetch<'_, T> { +impl Clone for OrFetch<'_, '_, T> { fn clone(&self) -> Self { Self { fetch: self.fetch.clone(), @@ -389,15 +401,15 @@ macro_rules! impl_or_query_filter { /// `update_component_access` replace the filters with a disjunction where every element is a conjunction of the previous filters and the filters of one of the subqueries. /// This is sound because `matches_component_set` returns a disjunction of the results of the subqueries' implementations. unsafe impl<$($filter: QueryFilter),*> WorldQuery for Or<($($filter,)*)> { - type Fetch<'w> = ($(OrFetch<'w, $filter>,)*); - type Item<'w> = bool; + type Fetch<'w, 's> = ($(OrFetch<'w, 's, $filter>,)*); + type Item<'w, 's> =bool; type State = ($($filter::State,)*); - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + fn shrink<'wlong: 'wshort, 'wshort, 's>(item: Self::Item<'wlong, 's>) -> Self::Item<'wshort, 's> { item } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(fetch: Self::Fetch<'wlong, 's>) -> Self::Fetch<'wshort, 's> { let ($($filter,)*) = fetch; ($( OrFetch { @@ -410,7 +422,7 @@ macro_rules! impl_or_query_filter { const IS_DENSE: bool = true $(&& $filter::IS_DENSE)*; #[inline] - unsafe fn init_fetch<'w>(world: UnsafeWorldCell<'w>, state: &Self::State, last_run: Tick, this_run: Tick) -> Self::Fetch<'w> { + unsafe fn init_fetch<'w, 's>(world: UnsafeWorldCell<'w>, state: &'s Self::State, last_run: Tick, this_run: Tick) -> Self::Fetch<'w, 's> { let ($($filter,)*) = state; ($(OrFetch { // SAFETY: The invariants are uphold by the caller. @@ -420,7 +432,7 @@ macro_rules! impl_or_query_filter { } #[inline] - unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table) { + unsafe fn set_table<'w, 's>(fetch: &mut Self::Fetch<'w, 's>, state: &'s Self::State, table: &'w Table) { let ($($filter,)*) = fetch; let ($($state,)*) = state; $( @@ -433,9 +445,9 @@ macro_rules! impl_or_query_filter { } #[inline] - unsafe fn set_archetype<'w>( - fetch: &mut Self::Fetch<'w>, - state: & Self::State, + unsafe fn set_archetype<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, + state: &'s Self::State, archetype: &'w Archetype, table: &'w Table ) { @@ -451,11 +463,11 @@ macro_rules! impl_or_query_filter { } #[inline(always)] - unsafe fn fetch<'w>( - fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, _entity: Entity, _table_row: TableRow - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { let ($($filter,)*) = fetch; // SAFETY: The invariants are uphold by the caller. false $(|| ($filter.matches && unsafe { $filter::filter_fetch(&mut $filter.fetch, _entity, _table_row) }))* @@ -503,7 +515,7 @@ macro_rules! impl_or_query_filter { #[inline(always)] unsafe fn filter_fetch( - fetch: &mut Self::Fetch<'_>, + fetch: &mut Self::Fetch<'_, '_>, entity: Entity, table_row: TableRow ) -> bool { @@ -526,7 +538,7 @@ macro_rules! impl_tuple_query_filter { #[inline(always)] unsafe fn filter_fetch( - fetch: &mut Self::Fetch<'_>, + fetch: &mut Self::Fetch<'_, '_>, _entity: Entity, _table_row: TableRow ) -> bool { @@ -629,26 +641,30 @@ pub struct AddedFetch<'w> { /// `update_component_access` adds a `With` filter for a component. /// This is sound because `matches_component_set` returns whether the set contains that component. unsafe impl WorldQuery for Added { - type Item<'w> = bool; - type Fetch<'w> = AddedFetch<'w>; + type Item<'w, 's> = bool; + type Fetch<'w, 's> = AddedFetch<'w>; type State = ComponentId; - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { item } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { fetch } #[inline] - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, - &id: &ComponentId, + &id: &'s ComponentId, last_run: Tick, this_run: Tick, - ) -> Self::Fetch<'w> { - Self::Fetch::<'w> { + ) -> Self::Fetch<'w, 's> { + Self::Fetch::<'w, 's> { table_ticks: None, sparse_set: (T::STORAGE_TYPE == StorageType::SparseSet) .then(|| world.storages().sparse_sets.get(id).debug_checked_unwrap()), @@ -665,9 +681,9 @@ unsafe impl WorldQuery for Added { }; #[inline] - unsafe fn set_archetype<'w>( - fetch: &mut Self::Fetch<'w>, - component_id: &ComponentId, + unsafe fn set_archetype<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, + component_id: &'s ComponentId, _archetype: &'w Archetype, table: &'w Table, ) { @@ -680,9 +696,9 @@ unsafe impl WorldQuery for Added { } #[inline] - unsafe fn set_table<'w>( - fetch: &mut Self::Fetch<'w>, - &component_id: &ComponentId, + unsafe fn set_table<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, + &component_id: &'s ComponentId, table: &'w Table, ) { fetch.table_ticks = Some( @@ -694,11 +710,11 @@ unsafe impl WorldQuery for Added { } #[inline(always)] - unsafe fn fetch<'w>( - fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, entity: Entity, table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { match T::STORAGE_TYPE { StorageType::Table => { // SAFETY: STORAGE_TYPE = Table @@ -750,7 +766,7 @@ unsafe impl QueryFilter for Added { const IS_ARCHETYPAL: bool = false; #[inline(always)] unsafe fn filter_fetch( - fetch: &mut Self::Fetch<'_>, + fetch: &mut Self::Fetch<'_, '_>, entity: Entity, table_row: TableRow, ) -> bool { @@ -847,26 +863,30 @@ pub struct ChangedFetch<'w> { /// `update_component_access` adds a `With` filter for a component. /// This is sound because `matches_component_set` returns whether the set contains that component. unsafe impl WorldQuery for Changed { - type Item<'w> = bool; - type Fetch<'w> = ChangedFetch<'w>; + type Item<'w, 's> = bool; + type Fetch<'w, 's> = ChangedFetch<'w>; type State = ComponentId; - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { item } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { fetch } #[inline] - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, - &id: &ComponentId, + &id: &'s ComponentId, last_run: Tick, this_run: Tick, - ) -> Self::Fetch<'w> { - Self::Fetch::<'w> { + ) -> Self::Fetch<'w, 's> { + Self::Fetch::<'w, 's> { table_ticks: None, sparse_set: (T::STORAGE_TYPE == StorageType::SparseSet) .then(|| world.storages().sparse_sets.get(id).debug_checked_unwrap()), @@ -883,9 +903,9 @@ unsafe impl WorldQuery for Changed { }; #[inline] - unsafe fn set_archetype<'w>( - fetch: &mut Self::Fetch<'w>, - component_id: &ComponentId, + unsafe fn set_archetype<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, + component_id: &'s ComponentId, _archetype: &'w Archetype, table: &'w Table, ) { @@ -898,9 +918,9 @@ unsafe impl WorldQuery for Changed { } #[inline] - unsafe fn set_table<'w>( - fetch: &mut Self::Fetch<'w>, - &component_id: &ComponentId, + unsafe fn set_table<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, + &component_id: &'s ComponentId, table: &'w Table, ) { fetch.table_ticks = Some( @@ -912,11 +932,11 @@ unsafe impl WorldQuery for Changed { } #[inline(always)] - unsafe fn fetch<'w>( - fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, entity: Entity, table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { match T::STORAGE_TYPE { StorageType::Table => { // SAFETY: STORAGE_TYPE = Table @@ -969,7 +989,7 @@ unsafe impl QueryFilter for Changed { #[inline(always)] unsafe fn filter_fetch( - fetch: &mut Self::Fetch<'_>, + fetch: &mut Self::Fetch<'_, '_>, entity: Entity, table_row: TableRow, ) -> bool { diff --git a/crates/bevy_ecs/src/query/iter.rs b/crates/bevy_ecs/src/query/iter.rs index ff5bfd7a07f62..23fc040be9a15 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -136,7 +136,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { range: Option>, ) -> B where - Func: FnMut(B, D::Item<'w>) -> B, + Func: FnMut(B, D::Item<'w, 's>) -> B, { if self.cursor.is_dense { // SAFETY: `self.cursor.is_dense` is true, so storage ids are guaranteed to be table ids. @@ -199,7 +199,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { rows: Range, ) -> B where - Func: FnMut(B, D::Item<'w>) -> B, + Func: FnMut(B, D::Item<'w, 's>) -> B, { if table.is_empty() { return accum; @@ -254,7 +254,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { indices: Range, ) -> B where - Func: FnMut(B, D::Item<'w>) -> B, + Func: FnMut(B, D::Item<'w, 's>) -> B, { if archetype.is_empty() { return accum; @@ -323,7 +323,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { rows: Range, ) -> B where - Func: FnMut(B, D::Item<'w>) -> B, + Func: FnMut(B, D::Item<'w, 's>) -> B, { if archetype.is_empty() { return accum; @@ -484,7 +484,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// # schedule.add_systems((system_1, system_2, system_3)); /// # schedule.run(&mut world); /// ``` - pub fn sort: Ord> + ReleaseStateQueryData + 'w>( + pub fn sort: Ord> + ReleaseStateQueryData + 'w>( self, ) -> QuerySortedIter< 'w, @@ -577,7 +577,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// # schedule.run(&mut world); /// ``` pub fn sort_unstable< - L: ReadOnlyQueryData: Ord> + ReleaseStateQueryData + 'w, + L: ReadOnlyQueryData: Ord> + ReleaseStateQueryData + 'w, >( self, ) -> QuerySortedIter< @@ -679,7 +679,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// ``` pub fn sort_by( self, - mut compare: impl FnMut(&L::Item<'w>, &L::Item<'w>) -> Ordering, + mut compare: impl FnMut(&L::Item<'w, 'static>, &L::Item<'w, 'static>) -> Ordering, ) -> QuerySortedIter< 'w, 's, @@ -745,7 +745,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty. pub fn sort_unstable_by( self, - mut compare: impl FnMut(&L::Item<'w>, &L::Item<'w>) -> Ordering, + mut compare: impl FnMut(&L::Item<'w, 'static>, &L::Item<'w, 'static>) -> Ordering, ) -> QuerySortedIter< 'w, 's, @@ -871,7 +871,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// ``` pub fn sort_by_key( self, - mut f: impl FnMut(&L::Item<'w>) -> K, + mut f: impl FnMut(&L::Item<'w, 'static>) -> K, ) -> QuerySortedIter< 'w, 's, @@ -940,7 +940,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty. pub fn sort_unstable_by_key( self, - mut f: impl FnMut(&L::Item<'w>) -> K, + mut f: impl FnMut(&L::Item<'w, 'static>) -> K, ) -> QuerySortedIter< 'w, 's, @@ -1010,7 +1010,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// pub fn sort_by_cached_key( self, - mut f: impl FnMut(&L::Item<'w>) -> K, + mut f: impl FnMut(&L::Item<'w, 'static>) -> K, ) -> QuerySortedIter< 'w, 's, @@ -1062,7 +1062,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { } impl<'w, 's, D: QueryData, F: QueryFilter> Iterator for QueryIter<'w, 's, D, F> { - type Item = D::Item<'w>; + type Item = D::Item<'w, 's>; #[inline(always)] fn next(&mut self) -> Option { @@ -1125,7 +1125,7 @@ where entities: &'w Entities, tables: &'w Tables, archetypes: &'w Archetypes, - fetch: D::Fetch<'w>, + fetch: D::Fetch<'w, 's>, query_state: &'s QueryState, } @@ -1160,7 +1160,7 @@ where /// # Safety /// `entity` must stem from `self.entity_iter`, and not have been passed before. #[inline(always)] - unsafe fn fetch_next(&mut self, entity: Entity) -> D::Item<'w> { + unsafe fn fetch_next(&mut self, entity: Entity) -> D::Item<'w, 's> { let (location, archetype, table); // SAFETY: // `tables` and `archetypes` belong to the same world that the [`QueryIter`] @@ -1198,7 +1198,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> Iterator where I: Iterator, { - type Item = D::Item<'w>; + type Item = D::Item<'w, 's>; #[inline(always)] fn next(&mut self) -> Option { @@ -1259,8 +1259,8 @@ pub struct QueryManyIter<'w, 's, D: QueryData, F: QueryFilter, I: Iterator, - filter: F::Fetch<'w>, + fetch: D::Fetch<'w, 's>, + filter: F::Fetch<'w, 's>, query_state: &'s QueryState, } @@ -1306,10 +1306,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator>> entities: &'w Entities, tables: &'w Tables, archetypes: &'w Archetypes, - fetch: &mut D::Fetch<'w>, - filter: &mut F::Fetch<'w>, + fetch: &mut D::Fetch<'w, 's>, + filter: &mut F::Fetch<'w, 's>, query_state: &'s QueryState, - ) -> Option> { + ) -> Option> { for entity in entity_iter { let entity = *entity.borrow(); let Some(location) = entities.get(entity) else { @@ -1351,7 +1351,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator>> /// Get next result from the query #[inline(always)] - pub fn fetch_next(&mut self) -> Option> { + pub fn fetch_next(&mut self) -> Option> { // SAFETY: // All arguments stem from self. // We are limiting the returned reference to self, @@ -1377,7 +1377,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: DoubleEndedIterator Option> { + pub fn fetch_next_back(&mut self) -> Option> { // SAFETY: // All arguments stem from self. // We are limiting the returned reference to self, @@ -1401,7 +1401,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: DoubleEndedIterator>> Iterator for QueryManyIter<'w, 's, D, F, I> { - type Item = D::Item<'w>; + type Item = D::Item<'w, 's>; #[inline(always)] fn next(&mut self) -> Option { @@ -1587,7 +1587,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, const K: usize> QueryCombinationIter< ///. /// It is always safe for shared access. #[inline] - unsafe fn fetch_next_aliased_unchecked(&mut self) -> Option<[D::Item<'w>; K]> { + unsafe fn fetch_next_aliased_unchecked(&mut self) -> Option<[D::Item<'w, 's>; K]> { // PERF: can speed up the following code using `cursor.remaining()` instead of `next_item.is_none()` // when D::IS_ARCHETYPAL && F::IS_ARCHETYPAL // @@ -1613,9 +1613,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter, const K: usize> QueryCombinationIter< } } - let mut values = MaybeUninit::<[D::Item<'w>; K]>::uninit(); + let mut values = MaybeUninit::<[D::Item<'w, 's>; K]>::uninit(); - let ptr = values.as_mut_ptr().cast::>(); + let ptr = values.as_mut_ptr().cast::>(); for (offset, cursor) in self.cursors.iter_mut().enumerate() { ptr.add(offset).write(cursor.peek_last().unwrap()); } @@ -1625,7 +1625,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, const K: usize> QueryCombinationIter< /// Get next combination of queried components #[inline] - pub fn fetch_next(&mut self) -> Option<[D::Item<'_>; K]> { + pub fn fetch_next(&mut self) -> Option<[D::Item<'_, 's>; K]> { // SAFETY: we are limiting the returned reference to self, // making sure this method cannot be called multiple times without getting rid // of any previously returned unique references first, thus preventing aliasing. @@ -1642,7 +1642,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, const K: usize> QueryCombinationIter< impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, const K: usize> Iterator for QueryCombinationIter<'w, 's, D, F, K> { - type Item = [D::Item<'w>; K]; + type Item = [D::Item<'w, 's>; K]; #[inline] fn next(&mut self) -> Option { @@ -1711,8 +1711,8 @@ struct QueryIterationCursor<'w, 's, D: QueryData, F: QueryFilter> { storage_id_iter: std::slice::Iter<'s, StorageId>, table_entities: &'w [Entity], archetype_entities: &'w [ArchetypeEntity], - fetch: D::Fetch<'w>, - filter: F::Fetch<'w>, + fetch: D::Fetch<'w, 's>, + filter: F::Fetch<'w, 's>, // length of the table or length of the archetype, depending on whether both `D`'s and `F`'s fetches are dense current_len: usize, // either table row or archetype index, depending on whether both `D`'s and `F`'s fetches are dense @@ -1792,7 +1792,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIterationCursor<'w, 's, D, F> { /// The result of `next` and any previous calls to `peek_last` with this row must have been /// dropped to prevent aliasing mutable references. #[inline] - unsafe fn peek_last(&mut self) -> Option> { + unsafe fn peek_last(&mut self) -> Option> { if self.current_row > 0 { let index = self.current_row - 1; if self.is_dense { @@ -1855,7 +1855,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIterationCursor<'w, 's, D, F> { tables: &'w Tables, archetypes: &'w Archetypes, query_state: &'s QueryState, - ) -> Option> { + ) -> Option> { if self.is_dense { loop { // we are on the beginning of the query, or finished processing a table, so skip to the next diff --git a/crates/bevy_ecs/src/query/par_iter.rs b/crates/bevy_ecs/src/query/par_iter.rs index b3ea93fbbc514..2f72a9b4669ac 100644 --- a/crates/bevy_ecs/src/query/par_iter.rs +++ b/crates/bevy_ecs/src/query/par_iter.rs @@ -34,7 +34,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryParIter<'w, 's, D, F> { /// /// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool #[inline] - pub fn for_each) + Send + Sync + Clone>(self, func: FN) { + pub fn for_each) + Send + Sync + Clone>(self, func: FN) { self.for_each_init(|| {}, |_, item| func(item)); } @@ -71,7 +71,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryParIter<'w, 's, D, F> { #[inline] pub fn for_each_init(self, init: INIT, func: FN) where - FN: Fn(&mut T, QueryItem<'w, D>) + Send + Sync + Clone, + FN: Fn(&mut T, QueryItem<'w, 's, D>) + Send + Sync + Clone, INIT: Fn() -> T + Sync + Send + Clone, { let func = |mut init, item| { diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index 6ac740255c055..e666b64d2ec22 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -744,7 +744,7 @@ impl QueryState { &mut self, world: &'w World, entity: Entity, - ) -> Result, QueryEntityError> { + ) -> Result, QueryEntityError> { self.update_archetypes(world); // SAFETY: query is read only unsafe { @@ -794,7 +794,7 @@ impl QueryState { &mut self, world: &'w World, entities: [Entity; N], - ) -> Result<[ROQueryItem<'w, D>; N], QueryEntityError> { + ) -> Result<[ROQueryItem<'w, '_, D>; N], QueryEntityError> { self.update_archetypes(world); // SAFETY: @@ -818,7 +818,7 @@ impl QueryState { &mut self, world: &'w mut World, entity: Entity, - ) -> Result, QueryEntityError> { + ) -> Result, QueryEntityError> { self.update_archetypes(world); let change_tick = world.change_tick(); let last_change_tick = world.last_change_tick(); @@ -876,7 +876,7 @@ impl QueryState { &mut self, world: &'w mut World, entities: [Entity; N], - ) -> Result<[D::Item<'w>; N], QueryEntityError> { + ) -> Result<[D::Item<'w, '_>; N], QueryEntityError> { self.update_archetypes(world); let change_tick = world.change_tick(); @@ -911,7 +911,7 @@ impl QueryState { &self, world: &'w World, entity: Entity, - ) -> Result, QueryEntityError> { + ) -> Result, QueryEntityError> { self.validate_world(world.id()); // SAFETY: query is read only and world is validated unsafe { @@ -937,7 +937,7 @@ impl QueryState { &mut self, world: UnsafeWorldCell<'w>, entity: Entity, - ) -> Result, QueryEntityError> { + ) -> Result, QueryEntityError> { self.update_archetypes_unsafe_world_cell(world); self.get_unchecked_manual(world, entity, world.last_change_tick(), world.change_tick()) } @@ -960,7 +960,7 @@ impl QueryState { entity: Entity, last_run: Tick, this_run: Tick, - ) -> Result, QueryEntityError> { + ) -> Result, QueryEntityError> { let location = world .entities() .get(entity) @@ -1008,7 +1008,7 @@ impl QueryState { entities: [Entity; N], last_run: Tick, this_run: Tick, - ) -> Result<[ROQueryItem<'w, D>; N], QueryEntityError> { + ) -> Result<[ROQueryItem<'w, '_, D>; N], QueryEntityError> { let mut values = [(); N].map(|_| MaybeUninit::uninit()); for (value, entity) in std::iter::zip(&mut values, entities) { @@ -1042,7 +1042,7 @@ impl QueryState { entities: [Entity; N], last_run: Tick, this_run: Tick, - ) -> Result<[D::Item<'w>; N], QueryEntityError> { + ) -> Result<[D::Item<'w, '_>; N], QueryEntityError> { // Verify that all entities are unique for i in 0..N { for j in 0..i { @@ -1483,8 +1483,8 @@ impl QueryState { /// /// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool #[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))] - pub(crate) unsafe fn par_fold_init_unchecked_manual<'w, T, FN, INIT>( - &self, + pub(crate) unsafe fn par_fold_init_unchecked_manual<'w, 's, T, FN, INIT>( + &'s self, init_accum: INIT, world: UnsafeWorldCell<'w>, batch_size: usize, @@ -1492,7 +1492,7 @@ impl QueryState { last_run: Tick, this_run: Tick, ) where - FN: Fn(T, D::Item<'w>) -> T + Send + Sync + Clone, + FN: Fn(T, D::Item<'w, 's>) -> T + Send + Sync + Clone, INIT: Fn() -> T + Sync + Send + Clone, { // NOTE: If you are changing query iteration code, remember to update the following places, where relevant: @@ -1588,7 +1588,7 @@ impl QueryState { /// [`get_single`](Self::get_single) to return a `Result` instead of panicking. #[track_caller] #[inline] - pub fn single<'w>(&mut self, world: &'w World) -> ROQueryItem<'w, D> { + pub fn single<'w>(&mut self, world: &'w World) -> ROQueryItem<'w, '_, D> { match self.get_single(world) { Ok(items) => items, Err(error) => panic!("Cannot get single query result: {error}"), @@ -1607,7 +1607,7 @@ impl QueryState { pub fn get_single<'w>( &mut self, world: &'w World, - ) -> Result, QuerySingleError> { + ) -> Result, QuerySingleError> { self.update_archetypes(world); // SAFETY: query is read only @@ -1629,7 +1629,7 @@ impl QueryState { /// [`get_single_mut`](Self::get_single_mut) to return a `Result` instead of panicking. #[track_caller] #[inline] - pub fn single_mut<'w>(&mut self, world: &'w mut World) -> D::Item<'w> { + pub fn single_mut<'w>(&mut self, world: &'w mut World) -> D::Item<'w, '_> { // SAFETY: query has unique world access match self.get_single_mut(world) { Ok(items) => items, @@ -1646,7 +1646,7 @@ impl QueryState { pub fn get_single_mut<'w>( &mut self, world: &'w mut World, - ) -> Result, QuerySingleError> { + ) -> Result, QuerySingleError> { self.update_archetypes(world); let change_tick = world.change_tick(); @@ -1674,7 +1674,7 @@ impl QueryState { pub unsafe fn get_single_unchecked<'w>( &mut self, world: UnsafeWorldCell<'w>, - ) -> Result, QuerySingleError> { + ) -> Result, QuerySingleError> { self.update_archetypes_unsafe_world_cell(world); self.get_single_unchecked_manual(world, world.last_change_tick(), world.change_tick()) } @@ -1695,7 +1695,7 @@ impl QueryState { world: UnsafeWorldCell<'w>, last_run: Tick, this_run: Tick, - ) -> Result, QuerySingleError> { + ) -> Result, QuerySingleError> { let mut query = self.iter_unchecked_manual(world, last_run, this_run); let first = query.next(); let extra = query.next().is_some(); diff --git a/crates/bevy_ecs/src/query/world_query.rs b/crates/bevy_ecs/src/query/world_query.rs index f2da8b3558f26..caed84b2208f8 100644 --- a/crates/bevy_ecs/src/query/world_query.rs +++ b/crates/bevy_ecs/src/query/world_query.rs @@ -40,10 +40,10 @@ pub unsafe trait WorldQuery { /// For `QueryData` this will be the item returned by the query. /// For `QueryFilter` this will be either `()`, or a `bool` indicating whether the entity should be included /// or a tuple of such things. - type Item<'a>; + type Item<'w, 's>; /// Per archetype/table state used by this [`WorldQuery`] to fetch [`Self::Item`](WorldQuery::Item) - type Fetch<'a>: Clone; + type Fetch<'w, 's>: Clone; /// State used to construct a [`Self::Fetch`](WorldQuery::Fetch). This will be cached inside [`QueryState`](crate::query::QueryState), /// so it is best to move as much data / computation here as possible to reduce the cost of @@ -51,10 +51,14 @@ pub unsafe trait WorldQuery { type State: Send + Sync + Sized; /// This function manually implements subtyping for the query items. - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort>; + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's>; /// This function manually implements subtyping for the query fetches. - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort>; + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's>; /// Creates a new instance of this fetch. /// @@ -62,12 +66,12 @@ pub unsafe trait WorldQuery { /// /// - `state` must have been initialized (via [`WorldQuery::init_state`]) using the same `world` passed /// in to this function. - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, - state: &Self::State, + state: &'s Self::State, last_run: Tick, this_run: Tick, - ) -> Self::Fetch<'w>; + ) -> Self::Fetch<'w, 's>; /// Returns true if (and only if) every table of every archetype matched by this fetch contains /// all of the matched components. This is used to select a more efficient "table iterator" @@ -85,9 +89,9 @@ pub unsafe trait WorldQuery { /// - `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>( - fetch: &mut Self::Fetch<'w>, - state: &Self::State, + unsafe fn set_archetype<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, + state: &'s Self::State, archetype: &'w Archetype, table: &'w Table, ); @@ -99,7 +103,11 @@ pub unsafe trait WorldQuery { /// /// - `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); + unsafe fn set_table<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, + state: &'s Self::State, + table: &'w Table, + ); /// Sets available accesses for implementors with dynamic access such as [`FilteredEntityRef`](crate::world::FilteredEntityRef) /// or [`FilteredEntityMut`](crate::world::FilteredEntityMut). @@ -116,11 +124,11 @@ pub unsafe trait WorldQuery { /// /// Must always be called _after_ [`WorldQuery::set_table`] or [`WorldQuery::set_archetype`]. `entity` and /// `table_row` must be in the range of the current table and archetype. - unsafe fn fetch<'w>( - fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, entity: Entity, table_row: TableRow, - ) -> Self::Item<'w>; + ) -> Self::Item<'w, 's>; /// Adds any component accesses used by this [`WorldQuery`] to `access`. /// @@ -158,18 +166,18 @@ macro_rules! impl_tuple_world_query { /// `update_component_access` adds all `With` and `Without` filters from the subqueries. /// This is sound because `matches_component_set` always returns `false` if any the subqueries' implementations return `false`. unsafe impl<$($name: WorldQuery),*> WorldQuery for ($($name,)*) { - type Fetch<'w> = ($($name::Fetch<'w>,)*); - type Item<'w> = ($($name::Item<'w>,)*); + type Fetch<'w, 's> = ($($name::Fetch<'w, 's>,)*); + type Item<'w, 's> = ($($name::Item<'w, 's>,)*); type State = ($($name::State,)*); - fn shrink<'wlong: 'wshort, 'wshort>(item: Self::Item<'wlong>) -> Self::Item<'wshort> { + fn shrink<'wlong: 'wshort, 'wshort, 's>(item: Self::Item<'wlong, 's>) -> Self::Item<'wshort, 's> { let ($($name,)*) = item; ($( $name::shrink($name), )*) } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(fetch: Self::Fetch<'wlong, 's>) -> Self::Fetch<'wshort, 's> { let ($($name,)*) = fetch; ($( $name::shrink_fetch($name), @@ -178,7 +186,7 @@ macro_rules! impl_tuple_world_query { #[inline] #[allow(clippy::unused_unit)] - unsafe fn init_fetch<'w>(_world: UnsafeWorldCell<'w>, state: &Self::State, _last_run: Tick, _this_run: Tick) -> Self::Fetch<'w> { + unsafe fn init_fetch<'w, 's>(_world: UnsafeWorldCell<'w>, state: &'s Self::State, _last_run: Tick, _this_run: Tick) -> Self::Fetch<'w, 's> { let ($($name,)*) = state; // SAFETY: The invariants are uphold by the caller. ($(unsafe { $name::init_fetch(_world, $name, _last_run, _this_run) },)*) @@ -187,9 +195,9 @@ macro_rules! impl_tuple_world_query { const IS_DENSE: bool = true $(&& $name::IS_DENSE)*; #[inline] - unsafe fn set_archetype<'w>( - _fetch: &mut Self::Fetch<'w>, - _state: &Self::State, + unsafe fn set_archetype<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, _archetype: &'w Archetype, _table: &'w Table ) { @@ -200,7 +208,7 @@ macro_rules! impl_tuple_world_query { } #[inline] - unsafe fn set_table<'w>(_fetch: &mut Self::Fetch<'w>, _state: &Self::State, _table: &'w Table) { + unsafe fn set_table<'w, 's>(_fetch: &mut Self::Fetch<'w, 's>, _state: &'s Self::State, _table: &'w Table) { let ($($name,)*) = _fetch; let ($($state,)*) = _state; // SAFETY: The invariants are uphold by the caller. @@ -209,11 +217,11 @@ macro_rules! impl_tuple_world_query { #[inline(always)] #[allow(clippy::unused_unit)] - unsafe fn fetch<'w>( - _fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, _entity: Entity, _table_row: TableRow - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { let ($($name,)*) = _fetch; // SAFETY: The invariants are uphold by the caller. ($(unsafe { $name::fetch($name, _entity, _table_row) },)*) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index ddff01e19fa11..8029610232a8f 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -864,7 +864,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// /// - [`get_mut`](Self::get_mut) to get a mutable query item. #[inline] - pub fn get(&self, entity: Entity) -> Result, QueryEntityError> { + pub fn get(&self, entity: Entity) -> Result, QueryEntityError> { // SAFETY: system runs without conflicts with other systems. // same-system queries have runtime borrow checks when they conflict unsafe { @@ -891,7 +891,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn get_many( &self, entities: [Entity; N], - ) -> Result<[ROQueryItem<'_, D>; N], QueryEntityError> { + ) -> Result<[ROQueryItem<'_, 's, D>; N], QueryEntityError> { // SAFETY: // - `&self` ensures there is no mutable access to any components accessible to this query. // - `self.world` matches `self.state`. @@ -944,7 +944,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// - [`get_many`](Self::get_many) for the non-panicking version. #[inline] #[track_caller] - pub fn many(&self, entities: [Entity; N]) -> [ROQueryItem<'_, D>; N] { + pub fn many(&self, entities: [Entity; N]) -> [ROQueryItem<'_, 's, D>; N] { match self.get_many(entities) { Ok(items) => items, Err(error) => panic!("Cannot get query results: {error}"), @@ -981,7 +981,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// /// - [`get`](Self::get) to get a read-only query item. #[inline] - pub fn get_mut(&mut self, entity: Entity) -> Result, QueryEntityError> { + pub fn get_mut(&mut self, entity: Entity) -> Result, QueryEntityError> { // SAFETY: system runs without conflicts with other systems. // same-system queries have runtime borrow checks when they conflict unsafe { @@ -1003,7 +1003,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn get_many_mut( &mut self, entities: [Entity; N], - ) -> Result<[D::Item<'_>; N], QueryEntityError> { + ) -> Result<[D::Item<'_, 's>; N], QueryEntityError> { // SAFETY: scheduler ensures safe Query world access unsafe { self.state @@ -1061,7 +1061,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// - [`many`](Self::many) to get read-only query items. #[inline] #[track_caller] - pub fn many_mut(&mut self, entities: [Entity; N]) -> [D::Item<'_>; N] { + pub fn many_mut(&mut self, entities: [Entity; N]) -> [D::Item<'_, 's>; N] { match self.get_many_mut(entities) { Ok(items) => items, Err(error) => panic!("Cannot get query result: {error}"), @@ -1083,7 +1083,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// /// - [`get_mut`](Self::get_mut) for the safe version. #[inline] - pub unsafe fn get_unchecked(&self, entity: Entity) -> Result, QueryEntityError> { + pub unsafe fn get_unchecked( + &self, + entity: Entity, + ) -> Result, QueryEntityError> { // SEMI-SAFETY: system runs without conflicts with other systems. // same-system queries have runtime borrow checks when they conflict unsafe { @@ -1118,7 +1121,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// - [`get_single`](Self::get_single) for the non-panicking version. /// - [`single_mut`](Self::single_mut) to get the mutable query item. #[track_caller] - pub fn single(&self) -> ROQueryItem<'_, D> { + pub fn single(&self) -> ROQueryItem<'_, 's, D> { self.get_single().unwrap() } @@ -1154,7 +1157,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// - [`get_single_mut`](Self::get_single_mut) to get the mutable query item. /// - [`single`](Self::single) for the panicking version. #[inline] - pub fn get_single(&self) -> Result, QuerySingleError> { + pub fn get_single(&self) -> Result, QuerySingleError> { // SAFETY: // the query ensures that the components it accesses are not mutably accessible somewhere else // and the query is read only. @@ -1195,7 +1198,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// - [`get_single_mut`](Self::get_single_mut) for the non-panicking version. /// - [`single`](Self::single) to get the read-only query item. #[track_caller] - pub fn single_mut(&mut self) -> D::Item<'_> { + pub fn single_mut(&mut self) -> D::Item<'_, 's> { self.get_single_mut().unwrap() } @@ -1225,7 +1228,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// - [`get_single`](Self::get_single) to get the read-only query item. /// - [`single_mut`](Self::single_mut) for the panicking version. #[inline] - pub fn get_single_mut(&mut self) -> Result, QuerySingleError> { + pub fn get_single_mut(&mut self) -> Result, QuerySingleError> { // SAFETY: // the query ensures mutable access to the components it accesses, and the query // is uniquely borrowed @@ -1493,7 +1496,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { } impl<'w, 's, D: QueryData, F: QueryFilter> IntoIterator for &'w Query<'_, 's, D, F> { - type Item = ROQueryItem<'w, D>; + type Item = ROQueryItem<'w, 's, D>; type IntoIter = QueryIter<'w, 's, D::ReadOnly, F>; fn into_iter(self) -> Self::IntoIter { @@ -1502,7 +1505,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> IntoIterator for &'w Query<'_, 's, D, } impl<'w, 's, D: QueryData, F: QueryFilter> IntoIterator for &'w mut Query<'_, 's, D, F> { - type Item = D::Item<'w>; + type Item = D::Item<'w, 's>; type IntoIter = QueryIter<'w, 's, D, F>; fn into_iter(self) -> Self::IntoIter { @@ -1544,7 +1547,7 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter> Query<'w, 's, D, F> { /// # bevy_ecs::system::assert_is_system(print_selected_character_name_system); /// ``` #[inline] - pub fn get_inner(&self, entity: Entity) -> Result, QueryEntityError> { + pub fn get_inner(&self, entity: Entity) -> Result, QueryEntityError> { // SAFETY: system runs without conflicts with other systems. // same-system queries have runtime borrow checks when they conflict unsafe { diff --git a/crates/bevy_ecs/src/world/entity_ref.rs b/crates/bevy_ecs/src/world/entity_ref.rs index 4ac5731c6a7ae..a5329e50a5296 100644 --- a/crates/bevy_ecs/src/world/entity_ref.rs +++ b/crates/bevy_ecs/src/world/entity_ref.rs @@ -162,7 +162,7 @@ impl<'w> EntityRef<'w> { /// # Panics /// /// If the entity does not have the components required by the query `Q`. - pub fn components(&self) -> Q::Item<'w> { + pub fn components(&self) -> Q::Item<'w, 'static> { self.get_components::().expect(QUERY_MISMATCH_ERROR) } @@ -170,7 +170,7 @@ impl<'w> EntityRef<'w> { /// or `None` if the entity does not have the components required by the query `Q`. pub fn get_components( &self, - ) -> Option> { + ) -> Option> { // SAFETY: We have read-only access to all components of this entity. unsafe { self.0.get_components::() } } @@ -374,7 +374,7 @@ impl<'w> EntityMut<'w> { /// # Panics /// /// If the entity does not have the components required by the query `Q`. - pub fn components(&self) -> Q::Item<'_> { + pub fn components(&self) -> Q::Item<'_, 'static> { self.get_components::().expect(QUERY_MISMATCH_ERROR) } @@ -382,7 +382,7 @@ impl<'w> EntityMut<'w> { /// or `None` if the entity does not have the components required by the query `Q`. pub fn get_components( &self, - ) -> Option> { + ) -> Option> { // SAFETY: We have read-only access to all components of this entity. unsafe { self.0.get_components::() } } @@ -690,7 +690,7 @@ impl<'w> EntityWorldMut<'w> { /// /// If the entity does not have the components required by the query `Q`. #[inline] - pub fn components(&self) -> Q::Item<'_> { + pub fn components(&self) -> Q::Item<'_, 'static> { EntityRef::from(self).components::() } @@ -699,7 +699,7 @@ impl<'w> EntityWorldMut<'w> { #[inline] pub fn get_components( &self, - ) -> Option> { + ) -> Option> { EntityRef::from(self).get_components::() } diff --git a/crates/bevy_ecs/src/world/unsafe_world_cell.rs b/crates/bevy_ecs/src/world/unsafe_world_cell.rs index d1ce0ce8c97cb..ae98dffb3779d 100644 --- a/crates/bevy_ecs/src/world/unsafe_world_cell.rs +++ b/crates/bevy_ecs/src/world/unsafe_world_cell.rs @@ -893,7 +893,7 @@ impl<'w> UnsafeEntityCell<'w> { /// - no mutable references to the queried data exist at the same time pub(crate) unsafe fn get_components( &self, - ) -> Option> { + ) -> Option> { // SAFETY: World is only used to access query data and initialize query state let state = unsafe { let world = self.world().world(); diff --git a/crates/bevy_gizmos/src/lib.rs b/crates/bevy_gizmos/src/lib.rs index bbef44df46677..920ea79eea37e 100644 --- a/crates/bevy_gizmos/src/lib.rs +++ b/crates/bevy_gizmos/src/lib.rs @@ -573,8 +573,8 @@ impl RenderCommand

for SetLineGizmoBindGroup #[inline] fn render<'w>( _item: &P, - _view: ROQueryItem<'w, Self::ViewQuery>, - uniform_index: Option>, + _view: ROQueryItem<'w, '_, Self::ViewQuery>, + uniform_index: Option>, bind_group: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { @@ -601,8 +601,8 @@ impl RenderCommand

for DrawLineGizmo { #[inline] fn render<'w>( _item: &P, - _view: ROQueryItem<'w, Self::ViewQuery>, - handle: Option>, + _view: ROQueryItem<'w, '_, Self::ViewQuery>, + handle: Option>, line_gizmos: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { @@ -654,8 +654,8 @@ impl RenderCommand

for DrawLineJointGizmo { #[inline] fn render<'w>( _item: &P, - _view: ROQueryItem<'w, Self::ViewQuery>, - handle: Option>, + _view: ROQueryItem<'w, '_, Self::ViewQuery>, + handle: Option>, line_gizmos: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { diff --git a/crates/bevy_hierarchy/src/query_extension.rs b/crates/bevy_hierarchy/src/query_extension.rs index de342846a7a82..c91b874cf8c86 100644 --- a/crates/bevy_hierarchy/src/query_extension.rs +++ b/crates/bevy_hierarchy/src/query_extension.rs @@ -32,7 +32,7 @@ pub trait HierarchyQueryExt<'w, 's, D: QueryData, F: QueryFilter> { /// ``` fn iter_descendants(&'w self, entity: Entity) -> DescendantIter<'w, 's, D, F> where - D::ReadOnly: WorldQuery = &'w Children>; + D::ReadOnly: WorldQuery = &'w Children>; /// Returns an [`Iterator`] of [`Entity`]s over all of `entity`s ancestors. /// @@ -54,20 +54,20 @@ pub trait HierarchyQueryExt<'w, 's, D: QueryData, F: QueryFilter> { /// ``` fn iter_ancestors(&'w self, entity: Entity) -> AncestorIter<'w, 's, D, F> where - D::ReadOnly: WorldQuery = &'w Parent>; + D::ReadOnly: WorldQuery = &'w Parent>; } impl<'w, 's, D: QueryData, F: QueryFilter> HierarchyQueryExt<'w, 's, D, F> for Query<'w, 's, D, F> { fn iter_descendants(&'w self, entity: Entity) -> DescendantIter<'w, 's, D, F> where - D::ReadOnly: WorldQuery = &'w Children>, + D::ReadOnly: WorldQuery = &'w Children>, { DescendantIter::new(self, entity) } fn iter_ancestors(&'w self, entity: Entity) -> AncestorIter<'w, 's, D, F> where - D::ReadOnly: WorldQuery = &'w Parent>, + D::ReadOnly: WorldQuery = &'w Parent>, { AncestorIter::new(self, entity) } @@ -78,7 +78,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> HierarchyQueryExt<'w, 's, D, F> for Q /// Traverses the hierarchy breadth-first. pub struct DescendantIter<'w, 's, D: QueryData, F: QueryFilter> where - D::ReadOnly: WorldQuery = &'w Children>, + D::ReadOnly: WorldQuery = &'w Children>, { children_query: &'w Query<'w, 's, D, F>, vecdeque: VecDeque, @@ -86,7 +86,7 @@ where impl<'w, 's, D: QueryData, F: QueryFilter> DescendantIter<'w, 's, D, F> where - D::ReadOnly: WorldQuery = &'w Children>, + D::ReadOnly: WorldQuery = &'w Children>, { /// Returns a new [`DescendantIter`]. pub fn new(children_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self { @@ -104,7 +104,7 @@ where impl<'w, 's, D: QueryData, F: QueryFilter> Iterator for DescendantIter<'w, 's, D, F> where - D::ReadOnly: WorldQuery = &'w Children>, + D::ReadOnly: WorldQuery = &'w Children>, { type Item = Entity; @@ -122,7 +122,7 @@ where /// An [`Iterator`] of [`Entity`]s over the ancestors of an [`Entity`]. pub struct AncestorIter<'w, 's, D: QueryData, F: QueryFilter> where - D::ReadOnly: WorldQuery = &'w Parent>, + D::ReadOnly: WorldQuery = &'w Parent>, { parent_query: &'w Query<'w, 's, D, F>, next: Option, @@ -130,7 +130,7 @@ where impl<'w, 's, D: QueryData, F: QueryFilter> AncestorIter<'w, 's, D, F> where - D::ReadOnly: WorldQuery = &'w Parent>, + D::ReadOnly: WorldQuery = &'w Parent>, { /// Returns a new [`AncestorIter`]. pub fn new(parent_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self { @@ -143,7 +143,7 @@ where impl<'w, 's, D: QueryData, F: QueryFilter> Iterator for AncestorIter<'w, 's, D, F> where - D::ReadOnly: WorldQuery = &'w Parent>, + D::ReadOnly: WorldQuery = &'w Parent>, { type Item = Entity; diff --git a/crates/bevy_pbr/src/light_probe/environment_map.rs b/crates/bevy_pbr/src/light_probe/environment_map.rs index a9be284fba0c0..b9c84da3da1a7 100644 --- a/crates/bevy_pbr/src/light_probe/environment_map.rs +++ b/crates/bevy_pbr/src/light_probe/environment_map.rs @@ -203,7 +203,7 @@ impl ExtractInstance for EnvironmentMapIds { type QueryFilter = (); - fn extract(item: QueryItem<'_, Self::QueryData>) -> Option { + fn extract(item: QueryItem<'_, '_, Self::QueryData>) -> Option { Some(EnvironmentMapIds { diffuse: item.diffuse_map.id(), specular: item.specular_map.id(), diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 007ed983e5fad..dff1d82c4c1e4 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -2184,7 +2184,7 @@ impl RenderCommand

for SetMeshViewBindGroup view_ssr, view_environment_map, mesh_view_bind_group, - ): ROQueryItem<'w, Self::ViewQuery>, + ): ROQueryItem<'w, '_, Self::ViewQuery>, _entity: Option<()>, _: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, diff --git a/crates/bevy_pbr/src/ssr/mod.rs b/crates/bevy_pbr/src/ssr/mod.rs index 6d9c8c6dd79e7..81f264c85751c 100644 --- a/crates/bevy_pbr/src/ssr/mod.rs +++ b/crates/bevy_pbr/src/ssr/mod.rs @@ -282,7 +282,7 @@ impl ViewNode for ScreenSpaceReflectionsNode { view_environment_map_offset, view_bind_group, ssr_pipeline_id, - ): QueryItem<'w, Self::ViewQuery>, + ): QueryItem<'w, '_, Self::ViewQuery>, world: &'w World, ) -> Result<(), NodeRunError> { // Grab the render pipeline. @@ -496,7 +496,7 @@ impl ExtractComponent for ScreenSpaceReflections { type Out = ScreenSpaceReflectionsUniform; - fn extract_component(settings: QueryItem<'_, Self::QueryData>) -> Option { + fn extract_component(settings: QueryItem<'_, '_, Self::QueryData>) -> Option { if !DEPTH_TEXTURE_SAMPLING_SUPPORTED { info_once!( "Disabling screen-space reflections on this platform because depth textures \ diff --git a/crates/bevy_pbr/src/volumetric_fog/render.rs b/crates/bevy_pbr/src/volumetric_fog/render.rs index 9a35a92eae31c..ad1ac4276b79b 100644 --- a/crates/bevy_pbr/src/volumetric_fog/render.rs +++ b/crates/bevy_pbr/src/volumetric_fog/render.rs @@ -327,7 +327,7 @@ impl ViewNode for VolumetricFogNode { view_ssr_offset, msaa, view_environment_map_offset, - ): QueryItem<'w, Self::ViewQuery>, + ): QueryItem<'w, '_, Self::ViewQuery>, world: &'w World, ) -> Result<(), NodeRunError> { let pipeline_cache = world.resource::(); diff --git a/crates/bevy_render/macros/src/extract_component.rs b/crates/bevy_render/macros/src/extract_component.rs index 80d1aa57ca5b5..f4248aadbba85 100644 --- a/crates/bevy_render/macros/src/extract_component.rs +++ b/crates/bevy_render/macros/src/extract_component.rs @@ -43,7 +43,7 @@ pub fn derive_extract_component(input: TokenStream) -> TokenStream { type QueryFilter = #filter; type Out = Self; - fn extract_component(item: #bevy_ecs_path::query::QueryItem<'_, Self::QueryData>) -> Option { + fn extract_component(item: #bevy_ecs_path::query::QueryItem<'_, '_, Self::QueryData>) -> Option { Some(item.clone()) } } diff --git a/crates/bevy_render/src/extract_component.rs b/crates/bevy_render/src/extract_component.rs index 4b327cf6af3e8..e09a000dea7af 100644 --- a/crates/bevy_render/src/extract_component.rs +++ b/crates/bevy_render/src/extract_component.rs @@ -58,7 +58,7 @@ pub trait ExtractComponent: Component { // type Out: Component = Self; /// Defines how the component is transferred into the "render world". - fn extract_component(item: QueryItem<'_, Self::QueryData>) -> Option; + fn extract_component(item: QueryItem<'_, '_, Self::QueryData>) -> Option; } /// This plugin prepares the components of the corresponding type for the GPU @@ -200,7 +200,7 @@ impl ExtractComponent for Handle { type Out = Handle; #[inline] - fn extract_component(handle: QueryItem<'_, Self::QueryData>) -> Option { + fn extract_component(handle: QueryItem<'_, '_, Self::QueryData>) -> Option { Some(handle.clone_weak()) } } diff --git a/crates/bevy_render/src/extract_instances.rs b/crates/bevy_render/src/extract_instances.rs index 537ca5f11e439..1c38df68d0951 100644 --- a/crates/bevy_render/src/extract_instances.rs +++ b/crates/bevy_render/src/extract_instances.rs @@ -34,7 +34,7 @@ pub trait ExtractInstance: Send + Sync + Sized + 'static { type QueryFilter: QueryFilter; /// Defines how the component is transferred into the "render world". - fn extract(item: QueryItem<'_, Self::QueryData>) -> Option; + fn extract(item: QueryItem<'_, '_, Self::QueryData>) -> Option; } /// This plugin extracts one or more components into the "render world" as @@ -142,7 +142,7 @@ where type QueryData = Read>; type QueryFilter = (); - fn extract(item: QueryItem<'_, Self::QueryData>) -> Option { + fn extract(item: QueryItem<'_, '_, Self::QueryData>) -> Option { Some(item.id()) } } diff --git a/crates/bevy_render/src/render_graph/node.rs b/crates/bevy_render/src/render_graph/node.rs index 8528457d420a1..e871f4355356a 100644 --- a/crates/bevy_render/src/render_graph/node.rs +++ b/crates/bevy_render/src/render_graph/node.rs @@ -355,7 +355,7 @@ pub trait ViewNode { &self, graph: &mut RenderGraphContext, render_context: &mut RenderContext<'w>, - view_query: QueryItem<'w, Self::ViewQuery>, + view_query: QueryItem<'w, '_, Self::ViewQuery>, world: &'w World, ) -> Result<(), NodeRunError>; } diff --git a/crates/bevy_render/src/render_phase/draw.rs b/crates/bevy_render/src/render_phase/draw.rs index 0880ae797efd3..5e90bab93e983 100644 --- a/crates/bevy_render/src/render_phase/draw.rs +++ b/crates/bevy_render/src/render_phase/draw.rs @@ -212,8 +212,8 @@ pub trait RenderCommand { /// issuing draw calls, etc.) via the [`TrackedRenderPass`]. fn render<'w>( item: &P, - view: ROQueryItem<'w, Self::ViewQuery>, - entity: Option>, + view: ROQueryItem<'w, '_, Self::ViewQuery>, + entity: Option>, param: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult; @@ -238,8 +238,8 @@ macro_rules! render_command_tuple_impl { #[allow(non_snake_case)] fn render<'w>( _item: &P, - ($($view,)*): ROQueryItem<'w, Self::ViewQuery>, - maybe_entities: Option>, + ($($view,)*): ROQueryItem<'w, '_, Self::ViewQuery>, + maybe_entities: Option>, ($($name,)*): SystemParamItem<'w, '_, Self::Param>, _pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { diff --git a/crates/bevy_sprite/src/lib.rs b/crates/bevy_sprite/src/lib.rs index 163d3878bc474..4e64eacd07b21 100644 --- a/crates/bevy_sprite/src/lib.rs +++ b/crates/bevy_sprite/src/lib.rs @@ -228,7 +228,7 @@ impl ExtractComponent for SpriteSource { type Out = SpriteSource; - fn extract_component(_: QueryItem<'_, Self::QueryData>) -> Option { + fn extract_component(_: QueryItem<'_, '_, Self::QueryData>) -> Option { Some(SpriteSource) } } diff --git a/crates/bevy_sprite/src/mesh2d/mesh.rs b/crates/bevy_sprite/src/mesh2d/mesh.rs index 7ef45ec298ed9..ae14b1eb97dc0 100644 --- a/crates/bevy_sprite/src/mesh2d/mesh.rs +++ b/crates/bevy_sprite/src/mesh2d/mesh.rs @@ -775,7 +775,7 @@ impl RenderCommand

for SetMesh2dViewBindGroup( _item: &P, - (view_uniform, mesh2d_view_bind_group): ROQueryItem<'w, Self::ViewQuery>, + (view_uniform, mesh2d_view_bind_group): ROQueryItem<'w, '_, Self::ViewQuery>, _view: Option<()>, _param: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, diff --git a/crates/bevy_sprite/src/render/mod.rs b/crates/bevy_sprite/src/render/mod.rs index 60c64131fe12b..468ea3a37e7cf 100644 --- a/crates/bevy_sprite/src/render/mod.rs +++ b/crates/bevy_sprite/src/render/mod.rs @@ -798,7 +798,7 @@ impl RenderCommand

for SetSpriteViewBindGroup( _item: &P, - (view_uniform, sprite_view_bind_group): ROQueryItem<'w, Self::ViewQuery>, + (view_uniform, sprite_view_bind_group): ROQueryItem<'w, '_, Self::ViewQuery>, _entity: Option<()>, _param: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, diff --git a/crates/bevy_ui/src/render/ui_material_pipeline.rs b/crates/bevy_ui/src/render/ui_material_pipeline.rs index 1a3cf489ac9be..aeecc1670a071 100644 --- a/crates/bevy_ui/src/render/ui_material_pipeline.rs +++ b/crates/bevy_ui/src/render/ui_material_pipeline.rs @@ -288,7 +288,7 @@ impl RenderCommand

fn render<'w>( _item: &P, _view: (), - material_handle: Option>, + material_handle: Option>, materials: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { diff --git a/examples/ecs/custom_query_param.rs b/examples/ecs/custom_query_param.rs index 43b02df732527..4e4d8a397118c 100644 --- a/examples/ecs/custom_query_param.rs +++ b/examples/ecs/custom_query_param.rs @@ -136,7 +136,7 @@ fn print_components_iter_mut( println!("Print components (iter_mut):"); for e in &mut query { // Re-declaring the variable to illustrate the type of the actual iterator item. - let e: CustomQueryItem<'_, _, _> = e; + let e: CustomQueryItem<'_, '_, _, _> = e; println!("Entity: {:?}", e.entity); println!("A: {:?}", e.a); println!("B: {:?}", e.b); @@ -154,7 +154,7 @@ fn print_components_iter( println!("Print components (iter):"); for e in &query { // Re-declaring the variable to illustrate the type of the actual iterator item. - let e: CustomQueryReadOnlyItem<'_, _, _> = e; + let e: CustomQueryReadOnlyItem<'_, '_, _, _> = e; println!("Entity: {:?}", e.entity); println!("A: {:?}", e.a); println!("B: {:?}", e.b); diff --git a/examples/shader/custom_phase_item.rs b/examples/shader/custom_phase_item.rs index 7a601b498992d..1c7a68b154e41 100644 --- a/examples/shader/custom_phase_item.rs +++ b/examples/shader/custom_phase_item.rs @@ -69,8 +69,8 @@ where fn render<'w>( _: &P, - _: ROQueryItem<'w, Self::ViewQuery>, - _: Option>, + _: ROQueryItem<'w, '_, Self::ViewQuery>, + _: Option>, custom_phase_item_buffers: SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, ) -> RenderCommandResult { diff --git a/examples/shader/shader_instancing.rs b/examples/shader/shader_instancing.rs index 0fe1c2713a2a6..620cf7384c884 100644 --- a/examples/shader/shader_instancing.rs +++ b/examples/shader/shader_instancing.rs @@ -77,7 +77,7 @@ impl ExtractComponent for InstanceMaterialData { type QueryFilter = (); type Out = Self; - fn extract_component(item: QueryItem<'_, Self::QueryData>) -> Option { + fn extract_component(item: QueryItem<'_, '_, Self::QueryData>) -> Option { Some(InstanceMaterialData(item.0.clone())) } } From f6f425927003ae03be8e1ba52b8eddd5aa3ba016 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Mon, 23 Sep 2024 14:42:55 -0400 Subject: [PATCH 04/18] Fix merge conflicts with traversal changes. --- crates/bevy_ecs/src/observer/mod.rs | 2 +- crates/bevy_ecs/src/traversal.rs | 11 +++++++---- crates/bevy_hierarchy/src/components/parent.rs | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/crates/bevy_ecs/src/observer/mod.rs b/crates/bevy_ecs/src/observer/mod.rs index a339bf6b1f479..15068365f373b 100644 --- a/crates/bevy_ecs/src/observer/mod.rs +++ b/crates/bevy_ecs/src/observer/mod.rs @@ -566,7 +566,7 @@ mod tests { struct Parent(Entity); impl Traversal for &'_ Parent { - fn traverse(item: Self::Item<'_>) -> Option { + fn traverse(item: Self::Item<'_, '_>) -> Option { Some(item.0) } } diff --git a/crates/bevy_ecs/src/traversal.rs b/crates/bevy_ecs/src/traversal.rs index 16a92802fd524..ffe0c27511689 100644 --- a/crates/bevy_ecs/src/traversal.rs +++ b/crates/bevy_ecs/src/traversal.rs @@ -1,6 +1,9 @@ //! A trait for components that let you traverse the ECS. -use crate::{entity::Entity, query::ReadOnlyQueryData}; +use crate::{ + entity::Entity, + query::{ReadOnlyQueryData, ReleaseStateQueryData}, +}; /// A component that can point to another entity, and which can be used to define a path through the ECS. /// @@ -16,13 +19,13 @@ use crate::{entity::Entity, query::ReadOnlyQueryData}; /// [specify the direction]: crate::event::Event::Traversal /// [event propagation]: crate::observer::Trigger::propagate /// [observers]: crate::observer::Observer -pub trait Traversal: ReadOnlyQueryData { +pub trait Traversal: ReadOnlyQueryData + ReleaseStateQueryData { /// Returns the next entity to visit. - fn traverse(item: Self::Item<'_>) -> Option; + fn traverse(item: Self::Item<'_, '_>) -> Option; } impl Traversal for () { - fn traverse(_: Self::Item<'_>) -> Option { + fn traverse(_: Self::Item<'_, '_>) -> Option { None } } diff --git a/crates/bevy_hierarchy/src/components/parent.rs b/crates/bevy_hierarchy/src/components/parent.rs index 4bd1ea40859c9..489c2a9c8d41d 100644 --- a/crates/bevy_hierarchy/src/components/parent.rs +++ b/crates/bevy_hierarchy/src/components/parent.rs @@ -80,7 +80,7 @@ impl Deref for Parent { /// /// [event propagation]: bevy_ecs::observer::Trigger::propagate impl Traversal for &Parent { - fn traverse(item: Self::Item<'_>) -> Option { + fn traverse(item: Self::Item<'_, '_>) -> Option { Some(item.0) } } From 0872293e4c7a3545fe7a7596e7973f4eebf05c1d Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Sat, 28 Sep 2024 20:10:28 -0400 Subject: [PATCH 05/18] Link to update_archetypes() and corresponding _manual() methods where they are necessary to work around borrowing QueryState mutably. --- crates/bevy_ecs/src/query/state.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index f9fa239e63c69..a2daa38816415 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -738,6 +738,10 @@ impl QueryState { /// /// This can only be called for read-only queries, see [`Self::get_mut`] for write-queries. /// + /// If you need to get multiple items at once but get borrowing errors, + /// consider using [`Self::update_archetypes`] followed by multiple [`Self::get_manual`] calls, + /// or making a single call with [`Self::get_many`] or [`Self::iter_many`]. + /// /// This is always guaranteed to run in `O(1)` time. #[inline] pub fn get<'w>( @@ -1066,6 +1070,9 @@ impl QueryState { /// Returns an [`Iterator`] over the query results for the given [`World`]. /// /// This can only be called for read-only queries, see [`Self::iter_mut`] for write-queries. + /// + /// If you need to iterate multiple times at once but get borrowing errors, + /// consider using [`Self::update_archetypes`] followed by multiple [`Self::iter_manual`] calls. #[inline] pub fn iter<'w, 's>(&'s mut self, world: &'w World) -> QueryIter<'w, 's, D::ReadOnly, F> { self.update_archetypes(world); @@ -1194,6 +1201,9 @@ impl QueryState { /// Items are returned in the order of the list of entities. /// Entities that don't match the query are skipped. /// + /// If you need to iterate multiple times at once but get borrowing errors, + /// consider using [`Self::update_archetypes`] followed by multiple [`Self::iter_many_manual`] calls. + /// /// # See also /// /// - [`iter_many_mut`](Self::iter_many_mut) to get mutable query items. From d1fbada752256038f09858fbd3d5893f644464cb Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Sat, 28 Sep 2024 20:44:27 -0400 Subject: [PATCH 06/18] Fix merge conflicts with QuerySingle. --- crates/bevy_ecs/src/system/query.rs | 14 +++++++------- crates/bevy_ecs/src/system/system_param.rs | 20 ++++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 3377f10319052..8b735721e1545 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -1645,28 +1645,28 @@ impl<'w, 'q, Q: QueryData, F: QueryFilter> From<&'q mut Query<'w, '_, Q, F>> /// Use [`Option>`] instead if zero or one matching entities can exist. /// /// See [`Query`] for more details. -pub struct QuerySingle<'w, D: QueryData, F: QueryFilter = ()> { - pub(crate) item: D::Item<'w>, +pub struct QuerySingle<'w, 's, D: QueryData, F: QueryFilter = ()> { + pub(crate) item: D::Item<'w, 's>, pub(crate) _filter: PhantomData, } -impl<'w, D: QueryData, F: QueryFilter> Deref for QuerySingle<'w, D, F> { - type Target = D::Item<'w>; +impl<'w, 's, D: QueryData, F: QueryFilter> Deref for QuerySingle<'w, 's, D, F> { + type Target = D::Item<'w, 's>; fn deref(&self) -> &Self::Target { &self.item } } -impl<'w, D: QueryData, F: QueryFilter> DerefMut for QuerySingle<'w, D, F> { +impl<'w, 's, D: QueryData, F: QueryFilter> DerefMut for QuerySingle<'w, 's, D, F> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.item } } -impl<'w, D: QueryData, F: QueryFilter> QuerySingle<'w, D, F> { +impl<'w, 's, D: QueryData, F: QueryFilter> QuerySingle<'w, 's, D, F> { /// Returns the inner item with ownership. - pub fn into_inner(self) -> D::Item<'w> { + pub fn into_inner(self) -> D::Item<'w, 's> { self.item } } diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index fdcf36a018ba3..8576f60052a2d 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -367,11 +367,11 @@ fn assert_component_access_compatibility( // SAFETY: Relevant query ComponentId and ArchetypeComponentId access is applied to SystemMeta. If // this Query conflicts with any prior access, a panic will occur. -unsafe impl<'a, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam - for QuerySingle<'a, D, F> +unsafe impl SystemParam + for QuerySingle<'_, '_, D, F> { type State = QueryState; - type Item<'w, 's> = QuerySingle<'w, D, F>; + type Item<'w, 's> = QuerySingle<'w, 's, D, F>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { Query::init_state(world, system_meta) @@ -427,11 +427,11 @@ unsafe impl<'a, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam // SAFETY: Relevant query ComponentId and ArchetypeComponentId access is applied to SystemMeta. If // this Query conflicts with any prior access, a panic will occur. -unsafe impl<'a, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam - for Option> +unsafe impl SystemParam + for Option> { type State = QueryState; - type Item<'w, 's> = Option>; + type Item<'w, 's> = Option>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { QuerySingle::init_state(world, system_meta) @@ -488,14 +488,14 @@ unsafe impl<'a, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam } // SAFETY: QueryState is constrained to read-only fetches, so it only reads World. -unsafe impl<'a, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam - for QuerySingle<'a, D, F> +unsafe impl ReadOnlySystemParam + for QuerySingle<'_, '_, D, F> { } // SAFETY: QueryState is constrained to read-only fetches, so it only reads World. -unsafe impl<'a, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam - for Option> +unsafe impl ReadOnlySystemParam + for Option> { } From 174af451cf698732543fcf50288493ae1323d5d7 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Sun, 10 Nov 2024 10:32:41 -0500 Subject: [PATCH 07/18] Fix new uses of Item<'w>. --- crates/bevy_hierarchy/src/query_extension.rs | 30 ++++---- crates/bevy_render/src/sync_world.rs | 74 +++++++++++--------- 2 files changed, 54 insertions(+), 50 deletions(-) diff --git a/crates/bevy_hierarchy/src/query_extension.rs b/crates/bevy_hierarchy/src/query_extension.rs index 419e02ffbe5ad..08ca7779d9672 100644 --- a/crates/bevy_hierarchy/src/query_extension.rs +++ b/crates/bevy_hierarchy/src/query_extension.rs @@ -14,21 +14,21 @@ pub trait HierarchyQueryExt<'w, 's, D: QueryData, F: QueryFilter> { /// Returns the parent [`Entity`] of the given `entity`, if any. fn parent(&'w self, entity: Entity) -> Option where - D::ReadOnly: WorldQuery = &'w Parent>; + D::ReadOnly: WorldQuery = &'w Parent>; /// Returns a slice over the [`Children`] of the given `entity`. /// /// This may be empty if the `entity` has no children. fn children(&'w self, entity: Entity) -> &'w [Entity] where - D::ReadOnly: WorldQuery = &'w Children>; + D::ReadOnly: WorldQuery = &'w Children>; /// Returns the topmost ancestor of the given `entity`. /// /// This may be the entity itself if it has no parent. fn root_ancestor(&'w self, entity: Entity) -> Entity where - D::ReadOnly: WorldQuery = &'w Parent>; + D::ReadOnly: WorldQuery = &'w Parent>; /// Returns an [`Iterator`] of [`Entity`]s over the leaves of the hierarchy that are underneath this `entity`. /// @@ -39,14 +39,14 @@ pub trait HierarchyQueryExt<'w, 's, D: QueryData, F: QueryFilter> { /// Traverses the hierarchy depth-first. fn iter_leaves(&'w self, entity: Entity) -> impl Iterator + 'w where - D::ReadOnly: WorldQuery = &'w Children>; + D::ReadOnly: WorldQuery = &'w Children>; /// Returns an [`Iterator`] of [`Entity`]s over the `entity`s immediate siblings, who share the same parent. /// /// The entity itself is not included in the iterator. fn iter_siblings(&'w self, entity: Entity) -> impl Iterator where - D::ReadOnly: WorldQuery = (Option<&'w Parent>, Option<&'w Children>)>; + D::ReadOnly: WorldQuery = (Option<&'w Parent>, Option<&'w Children>)>; /// Returns an [`Iterator`] of [`Entity`]s over all of `entity`s descendants. /// @@ -81,7 +81,7 @@ pub trait HierarchyQueryExt<'w, 's, D: QueryData, F: QueryFilter> { entity: Entity, ) -> DescendantDepthFirstIter<'w, 's, D, F> where - D::ReadOnly: WorldQuery = &'w Children>; + D::ReadOnly: WorldQuery = &'w Children>; /// Returns an [`Iterator`] of [`Entity`]s over all of `entity`s ancestors. /// @@ -109,14 +109,14 @@ pub trait HierarchyQueryExt<'w, 's, D: QueryData, F: QueryFilter> { impl<'w, 's, D: QueryData, F: QueryFilter> HierarchyQueryExt<'w, 's, D, F> for Query<'w, 's, D, F> { fn parent(&'w self, entity: Entity) -> Option where - ::ReadOnly: WorldQuery = &'w Parent>, + ::ReadOnly: WorldQuery = &'w Parent>, { self.get(entity).map(Parent::get).ok() } fn children(&'w self, entity: Entity) -> &'w [Entity] where - ::ReadOnly: WorldQuery = &'w Children>, + ::ReadOnly: WorldQuery = &'w Children>, { self.get(entity) .map_or(&[] as &[Entity], |children| children) @@ -124,7 +124,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> HierarchyQueryExt<'w, 's, D, F> for Q fn root_ancestor(&'w self, entity: Entity) -> Entity where - ::ReadOnly: WorldQuery = &'w Parent>, + ::ReadOnly: WorldQuery = &'w Parent>, { // Recursively search up the tree until we're out of parents match self.get(entity) { @@ -135,7 +135,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> HierarchyQueryExt<'w, 's, D, F> for Q fn iter_leaves(&'w self, entity: Entity) -> impl Iterator where - ::ReadOnly: WorldQuery = &'w Children>, + ::ReadOnly: WorldQuery = &'w Children>, { self.iter_descendants_depth_first(entity).filter(|entity| { self.get(*entity) @@ -148,7 +148,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> HierarchyQueryExt<'w, 's, D, F> for Q fn iter_siblings(&'w self, entity: Entity) -> impl Iterator where - D::ReadOnly: WorldQuery = (Option<&'w Parent>, Option<&'w Children>)>, + D::ReadOnly: WorldQuery = (Option<&'w Parent>, Option<&'w Children>)>, { self.get(entity) .ok() @@ -172,7 +172,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> HierarchyQueryExt<'w, 's, D, F> for Q entity: Entity, ) -> DescendantDepthFirstIter<'w, 's, D, F> where - D::ReadOnly: WorldQuery = &'w Children>, + D::ReadOnly: WorldQuery = &'w Children>, { DescendantDepthFirstIter::new(self, entity) } @@ -236,7 +236,7 @@ where /// Traverses the hierarchy depth-first. pub struct DescendantDepthFirstIter<'w, 's, D: QueryData, F: QueryFilter> where - D::ReadOnly: WorldQuery = &'w Children>, + D::ReadOnly: WorldQuery = &'w Children>, { children_query: &'w Query<'w, 's, D, F>, stack: SmallVec<[Entity; 8]>, @@ -244,7 +244,7 @@ where impl<'w, 's, D: QueryData, F: QueryFilter> DescendantDepthFirstIter<'w, 's, D, F> where - D::ReadOnly: WorldQuery = &'w Children>, + D::ReadOnly: WorldQuery = &'w Children>, { /// Returns a new [`DescendantDepthFirstIter`]. pub fn new(children_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self { @@ -261,7 +261,7 @@ where impl<'w, 's, D: QueryData, F: QueryFilter> Iterator for DescendantDepthFirstIter<'w, 's, D, F> where - D::ReadOnly: WorldQuery = &'w Children>, + D::ReadOnly: WorldQuery = &'w Children>, { type Item = Entity; diff --git a/crates/bevy_render/src/sync_world.rs b/crates/bevy_render/src/sync_world.rs index 6cee2885d0669..0140bbc2ee204 100644 --- a/crates/bevy_render/src/sync_world.rs +++ b/crates/bevy_render/src/sync_world.rs @@ -266,27 +266,29 @@ mod render_entities_world_query_impls { /// SAFETY: defers completely to `&RenderEntity` implementation, /// and then only modifies the output safely. unsafe impl WorldQuery for RenderEntity { - type Item<'w> = Entity; - type Fetch<'w> = <&'static RenderEntity as WorldQuery>::Fetch<'w>; + type Item<'w, 's> = Entity; + type Fetch<'w, 's> = <&'static RenderEntity as WorldQuery>::Fetch<'w, 's>; type State = <&'static RenderEntity as WorldQuery>::State; - fn shrink<'wlong: 'wshort, 'wshort>(item: Entity) -> Entity { + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { item } - fn shrink_fetch<'wlong: 'wshort, 'wshort>( - fetch: Self::Fetch<'wlong>, - ) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { fetch } #[inline] - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, - component_id: &ComponentId, + component_id: &'s ComponentId, last_run: Tick, this_run: Tick, - ) -> Self::Fetch<'w> { + ) -> Self::Fetch<'w, 's> { // SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`. unsafe { <&RenderEntity as WorldQuery>::init_fetch(world, component_id, last_run, this_run) @@ -296,9 +298,9 @@ mod render_entities_world_query_impls { const IS_DENSE: bool = <&'static RenderEntity as WorldQuery>::IS_DENSE; #[inline] - unsafe fn set_archetype<'w>( - fetch: &mut Self::Fetch<'w>, - component_id: &ComponentId, + unsafe fn set_archetype<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, + component_id: &'s ComponentId, archetype: &'w Archetype, table: &'w Table, ) { @@ -309,9 +311,9 @@ mod render_entities_world_query_impls { } #[inline] - unsafe fn set_table<'w>( - fetch: &mut Self::Fetch<'w>, - &component_id: &ComponentId, + unsafe fn set_table<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, + &component_id: &'s ComponentId, table: &'w Table, ) { // SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`. @@ -319,11 +321,11 @@ mod render_entities_world_query_impls { } #[inline(always)] - unsafe fn fetch<'w>( - fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, entity: Entity, table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { // SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`. let component = unsafe { <&RenderEntity as WorldQuery>::fetch(fetch, entity, table_row) }; @@ -365,27 +367,29 @@ mod render_entities_world_query_impls { /// SAFETY: defers completely to `&RenderEntity` implementation, /// and then only modifies the output safely. unsafe impl WorldQuery for MainEntity { - type Item<'w> = Entity; - type Fetch<'w> = <&'static MainEntity as WorldQuery>::Fetch<'w>; + type Item<'w, 's> = Entity; + type Fetch<'w, 's> = <&'static MainEntity as WorldQuery>::Fetch<'w, 's>; type State = <&'static MainEntity as WorldQuery>::State; - fn shrink<'wlong: 'wshort, 'wshort>(item: Entity) -> Entity { + fn shrink<'wlong: 'wshort, 'wshort, 's>( + item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { item } - fn shrink_fetch<'wlong: 'wshort, 'wshort>( - fetch: Self::Fetch<'wlong>, - ) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { fetch } #[inline] - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, - component_id: &ComponentId, + component_id: &'s ComponentId, last_run: Tick, this_run: Tick, - ) -> Self::Fetch<'w> { + ) -> Self::Fetch<'w, 's> { // SAFETY: defers to the `&T` implementation, with T set to `MainEntity`. unsafe { <&MainEntity as WorldQuery>::init_fetch(world, component_id, last_run, this_run) @@ -395,8 +399,8 @@ mod render_entities_world_query_impls { const IS_DENSE: bool = <&'static MainEntity as WorldQuery>::IS_DENSE; #[inline] - unsafe fn set_archetype<'w>( - fetch: &mut Self::Fetch<'w>, + unsafe fn set_archetype<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, component_id: &ComponentId, archetype: &'w Archetype, table: &'w Table, @@ -408,9 +412,9 @@ mod render_entities_world_query_impls { } #[inline] - unsafe fn set_table<'w>( - fetch: &mut Self::Fetch<'w>, - &component_id: &ComponentId, + unsafe fn set_table<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, + &component_id: &'s ComponentId, table: &'w Table, ) { // SAFETY: defers to the `&T` implementation, with T set to `MainEntity`. @@ -418,11 +422,11 @@ mod render_entities_world_query_impls { } #[inline(always)] - unsafe fn fetch<'w>( - fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, entity: Entity, table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { // SAFETY: defers to the `&T` implementation, with T set to `MainEntity`. let component = unsafe { <&MainEntity as WorldQuery>::fetch(fetch, entity, table_row) }; component.id() From a080cb00c55ed8fcdca9b40346db2c2f666912ca Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Sat, 8 Feb 2025 21:09:51 -0500 Subject: [PATCH 08/18] Fix build. --- .../src/experimental/mip_generation/mod.rs | 1 + crates/bevy_core_pipeline/src/prepass/node.rs | 4 +- crates/bevy_ecs/src/query/fetch.rs | 2 +- crates/bevy_ecs/src/query/iter.rs | 32 ++++++++-------- crates/bevy_ecs/src/query/mod.rs | 38 +++++++++++-------- crates/bevy_ecs/src/query/world_query.rs | 2 +- .../src/relationship/relationship_query.rs | 36 +++++++++--------- crates/bevy_ecs/src/system/query.rs | 8 ++-- crates/bevy_ecs/src/traversal.rs | 2 +- crates/bevy_pbr/src/atmosphere/mod.rs | 4 +- crates/bevy_pbr/src/atmosphere/node.rs | 2 +- crates/bevy_sprite/src/render/mod.rs | 4 +- 12 files changed, 71 insertions(+), 64 deletions(-) diff --git a/crates/bevy_core_pipeline/src/experimental/mip_generation/mod.rs b/crates/bevy_core_pipeline/src/experimental/mip_generation/mod.rs index 3140408886b6d..4bc8b1f1ba919 100644 --- a/crates/bevy_core_pipeline/src/experimental/mip_generation/mod.rs +++ b/crates/bevy_core_pipeline/src/experimental/mip_generation/mod.rs @@ -163,6 +163,7 @@ impl ViewNode for DownsampleDepthNode { render_context: &mut RenderContext<'w>, (view_depth_pyramid, view_downsample_depth_bind_group, view_depth_texture): QueryItem< 'w, + '_, Self::ViewQuery, >, world: &'w World, diff --git a/crates/bevy_core_pipeline/src/prepass/node.rs b/crates/bevy_core_pipeline/src/prepass/node.rs index 0519ec19ef81b..04bae5be4c371 100644 --- a/crates/bevy_core_pipeline/src/prepass/node.rs +++ b/crates/bevy_core_pipeline/src/prepass/node.rs @@ -36,7 +36,7 @@ impl ViewNode for EarlyPrepassNode { &self, graph: &mut RenderGraphContext, render_context: &mut RenderContext<'w>, - view_query: QueryItem<'w, Self::ViewQuery>, + view_query: QueryItem<'w, '_, Self::ViewQuery>, world: &'w World, ) -> Result<(), NodeRunError> { run_prepass(graph, render_context, view_query, world, "early prepass") @@ -110,7 +110,7 @@ fn run_prepass<'w>( view_prev_uniform_offset, _, _, - ): QueryItem<'w, ::ViewQuery>, + ): QueryItem<'w, '_, ::ViewQuery>, world: &'w World, label: &'static str, ) -> Result<(), NodeRunError> { diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 2b88bb06f0fb0..6bf57503ec168 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -1737,7 +1737,7 @@ unsafe impl<'__w, T: Component> QueryData for &'__w mut T type ReadOnly = &'__w T; } -impl ReleaseStateQueryData for &mut T { +impl> ReleaseStateQueryData for &mut T { fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { item } diff --git a/crates/bevy_ecs/src/query/iter.rs b/crates/bevy_ecs/src/query/iter.rs index 217639cfb232a..bfe2b24b5f63f 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -826,9 +826,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// # Panics /// /// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty. - fn sort_impl( + fn sort_impl( self, - f: impl FnOnce(&mut Vec<(L::Item<'w>, NeutralOrd)>), + f: impl FnOnce(&mut Vec<(L::Item<'w, 'static>, NeutralOrd)>), ) -> QuerySortedIter< 'w, 's, @@ -1335,7 +1335,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > where - L::Item<'w>: Ord, + for<'l> L::Item<'w, 'l>: Ord, { self.sort_impl::(|keyed_query| keyed_query.sort()) } @@ -1393,7 +1393,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > where - L::Item<'w>: Ord, + for<'l> L::Item<'w, 'l>: Ord, { self.sort_impl::(|keyed_query| keyed_query.sort_unstable()) } @@ -1450,7 +1450,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> /// ``` pub fn sort_by( self, - mut compare: impl FnMut(&L::Item<'w>, &L::Item<'w>) -> Ordering, + mut compare: impl FnMut(&L::Item<'w, '_>, &L::Item<'w, '_>) -> Ordering, ) -> QuerySortedManyIter< 'w, 's, @@ -1481,7 +1481,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> /// called on [`QueryManyIter`] before. pub fn sort_unstable_by( self, - mut compare: impl FnMut(&L::Item<'w>, &L::Item<'w>) -> Ordering, + mut compare: impl FnMut(&L::Item<'w, '_>, &L::Item<'w, '_>) -> Ordering, ) -> QuerySortedManyIter< 'w, 's, @@ -1575,7 +1575,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> /// ``` pub fn sort_by_key( self, - mut f: impl FnMut(&L::Item<'w>) -> K, + mut f: impl FnMut(&L::Item<'w, '_>) -> K, ) -> QuerySortedManyIter< 'w, 's, @@ -1607,7 +1607,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> /// called on [`QueryManyIter`] before. pub fn sort_unstable_by_key( self, - mut f: impl FnMut(&L::Item<'w>) -> K, + mut f: impl FnMut(&L::Item<'w, '_>) -> K, ) -> QuerySortedManyIter< 'w, 's, @@ -1641,7 +1641,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> /// called on [`QueryManyIter`] before. pub fn sort_by_cached_key( self, - mut f: impl FnMut(&L::Item<'w>) -> K, + mut f: impl FnMut(&L::Item<'w, '_>) -> K, ) -> QuerySortedManyIter< 'w, 's, @@ -1670,7 +1670,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> /// called on [`QueryManyIter`] before. fn sort_impl( self, - f: impl FnOnce(&mut Vec<(L::Item<'w>, NeutralOrd)>), + f: impl FnOnce(&mut Vec<(L::Item<'w, '_>, NeutralOrd)>), ) -> QuerySortedManyIter< 'w, 's, @@ -1854,7 +1854,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: EntitySetIterator> impl<'w, 's, D: QueryData, F: QueryFilter, I: EntitySetIterator> Iterator for QueryManyUniqueIter<'w, 's, D, F, I> { - type Item = D::Item<'w>; + type Item = D::Item<'w, 's>; #[inline(always)] fn next(&mut self) -> Option { @@ -1908,7 +1908,7 @@ pub struct QuerySortedManyIter<'w, 's, D: QueryData, F: QueryFilter, I: Iterator entities: &'w Entities, tables: &'w Tables, archetypes: &'w Archetypes, - fetch: D::Fetch<'w>, + fetch: D::Fetch<'w, 's>, query_state: &'s QueryState, } @@ -1947,7 +1947,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> /// It is always safe for shared access. /// `entity` must stem from `self.entity_iter`, and not have been passed before. #[inline(always)] - unsafe fn fetch_next_aliased_unchecked(&mut self, entity: Entity) -> D::Item<'w> { + unsafe fn fetch_next_aliased_unchecked(&mut self, entity: Entity) -> D::Item<'w, 's> { let (location, archetype, table); // SAFETY: // `tables` and `archetypes` belong to the same world that the [`QueryIter`] @@ -1981,7 +1981,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> /// Get next result from the query #[inline(always)] - pub fn fetch_next(&mut self) -> Option> { + pub fn fetch_next(&mut self) -> Option> { let entity = self.entity_iter.next()?; // SAFETY: @@ -2000,7 +2000,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: DoubleEndedIterator { /// Get next result from the query #[inline(always)] - pub fn fetch_next_back(&mut self) -> Option> { + pub fn fetch_next_back(&mut self) -> Option> { let entity = self.entity_iter.next_back()?; // SAFETY: @@ -2017,7 +2017,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: DoubleEndedIterator impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, I: Iterator> Iterator for QuerySortedManyIter<'w, 's, D, F, I> { - type Item = D::Item<'w>; + type Item = D::Item<'w, 's>; #[inline(always)] fn next(&mut self) -> Option { diff --git a/crates/bevy_ecs/src/query/mod.rs b/crates/bevy_ecs/src/query/mod.rs index 6104d0a543abb..9d0a2cf716181 100644 --- a/crates/bevy_ecs/src/query/mod.rs +++ b/crates/bevy_ecs/src/query/mod.rs @@ -809,47 +809,53 @@ mod tests { /// `update_component_access` adds resource read access for `R`. /// `update_archetype_component_access` does nothing, as this accesses no components. unsafe impl WorldQuery for ReadsRData { - type Item<'w> = (); - type Fetch<'w> = (); + type Item<'w, 's> = (); + type Fetch<'w, 's> = (); type State = ComponentId; - fn shrink<'wlong: 'wshort, 'wshort>(_item: Self::Item<'wlong>) -> Self::Item<'wshort> {} + fn shrink<'wlong: 'wshort, 'wshort, 's>( + _item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { + } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {} + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + _: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { + } - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( _world: UnsafeWorldCell<'w>, - _state: &Self::State, + _state: &'s Self::State, _last_run: Tick, _this_run: Tick, - ) -> Self::Fetch<'w> { + ) -> Self::Fetch<'w, 's> { } const IS_DENSE: bool = true; #[inline] - unsafe fn set_archetype<'w>( - _fetch: &mut Self::Fetch<'w>, - _state: &Self::State, + unsafe fn set_archetype<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, _archetype: &'w Archetype, _table: &Table, ) { } #[inline] - unsafe fn set_table<'w>( - _fetch: &mut Self::Fetch<'w>, - _state: &Self::State, + unsafe fn set_table<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, _table: &'w Table, ) { } #[inline(always)] - unsafe fn fetch<'w>( - _fetch: &mut Self::Fetch<'w>, + unsafe fn fetch<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, _entity: Entity, _table_row: TableRow, - ) -> Self::Item<'w> { + ) -> Self::Item<'w, 's> { } fn update_component_access( diff --git a/crates/bevy_ecs/src/query/world_query.rs b/crates/bevy_ecs/src/query/world_query.rs index fcbc28ea3da2c..06629be0239d9 100644 --- a/crates/bevy_ecs/src/query/world_query.rs +++ b/crates/bevy_ecs/src/query/world_query.rs @@ -217,7 +217,7 @@ macro_rules! impl_tuple_world_query { } #[inline] - unsafe fn init_fetch<'w, 's>(_world: UnsafeWorldCell<'w>, state: &'s Self::State, _last_run: Tick, _this_run: Tick) -> Self::Fetch<'w, 's> { + unsafe fn init_fetch<'w, 's>(world: UnsafeWorldCell<'w>, state: &'s Self::State, last_run: Tick, this_run: Tick) -> Self::Fetch<'w, 's> { let ($($name,)*) = state; // SAFETY: The invariants are upheld by the caller. ($(unsafe { $name::init_fetch(world, $name, last_run, this_run) },)*) diff --git a/crates/bevy_ecs/src/relationship/relationship_query.rs b/crates/bevy_ecs/src/relationship/relationship_query.rs index cc7f66fb3a064..a7573bc15a6d9 100644 --- a/crates/bevy_ecs/src/relationship/relationship_query.rs +++ b/crates/bevy_ecs/src/relationship/relationship_query.rs @@ -14,7 +14,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// target entity of that relationship. pub fn related(&'w self, entity: Entity) -> Option where - ::ReadOnly: WorldQuery = &'w R>, + ::ReadOnly: WorldQuery = &'w R>, { self.get(entity).map(R::get).ok() } @@ -26,7 +26,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { entity: Entity, ) -> impl Iterator + 'w where - ::ReadOnly: WorldQuery = &'w S>, + ::ReadOnly: WorldQuery = &'w S>, { self.get(entity) .into_iter() @@ -42,7 +42,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity. pub fn root_ancestor(&'w self, entity: Entity) -> Entity where - ::ReadOnly: WorldQuery = &'w R>, + ::ReadOnly: WorldQuery = &'w R>, { // Recursively search up the tree until we're out of parents match self.get(entity) { @@ -60,9 +60,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn iter_leaves( &'w self, entity: Entity, - ) -> impl Iterator + 'w + ) -> impl Iterator + use<'w, 's, S, D, F> where - ::ReadOnly: WorldQuery = &'w S>, + ::ReadOnly: WorldQuery = &'w S>, SourceIter<'w, S>: DoubleEndedIterator, { self.iter_descendants_depth_first(entity).filter(|entity| { @@ -80,7 +80,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { entity: Entity, ) -> impl Iterator + 'w where - D::ReadOnly: WorldQuery = (Option<&'w R>, Option<&'w R::RelationshipTarget>)>, + D::ReadOnly: WorldQuery = (Option<&'w R>, Option<&'w R::RelationshipTarget>)>, { self.get(entity) .ok() @@ -103,7 +103,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { entity: Entity, ) -> DescendantIter<'w, 's, D, F, S> where - D::ReadOnly: WorldQuery = &'w S>, + D::ReadOnly: WorldQuery = &'w S>, { DescendantIter::new(self, entity) } @@ -120,7 +120,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { entity: Entity, ) -> DescendantDepthFirstIter<'w, 's, D, F, S> where - D::ReadOnly: WorldQuery = &'w S>, + D::ReadOnly: WorldQuery = &'w S>, SourceIter<'w, S>: DoubleEndedIterator, { DescendantDepthFirstIter::new(self, entity) @@ -137,7 +137,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { entity: Entity, ) -> AncestorIter<'w, 's, D, F, R> where - D::ReadOnly: WorldQuery = &'w R>, + D::ReadOnly: WorldQuery = &'w R>, { AncestorIter::new(self, entity) } @@ -148,7 +148,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// Traverses the hierarchy breadth-first. pub struct DescendantIter<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> where - D::ReadOnly: WorldQuery = &'w S>, + D::ReadOnly: WorldQuery = &'w S>, { children_query: &'w Query<'w, 's, D, F>, vecdeque: VecDeque, @@ -156,7 +156,7 @@ where impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> DescendantIter<'w, 's, D, F, S> where - D::ReadOnly: WorldQuery = &'w S>, + D::ReadOnly: WorldQuery = &'w S>, { /// Returns a new [`DescendantIter`]. pub fn new(children_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self { @@ -174,7 +174,7 @@ where impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> Iterator for DescendantIter<'w, 's, D, F, S> where - D::ReadOnly: WorldQuery = &'w S>, + D::ReadOnly: WorldQuery = &'w S>, { type Item = Entity; @@ -194,7 +194,7 @@ where /// Traverses the hierarchy depth-first. pub struct DescendantDepthFirstIter<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> where - D::ReadOnly: WorldQuery = &'w S>, + D::ReadOnly: WorldQuery = &'w S>, { children_query: &'w Query<'w, 's, D, F>, stack: SmallVec<[Entity; 8]>, @@ -203,7 +203,7 @@ where impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> DescendantDepthFirstIter<'w, 's, D, F, S> where - D::ReadOnly: WorldQuery = &'w S>, + D::ReadOnly: WorldQuery = &'w S>, SourceIter<'w, S>: DoubleEndedIterator, { /// Returns a new [`DescendantDepthFirstIter`]. @@ -220,7 +220,7 @@ where impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> Iterator for DescendantDepthFirstIter<'w, 's, D, F, S> where - D::ReadOnly: WorldQuery = &'w S>, + D::ReadOnly: WorldQuery = &'w S>, SourceIter<'w, S>: DoubleEndedIterator, { type Item = Entity; @@ -239,7 +239,7 @@ where /// An [`Iterator`] of [`Entity`]s over the ancestors of an [`Entity`]. pub struct AncestorIter<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> where - D::ReadOnly: WorldQuery = &'w R>, + D::ReadOnly: WorldQuery = &'w R>, { parent_query: &'w Query<'w, 's, D, F>, next: Option, @@ -247,7 +247,7 @@ where impl<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> AncestorIter<'w, 's, D, F, R> where - D::ReadOnly: WorldQuery = &'w R>, + D::ReadOnly: WorldQuery = &'w R>, { /// Returns a new [`AncestorIter`]. pub fn new(parent_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self { @@ -261,7 +261,7 @@ where impl<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> Iterator for AncestorIter<'w, 's, D, F, R> where - D::ReadOnly: WorldQuery = &'w R>, + D::ReadOnly: WorldQuery = &'w R>, { type Item = Entity; diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index fe8aaf9c971dc..fe237d70de56b 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -1233,7 +1233,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// /// - [`get_mut`](Self::get_mut) to get the item using a mutable borrow of the [`Query`]. #[inline] - pub fn get_inner(self, entity: Entity) -> Result, QueryEntityError<'w>> { + pub fn get_inner(self, entity: Entity) -> Result, QueryEntityError<'w>> { // SAFETY: system runs without conflicts with other systems. // same-system queries have runtime borrow checks when they conflict unsafe { @@ -1273,7 +1273,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn get_many_inner( self, entities: [Entity; N], - ) -> Result<[D::Item<'w>; N], QueryEntityError<'w>> { + ) -> Result<[D::Item<'w, 's>; N], QueryEntityError<'w>> { // SAFETY: scheduler ensures safe Query world access unsafe { self.state @@ -1516,7 +1516,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// - [`get_single`](Self::get_single) to get the read-only query item. /// - [`get_single_mut`](Self::get_single_mut) to get the mutable query item. #[inline] - pub fn get_single_inner(self) -> Result, QuerySingleError> { + pub fn get_single_inner(self) -> Result, QuerySingleError> { // SAFETY: // the query ensures mutable access to the components it accesses, and the query // is uniquely borrowed @@ -2025,7 +2025,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { } impl<'w, 's, D: QueryData, F: QueryFilter> IntoIterator for Query<'w, 's, D, F> { - type Item = D::Item<'w>; + type Item = D::Item<'w, 's>; type IntoIter = QueryIter<'w, 's, D, F>; fn into_iter(self) -> Self::IntoIter { diff --git a/crates/bevy_ecs/src/traversal.rs b/crates/bevy_ecs/src/traversal.rs index 2a2bcdeade887..a4d05540ebfda 100644 --- a/crates/bevy_ecs/src/traversal.rs +++ b/crates/bevy_ecs/src/traversal.rs @@ -43,7 +43,7 @@ impl Traversal for () { /// /// [event propagation]: crate::observer::Trigger::propagate impl Traversal for &R { - fn traverse(item: Self::Item<'_>, _data: &D) -> Option { + fn traverse(item: Self::Item<'_, '_>, _data: &D) -> Option { Some(item.get()) } } diff --git a/crates/bevy_pbr/src/atmosphere/mod.rs b/crates/bevy_pbr/src/atmosphere/mod.rs index ae110b22429a8..4fd9aa0cb941c 100644 --- a/crates/bevy_pbr/src/atmosphere/mod.rs +++ b/crates/bevy_pbr/src/atmosphere/mod.rs @@ -360,7 +360,7 @@ impl ExtractComponent for Atmosphere { type Out = Atmosphere; - fn extract_component(item: QueryItem<'_, Self::QueryData>) -> Option { + fn extract_component(item: QueryItem<'_, '_, Self::QueryData>) -> Option { Some(item.clone()) } } @@ -455,7 +455,7 @@ impl ExtractComponent for AtmosphereSettings { type Out = AtmosphereSettings; - fn extract_component(item: QueryItem<'_, Self::QueryData>) -> Option { + fn extract_component(item: QueryItem<'_, '_, Self::QueryData>) -> Option { Some(item.clone()) } } diff --git a/crates/bevy_pbr/src/atmosphere/node.rs b/crates/bevy_pbr/src/atmosphere/node.rs index 851447d760fc3..e09b27c590a04 100644 --- a/crates/bevy_pbr/src/atmosphere/node.rs +++ b/crates/bevy_pbr/src/atmosphere/node.rs @@ -181,7 +181,7 @@ impl ViewNode for RenderSkyNode { view_uniforms_offset, lights_uniforms_offset, render_sky_pipeline_id, - ): QueryItem<'w, Self::ViewQuery>, + ): QueryItem<'w, '_, Self::ViewQuery>, world: &'w World, ) -> Result<(), NodeRunError> { let pipeline_cache = world.resource::(); diff --git a/crates/bevy_sprite/src/render/mod.rs b/crates/bevy_sprite/src/render/mod.rs index 920dbd4f8b86f..1127f9231d5d2 100644 --- a/crates/bevy_sprite/src/render/mod.rs +++ b/crates/bevy_sprite/src/render/mod.rs @@ -840,7 +840,7 @@ impl RenderCommand

for SetSpriteTextureBindGrou fn render<'w>( item: &P, - view: ROQueryItem<'w, Self::ViewQuery>, + view: ROQueryItem<'w, '_, Self::ViewQuery>, _entity: Option<()>, (image_bind_groups, batches): SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, @@ -870,7 +870,7 @@ impl RenderCommand

for DrawSpriteBatch { fn render<'w>( item: &P, - view: ROQueryItem<'w, Self::ViewQuery>, + view: ROQueryItem<'w, '_, Self::ViewQuery>, _entity: Option<()>, (sprite_meta, batches): SystemParamItem<'w, '_, Self::Param>, pass: &mut TrackedRenderPass<'w>, From ac313fd7d314d6cc1a8c9c9f1c1fa3d1fec58f18 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Sat, 8 Feb 2025 22:13:09 -0500 Subject: [PATCH 09/18] Update AssetChanged. --- crates/bevy_asset/src/asset_changed.rs | 42 +++++++++++++++++--------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/crates/bevy_asset/src/asset_changed.rs b/crates/bevy_asset/src/asset_changed.rs index a9b46a29f9f9e..a80b694480bc9 100644 --- a/crates/bevy_asset/src/asset_changed.rs +++ b/crates/bevy_asset/src/asset_changed.rs @@ -9,7 +9,7 @@ use bevy_ecs::{ archetype::Archetype, component::{ComponentId, Tick}, prelude::{Entity, Resource, World}, - query::{FilteredAccess, QueryFilter, QueryItem, ReadFetch, WorldQuery}, + query::{FilteredAccess, QueryFilter, ReadFetch, WorldQuery}, storage::{Table, TableRow}, world::unsafe_world_cell::UnsafeWorldCell, }; @@ -151,23 +151,28 @@ pub struct AssetChangedState { #[expect(unsafe_code, reason = "WorldQuery is an unsafe trait.")] /// SAFETY: `ROQueryFetch` is the same as `QueryFetch` unsafe impl WorldQuery for AssetChanged { - type Item<'w> = (); - type Fetch<'w> = AssetChangedFetch<'w, A>; + type Item<'w, 's> = (); + type Fetch<'w, 's> = AssetChangedFetch<'w, A>; type State = AssetChangedState; - fn shrink<'wlong: 'wshort, 'wshort>(_: QueryItem<'wlong, Self>) -> QueryItem<'wshort, Self> {} + fn shrink<'wlong: 'wshort, 'wshort, 's>( + _item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { + } - fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + fetch: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { fetch } - unsafe fn init_fetch<'w>( + unsafe fn init_fetch<'w, 's>( world: UnsafeWorldCell<'w>, - state: &Self::State, + state: &'s Self::State, last_run: Tick, this_run: Tick, - ) -> Self::Fetch<'w> { + ) -> Self::Fetch<'w, 's> { // SAFETY: // - `AssetChanges` is private and only accessed mutably in the `AssetEvents` schedule // - `resource_id` was obtained from the type ID of `AssetChanges`. @@ -205,9 +210,9 @@ unsafe impl WorldQuery for AssetChanged { const IS_DENSE: bool = <&A>::IS_DENSE; - unsafe fn set_archetype<'w>( - fetch: &mut Self::Fetch<'w>, - state: &Self::State, + unsafe fn set_archetype<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, + state: &'s Self::State, archetype: &'w Archetype, table: &'w Table, ) { @@ -219,7 +224,11 @@ unsafe impl WorldQuery for AssetChanged { } } - unsafe fn set_table<'w>(fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table) { + unsafe fn set_table<'w, 's>( + fetch: &mut Self::Fetch<'w, 's>, + state: &Self::State, + table: &'w Table, + ) { if let Some(inner) = &mut fetch.inner { // SAFETY: We delegate to the inner `set_table` for `A` unsafe { @@ -228,7 +237,12 @@ unsafe impl WorldQuery for AssetChanged { } } - unsafe fn fetch<'w>(_: &mut Self::Fetch<'w>, _: Entity, _: TableRow) -> Self::Item<'w> {} + unsafe fn fetch<'w, 's>( + _: &mut Self::Fetch<'w, 's>, + _: Entity, + _: TableRow, + ) -> Self::Item<'w, 's> { + } #[inline] fn update_component_access(state: &Self::State, access: &mut FilteredAccess) { @@ -271,7 +285,7 @@ unsafe impl QueryFilter for AssetChanged { #[inline] unsafe fn filter_fetch( - fetch: &mut Self::Fetch<'_>, + fetch: &mut Self::Fetch<'_, '_>, entity: Entity, table_row: TableRow, ) -> bool { From 9a74906e538cd2856cf27c0d98c8e2f5fcb2cac4 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Sat, 8 Feb 2025 22:18:53 -0500 Subject: [PATCH 10/18] impl ReleaseStateQueryData for Traversal types. --- crates/bevy_input_focus/src/lib.rs | 18 ++++++++++++++++-- crates/bevy_picking/src/events.rs | 18 ++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/crates/bevy_input_focus/src/lib.rs b/crates/bevy_input_focus/src/lib.rs index 0ec0b428978e9..4d17730ea8679 100644 --- a/crates/bevy_input_focus/src/lib.rs +++ b/crates/bevy_input_focus/src/lib.rs @@ -31,7 +31,12 @@ mod autofocus; pub use autofocus::*; use bevy_app::{App, Plugin, PreUpdate, Startup}; -use bevy_ecs::{prelude::*, query::QueryData, system::SystemParam, traversal::Traversal}; +use bevy_ecs::{ + prelude::*, + query::{QueryData, ReleaseStateQueryData}, + system::SystemParam, + traversal::Traversal, +}; use bevy_input::{gamepad::GamepadButtonChangedEvent, keyboard::KeyboardInput, mouse::MouseWheel}; use bevy_window::{PrimaryWindow, Window}; use core::fmt::Debug; @@ -155,8 +160,17 @@ pub struct WindowTraversal { window: Option<&'static Window>, } +impl ReleaseStateQueryData for WindowTraversal { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { + WindowTraversalItem { + parent: item.parent, + window: item.window, + } + } +} + impl Traversal> for WindowTraversal { - fn traverse(item: Self::Item<'_>, event: &FocusedInput) -> Option { + fn traverse(item: Self::Item<'_, '_>, event: &FocusedInput) -> Option { let WindowTraversalItem { parent, window } = item; // Send event to parent, if it has one. diff --git a/crates/bevy_picking/src/events.rs b/crates/bevy_picking/src/events.rs index f5a4b8d67f412..12ad9404e4488 100644 --- a/crates/bevy_picking/src/events.rs +++ b/crates/bevy_picking/src/events.rs @@ -39,7 +39,12 @@ use core::{fmt::Debug, time::Duration}; -use bevy_ecs::{prelude::*, query::QueryData, system::SystemParam, traversal::Traversal}; +use bevy_ecs::{ + prelude::*, + query::{QueryData, ReleaseStateQueryData}, + system::SystemParam, + traversal::Traversal, +}; use bevy_math::Vec2; use bevy_platform_support::collections::HashMap; use bevy_platform_support::time::Instant; @@ -82,11 +87,20 @@ pub struct PointerTraversal { window: Option<&'static Window>, } +impl ReleaseStateQueryData for PointerTraversal { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { + PointerTraversalItem { + parent: item.parent, + window: item.window, + } + } +} + impl Traversal> for PointerTraversal where E: Debug + Clone + Reflect, { - fn traverse(item: Self::Item<'_>, pointer: &Pointer) -> Option { + fn traverse(item: Self::Item<'_, '_>, pointer: &Pointer) -> Option { let PointerTraversalItem { parent, window } = item; // Send event to parent, if it has one. From 6188a868b03d525c2b971bc9a6bc3daaed83891e Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Sun, 9 Feb 2025 12:28:28 -0500 Subject: [PATCH 11/18] Add `expect` and `reason` for `allow(clippy::unused_unit)` in tuple impls of `ReleaseStateQueryData`. --- crates/bevy_ecs/src/query/fetch.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 6bf57503ec168..29b584b1ae125 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -2188,7 +2188,14 @@ macro_rules! impl_tuple_query_data { /// SAFETY: each item in the tuple is read only unsafe impl<$($name: ReadOnlyQueryData),*> ReadOnlyQueryData for ($($name,)*) {} - #[allow(clippy::unused_unit)] + #[expect( + clippy::allow_attributes, + reason = "This is a tuple-related macro; as such the lints below may not always apply." + )] + #[allow( + clippy::unused_unit, + reason = "Zero-length tuples will generate some function bodies equivalent to `()`; however, this macro is meant for all applicable tuples, and as such it makes no sense to rewrite it just for that case." + )] impl<$($name: ReleaseStateQueryData),*> ReleaseStateQueryData for ($($name,)*) { fn release_state<'w>(($($item,)*): Self::Item<'w, '_>) -> Self::Item<'w, 'static> { ($($name::release_state($item),)*) @@ -2341,7 +2348,14 @@ macro_rules! impl_anytuple_fetch { /// SAFETY: each item in the tuple is read only unsafe impl<$($name: ReadOnlyQueryData),*> ReadOnlyQueryData for AnyOf<($($name,)*)> {} - #[allow(clippy::unused_unit)] + #[expect( + clippy::allow_attributes, + reason = "This is a tuple-related macro; as such the lints below may not always apply." + )] + #[allow( + clippy::unused_unit, + reason = "Zero-length tuples will generate some function bodies equivalent to `()`; however, this macro is meant for all applicable tuples, and as such it makes no sense to rewrite it just for that case." + )] impl<$($name: ReleaseStateQueryData),*> ReleaseStateQueryData for AnyOf<($($name,)*)> { fn release_state<'w>(($($item,)*): Self::Item<'w, '_>) -> Self::Item<'w, 'static> { ($($item.map(|$item| $name::release_state($item)),)*) From 5dce18f9a580ae6ee6564608f901c42331a7041b Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Mon, 10 Feb 2025 12:50:12 -0500 Subject: [PATCH 12/18] Restore changes lost by bad merging. --- crates/bevy_ecs/src/query/fetch.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 4e23de58e58ae..319c096a3ee76 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -1187,7 +1187,7 @@ impl ReleaseStateQueryData for &Archetype { } } -#[doc(hidden)] +/// The [`WorldQuery::Fetch`] type for `& T`. pub struct ReadFetch<'w, T: Component> { components: StorageSwitch< T, @@ -1563,7 +1563,7 @@ impl ReleaseStateQueryData for Ref<'_, T> { } } -#[doc(hidden)] +/// The [`WorldQuery::Fetch`] type for `&mut T`. pub struct WriteFetch<'w, T: Component> { components: StorageSwitch< T, @@ -2203,7 +2203,6 @@ pub struct AnyOf(PhantomData); macro_rules! impl_tuple_query_data { ($(#[$meta:meta])* $(($name: ident, $item: ident)),*) => { - #[expect( clippy::allow_attributes, reason = "This is a tuple-related macro; as such the lints below may not always apply." From d63f936b85118968198421f21ffca45b42447f9a Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Sun, 9 Feb 2025 19:42:59 -0500 Subject: [PATCH 13/18] impl ReleaseStateQueryData for Option, MainEntity, and RenderEntity. --- crates/bevy_ecs/src/query/fetch.rs | 6 ++++++ crates/bevy_render/src/sync_world.rs | 14 +++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 319c096a3ee76..fac3d284d08bb 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -2020,6 +2020,12 @@ unsafe impl QueryData for Option { /// SAFETY: [`OptionFetch`] is read only because `T` is read only unsafe impl ReadOnlyQueryData for Option {} +impl ReleaseStateQueryData for Option { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { + item.map(T::release_state) + } +} + /// Returns a bool that describes if an entity has the component `T`. /// /// This can be used in a [`Query`](crate::system::Query) if you want to know whether or not entities diff --git a/crates/bevy_render/src/sync_world.rs b/crates/bevy_render/src/sync_world.rs index 697f2e8eaf7e0..e0b50a0678a76 100644 --- a/crates/bevy_render/src/sync_world.rs +++ b/crates/bevy_render/src/sync_world.rs @@ -277,7 +277,7 @@ mod render_entities_world_query_impls { archetype::Archetype, component::{ComponentId, Components, Tick}, entity::Entity, - query::{FilteredAccess, QueryData, ReadOnlyQueryData, WorldQuery}, + query::{FilteredAccess, QueryData, ReadOnlyQueryData, ReleaseStateQueryData, WorldQuery}, storage::{Table, TableRow}, world::{unsafe_world_cell::UnsafeWorldCell, World}, }; @@ -383,6 +383,12 @@ mod render_entities_world_query_impls { // SAFETY: the underlying `Entity` is copied, and no mutable access is provided. unsafe impl ReadOnlyQueryData for RenderEntity {} + impl ReleaseStateQueryData for RenderEntity { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { + item + } + } + /// SAFETY: defers completely to `&RenderEntity` implementation, /// and then only modifies the output safely. unsafe impl WorldQuery for MainEntity { @@ -482,6 +488,12 @@ mod render_entities_world_query_impls { // SAFETY: the underlying `Entity` is copied, and no mutable access is provided. unsafe impl ReadOnlyQueryData for MainEntity {} + + impl ReleaseStateQueryData for MainEntity { + fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { + item + } + } } #[cfg(test)] From 7ad98aa3089eb51b754a3825d5f99e2b15a96361 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Sun, 9 Feb 2025 19:37:33 -0500 Subject: [PATCH 14/18] Implement ReleaseStateQueryData for derived QueryData. --- crates/bevy_ecs/macros/src/query_data.rs | 24 +++++ crates/bevy_ecs/src/query/fetch.rs | 116 +++++++++++++++++++++++ crates/bevy_input_focus/src/lib.rs | 16 +--- crates/bevy_picking/src/events.rs | 16 +--- 4 files changed, 142 insertions(+), 30 deletions(-) diff --git a/crates/bevy_ecs/macros/src/query_data.rs b/crates/bevy_ecs/macros/src/query_data.rs index 8a8cc19bdaa56..0739ec6d6cdf9 100644 --- a/crates/bevy_ecs/macros/src/query_data.rs +++ b/crates/bevy_ecs/macros/src/query_data.rs @@ -280,6 +280,18 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream { } } } + + impl #user_impl_generics #path::query::ReleaseStateQueryData + for #read_only_struct_name #user_ty_generics #user_where_clauses + // Make these HRTBs with an unused lifetime parameter to allow trivial constraints + // See https://github.com/rust-lang/rust/issues/48214 + where #(for<'__a> #field_types: #path::query::QueryData,)* { + fn release_state<'__w>(_item: Self::Item<'__w, '_>) -> Self::Item<'__w, 'static> { + Self::Item { + #(#field_idents: <#read_only_field_types>::release_state(_item.#field_idents),)* + } + } + } } } else { quote! {} @@ -315,6 +327,18 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream { } } + impl #user_impl_generics #path::query::ReleaseStateQueryData + for #struct_name #user_ty_generics #user_where_clauses + // Make these HRTBs with an unused lifetime parameter to allow trivial constraints + // See https://github.com/rust-lang/rust/issues/48214 + where #(for<'__a> #field_types: #path::query::ReleaseStateQueryData,)* { + fn release_state<'__w>(_item: Self::Item<'__w, '_>) -> Self::Item<'__w, 'static> { + Self::Item { + #(#field_idents: <#field_types>::release_state(_item.#field_idents),)* + } + } + } + #read_only_data_impl } }; diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index fac3d284d08bb..eb5460418b24a 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -2744,6 +2744,122 @@ mod tests { assert_is_system(ignored_system); } + #[test] + fn derive_release_state() { + struct NonReleaseQueryData; + + /// SAFETY: + /// `update_component_access` and `update_archetype_component_access` do nothing. + /// This is sound because `fetch` does not access components. + unsafe impl WorldQuery for NonReleaseQueryData { + type Fetch<'w, 's> = (); + type State = (); + + fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( + _: Self::Fetch<'wlong, 's>, + ) -> Self::Fetch<'wshort, 's> { + } + + unsafe fn init_fetch<'w, 's>( + _world: UnsafeWorldCell<'w>, + _state: &'s Self::State, + _last_run: Tick, + _this_run: Tick, + ) -> Self::Fetch<'w, 's> { + } + + const IS_DENSE: bool = true; + + #[inline] + unsafe fn set_archetype<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, + _archetype: &'w Archetype, + _table: &Table, + ) { + } + + #[inline] + unsafe fn set_table<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _state: &'s Self::State, + _table: &'w Table, + ) { + } + + fn update_component_access( + _state: &Self::State, + _access: &mut FilteredAccess, + ) { + } + + fn init_state(_world: &mut World) {} + + fn get_state(_components: &Components) -> Option<()> { + Some(()) + } + + fn matches_component_set( + _state: &Self::State, + _set_contains_id: &impl Fn(ComponentId) -> bool, + ) -> bool { + true + } + } + + /// SAFETY: `Self` is the same as `Self::ReadOnly` + unsafe impl QueryData for NonReleaseQueryData { + type ReadOnly = Self; + + type Item<'w, 's> = (); + + fn shrink<'wlong: 'wshort, 'wshort, 's>( + _item: Self::Item<'wlong, 's>, + ) -> Self::Item<'wshort, 's> { + } + + #[inline(always)] + unsafe fn fetch<'w, 's>( + _fetch: &mut Self::Fetch<'w, 's>, + _entity: Entity, + _table_row: TableRow, + ) -> Self::Item<'w, 's> { + } + } + + /// SAFETY: access is read only + unsafe impl ReadOnlyQueryData for NonReleaseQueryData {} + + #[derive(QueryData)] + pub struct DerivedNonReleaseRead { + non_release: NonReleaseQueryData, + a: &'static A, + } + + #[derive(QueryData)] + #[query_data(mutable)] + pub struct DerivedNonReleaseMutable { + non_release: NonReleaseQueryData, + a: &'static mut A, + } + + #[derive(QueryData)] + pub struct DerivedReleaseRead { + a: &'static A, + } + + #[derive(QueryData)] + #[query_data(mutable)] + pub struct DerivedReleaseMutable { + a: &'static mut A, + } + + fn assert_is_release_state() {} + + assert_is_release_state::(); + assert_is_release_state::(); + } + // Ensures that each field of a `WorldQuery` struct's read-only variant // has the same visibility as its corresponding mutable field. #[test] diff --git a/crates/bevy_input_focus/src/lib.rs b/crates/bevy_input_focus/src/lib.rs index 4d17730ea8679..8d8beb44da828 100644 --- a/crates/bevy_input_focus/src/lib.rs +++ b/crates/bevy_input_focus/src/lib.rs @@ -31,12 +31,7 @@ mod autofocus; pub use autofocus::*; use bevy_app::{App, Plugin, PreUpdate, Startup}; -use bevy_ecs::{ - prelude::*, - query::{QueryData, ReleaseStateQueryData}, - system::SystemParam, - traversal::Traversal, -}; +use bevy_ecs::{prelude::*, query::QueryData, system::SystemParam, traversal::Traversal}; use bevy_input::{gamepad::GamepadButtonChangedEvent, keyboard::KeyboardInput, mouse::MouseWheel}; use bevy_window::{PrimaryWindow, Window}; use core::fmt::Debug; @@ -160,15 +155,6 @@ pub struct WindowTraversal { window: Option<&'static Window>, } -impl ReleaseStateQueryData for WindowTraversal { - fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { - WindowTraversalItem { - parent: item.parent, - window: item.window, - } - } -} - impl Traversal> for WindowTraversal { fn traverse(item: Self::Item<'_, '_>, event: &FocusedInput) -> Option { let WindowTraversalItem { parent, window } = item; diff --git a/crates/bevy_picking/src/events.rs b/crates/bevy_picking/src/events.rs index d95dae03ada86..5f5b2a2c67810 100644 --- a/crates/bevy_picking/src/events.rs +++ b/crates/bevy_picking/src/events.rs @@ -39,12 +39,7 @@ use core::{fmt::Debug, time::Duration}; -use bevy_ecs::{ - prelude::*, - query::{QueryData, ReleaseStateQueryData}, - system::SystemParam, - traversal::Traversal, -}; +use bevy_ecs::{prelude::*, query::QueryData, system::SystemParam, traversal::Traversal}; use bevy_math::Vec2; use bevy_platform_support::collections::HashMap; use bevy_platform_support::time::Instant; @@ -87,15 +82,6 @@ pub struct PointerTraversal { window: Option<&'static Window>, } -impl ReleaseStateQueryData for PointerTraversal { - fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static> { - PointerTraversalItem { - parent: item.parent, - window: item.window, - } - } -} - impl Traversal> for PointerTraversal where E: Debug + Clone + Reflect, From e89a909b02f9072482013c26254ba3a1548e2049 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Sun, 9 Feb 2025 12:57:58 -0500 Subject: [PATCH 15/18] Use `collect()` in `QueryIter::sort()`. This prevents lens items from borrowing from the state, letting us drop the `ReleaseStateQueryData` requirement. --- crates/bevy_ecs/src/query/iter.rs | 50 ++++++++++++++++++------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/crates/bevy_ecs/src/query/iter.rs b/crates/bevy_ecs/src/query/iter.rs index 0a2555d923a0c..0f8d108849003 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -1,4 +1,4 @@ -use super::{QueryData, QueryFilter, ReadOnlyQueryData, ReleaseStateQueryData}; +use super::{QueryData, QueryFilter, ReadOnlyQueryData}; use crate::{ archetype::{Archetype, ArchetypeEntity, Archetypes}, bundle::Bundle, @@ -487,7 +487,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// # schedule.add_systems((system_1, system_2, system_3)); /// # schedule.run(&mut world); /// ``` - pub fn sort: Ord> + ReleaseStateQueryData + 'w>( + pub fn sort( self, ) -> QuerySortedIter< 'w, @@ -495,7 +495,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { D, F, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, - > { + > + where + for<'l> L::Item<'w, 'l>: Ord, + { self.sort_impl::(|keyed_query| keyed_query.sort()) } @@ -541,9 +544,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// # schedule.add_systems((system_1)); /// # schedule.run(&mut world); /// ``` - pub fn sort_unstable< - L: ReadOnlyQueryData: Ord> + ReleaseStateQueryData + 'w, - >( + pub fn sort_unstable( self, ) -> QuerySortedIter< 'w, @@ -551,7 +552,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { D, F, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, - > { + > + where + for<'l> L::Item<'w, 'l>: Ord, + { self.sort_impl::(|keyed_query| keyed_query.sort_unstable()) } @@ -604,9 +608,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// # schedule.add_systems((system_1)); /// # schedule.run(&mut world); /// ``` - pub fn sort_by( + pub fn sort_by( self, - mut compare: impl FnMut(&L::Item<'w, 'static>, &L::Item<'w, 'static>) -> Ordering, + mut compare: impl FnMut(&L::Item<'w, '_>, &L::Item<'w, '_>) -> Ordering, ) -> QuerySortedIter< 'w, 's, @@ -636,9 +640,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// # Panics /// /// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty. - pub fn sort_unstable_by( + pub fn sort_unstable_by( self, - mut compare: impl FnMut(&L::Item<'w, 'static>, &L::Item<'w, 'static>) -> Ordering, + mut compare: impl FnMut(&L::Item<'w, '_>, &L::Item<'w, '_>) -> Ordering, ) -> QuerySortedIter< 'w, 's, @@ -728,9 +732,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// # schedule.add_systems((system_1, system_2)); /// # schedule.run(&mut world); /// ``` - pub fn sort_by_key( + pub fn sort_by_key( self, - mut f: impl FnMut(&L::Item<'w, 'static>) -> K, + mut f: impl FnMut(&L::Item<'w, '_>) -> K, ) -> QuerySortedIter< 'w, 's, @@ -761,9 +765,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// # Panics /// /// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty. - pub fn sort_unstable_by_key( + pub fn sort_unstable_by_key( self, - mut f: impl FnMut(&L::Item<'w, 'static>) -> K, + mut f: impl FnMut(&L::Item<'w, '_>) -> K, ) -> QuerySortedIter< 'w, 's, @@ -796,9 +800,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// # Panics /// /// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty. - pub fn sort_by_cached_key( + pub fn sort_by_cached_key( self, - mut f: impl FnMut(&L::Item<'w, 'static>) -> K, + mut f: impl FnMut(&L::Item<'w, '_>) -> K, ) -> QuerySortedIter< 'w, 's, @@ -826,9 +830,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// # Panics /// /// This will panic if `next` has been called on `QueryIter` before, unless the underlying `Query` is empty. - fn sort_impl( + fn sort_impl( self, - f: impl FnOnce(&mut Vec<(L::Item<'w, 'static>, NeutralOrd)>), + f: impl FnOnce(&mut Vec<(L::Item<'w, '_>, NeutralOrd)>), ) -> QuerySortedIter< 'w, 's, @@ -853,10 +857,14 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { // The original query iter has not been iterated on, so no items are aliased from it. let query_lens = unsafe { query_lens_state.query_unchecked_manual(world) }.into_iter(); let mut keyed_query: Vec<_> = query_lens - .map(|(key, entity)| (L::release_state(key), NeutralOrd(entity))) + .map(|(key, entity)| (key, NeutralOrd(entity))) .collect(); f(&mut keyed_query); - let entity_iter = keyed_query.into_iter().map(|(.., entity)| entity.0); + let entity_iter = keyed_query + .into_iter() + .map(|(.., entity)| entity.0) + .collect::>() + .into_iter(); // SAFETY: // `self.world` has permission to access the required components. // Each lens query item is dropped before the respective actual query item is accessed. From f7c3b2792adab8b94f3ed824e294403679ad1442 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Tue, 11 Feb 2025 21:15:43 -0500 Subject: [PATCH 16/18] Update new uses of `QueryItem` to include `'s` lifetime. --- crates/bevy_ecs/src/system/query.rs | 2 +- examples/shader/custom_render_phase.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 246eaafe1d398..3d6ee7b995504 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -1300,7 +1300,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn get_many_readonly( self, entities: [Entity; N], - ) -> Result<[D::Item<'w>; N], QueryEntityError<'w>> + ) -> Result<[D::Item<'w, 's>; N], QueryEntityError<'w>> where D: ReadOnlyQueryData, { diff --git a/examples/shader/custom_render_phase.rs b/examples/shader/custom_render_phase.rs index 12a9c55f2ff77..6a1690fc364e3 100644 --- a/examples/shader/custom_render_phase.rs +++ b/examples/shader/custom_render_phase.rs @@ -587,7 +587,7 @@ impl ViewNode for CustomDrawNode { &self, graph: &mut RenderGraphContext, render_context: &mut RenderContext<'w>, - (camera, view, target): QueryItem<'w, Self::ViewQuery>, + (camera, view, target): QueryItem<'w, '_, Self::ViewQuery>, world: &'w World, ) -> Result<(), NodeRunError> { // First, we need to get our phases resource From 4e602567d6da1a54fcce9ab82817e05ae61c329f Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Wed, 12 Feb 2025 14:13:09 -0500 Subject: [PATCH 17/18] Document that most QueryData types impl ReleaseStateQueryData. --- crates/bevy_ecs/src/query/fetch.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 2a0e0e02b3db6..63f1a1740fd31 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -320,6 +320,11 @@ pub type QueryItem<'w, 's, Q> = ::Item<'w, 's>; pub type ROQueryItem<'w, 's, D> = QueryItem<'w, 's, ::ReadOnly>; /// A [`QueryData`] that does not borrow from its [`QueryState`](crate::query::QueryState). +/// +/// This is implemented by most `QueryData` types. +/// The main exceptions are [`FilteredEntityRef`], [`FilteredEntityMut`], [`EntityRefExcept`], and [`EntityMutExcept`], +/// which borrow an access list from their query state. +/// Consider using a full [`EntityRef`] or [`EntityMut`] if you would need those. pub trait ReleaseStateQueryData: QueryData { /// Releases the borrow from the query state by converting an item to have a `'static` state lifetime. fn release_state<'w>(item: Self::Item<'w, '_>) -> Self::Item<'w, 'static>; From a748abe565d4e27427bd3dc8b40a9e2d70944bd2 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Fri, 7 Mar 2025 14:12:59 -0500 Subject: [PATCH 18/18] Add `'s` lifetime to new uses of QueryItem. Add `const IS_READ_ONLY` to `NonReleaseQueryData`. --- crates/bevy_core_pipeline/src/deferred/node.rs | 3 ++- crates/bevy_ecs/src/query/fetch.rs | 1 + crates/bevy_ecs/src/query/par_iter.rs | 8 ++++---- crates/bevy_ecs/src/query/state.rs | 11 +++++++---- crates/bevy_ecs/src/system/query.rs | 14 +++++++------- crates/bevy_pbr/src/render/mesh.rs | 2 +- 6 files changed, 22 insertions(+), 17 deletions(-) diff --git a/crates/bevy_core_pipeline/src/deferred/node.rs b/crates/bevy_core_pipeline/src/deferred/node.rs index b0731beb11fbb..e786d2a222cb8 100644 --- a/crates/bevy_core_pipeline/src/deferred/node.rs +++ b/crates/bevy_core_pipeline/src/deferred/node.rs @@ -36,7 +36,7 @@ impl ViewNode for EarlyDeferredGBufferPrepassNode { &self, graph: &mut RenderGraphContext, render_context: &mut RenderContext<'w>, - view_query: QueryItem<'w, Self::ViewQuery>, + view_query: QueryItem<'w, '_, Self::ViewQuery>, world: &'w World, ) -> Result<(), NodeRunError> { run_deferred_prepass( @@ -107,6 +107,7 @@ fn run_deferred_prepass<'w>( render_context: &mut RenderContext<'w>, (camera, extracted_view, view_depth_texture, view_prepass_textures, _, _): QueryItem< 'w, + '_, ::ViewQuery, >, is_late: bool, diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index c61d7e7f673a4..1c53594b80ac1 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -2830,6 +2830,7 @@ mod tests { /// SAFETY: `Self` is the same as `Self::ReadOnly` unsafe impl QueryData for NonReleaseQueryData { type ReadOnly = Self; + const IS_READ_ONLY: bool = true; type Item<'w, 's> = (); diff --git a/crates/bevy_ecs/src/query/par_iter.rs b/crates/bevy_ecs/src/query/par_iter.rs index 8d98466bce038..c16230dabbb90 100644 --- a/crates/bevy_ecs/src/query/par_iter.rs +++ b/crates/bevy_ecs/src/query/par_iter.rs @@ -189,7 +189,7 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, E: EntityBorrow + Sync> /// /// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool #[inline] - pub fn for_each) + Send + Sync + Clone>(self, func: FN) { + pub fn for_each) + Send + Sync + Clone>(self, func: FN) { self.for_each_init(|| {}, |_, item| func(item)); } @@ -246,7 +246,7 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, E: EntityBorrow + Sync> #[inline] pub fn for_each_init(self, init: INIT, func: FN) where - FN: Fn(&mut T, QueryItem<'w, D>) + Send + Sync + Clone, + FN: Fn(&mut T, QueryItem<'w, 's, D>) + Send + Sync + Clone, INIT: Fn() -> T + Sync + Send + Clone, { let func = |mut init, item| { @@ -349,7 +349,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, E: TrustedEntityBorrow + Sync> /// /// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool #[inline] - pub fn for_each) + Send + Sync + Clone>(self, func: FN) { + pub fn for_each) + Send + Sync + Clone>(self, func: FN) { self.for_each_init(|| {}, |_, item| func(item)); } @@ -406,7 +406,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, E: TrustedEntityBorrow + Sync> #[inline] pub fn for_each_init(self, init: INIT, func: FN) where - FN: Fn(&mut T, QueryItem<'w, D>) + Send + Sync + Clone, + FN: Fn(&mut T, QueryItem<'w, 's, D>) + Send + Sync + Clone, INIT: Fn() -> T + Sync + Send + Clone, { let func = |mut init, item| { diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index fac1b1d19ce9c..45b8537800d4f 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -1592,8 +1592,8 @@ impl QueryState { /// /// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool #[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))] - pub(crate) unsafe fn par_many_fold_init_unchecked_manual<'w, T, FN, INIT, E>( - &self, + pub(crate) unsafe fn par_many_fold_init_unchecked_manual<'w, 's, T, FN, INIT, E>( + &'s self, init_accum: INIT, world: UnsafeWorldCell<'w>, entity_list: &[E], @@ -1602,7 +1602,7 @@ impl QueryState { last_run: Tick, this_run: Tick, ) where - FN: Fn(T, D::Item<'w>) -> T + Send + Sync + Clone, + FN: Fn(T, D::Item<'w, 's>) -> T + Send + Sync + Clone, INIT: Fn() -> T + Sync + Send + Clone, E: EntityBorrow + Sync, { @@ -1714,7 +1714,10 @@ impl QueryState { /// /// Simply unwrapping the [`Result`] also works, but should generally be reserved for tests. #[inline] - pub fn single<'w>(&mut self, world: &'w World) -> Result, QuerySingleError> { + pub fn single<'w>( + &mut self, + world: &'w World, + ) -> Result, QuerySingleError> { self.query(world).single_inner() } diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index a9259748966b9..ab4a4f965ac69 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -1079,7 +1079,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// [`par_iter_mut`]: Self::par_iter_mut /// [`World`]: crate::world::World #[inline] - pub fn par_iter(&self) -> QueryParIter<'_, '_, D::ReadOnly, F> { + pub fn par_iter(&self) -> QueryParIter<'_, 's, D::ReadOnly, F> { self.as_readonly().par_iter_inner() } @@ -1114,7 +1114,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// [`par_iter`]: Self::par_iter /// [`World`]: crate::world::World #[inline] - pub fn par_iter_mut(&mut self) -> QueryParIter<'_, '_, D, F> { + pub fn par_iter_mut(&mut self) -> QueryParIter<'_, 's, D, F> { self.reborrow().par_iter_inner() } @@ -1174,7 +1174,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn par_iter_many>( &self, entities: EntityList, - ) -> QueryParManyIter<'_, '_, D::ReadOnly, F, EntityList::Item> { + ) -> QueryParManyIter<'_, 's, D::ReadOnly, F, EntityList::Item> { QueryParManyIter { world: self.world, state: self.state.as_readonly(), @@ -1203,7 +1203,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn par_iter_many_unique>( &self, entities: EntityList, - ) -> QueryParManyUniqueIter<'_, '_, D::ReadOnly, F, EntityList::Item> { + ) -> QueryParManyUniqueIter<'_, 's, D::ReadOnly, F, EntityList::Item> { QueryParManyUniqueIter { world: self.world, state: self.state.as_readonly(), @@ -1232,7 +1232,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn par_iter_many_unique_mut>( &mut self, entities: EntityList, - ) -> QueryParManyUniqueIter<'_, '_, D, F, EntityList::Item> { + ) -> QueryParManyUniqueIter<'_, 's, D, F, EntityList::Item> { QueryParManyUniqueIter { world: self.world, state: self.state, @@ -1620,7 +1620,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { unsafe fn get_many_impl( self, entities: [Entity; N], - ) -> Result<[D::Item<'w>; N], QueryEntityError<'w>> { + ) -> Result<[D::Item<'w, 's>; N], QueryEntityError<'w>> { let mut values = [(); N].map(|_| MaybeUninit::uninit()); for (value, entity) in core::iter::zip(&mut values, entities) { @@ -1684,7 +1684,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { #[inline] #[track_caller] #[deprecated(note = "Use `get_many_mut` instead and handle the Result.")] - pub fn many_mut(&mut self, entities: [Entity; N]) -> [D::Item<'_, '_>; N] { + pub fn many_mut(&mut self, entities: [Entity; N]) -> [D::Item<'_, 's>; N] { match self.get_many_mut(entities) { Ok(items) => items, Err(error) => panic!("Cannot get query result: {error}"), diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index c3145a744520e..233de4ae1236c 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -1567,7 +1567,7 @@ fn extract_mesh_for_gpu_building( not_shadow_caster, no_automatic_batching, visibility_range, - ): ::Item<'_>, + ): ::Item<'_, '_>, render_visibility_ranges: &RenderVisibilityRanges, render_mesh_instances: &RenderMeshInstancesGpu, queue: &mut RenderMeshInstanceGpuQueue,