From e943852a163ba5deeab31685b3655a6fbba5248e Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Tue, 18 Feb 2025 15:30:13 -0500 Subject: [PATCH 01/18] Make Query generic over the State type so it can use either owned or borrowed state. --- crates/bevy_ecs/src/query/iter.rs | 427 +++++++++--------- crates/bevy_ecs/src/query/mod.rs | 2 +- crates/bevy_ecs/src/query/par_iter.rs | 64 +-- crates/bevy_ecs/src/query/state.rs | 137 +++++- .../src/relationship/relationship_query.rs | 90 ++-- crates/bevy_ecs/src/system/query.rs | 143 ++++-- 6 files changed, 502 insertions(+), 361 deletions(-) diff --git a/crates/bevy_ecs/src/query/iter.rs b/crates/bevy_ecs/src/query/iter.rs index 58034618cb887..08891df558180 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -1,10 +1,10 @@ -use super::{QueryData, QueryFilter, ReadOnlyQueryData}; +use super::{QueryData, QueryFilter, ReadOnlyQueryData, WorldQuery}; use crate::{ archetype::{Archetype, ArchetypeEntity, Archetypes}, bundle::Bundle, component::Tick, entity::{Entities, Entity, EntityBorrow, EntitySet, EntitySetIterator}, - query::{ArchetypeFilter, DebugCheckedUnwrap, QueryState, StorageId}, + query::{ArchetypeFilter, DebugCheckedUnwrap, QueryState, QueryStateBorrow, StorageId}, storage::{Table, TableRow, Tables}, world::{ unsafe_world_cell::UnsafeWorldCell, EntityMut, EntityMutExcept, EntityRef, EntityRefExcept, @@ -24,32 +24,33 @@ use core::{ /// /// This struct is created by the [`Query::iter`](crate::system::Query::iter) and /// [`Query::iter_mut`](crate::system::Query::iter_mut) methods. -pub struct QueryIter<'w, 's, D: QueryData, F: QueryFilter> { +pub struct QueryIter<'w, S: QueryStateBorrow> { world: UnsafeWorldCell<'w>, tables: &'w Tables, archetypes: &'w Archetypes, - query_state: &'s QueryState, - cursor: QueryIterationCursor<'w, 's, D, F>, + query_state: S, + cursor: QueryIterationCursor<'w, S>, } -impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { +impl<'w, D: QueryData, F: QueryFilter, S: QueryStateBorrow> QueryIter<'w, S> { /// # Safety /// - `world` must have permission to access any of the components registered in `query_state`. /// - `world` must be the same one used to initialize `query_state`. pub(crate) unsafe fn new( world: UnsafeWorldCell<'w>, - query_state: &'s QueryState, + query_state: S, last_run: Tick, this_run: Tick, ) -> Self { + // SAFETY: The invariants are upheld by the caller. + let cursor = unsafe { QueryIterationCursor::init(world, &query_state, last_run, this_run) }; QueryIter { world, query_state, // SAFETY: We only access table data that has been registered in `query_state`. tables: unsafe { &world.storages().tables }, archetypes: world.archetypes(), - // SAFETY: The invariants are upheld by the caller. - cursor: unsafe { QueryIterationCursor::init(world, query_state, last_run, this_run) }, + cursor, } } @@ -78,9 +79,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// } /// } /// ``` - pub fn remaining(&self) -> QueryIter<'w, 's, D, F> + pub fn remaining(&self) -> Self where D: ReadOnlyQueryData, + S: Copy, { QueryIter { world: self.world, @@ -115,12 +117,12 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { /// } /// } /// ``` - pub fn remaining_mut(&mut self) -> QueryIter<'_, 's, D, F> { + pub fn remaining_mut(&mut self) -> QueryIter<'_, &QueryState> { QueryIter { world: self.world, tables: self.tables, archetypes: self.archetypes, - query_state: self.query_state, + query_state: self.query_state.borrow(), cursor: self.cursor.reborrow(), } } @@ -212,10 +214,14 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { "TableRow is only valid up to u32::MAX" ); - D::set_table(&mut self.cursor.fetch, &self.query_state.fetch_state, table); + D::set_table( + &mut self.cursor.fetch, + &self.query_state.borrow().fetch_state, + table, + ); F::set_table( &mut self.cursor.filter, - &self.query_state.filter_state, + &self.query_state.borrow().filter_state, table, ); @@ -265,13 +271,13 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { let table = self.tables.get(archetype.table_id()).debug_checked_unwrap(); D::set_archetype( &mut self.cursor.fetch, - &self.query_state.fetch_state, + &self.query_state.borrow().fetch_state, archetype, table, ); F::set_archetype( &mut self.cursor.filter, - &self.query_state.filter_state, + &self.query_state.borrow().filter_state, archetype, table, ); @@ -343,13 +349,13 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { D::set_archetype( &mut self.cursor.fetch, - &self.query_state.fetch_state, + &self.query_state.borrow().fetch_state, archetype, table, ); F::set_archetype( &mut self.cursor.filter, - &self.query_state.filter_state, + &self.query_state.borrow().filter_state, archetype, table, ); @@ -491,9 +497,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { self, ) -> QuerySortedIter< 'w, - 's, - D, - F, + S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > where @@ -548,9 +552,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { self, ) -> QuerySortedIter< 'w, - 's, - D, - F, + S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > where @@ -613,9 +615,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { mut compare: impl FnMut(&L::Item<'_>, &L::Item<'_>) -> Ordering, ) -> QuerySortedIter< 'w, - 's, - D, - F, + S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > { self.sort_impl::(move |keyed_query| { @@ -645,9 +645,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { mut compare: impl FnMut(&L::Item<'_>, &L::Item<'_>) -> Ordering, ) -> QuerySortedIter< 'w, - 's, - D, - F, + S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > { self.sort_impl::(move |keyed_query| { @@ -737,9 +735,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { mut f: impl FnMut(&L::Item<'_>) -> K, ) -> QuerySortedIter< 'w, - 's, - D, - F, + S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > where @@ -770,9 +766,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { mut f: impl FnMut(&L::Item<'_>) -> K, ) -> QuerySortedIter< 'w, - 's, - D, - F, + S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > where @@ -805,9 +799,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { mut f: impl FnMut(&L::Item<'_>) -> K, ) -> QuerySortedIter< 'w, - 's, - D, - F, + S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > where @@ -835,9 +827,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { f: impl FnOnce(&mut Vec<(L::Item<'_>, NeutralOrd)>), ) -> QuerySortedIter< 'w, - 's, - D, - F, + S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > { // On the first successful iteration of `QueryIterationCursor`, `archetype_entities` or `table_entities` @@ -850,7 +840,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { let world = self.world; - let query_lens_state = self.query_state.transmute_filtered::<(L, Entity), F>(world); + let query_lens_state = self + .query_state + .borrow() + .transmute_filtered::<(L, Entity), F>(world); // SAFETY: // `self.world` has permission to access the required components. @@ -877,7 +870,9 @@ 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> { +impl<'w, D: QueryData, F: QueryFilter, S: QueryStateBorrow> Iterator + for QueryIter<'w, S> +{ type Item = D::Item<'w>; #[inline(always)] @@ -887,7 +882,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Iterator for QueryIter<'w, 's, D, F> // `query_state` is the state that was passed to `QueryIterationCursor::init`. unsafe { self.cursor - .next(self.tables, self.archetypes, self.query_state) + .next(self.tables, self.archetypes, self.query_state.borrow()) } } @@ -910,7 +905,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Iterator for QueryIter<'w, 's, D, F> accum = func(accum, item); } - for id in self.cursor.storage_id_iter.clone().copied() { + for id in self.cursor.storage_id_iter.clone() { // SAFETY: // - The range(None) is equivalent to [0, storage.entity_count) accum = unsafe { self.fold_over_storage_range(accum, &mut func, id, None) }; @@ -920,48 +915,48 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Iterator for QueryIter<'w, 's, D, F> } // This is correct as [`QueryIter`] always returns `None` once exhausted. -impl<'w, 's, D: QueryData, F: QueryFilter> FusedIterator for QueryIter<'w, 's, D, F> {} +impl<'w, S: QueryStateBorrow> FusedIterator for QueryIter<'w, S> {} // SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. -unsafe impl<'w, 's, F: QueryFilter> EntitySetIterator for QueryIter<'w, 's, Entity, F> {} +unsafe impl<'w, F: QueryFilter> EntitySetIterator for QueryIter<'w, &QueryState> {} // SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. -unsafe impl<'w, 's, F: QueryFilter> EntitySetIterator for QueryIter<'w, 's, EntityRef<'_>, F> {} +unsafe impl<'w, F: QueryFilter> EntitySetIterator for QueryIter<'w, &QueryState, F>> {} // SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. -unsafe impl<'w, 's, F: QueryFilter> EntitySetIterator for QueryIter<'w, 's, EntityMut<'_>, F> {} +unsafe impl<'w, F: QueryFilter> EntitySetIterator for QueryIter<'w, &QueryState, F>> {} // SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. -unsafe impl<'w, 's, F: QueryFilter> EntitySetIterator - for QueryIter<'w, 's, FilteredEntityRef<'_>, F> +unsafe impl<'w, F: QueryFilter> EntitySetIterator + for QueryIter<'w, &QueryState, F>> { } // SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. -unsafe impl<'w, 's, F: QueryFilter> EntitySetIterator - for QueryIter<'w, 's, FilteredEntityMut<'_>, F> +unsafe impl<'w, F: QueryFilter> EntitySetIterator + for QueryIter<'w, &QueryState, F>> { } // SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. -unsafe impl<'w, 's, F: QueryFilter, B: Bundle> EntitySetIterator - for QueryIter<'w, 's, EntityRefExcept<'_, B>, F> +unsafe impl<'w, F: QueryFilter, B: Bundle> EntitySetIterator + for QueryIter<'w, &QueryState, F>> { } // SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. -unsafe impl<'w, 's, F: QueryFilter, B: Bundle> EntitySetIterator - for QueryIter<'w, 's, EntityMutExcept<'_, B>, F> +unsafe impl<'w, F: QueryFilter, B: Bundle> EntitySetIterator + for QueryIter<'w, &QueryState, F>> { } -impl<'w, 's, D: QueryData, F: QueryFilter> Debug for QueryIter<'w, 's, D, F> { +impl<'w, S: QueryStateBorrow> Debug for QueryIter<'w, S> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QueryIter").finish() } } -impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter> Clone for QueryIter<'w, 's, D, F> { +impl<'w, S: QueryStateBorrow + Copy> Clone for QueryIter<'w, S> { fn clone(&self) -> Self { self.remaining() } @@ -972,7 +967,7 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter> Clone for QueryIter<'w, 's, D /// This struct is created by the [`QueryIter::sort`], [`QueryIter::sort_unstable`], /// [`QueryIter::sort_by`], [`QueryIter::sort_unstable_by`], [`QueryIter::sort_by_key`], /// [`QueryIter::sort_unstable_by_key`], and [`QueryIter::sort_by_cached_key`] methods. -pub struct QuerySortedIter<'w, 's, D: QueryData, F: QueryFilter, I> +pub struct QuerySortedIter<'w, S: QueryStateBorrow, I> where I: Iterator, { @@ -980,11 +975,11 @@ where entities: &'w Entities, tables: &'w Tables, archetypes: &'w Archetypes, - fetch: D::Fetch<'w>, - query_state: &'s QueryState, + fetch: ::Fetch<'w>, + query_state: S, } -impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> QuerySortedIter<'w, 's, D, F, I> +impl<'w, D: QueryData, S: QueryStateBorrow, I: Iterator> QuerySortedIter<'w, S, I> where I: Iterator, { @@ -994,12 +989,12 @@ where /// - `entity_list` must only contain unique entities or be empty. pub(crate) unsafe fn new>( world: UnsafeWorldCell<'w>, - query_state: &'s QueryState, + query_state: S, entity_list: EntityList, last_run: Tick, this_run: Tick, - ) -> QuerySortedIter<'w, 's, D, F, I> { - let fetch = D::init_fetch(world, &query_state.fetch_state, last_run, this_run); + ) -> Self { + let fetch = D::init_fetch(world, &query_state.borrow().fetch_state, last_run, this_run); QuerySortedIter { query_state, entities: world.entities(), @@ -1034,7 +1029,7 @@ where unsafe { D::set_archetype( &mut self.fetch, - &self.query_state.fetch_state, + &self.query_state.borrow().fetch_state, archetype, table, ); @@ -1048,8 +1043,8 @@ where } } -impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> Iterator - for QuerySortedIter<'w, 's, D, F, I> +impl<'w, D: QueryData, S: QueryStateBorrow, I: Iterator> Iterator + for QuerySortedIter<'w, S, I> where I: Iterator, { @@ -1067,8 +1062,7 @@ where } } -impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> DoubleEndedIterator - for QuerySortedIter<'w, 's, D, F, I> +impl<'w, S: QueryStateBorrow, I: Iterator> DoubleEndedIterator for QuerySortedIter<'w, S, I> where I: DoubleEndedIterator, { @@ -1080,32 +1074,26 @@ where } } -impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> ExactSizeIterator - for QuerySortedIter<'w, 's, D, F, I> -where - I: ExactSizeIterator, +impl<'w, S: QueryStateBorrow, I: Iterator> ExactSizeIterator for QuerySortedIter<'w, S, I> where + I: ExactSizeIterator { } // This is correct as [`QuerySortedIter`] returns `None` once exhausted if `entity_iter` does. -impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> FusedIterator - for QuerySortedIter<'w, 's, D, F, I> -where - I: FusedIterator, +impl<'w, S: QueryStateBorrow, I: Iterator> FusedIterator for QuerySortedIter<'w, S, I> where + I: FusedIterator { } // SAFETY: // `I` stems from a collected and sorted `EntitySetIterator` ([`QueryIter`]). // Fetching unique entities maintains uniqueness. -unsafe impl<'w, 's, F: QueryFilter, I: Iterator> EntitySetIterator - for QuerySortedIter<'w, 's, Entity, F, I> +unsafe impl<'w, F: QueryFilter, I: Iterator> EntitySetIterator + for QuerySortedIter<'w, &QueryState, I> { } -impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> Debug - for QuerySortedIter<'w, 's, D, F, I> -{ +impl<'w, S: QueryStateBorrow, I: Iterator> Debug for QuerySortedIter<'w, S, I> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QuerySortedIter").finish() } @@ -1117,32 +1105,42 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> Debug /// Entities that don't match the query are skipped. /// /// This struct is created by the [`Query::iter_many`](crate::system::Query::iter_many) and [`Query::iter_many_mut`](crate::system::Query::iter_many_mut) methods. -pub struct QueryManyIter<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> { +pub struct QueryManyIter<'w, S: QueryStateBorrow, I: Iterator> { world: UnsafeWorldCell<'w>, entity_iter: I, entities: &'w Entities, tables: &'w Tables, archetypes: &'w Archetypes, - fetch: D::Fetch<'w>, - filter: F::Fetch<'w>, - query_state: &'s QueryState, + fetch: ::Fetch<'w>, + filter: ::Fetch<'w>, + query_state: S, } -impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> - QueryManyIter<'w, 's, D, F, I> +impl< + 'w, + D: QueryData, + F: QueryFilter, + S: QueryStateBorrow, + I: Iterator, + > QueryManyIter<'w, S, I> { /// # Safety /// - `world` must have permission to access any of the components registered in `query_state`. /// - `world` must be the same one used to initialize `query_state`. pub(crate) unsafe fn new>( world: UnsafeWorldCell<'w>, - query_state: &'s QueryState, + query_state: S, entity_list: EntityList, last_run: Tick, this_run: Tick, - ) -> QueryManyIter<'w, 's, D, F, I> { - let fetch = D::init_fetch(world, &query_state.fetch_state, last_run, this_run); - let filter = F::init_fetch(world, &query_state.filter_state, last_run, this_run); + ) -> Self { + let fetch = D::init_fetch(world, &query_state.borrow().fetch_state, last_run, this_run); + let filter = F::init_fetch( + world, + &query_state.borrow().filter_state, + last_run, + this_run, + ); QueryManyIter { world, query_state, @@ -1173,7 +1171,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> archetypes: &'w Archetypes, fetch: &mut D::Fetch<'w>, filter: &mut F::Fetch<'w>, - query_state: &'s QueryState, + query_state: &QueryState, ) -> Option> { for entity_borrow in entity_iter { let entity = entity_borrow.entity(); @@ -1230,7 +1228,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> self.archetypes, &mut self.fetch, &mut self.filter, - self.query_state, + self.query_state.borrow(), ) .map(D::shrink) } @@ -1334,9 +1332,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> self, ) -> QuerySortedManyIter< 'w, - 's, - D, - F, + S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > where @@ -1392,9 +1388,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> self, ) -> QuerySortedManyIter< 'w, - 's, - D, - F, + S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > where @@ -1458,9 +1452,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> mut compare: impl FnMut(&L::Item<'_>, &L::Item<'_>) -> Ordering, ) -> QuerySortedManyIter< 'w, - 's, - D, - F, + S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > { self.sort_impl::(move |keyed_query| { @@ -1489,9 +1481,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> mut compare: impl FnMut(&L::Item<'_>, &L::Item<'_>) -> Ordering, ) -> QuerySortedManyIter< 'w, - 's, - D, - F, + S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > { self.sort_impl::(move |keyed_query| { @@ -1583,9 +1573,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> mut f: impl FnMut(&L::Item<'_>) -> K, ) -> QuerySortedManyIter< 'w, - 's, - D, - F, + S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > where @@ -1615,9 +1603,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> mut f: impl FnMut(&L::Item<'_>) -> K, ) -> QuerySortedManyIter< 'w, - 's, - D, - F, + S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > where @@ -1649,9 +1635,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> mut f: impl FnMut(&L::Item<'_>) -> K, ) -> QuerySortedManyIter< 'w, - 's, - D, - F, + S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > where @@ -1678,14 +1662,15 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> f: impl FnOnce(&mut Vec<(L::Item<'_>, NeutralOrd)>), ) -> QuerySortedManyIter< 'w, - 's, - D, - F, + S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > { let world = self.world; - let query_lens_state = self.query_state.transmute_filtered::<(L, Entity), F>(world); + let query_lens_state = self + .query_state + .borrow() + .transmute_filtered::<(L, Entity), F>(world); // SAFETY: // `self.world` has permission to access the required components. @@ -1720,8 +1705,12 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> } } -impl<'w, 's, D: QueryData, F: QueryFilter, I: DoubleEndedIterator> - QueryManyIter<'w, 's, D, F, I> +impl< + 'w, + D: QueryData, + S: QueryStateBorrow, + I: DoubleEndedIterator, + > QueryManyIter<'w, S, I> { /// Get next result from the back of the query #[inline(always)] @@ -1739,15 +1728,15 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: DoubleEndedIterator> Iterator - for QueryManyIter<'w, 's, D, F, I> +impl<'w, D: ReadOnlyQueryData, S: QueryStateBorrow, I: Iterator> + Iterator for QueryManyIter<'w, S, I> { type Item = D::Item<'w>; @@ -1764,7 +1753,7 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, I: Iterator> - DoubleEndedIterator for QueryManyIter<'w, 's, D, F, I> +impl< + 'w, + D: ReadOnlyQueryData, + S: QueryStateBorrow, + I: DoubleEndedIterator, + > DoubleEndedIterator for QueryManyIter<'w, S, I> { #[inline(always)] fn next_back(&mut self) -> Option { @@ -1791,27 +1784,25 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, I: DoubleEndedIterator> FusedIterator - for QueryManyIter<'w, 's, D, F, I> +impl<'w, S: QueryStateBorrow, I: Iterator> + FusedIterator for QueryManyIter<'w, S, I> { } // SAFETY: Fetching unique entities maintains uniqueness. -unsafe impl<'w, 's, F: QueryFilter, I: EntitySetIterator> EntitySetIterator - for QueryManyIter<'w, 's, Entity, F, I> +unsafe impl<'w, F: QueryFilter, I: EntitySetIterator> EntitySetIterator + for QueryManyIter<'w, &QueryState, I> { } -impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> Debug - for QueryManyIter<'w, 's, D, F, I> -{ +impl<'w, S: QueryStateBorrow, I: Iterator> Debug for QueryManyIter<'w, S, I> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QueryManyIter").finish() } @@ -1830,23 +1821,23 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> Debu /// [`iter_many_unique`]: crate::system::Query::iter_many /// [`iter_many_unique_mut`]: crate::system::Query::iter_many_mut /// [`Query`]: crate::system::Query -pub struct QueryManyUniqueIter<'w, 's, D: QueryData, F: QueryFilter, I: EntitySetIterator>( - QueryManyIter<'w, 's, D, F, I>, +pub struct QueryManyUniqueIter<'w, S: QueryStateBorrow, I: EntitySetIterator>( + QueryManyIter<'w, S, I>, ); -impl<'w, 's, D: QueryData, F: QueryFilter, I: EntitySetIterator> - QueryManyUniqueIter<'w, 's, D, F, I> +impl<'w, D: QueryData, S: QueryStateBorrow, I: EntitySetIterator> + QueryManyUniqueIter<'w, S, I> { /// # Safety /// - `world` must have permission to access any of the components registered in `query_state`. /// - `world` must be the same one used to initialize `query_state`. pub(crate) unsafe fn new>( world: UnsafeWorldCell<'w>, - query_state: &'s QueryState, + query_state: S, entity_list: EntityList, last_run: Tick, this_run: Tick, - ) -> QueryManyUniqueIter<'w, 's, D, F, I> { + ) -> Self { QueryManyUniqueIter(QueryManyIter::new( world, query_state, @@ -1857,8 +1848,8 @@ 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> +impl<'w, D: QueryData, S: QueryStateBorrow, I: EntitySetIterator> Iterator + for QueryManyUniqueIter<'w, S, I> { type Item = D::Item<'w>; @@ -1866,14 +1857,14 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: EntitySetIterator> Iterator fn next(&mut self) -> Option { // SAFETY: Entities are guaranteed to be unique, thus do not alias. unsafe { - QueryManyIter::<'w, 's, D, F, I>::fetch_next_aliased_unchecked( + QueryManyIter::<'w, S, I>::fetch_next_aliased_unchecked( &mut self.0.entity_iter, self.0.entities, self.0.tables, self.0.archetypes, &mut self.0.fetch, &mut self.0.filter, - self.0.query_state, + self.0.query_state.borrow(), ) } } @@ -1885,20 +1876,18 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: EntitySetIterator> Iterator } // This is correct as [`QueryManyIter`] always returns `None` once exhausted. -impl<'w, 's, D: QueryData, F: QueryFilter, I: EntitySetIterator> FusedIterator - for QueryManyUniqueIter<'w, 's, D, F, I> +impl<'w, S: QueryStateBorrow, I: EntitySetIterator> FusedIterator + for QueryManyUniqueIter<'w, S, I> { } // SAFETY: Fetching unique entities maintains uniqueness. -unsafe impl<'w, 's, F: QueryFilter, I: EntitySetIterator> EntitySetIterator - for QueryManyUniqueIter<'w, 's, Entity, F, I> +unsafe impl<'w, F: QueryFilter, I: EntitySetIterator> EntitySetIterator + for QueryManyUniqueIter<'w, &QueryState, I> { } -impl<'w, 's, D: QueryData, F: QueryFilter, I: EntitySetIterator> Debug - for QueryManyUniqueIter<'w, 's, D, F, I> -{ +impl<'w, S: QueryStateBorrow, I: EntitySetIterator> Debug for QueryManyUniqueIter<'w, S, I> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QueryManyUniqueIter").finish() } @@ -1909,17 +1898,17 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: EntitySetIterator> Debug /// This struct is created by the [`sort`](QueryManyIter), [`sort_unstable`](QueryManyIter), /// [`sort_by`](QueryManyIter), [`sort_unstable_by`](QueryManyIter), [`sort_by_key`](QueryManyIter), /// [`sort_unstable_by_key`](QueryManyIter), and [`sort_by_cached_key`](QueryManyIter) methods of [`QueryManyIter`]. -pub struct QuerySortedManyIter<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> { +pub struct QuerySortedManyIter<'w, S: QueryStateBorrow, I: Iterator> { entity_iter: I, entities: &'w Entities, tables: &'w Tables, archetypes: &'w Archetypes, - fetch: D::Fetch<'w>, - query_state: &'s QueryState, + fetch: ::Fetch<'w>, + query_state: S, } -impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> - QuerySortedManyIter<'w, 's, D, F, I> +impl<'w, D: QueryData, S: QueryStateBorrow, I: Iterator> + QuerySortedManyIter<'w, S, I> { /// # Safety /// - `world` must have permission to access any of the components registered in `query_state`. @@ -1927,12 +1916,12 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> /// - `entity_list` must only contain unique entities or be empty. pub(crate) unsafe fn new>( world: UnsafeWorldCell<'w>, - query_state: &'s QueryState, + query_state: S, entity_list: EntityList, last_run: Tick, this_run: Tick, - ) -> QuerySortedManyIter<'w, 's, D, F, I> { - let fetch = D::init_fetch(world, &query_state.fetch_state, last_run, this_run); + ) -> QuerySortedManyIter<'w, S, I> { + let fetch = D::init_fetch(world, &query_state.borrow().fetch_state, last_run, this_run); QuerySortedManyIter { query_state, entities: world.entities(), @@ -1972,7 +1961,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> unsafe { D::set_archetype( &mut self.fetch, - &self.query_state.fetch_state, + &self.query_state.borrow().fetch_state, archetype, table, ); @@ -2001,8 +1990,8 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> } } -impl<'w, 's, D: QueryData, F: QueryFilter, I: DoubleEndedIterator> - QuerySortedManyIter<'w, 's, D, F, I> +impl<'w, D: QueryData, S: QueryStateBorrow, I: DoubleEndedIterator> + QuerySortedManyIter<'w, S, I> { /// Get next result from the query #[inline(always)] @@ -2020,8 +2009,8 @@ 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> +impl<'w, D: ReadOnlyQueryData, S: QueryStateBorrow, I: Iterator> Iterator + for QuerySortedManyIter<'w, S, I> { type Item = D::Item<'w>; @@ -2039,8 +2028,8 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, I: Iterator> I } } -impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, I: DoubleEndedIterator> - DoubleEndedIterator for QuerySortedManyIter<'w, 's, D, F, I> +impl<'w, S: QueryStateBorrow, I: DoubleEndedIterator> + DoubleEndedIterator for QuerySortedManyIter<'w, S, I> { #[inline(always)] fn next_back(&mut self) -> Option { @@ -2052,14 +2041,12 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, I: DoubleEndedIterator> - ExactSizeIterator for QuerySortedManyIter<'w, 's, D, F, I> +impl<'w, S: QueryStateBorrow, I: ExactSizeIterator> + ExactSizeIterator for QuerySortedManyIter<'w, S, I> { } -impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> Debug - for QuerySortedManyIter<'w, 's, D, F, I> -{ +impl<'w, S: QueryStateBorrow, I: Iterator> Debug for QuerySortedManyIter<'w, S, I> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QuerySortedManyIter").finish() } @@ -2128,20 +2115,22 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> Debug /// [`Query`]: crate::system::Query /// [`Query::iter_combinations`]: crate::system::Query::iter_combinations /// [`Query::iter_combinations_mut`]: crate::system::Query::iter_combinations_mut -pub struct QueryCombinationIter<'w, 's, D: QueryData, F: QueryFilter, const K: usize> { +pub struct QueryCombinationIter<'w, S: QueryStateBorrow, const K: usize> { tables: &'w Tables, archetypes: &'w Archetypes, - query_state: &'s QueryState, - cursors: [QueryIterationCursor<'w, 's, D, F>; K], + query_state: S, + cursors: [QueryIterationCursor<'w, S>; K], } -impl<'w, 's, D: QueryData, F: QueryFilter, const K: usize> QueryCombinationIter<'w, 's, D, F, K> { +impl<'w, D: QueryData, S: QueryStateBorrow, const K: usize> + QueryCombinationIter<'w, S, K> +{ /// # Safety /// - `world` must have permission to access any of the components registered in `query_state`. /// - `world` must be the same one used to initialize `query_state`. pub(crate) unsafe fn new( world: UnsafeWorldCell<'w>, - query_state: &'s QueryState, + query_state: S, last_run: Tick, this_run: Tick, ) -> Self { @@ -2149,20 +2138,18 @@ impl<'w, 's, D: QueryData, F: QueryFilter, const K: usize> QueryCombinationIter< // Initialize array with cursors. // There is no FromIterator on arrays, so instead initialize it manually with MaybeUninit - let mut array: MaybeUninit<[QueryIterationCursor<'w, 's, D, F>; K]> = MaybeUninit::uninit(); - let ptr = array - .as_mut_ptr() - .cast::>(); + let mut array: MaybeUninit<[QueryIterationCursor<'w, S>; K]> = MaybeUninit::uninit(); + let ptr = array.as_mut_ptr().cast::>(); ptr.write(QueryIterationCursor::init( world, - query_state, + &query_state, last_run, this_run, )); for slot in (1..K).map(|offset| ptr.add(offset)) { slot.write(QueryIterationCursor::init_empty( world, - query_state, + &query_state, last_run, this_run, )); @@ -2193,11 +2180,15 @@ impl<'w, 's, D: QueryData, F: QueryFilter, const K: usize> QueryCombinationIter< // Make cursor in index `j` for all `j` in `[i, K)` a copy of `c` advanced `j-i+1` times. // If no such `c` exists, return `None` 'outer: for i in (0..K).rev() { - match self.cursors[i].next(self.tables, self.archetypes, self.query_state) { + match self.cursors[i].next(self.tables, self.archetypes, self.query_state.borrow()) { Some(_) => { for j in (i + 1)..K { self.cursors[j] = self.cursors[j - 1].clone(); - match self.cursors[j].next(self.tables, self.archetypes, self.query_state) { + match self.cursors[j].next( + self.tables, + self.archetypes, + self.query_state.borrow(), + ) { Some(_) => {} None if i > 0 => continue 'outer, None => return None, @@ -2236,8 +2227,13 @@ impl<'w, 's, D: QueryData, F: QueryFilter, const K: usize> QueryCombinationIter< // Iterator type is intentionally implemented only for read-only access. // Doing so for mutable references would be unsound, because calling `next` // multiple times would allow multiple owned references to the same data to exist. -impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, const K: usize> Iterator - for QueryCombinationIter<'w, 's, D, F, K> +impl< + 'w, + D: ReadOnlyQueryData, + F: QueryFilter, + S: QueryStateBorrow, + const K: usize, + > Iterator for QueryCombinationIter<'w, S, K> { type Item = [D::Item<'w>; K]; @@ -2279,9 +2275,9 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, const K: usize> Iterator } } -impl<'w, 's, D: QueryData, F: QueryFilter> ExactSizeIterator for QueryIter<'w, 's, D, F> +impl<'w, S: QueryStateBorrow> ExactSizeIterator for QueryIter<'w, S> where - F: ArchetypeFilter, + S::Filter: ArchetypeFilter, { fn len(&self) -> usize { self.size_hint().0 @@ -2289,34 +2285,32 @@ where } // This is correct as [`QueryCombinationIter`] always returns `None` once exhausted. -impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, const K: usize> FusedIterator - for QueryCombinationIter<'w, 's, D, F, K> +impl<'w, S: QueryStateBorrow, const K: usize> FusedIterator + for QueryCombinationIter<'w, S, K> { } -impl<'w, 's, D: QueryData, F: QueryFilter, const K: usize> Debug - for QueryCombinationIter<'w, 's, D, F, K> -{ +impl<'w, S: QueryStateBorrow, const K: usize> Debug for QueryCombinationIter<'w, S, K> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QueryCombinationIter").finish() } } -struct QueryIterationCursor<'w, 's, D: QueryData, F: QueryFilter> { +struct QueryIterationCursor<'w, S: QueryStateBorrow> { // whether the query iteration is dense or not. Mirrors QueryState's `is_dense` field. is_dense: bool, - storage_id_iter: core::slice::Iter<'s, StorageId>, + storage_id_iter: S::StorageIter, table_entities: &'w [Entity], archetype_entities: &'w [ArchetypeEntity], - fetch: D::Fetch<'w>, - filter: F::Fetch<'w>, + fetch: ::Fetch<'w>, + filter: ::Fetch<'w>, // 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 current_row: usize, } -impl Clone for QueryIterationCursor<'_, '_, D, F> { +impl Clone for QueryIterationCursor<'_, S> { fn clone(&self) -> Self { Self { is_dense: self.is_dense, @@ -2331,18 +2325,20 @@ impl Clone for QueryIterationCursor<'_, '_, D, F> } } -impl<'w, 's, D: QueryData, F: QueryFilter> QueryIterationCursor<'w, 's, D, F> { +impl<'w, D: QueryData, F: QueryFilter, S: QueryStateBorrow> + QueryIterationCursor<'w, S> +{ /// # Safety /// - `world` must have permission to access any of the components registered in `query_state`. /// - `world` must be the same one used to initialize `query_state`. unsafe fn init_empty( world: UnsafeWorldCell<'w>, - query_state: &'s QueryState, + query_state: &S, last_run: Tick, this_run: Tick, ) -> Self { QueryIterationCursor { - storage_id_iter: [].iter(), + storage_id_iter: S::StorageIter::default(), ..Self::init(world, query_state, last_run, this_run) } } @@ -2352,32 +2348,37 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIterationCursor<'w, 's, D, F> { /// - `world` must be the same one used to initialize `query_state`. unsafe fn init( world: UnsafeWorldCell<'w>, - query_state: &'s QueryState, + query_state: &S, last_run: Tick, this_run: Tick, ) -> Self { - let fetch = D::init_fetch(world, &query_state.fetch_state, last_run, this_run); - let filter = F::init_fetch(world, &query_state.filter_state, last_run, this_run); + let fetch = D::init_fetch(world, &query_state.borrow().fetch_state, last_run, this_run); + let filter = F::init_fetch( + world, + &query_state.borrow().filter_state, + last_run, + this_run, + ); QueryIterationCursor { fetch, filter, table_entities: &[], archetype_entities: &[], - storage_id_iter: query_state.matched_storage_ids.iter(), - is_dense: query_state.is_dense, + storage_id_iter: query_state.storage_ids(), + is_dense: query_state.borrow().is_dense, current_len: 0, current_row: 0, } } - fn reborrow(&mut self) -> QueryIterationCursor<'_, 's, D, F> { + fn reborrow(&mut self) -> QueryIterationCursor<'_, &'_ QueryState> { QueryIterationCursor { is_dense: self.is_dense, fetch: D::shrink_fetch(self.fetch.clone()), filter: F::shrink_fetch(self.filter.clone()), table_entities: self.table_entities, archetype_entities: self.archetype_entities, - storage_id_iter: self.storage_id_iter.clone(), + storage_id_iter: S::reborrow_storage_ids(&self.storage_id_iter), current_len: self.current_len, current_row: self.current_row, } @@ -2453,7 +2454,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIterationCursor<'w, 's, D, F> { &mut self, tables: &'w Tables, archetypes: &'w Archetypes, - query_state: &'s QueryState, + query_state: &QueryState, ) -> Option> { if self.is_dense { loop { diff --git a/crates/bevy_ecs/src/query/mod.rs b/crates/bevy_ecs/src/query/mod.rs index 9ed6995876f12..b0f6b5f565dd9 100644 --- a/crates/bevy_ecs/src/query/mod.rs +++ b/crates/bevy_ecs/src/query/mod.rs @@ -166,7 +166,7 @@ mod tests { F: ArchetypeFilter, { let mut query = world.query_filtered::(); - let query_type = type_name::>(); + let query_type = type_name::, K>>(); let iter = query.iter_combinations::(world); assert_all_sizes_iterator_equal(iter, expected_size, 0, query_type); let iter = query.iter_combinations::(world); diff --git a/crates/bevy_ecs/src/query/par_iter.rs b/crates/bevy_ecs/src/query/par_iter.rs index 0805774f8cdde..41cda7ca83401 100644 --- a/crates/bevy_ecs/src/query/par_iter.rs +++ b/crates/bevy_ecs/src/query/par_iter.rs @@ -5,7 +5,7 @@ use crate::{ world::unsafe_world_cell::UnsafeWorldCell, }; -use super::{QueryData, QueryFilter, QueryItem, QueryState, ReadOnlyQueryData}; +use super::{QueryData, QueryItem, QueryStateBorrow, ReadOnlyQueryData}; use alloc::vec::Vec; @@ -13,15 +13,15 @@ use alloc::vec::Vec; /// /// This struct is created by the [`Query::par_iter`](crate::system::Query::par_iter) and /// [`Query::par_iter_mut`](crate::system::Query::par_iter_mut) methods. -pub struct QueryParIter<'w, 's, D: QueryData, F: QueryFilter> { +pub struct QueryParIter<'w, S: QueryStateBorrow> { pub(crate) world: UnsafeWorldCell<'w>, - pub(crate) state: &'s QueryState, + pub(crate) state: S, pub(crate) last_run: Tick, pub(crate) this_run: Tick, pub(crate) batching_strategy: BatchingStrategy, } -impl<'w, 's, D: QueryData, F: QueryFilter> QueryParIter<'w, 's, D, F> { +impl<'w, D: QueryData, S: QueryStateBorrow> QueryParIter<'w, S> { /// Changes the batching strategy used when iterating. /// /// For more information on how this affects the resultant iteration, see @@ -94,6 +94,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryParIter<'w, 's, D, F> { // at the same time. unsafe { self.state + .borrow() .query_unchecked_manual_with_ticks(self.world, self.last_run, self.this_run) .into_iter() .fold(init, func); @@ -107,6 +108,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryParIter<'w, 's, D, F> { // SAFETY: See the safety comment above. unsafe { self.state + .borrow() .query_unchecked_manual_with_ticks(self.world, self.last_run, self.this_run) .into_iter() .fold(init, func); @@ -116,7 +118,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryParIter<'w, 's, D, F> { let batch_size = self.get_batch_size(thread_count).max(1); // SAFETY: See the safety comment above. unsafe { - self.state.par_fold_init_unchecked_manual( + self.state.borrow().par_fold_init_unchecked_manual( init, self.world, batch_size, @@ -132,8 +134,8 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryParIter<'w, 's, D, F> { #[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))] fn get_batch_size(&self, thread_count: usize) -> usize { let max_items = || { - let id_iter = self.state.matched_storage_ids.iter(); - if self.state.is_dense { + let id_iter = self.state.storage_ids(); + if self.state.borrow().is_dense { // SAFETY: We only access table metadata. let tables = unsafe { &self.world.world_metadata().storages().tables }; id_iter @@ -160,17 +162,17 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryParIter<'w, 's, D, F> { /// /// [`Entity`]: crate::entity::Entity /// [`Query::par_iter_many`]: crate::system::Query::par_iter_many -pub struct QueryParManyIter<'w, 's, D: QueryData, F: QueryFilter, E: EntityBorrow> { +pub struct QueryParManyIter<'w, S: QueryStateBorrow, E: EntityBorrow> { pub(crate) world: UnsafeWorldCell<'w>, - pub(crate) state: &'s QueryState, + pub(crate) state: S, pub(crate) entity_list: Vec, pub(crate) last_run: Tick, pub(crate) this_run: Tick, pub(crate) batching_strategy: BatchingStrategy, } -impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, E: EntityBorrow + Sync> - QueryParManyIter<'w, 's, D, F, E> +impl<'w, D: ReadOnlyQueryData, S: QueryStateBorrow, E: EntityBorrow + Sync> + QueryParManyIter<'w, S, E> { /// Changes the batching strategy used when iterating. /// @@ -264,6 +266,7 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, E: EntityBorrow + Sync> // at the same time. unsafe { self.state + .borrow() .query_unchecked_manual_with_ticks(self.world, self.last_run, self.this_run) .iter_many_inner(&self.entity_list) .fold(init, func); @@ -277,6 +280,7 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, E: EntityBorrow + Sync> // SAFETY: See the safety comment above. unsafe { self.state + .borrow() .query_unchecked_manual_with_ticks(self.world, self.last_run, self.this_run) .iter_many_inner(&self.entity_list) .fold(init, func); @@ -286,7 +290,7 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, E: EntityBorrow + Sync> let batch_size = self.get_batch_size(thread_count).max(1); // SAFETY: See the safety comment above. unsafe { - self.state.par_many_fold_init_unchecked_manual( + self.state.borrow().par_many_fold_init_unchecked_manual( init, self.world, &self.entity_list, @@ -314,23 +318,17 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter, E: EntityBorrow + Sync> /// [`EntitySet`]: crate::entity::EntitySet /// [`Query::par_iter_many_unique`]: crate::system::Query::par_iter_many_unique /// [`Query::par_iter_many_unique_mut`]: crate::system::Query::par_iter_many_unique_mut -pub struct QueryParManyUniqueIter< - 'w, - 's, - D: QueryData, - F: QueryFilter, - E: TrustedEntityBorrow + Sync, -> { +pub struct QueryParManyUniqueIter<'w, S: QueryStateBorrow, E: TrustedEntityBorrow + Sync> { pub(crate) world: UnsafeWorldCell<'w>, - pub(crate) state: &'s QueryState, + pub(crate) state: S, pub(crate) entity_list: UniqueEntityVec, pub(crate) last_run: Tick, pub(crate) this_run: Tick, pub(crate) batching_strategy: BatchingStrategy, } -impl<'w, 's, D: QueryData, F: QueryFilter, E: TrustedEntityBorrow + Sync> - QueryParManyUniqueIter<'w, 's, D, F, E> +impl<'w, D: QueryData, S: QueryStateBorrow, E: TrustedEntityBorrow + Sync> + QueryParManyUniqueIter<'w, S, E> { /// Changes the batching strategy used when iterating. /// @@ -424,6 +422,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, E: TrustedEntityBorrow + Sync> // at the same time. unsafe { self.state + .borrow() .query_unchecked_manual_with_ticks(self.world, self.last_run, self.this_run) .iter_many_unique_inner(self.entity_list) .fold(init, func); @@ -437,6 +436,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, E: TrustedEntityBorrow + Sync> // SAFETY: See the safety comment above. unsafe { self.state + .borrow() .query_unchecked_manual_with_ticks(self.world, self.last_run, self.this_run) .iter_many_unique_inner(self.entity_list) .fold(init, func); @@ -446,15 +446,17 @@ impl<'w, 's, D: QueryData, F: QueryFilter, E: TrustedEntityBorrow + Sync> let batch_size = self.get_batch_size(thread_count).max(1); // SAFETY: See the safety comment above. unsafe { - self.state.par_many_unique_fold_init_unchecked_manual( - init, - self.world, - &self.entity_list, - batch_size, - func, - self.last_run, - self.this_run, - ); + self.state + .borrow() + .par_many_unique_fold_init_unchecked_manual( + init, + self.world, + &self.entity_list, + batch_size, + func, + self.last_run, + self.this_run, + ); } } } diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index 7013520f949a4..2f998a09589cb 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -13,8 +13,8 @@ use crate::{ #[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))] use crate::entity::{TrustedEntityBorrow, UniqueEntitySlice}; -use alloc::vec::Vec; -use core::{fmt, ptr}; +use alloc::vec::{self, Vec}; +use core::{borrow::Borrow, fmt, iter, ptr, slice}; use fixedbitset::FixedBitSet; use log::warn; #[cfg(feature = "trace")] @@ -42,7 +42,7 @@ use super::{ /// Must be initialized and accessed as a [`TableId`], if both generic parameters to the query are dense. /// Must be initialized and accessed as an [`ArchetypeId`] otherwise. #[derive(Clone, Copy)] -pub(super) union StorageId { +pub union StorageId { pub(super) table_id: TableId, pub(super) archetype_id: ArchetypeId, } @@ -87,6 +87,81 @@ pub struct QueryState { par_iter_span: Span, } +/// Abstracts over an owned or borrowed [`QueryState`]. +pub trait QueryStateBorrow: Borrow> { + /// The [`QueryData`] for this `QueryState`. + type Data: QueryData; + + /// The [`QueryFilter`] for this `QueryState`. + type Filter: QueryFilter; + + /// The type returned by [`Self::storage_ids`]. + type StorageIter: Iterator + Clone + Default; + + /// A read-only version of the state. + type ReadOnly: QueryStateBorrow< + Data = ::ReadOnly, + Filter = Self::Filter, + >; + + /// Iterates the storage ids that this [`QueryState`] matches. + fn storage_ids(&self) -> Self::StorageIter; + + /// Borrows the remainder of the [`Self::StorageIter`] as an iterator + /// usable with `&QueryState`. + fn reborrow_storage_ids( + storage_iter: &Self::StorageIter, + ) -> iter::Copied>; + + /// Converts this state to a read-only version. + fn into_readonly(self) -> Self::ReadOnly; +} + +impl QueryStateBorrow for QueryState { + type Data = D; + type Filter = F; + type StorageIter = vec::IntoIter; + type ReadOnly = QueryState; + + fn storage_ids(&self) -> Self::StorageIter { + // Query iteration holds both the state and the storage iterator, + // so the iterator cannot borrow from the state, + // which requires us to `clone` the `Vec` here. + self.matched_storage_ids.clone().into_iter() + } + + fn reborrow_storage_ids( + storage_iter: &Self::StorageIter, + ) -> iter::Copied> { + storage_iter.as_slice().iter().copied() + } + + fn into_readonly(self) -> Self::ReadOnly { + self.into_readonly() + } +} + +impl<'s, D: QueryData, F: QueryFilter> QueryStateBorrow for &'s QueryState { + type Data = D; + type Filter = F; + type StorageIter = iter::Copied>; + type ReadOnly = &'s QueryState; + + fn storage_ids(&self) -> Self::StorageIter { + self.matched_storage_ids.iter().copied() + } + + fn reborrow_storage_ids( + storage_iter: &Self::StorageIter, + ) -> iter::Copied> { + storage_iter.clone() + } + + fn into_readonly(self) -> Self::ReadOnly { + self.as_readonly() + } +} + impl fmt::Debug for QueryState { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("QueryState") @@ -114,6 +189,26 @@ impl QueryState { unsafe { self.as_transmuted_state::() } } + fn into_readonly(mut self) -> QueryState { + // This is not strictly necessary, since a `&QueryState` + // created using `as_readonly()` would have the full access, + // but it may avoid needing to clone the access later. + self.component_access.access_mut().clear_writes(); + QueryState { + world_id: self.world_id, + archetype_generation: self.archetype_generation, + matched_tables: self.matched_tables, + matched_archetypes: self.matched_archetypes, + component_access: self.component_access, + matched_storage_ids: self.matched_storage_ids, + is_dense: self.is_dense, + fetch_state: self.fetch_state, + filter_state: self.filter_state, + #[cfg(feature = "trace")] + par_iter_span: self.par_iter_span, + } + } + /// Converts this `QueryState` reference to a `QueryState` that does not return any data /// which can be faster. /// @@ -1099,7 +1194,10 @@ impl QueryState { /// /// This can only be called for read-only queries, see [`Self::iter_mut`] for write-queries. #[inline] - pub fn iter<'w, 's>(&'s mut self, world: &'w World) -> QueryIter<'w, 's, D::ReadOnly, F> { + pub fn iter<'w, 's>( + &'s mut self, + world: &'w World, + ) -> QueryIter<'w, &'s QueryState> { self.query(world).into_iter() } @@ -1108,7 +1206,7 @@ impl QueryState { /// This iterator is always guaranteed to return results from each matching entity once and only once. /// Iteration order is not guaranteed. #[inline] - pub fn iter_mut<'w, 's>(&'s mut self, world: &'w mut World) -> QueryIter<'w, 's, D, F> { + pub fn iter_mut<'w, 's>(&'s mut self, world: &'w mut World) -> QueryIter<'w, &'s Self> { self.query_mut(world).into_iter() } @@ -1120,7 +1218,10 @@ impl QueryState { /// /// This can only be called for read-only queries. #[inline] - pub fn iter_manual<'w, 's>(&'s self, world: &'w World) -> QueryIter<'w, 's, D::ReadOnly, F> { + pub fn iter_manual<'w, 's>( + &'s self, + world: &'w World, + ) -> QueryIter<'w, &'s QueryState> { self.query_manual(world).into_iter() } @@ -1152,7 +1253,7 @@ impl QueryState { pub fn iter_combinations<'w, 's, const K: usize>( &'s mut self, world: &'w World, - ) -> QueryCombinationIter<'w, 's, D::ReadOnly, F, K> { + ) -> QueryCombinationIter<'w, &'s QueryState, K> { self.query(world).iter_combinations_inner() } @@ -1177,7 +1278,7 @@ impl QueryState { pub fn iter_combinations_mut<'w, 's, const K: usize>( &'s mut self, world: &'w mut World, - ) -> QueryCombinationIter<'w, 's, D, F, K> { + ) -> QueryCombinationIter<'w, &'s Self, K> { self.query_mut(world).iter_combinations_inner() } @@ -1194,7 +1295,7 @@ impl QueryState { &'s mut self, world: &'w World, entities: EntityList, - ) -> QueryManyIter<'w, 's, D::ReadOnly, F, EntityList::IntoIter> { + ) -> QueryManyIter<'w, &'s QueryState, EntityList::IntoIter> { self.query(world).iter_many_inner(entities) } @@ -1217,7 +1318,7 @@ impl QueryState { &'s self, world: &'w World, entities: EntityList, - ) -> QueryManyIter<'w, 's, D::ReadOnly, F, EntityList::IntoIter> { + ) -> QueryManyIter<'w, &'s QueryState, EntityList::IntoIter> { self.query_manual(world).iter_many_inner(entities) } @@ -1230,7 +1331,7 @@ impl QueryState { &'s mut self, world: &'w mut World, entities: EntityList, - ) -> QueryManyIter<'w, 's, D, F, EntityList::IntoIter> { + ) -> QueryManyIter<'w, &'s Self, EntityList::IntoIter> { self.query_mut(world).iter_many_inner(entities) } @@ -1247,7 +1348,7 @@ impl QueryState { &'s mut self, world: &'w World, entities: EntityList, - ) -> QueryManyUniqueIter<'w, 's, D::ReadOnly, F, EntityList::IntoIter> { + ) -> QueryManyUniqueIter<'w, &'s QueryState, EntityList::IntoIter> { self.query(world).iter_many_unique_inner(entities) } @@ -1271,7 +1372,7 @@ impl QueryState { &'s self, world: &'w World, entities: EntityList, - ) -> QueryManyUniqueIter<'w, 's, D::ReadOnly, F, EntityList::IntoIter> { + ) -> QueryManyUniqueIter<'w, &'s QueryState, EntityList::IntoIter> { self.query_manual(world).iter_many_unique_inner(entities) } @@ -1284,7 +1385,7 @@ impl QueryState { &'s mut self, world: &'w mut World, entities: EntityList, - ) -> QueryManyUniqueIter<'w, 's, D, F, EntityList::IntoIter> { + ) -> QueryManyUniqueIter<'w, &'s Self, EntityList::IntoIter> { self.query_mut(world).iter_many_unique_inner(entities) } /// Returns an [`Iterator`] over the query results for the given [`World`]. @@ -1300,7 +1401,7 @@ impl QueryState { pub unsafe fn iter_unchecked<'w, 's>( &'s mut self, world: UnsafeWorldCell<'w>, - ) -> QueryIter<'w, 's, D, F> { + ) -> QueryIter<'w, &'s Self> { self.query_unchecked(world).into_iter() } @@ -1319,7 +1420,7 @@ impl QueryState { pub unsafe fn iter_combinations_unchecked<'w, 's, const K: usize>( &'s mut self, world: UnsafeWorldCell<'w>, - ) -> QueryCombinationIter<'w, 's, D, F, K> { + ) -> QueryCombinationIter<'w, &'s Self, K> { self.query_unchecked(world).iter_combinations_inner() } @@ -1335,7 +1436,7 @@ impl QueryState { pub fn par_iter<'w, 's>( &'s mut self, world: &'w World, - ) -> QueryParIter<'w, 's, D::ReadOnly, F> { + ) -> QueryParIter<'w, &'s QueryState> { self.query(world).par_iter_inner() } @@ -1384,7 +1485,7 @@ impl QueryState { /// [`par_iter`]: Self::par_iter /// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool #[inline] - pub fn par_iter_mut<'w, 's>(&'s mut self, world: &'w mut World) -> QueryParIter<'w, 's, D, F> { + pub fn par_iter_mut<'w, 's>(&'s mut self, world: &'w mut World) -> QueryParIter<'w, &'s Self> { self.query_mut(world).par_iter_inner() } diff --git a/crates/bevy_ecs/src/relationship/relationship_query.rs b/crates/bevy_ecs/src/relationship/relationship_query.rs index a2ec937c29b9a..2781244958c53 100644 --- a/crates/bevy_ecs/src/relationship/relationship_query.rs +++ b/crates/bevy_ecs/src/relationship/relationship_query.rs @@ -1,6 +1,6 @@ use crate::{ entity::Entity, - query::{QueryData, QueryFilter}, + query::{QueryData, QueryStateBorrow}, relationship::{Relationship, RelationshipTarget}, system::Query, }; @@ -9,7 +9,7 @@ use smallvec::SmallVec; use super::SourceIter; -impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { +impl<'w, 's, D: QueryData, S: QueryStateBorrow> Query<'w, 's, D, S::Filter, S> { /// If the given `entity` contains the `R` [`Relationship`] component, returns the /// target entity of that relationship. pub fn related(&'w self, entity: Entity) -> Option @@ -21,12 +21,12 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// If the given `entity` contains the `S` [`RelationshipTarget`] component, returns the /// source entities stored on that component. - pub fn relationship_sources( + pub fn relationship_sources( &'w self, entity: Entity, ) -> impl Iterator + 'w where - ::ReadOnly: QueryData = &'w S>, + ::ReadOnly: QueryData = &'w R>, { self.get(entity) .into_iter() @@ -57,13 +57,13 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// /// For relationship graphs that contain loops, this could loop infinitely. /// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity. - pub fn iter_leaves( + pub fn iter_leaves( &'w self, entity: Entity, ) -> impl Iterator + 'w where - ::ReadOnly: QueryData = &'w S>, - SourceIter<'w, S>: DoubleEndedIterator, + ::ReadOnly: QueryData = &'w R>, + SourceIter<'w, R>: DoubleEndedIterator, { self.iter_descendants_depth_first(entity).filter(|entity| { self.get(*entity) @@ -98,12 +98,12 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// /// For relationship graphs that contain loops, this could loop infinitely. /// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity. - pub fn iter_descendants( + pub fn iter_descendants( &'w self, entity: Entity, - ) -> DescendantIter<'w, 's, D, F, S> + ) -> DescendantIter<'w, 's, S, R> where - D::ReadOnly: QueryData = &'w S>, + D::ReadOnly: QueryData = &'w R>, { DescendantIter::new(self, entity) } @@ -115,13 +115,13 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// /// For relationship graphs that contain loops, this could loop infinitely. /// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity. - pub fn iter_descendants_depth_first( + pub fn iter_descendants_depth_first( &'w self, entity: Entity, - ) -> DescendantDepthFirstIter<'w, 's, D, F, S> + ) -> DescendantDepthFirstIter<'w, 's, S, R> where - D::ReadOnly: QueryData = &'w S>, - SourceIter<'w, S>: DoubleEndedIterator, + D::ReadOnly: QueryData = &'w R>, + SourceIter<'w, R>: DoubleEndedIterator, { DescendantDepthFirstIter::new(self, entity) } @@ -132,10 +132,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// /// For relationship graphs that contain loops, this could loop infinitely. /// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity. - pub fn iter_ancestors( - &'w self, - entity: Entity, - ) -> AncestorIter<'w, 's, D, F, R> + pub fn iter_ancestors(&'w self, entity: Entity) -> AncestorIter<'w, 's, S, R> where D::ReadOnly: QueryData = &'w R>, { @@ -146,20 +143,20 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// An [`Iterator`] of [`Entity`]s over the descendants of an [`Entity`]. /// /// Traverses the hierarchy breadth-first. -pub struct DescendantIter<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> +pub struct DescendantIter<'w, 's, S: QueryStateBorrow, R: RelationshipTarget> where - D::ReadOnly: QueryData = &'w S>, + ::ReadOnly: QueryData = &'w R>, { - children_query: &'w Query<'w, 's, D, F>, + children_query: &'w Query<'w, 's, S::Data, S::Filter, S>, vecdeque: VecDeque, } -impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> DescendantIter<'w, 's, D, F, S> +impl<'w, 's, S: QueryStateBorrow, R: RelationshipTarget> DescendantIter<'w, 's, S, R> where - D::ReadOnly: QueryData = &'w S>, + ::ReadOnly: QueryData = &'w R>, { /// Returns a new [`DescendantIter`]. - pub fn new(children_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self { + pub fn new(children_query: &'w Query<'w, 's, S::Data, S::Filter, S>, entity: Entity) -> Self { DescendantIter { children_query, vecdeque: children_query @@ -171,10 +168,9 @@ where } } -impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> Iterator - for DescendantIter<'w, 's, D, F, S> +impl<'w, 's, S: QueryStateBorrow, R: RelationshipTarget> Iterator for DescendantIter<'w, 's, S, R> where - D::ReadOnly: QueryData = &'w S>, + ::ReadOnly: QueryData = &'w R>, { type Item = Entity; @@ -192,22 +188,21 @@ where /// An [`Iterator`] of [`Entity`]s over the descendants of an [`Entity`]. /// /// Traverses the hierarchy depth-first. -pub struct DescendantDepthFirstIter<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> +pub struct DescendantDepthFirstIter<'w, 's, S: QueryStateBorrow, R: RelationshipTarget> where - D::ReadOnly: QueryData = &'w S>, + ::ReadOnly: QueryData = &'w R>, { - children_query: &'w Query<'w, 's, D, F>, + children_query: &'w Query<'w, 's, S::Data, S::Filter, S>, stack: SmallVec<[Entity; 8]>, } -impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> - DescendantDepthFirstIter<'w, 's, D, F, S> +impl<'w, 's, S: QueryStateBorrow, R: RelationshipTarget> DescendantDepthFirstIter<'w, 's, S, R> where - D::ReadOnly: QueryData = &'w S>, - SourceIter<'w, S>: DoubleEndedIterator, + ::ReadOnly: QueryData = &'w R>, + SourceIter<'w, R>: DoubleEndedIterator, { /// Returns a new [`DescendantDepthFirstIter`]. - pub fn new(children_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self { + pub fn new(children_query: &'w Query<'w, 's, S::Data, S::Filter, S>, entity: Entity) -> Self { DescendantDepthFirstIter { children_query, stack: children_query @@ -217,11 +212,11 @@ where } } -impl<'w, 's, D: QueryData, F: QueryFilter, S: RelationshipTarget> Iterator - for DescendantDepthFirstIter<'w, 's, D, F, S> +impl<'w, 's, S: QueryStateBorrow, R: RelationshipTarget> Iterator + for DescendantDepthFirstIter<'w, 's, S, R> where - D::ReadOnly: QueryData = &'w S>, - SourceIter<'w, S>: DoubleEndedIterator, + ::ReadOnly: QueryData = &'w R>, + SourceIter<'w, R>: DoubleEndedIterator, { type Item = Entity; @@ -237,20 +232,20 @@ where } /// An [`Iterator`] of [`Entity`]s over the ancestors of an [`Entity`]. -pub struct AncestorIter<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> +pub struct AncestorIter<'w, 's, S: QueryStateBorrow, R: Relationship> where - D::ReadOnly: QueryData = &'w R>, + ::ReadOnly: QueryData = &'w R>, { - parent_query: &'w Query<'w, 's, D, F>, + parent_query: &'w Query<'w, 's, S::Data, S::Filter, S>, next: Option, } -impl<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> AncestorIter<'w, 's, D, F, R> +impl<'w, 's, S: QueryStateBorrow, R: Relationship> AncestorIter<'w, 's, S, R> where - D::ReadOnly: QueryData = &'w R>, + ::ReadOnly: QueryData = &'w R>, { /// Returns a new [`AncestorIter`]. - pub fn new(parent_query: &'w Query<'w, 's, D, F>, entity: Entity) -> Self { + pub fn new(parent_query: &'w Query<'w, 's, S::Data, S::Filter, S>, entity: Entity) -> Self { AncestorIter { parent_query, next: Some(entity), @@ -258,10 +253,9 @@ where } } -impl<'w, 's, D: QueryData, F: QueryFilter, R: Relationship> Iterator - for AncestorIter<'w, 's, D, F, R> +impl<'w, 's, S: QueryStateBorrow, R: Relationship> Iterator for AncestorIter<'w, 's, S, R> where - D::ReadOnly: QueryData = &'w R>, + ::ReadOnly: QueryData = &'w R>, { type Item = Entity; diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index a9662f28c95f3..9d1c5c6822afa 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -5,7 +5,8 @@ use crate::{ query::{ DebugCheckedUnwrap, NopWorldQuery, QueryCombinationIter, QueryData, QueryEntityError, QueryFilter, QueryIter, QueryManyIter, QueryManyUniqueIter, QueryParIter, QueryParManyIter, - QueryParManyUniqueIter, QuerySingleError, QueryState, ROQueryItem, ReadOnlyQueryData, + QueryParManyUniqueIter, QuerySingleError, QueryState, QueryStateBorrow, ROQueryItem, + ReadOnlyQueryData, }, world::unsafe_world_cell::UnsafeWorldCell, }; @@ -374,12 +375,21 @@ use core::{ /// [`Table`]: crate::storage::Table /// [`With`]: crate::query::With /// [`Without`]: crate::query::Without -pub struct Query<'world, 'state, D: QueryData, F: QueryFilter = ()> { +pub struct Query< + 'world, + // Note that `'state` is only used in the default type for `S`. + // That's necessary to make `Query` be a valid `SystemParam`. + 'state, + D: QueryData, + F: QueryFilter = (), + S: QueryStateBorrow = &'state QueryState, +> { // SAFETY: Must have access to the components registered in `state`. world: UnsafeWorldCell<'world>, - state: &'state QueryState, + state: S, last_run: Tick, this_run: Tick, + marker: PhantomData<&'state QueryState>, } impl Clone for Query<'_, '_, D, F> { @@ -402,7 +412,9 @@ impl core::fmt::Debug for Query<'_, '_, D, F> { } } -impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { +impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateBorrow> + Query<'w, 's, D, F, S> +{ /// Creates a new query. /// /// # Safety @@ -413,7 +425,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { #[inline] pub(crate) unsafe fn new( world: UnsafeWorldCell<'w>, - state: &'s QueryState, + state: S, last_run: Tick, this_run: Tick, ) -> Self { @@ -422,6 +434,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { state, last_run, this_run, + marker: PhantomData, } } @@ -434,15 +447,15 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// # See also /// /// [`into_readonly`](Self::into_readonly) for a version that consumes the `Query` to return one with the full `'world` lifetime. - pub fn as_readonly(&self) -> Query<'_, 's, D::ReadOnly, F> { + pub fn as_readonly(&self) -> Query<'_, '_, D::ReadOnly, F> { // SAFETY: The reborrowed query is converted to read-only, so it cannot perform mutable access, // and the original query is held with a shared borrow, so it cannot perform mutable access either. unsafe { self.reborrow_unsafe() }.into_readonly() } /// Returns another `Query` from this does not return any data, which can be faster. - fn as_nop(&self) -> Query<'_, 's, NopWorldQuery, F> { - let new_state = self.state.as_nop(); + fn as_nop(&self) -> Query<'_, '_, NopWorldQuery, F> { + let new_state = self.state.borrow().as_nop(); // SAFETY: // - The reborrowed query is converted to read-only, so it cannot perform mutable access, // and the original query is held with a shared borrow, so it cannot perform mutable access either. @@ -461,8 +474,8 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// # See also /// /// [`as_readonly`](Self::as_readonly) for a version that borrows the `Query` instead of consuming it. - pub fn into_readonly(self) -> Query<'w, 's, D::ReadOnly, F> { - let new_state = self.state.as_readonly(); + pub fn into_readonly(self) -> Query<'w, 's, D::ReadOnly, F, S::ReadOnly> { + let new_state = self.state.into_readonly(); // SAFETY: // - This is memory safe because it turns the query immutable. // - The world matches because it was the same one used to construct self. @@ -493,7 +506,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// } /// } /// ``` - pub fn reborrow(&mut self) -> Query<'_, 's, D, F> { + pub fn reborrow(&mut self) -> Query<'_, '_, D, F> { // SAFETY: this query is exclusively borrowed while the new one exists, so // no overlapping access can occur. unsafe { self.reborrow_unsafe() } @@ -510,7 +523,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// # See also /// /// - [`reborrow`](Self::reborrow) for the safe versions. - pub unsafe fn reborrow_unsafe(&self) -> Query<'_, 's, D, F> { + pub unsafe fn reborrow_unsafe(&self) -> Query<'_, '_, D, F> { // SAFETY: // - This is memory safe because the caller ensures that there are no conflicting references. // - The world matches because it was the same one used to construct self. @@ -528,11 +541,18 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// # See also /// /// - [`reborrow_unsafe`](Self::reborrow_unsafe) for a safer version that constrains the returned `'w` lifetime to the length of the borrow. - unsafe fn copy_unsafe(&self) -> Query<'w, 's, D, F> { + unsafe fn copy_unsafe(&self) -> Query<'w, '_, D, F> { // SAFETY: // - This is memory safe because the caller ensures that there are no conflicting references. // - The world matches because it was the same one used to construct self. - unsafe { Query::new(self.world, self.state, self.last_run, self.this_run) } + unsafe { + Query::new( + self.world, + self.state.borrow(), + self.last_run, + self.this_run, + ) + } } /// Returns an [`Iterator`] over the read-only query items. @@ -562,7 +582,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// /// [`iter_mut`](Self::iter_mut) for mutable query items. #[inline] - pub fn iter(&self) -> QueryIter<'_, 's, D::ReadOnly, F> { + pub fn iter(&self) -> QueryIter<'_, &QueryState> { self.as_readonly().into_iter() } @@ -593,7 +613,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// /// [`iter`](Self::iter) for read-only query items. #[inline] - pub fn iter_mut(&mut self) -> QueryIter<'_, 's, D, F> { + pub fn iter_mut(&mut self) -> QueryIter<'_, &QueryState> { self.reborrow().into_iter() } @@ -623,7 +643,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { #[inline] pub fn iter_combinations( &self, - ) -> QueryCombinationIter<'_, 's, D::ReadOnly, F, K> { + ) -> QueryCombinationIter<'_, &QueryState, K> { self.as_readonly().iter_combinations_inner() } @@ -653,7 +673,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { #[inline] pub fn iter_combinations_mut( &mut self, - ) -> QueryCombinationIter<'_, 's, D, F, K> { + ) -> QueryCombinationIter<'_, &QueryState, K> { self.reborrow().iter_combinations_inner() } @@ -682,7 +702,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// - [`iter_combinations`](Self::iter_combinations) for read-only query item combinations. /// - [`iter_combinations_mut`](Self::iter_combinations_mut) for mutable query item combinations. #[inline] - pub fn iter_combinations_inner(self) -> QueryCombinationIter<'w, 's, D, F, K> { + pub fn iter_combinations_inner(self) -> QueryCombinationIter<'w, S, K> { // SAFETY: `self.world` has permission to access the required components. unsafe { QueryCombinationIter::new(self.world, self.state, self.last_run, self.this_run) } } @@ -728,7 +748,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn iter_many>( &self, entities: EntityList, - ) -> QueryManyIter<'_, 's, D::ReadOnly, F, EntityList::IntoIter> { + ) -> QueryManyIter<'_, &QueryState, EntityList::IntoIter> { self.as_readonly().iter_many_inner(entities) } @@ -773,7 +793,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn iter_many_mut>( &mut self, entities: EntityList, - ) -> QueryManyIter<'_, 's, D, F, EntityList::IntoIter> { + ) -> QueryManyIter<'_, &QueryState, EntityList::IntoIter> { self.reborrow().iter_many_inner(entities) } @@ -791,7 +811,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn iter_many_inner>( self, entities: EntityList, - ) -> QueryManyIter<'w, 's, D, F, EntityList::IntoIter> { + ) -> QueryManyIter<'w, S, EntityList::IntoIter> { // SAFETY: `self.world` has permission to access the required components. unsafe { QueryManyIter::new( @@ -856,7 +876,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn iter_many_unique( &self, entities: EntityList, - ) -> QueryManyUniqueIter<'_, 's, D::ReadOnly, F, EntityList::IntoIter> { + ) -> QueryManyUniqueIter<'_, &QueryState, EntityList::IntoIter> { self.as_readonly().iter_many_unique_inner(entities) } @@ -911,7 +931,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn iter_many_unique_mut( &mut self, entities: EntityList, - ) -> QueryManyUniqueIter<'_, 's, D, F, EntityList::IntoIter> { + ) -> QueryManyUniqueIter<'_, &QueryState, EntityList::IntoIter> { self.reborrow().iter_many_unique_inner(entities) } @@ -966,7 +986,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn iter_many_unique_inner( self, entities: EntityList, - ) -> QueryManyUniqueIter<'w, 's, D, F, EntityList::IntoIter> { + ) -> QueryManyUniqueIter<'w, S, EntityList::IntoIter> { // SAFETY: `self.world` has permission to access the required components. unsafe { QueryManyUniqueIter::new( @@ -993,7 +1013,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// /// - [`iter`](Self::iter) and [`iter_mut`](Self::iter_mut) for the safe versions. #[inline] - pub unsafe fn iter_unsafe(&self) -> QueryIter<'_, 's, D, F> { + pub unsafe fn iter_unsafe(&self) -> QueryIter<'_, &QueryState> { // SAFETY: The caller promises that this will not result in multiple mutable references. unsafe { self.reborrow_unsafe() }.into_iter() } @@ -1014,7 +1034,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { #[inline] pub unsafe fn iter_combinations_unsafe( &self, - ) -> QueryCombinationIter<'_, 's, D, F, K> { + ) -> QueryCombinationIter<'_, &QueryState, K> { // SAFETY: The caller promises that this will not result in multiple mutable references. unsafe { self.reborrow_unsafe() }.iter_combinations_inner() } @@ -1036,7 +1056,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub unsafe fn iter_many_unsafe>( &self, entities: EntityList, - ) -> QueryManyIter<'_, 's, D, F, EntityList::IntoIter> { + ) -> QueryManyIter<'_, &QueryState, EntityList::IntoIter> { // SAFETY: The caller promises that this will not result in multiple mutable references. unsafe { self.reborrow_unsafe() }.iter_many_inner(entities) } @@ -1058,7 +1078,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub unsafe fn iter_many_unique_unsafe( &self, entities: EntityList, - ) -> QueryManyUniqueIter<'_, 's, D, F, EntityList::IntoIter> { + ) -> QueryManyUniqueIter<'_, &QueryState, EntityList::IntoIter> { // SAFETY: The caller promises that this will not result in multiple mutable references. unsafe { self.reborrow_unsafe() }.iter_many_unique_inner(entities) } @@ -1079,7 +1099,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<'_, &QueryState> { self.as_readonly().par_iter_inner() } @@ -1114,7 +1134,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<'_, &QueryState> { self.reborrow().par_iter_inner() } @@ -1145,7 +1165,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// # bevy_ecs::system::assert_is_system(gravity_system); /// ``` #[inline] - pub fn par_iter_inner(self) -> QueryParIter<'w, 's, D, F> { + pub fn par_iter_inner(self) -> QueryParIter<'w, S> { QueryParIter { world: self.world, state: self.state, @@ -1174,10 +1194,10 @@ 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<'_, &QueryState, EntityList::Item> { QueryParManyIter { world: self.world, - state: self.state.as_readonly(), + state: self.state.borrow().as_readonly(), entity_list: entities.into_iter().collect(), last_run: self.last_run, this_run: self.this_run, @@ -1203,10 +1223,10 @@ 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<'_, &QueryState, EntityList::Item> { QueryParManyUniqueIter { world: self.world, - state: self.state.as_readonly(), + state: self.state.borrow().as_readonly(), entity_list: entities.into_iter().collect(), last_run: self.last_run, this_run: self.this_run, @@ -1232,10 +1252,10 @@ 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<'_, &QueryState, EntityList::Item> { QueryParManyUniqueIter { world: self.world, - state: self.state, + state: self.state.borrow(), entity_list: entities.into_iter().collect(), last_run: self.last_run, this_run: self.this_run, @@ -1440,6 +1460,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { .ok_or(EntityDoesNotExistError::new(entity, self.world.entities()))?; if !self .state + .borrow() .matched_archetypes .contains(location.archetype_id.index()) { @@ -1452,13 +1473,13 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { .debug_checked_unwrap(); let mut fetch = D::init_fetch( self.world, - &self.state.fetch_state, + &self.state.borrow().fetch_state, self.last_run, self.this_run, ); let mut filter = F::init_fetch( self.world, - &self.state.filter_state, + &self.state.borrow().filter_state, self.last_run, self.this_run, ); @@ -1469,8 +1490,18 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { .tables .get(location.table_id) .debug_checked_unwrap(); - D::set_archetype(&mut fetch, &self.state.fetch_state, archetype, table); - F::set_archetype(&mut filter, &self.state.filter_state, archetype, table); + D::set_archetype( + &mut fetch, + &self.state.borrow().fetch_state, + archetype, + table, + ); + F::set_archetype( + &mut filter, + &self.state.borrow().filter_state, + archetype, + table, + ); if F::filter_fetch(&mut filter, entity, location.table_row) { Ok(D::fetch(&mut fetch, entity, location.table_row)) @@ -2149,7 +2180,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { pub fn transmute_lens_filtered_inner( self, ) -> QueryLens<'w, NewD, NewF> { - let state = self.state.transmute_filtered::(self.world); + let state = self + .state + .borrow() + .transmute_filtered::(self.world); QueryLens { world: self.world, state, @@ -2302,6 +2336,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { ) -> QueryLens<'w, NewD, NewF> { let state = self .state + .borrow() .join_filtered::(self.world, other.state); QueryLens { world: self.world, @@ -2312,9 +2347,11 @@ 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> { +impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateBorrow> IntoIterator + for Query<'w, 's, D, F, S> +{ type Item = D::Item<'w>; - type IntoIter = QueryIter<'w, 's, D, F>; + type IntoIter = QueryIter<'w, S>; fn into_iter(self) -> Self::IntoIter { // SAFETY: @@ -2325,18 +2362,22 @@ impl<'w, 's, D: QueryData, F: QueryFilter> IntoIterator for Query<'w, 's, D, F> } } -impl<'w, 's, D: QueryData, F: QueryFilter> IntoIterator for &'w Query<'_, 's, D, F> { +impl<'w, D: QueryData, F: QueryFilter, S: QueryStateBorrow> IntoIterator + for &'w Query<'_, '_, D, F, S> +{ type Item = ROQueryItem<'w, D>; - type IntoIter = QueryIter<'w, 's, D::ReadOnly, F>; + type IntoIter = QueryIter<'w, &'w QueryState>; fn into_iter(self) -> Self::IntoIter { self.iter() } } -impl<'w, 's, D: QueryData, F: QueryFilter> IntoIterator for &'w mut Query<'_, 's, D, F> { +impl<'w, D: QueryData, F: QueryFilter, S: QueryStateBorrow> IntoIterator + for &'w mut Query<'_, '_, D, F, S> +{ type Item = D::Item<'w>; - type IntoIter = QueryIter<'w, 's, D, F>; + type IntoIter = QueryIter<'w, &'w QueryState>; fn into_iter(self) -> Self::IntoIter { self.iter_mut() @@ -2368,7 +2409,7 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter> Query<'w, 's, D, F> { /// # bevy_ecs::system::assert_is_system(report_names_system); /// ``` #[inline] - pub fn iter_inner(&self) -> QueryIter<'w, 's, D::ReadOnly, F> { + pub fn iter_inner(&self) -> QueryIter<'w, &'s QueryState> { (*self).into_iter() } } @@ -2391,6 +2432,7 @@ impl<'w, Q: QueryData, F: QueryFilter> QueryLens<'w, Q, F> { state: &self.state, last_run: self.last_run, this_run: self.this_run, + marker: PhantomData, } } } @@ -2405,6 +2447,7 @@ impl<'w, Q: ReadOnlyQueryData, F: QueryFilter> QueryLens<'w, Q, F> { state: &self.state, last_run: self.last_run, this_run: self.this_run, + marker: PhantomData, } } } From f7ff2b30ab1b6aed5b93ea43eda92539e31a4359 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Wed, 19 Feb 2025 11:48:00 -0500 Subject: [PATCH 02/18] Make QueryLens a type alias. --- crates/bevy_ecs/src/query/state.rs | 4 +-- crates/bevy_ecs/src/system/query.rs | 53 ++++++++++++----------------- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index 2f998a09589cb..f5d4b100b1fb8 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -2156,7 +2156,7 @@ mod tests { .run_system_once(|query: Query<&mut A>| { let mut readonly = query.as_readonly(); let mut lens: QueryLens<&mut A> = readonly.transmute_lens(); - bad(lens.query(), query.as_readonly()); + bad(lens.reborrow(), query.as_readonly()); }) .unwrap(); } @@ -2291,7 +2291,7 @@ mod tests { .run_system_once(|query_a: Query<&mut A>, mut query_b: Query<&mut B>| { let mut readonly = query_a.as_readonly(); let mut lens: QueryLens<(&mut A, &mut B)> = readonly.join(&mut query_b); - bad(lens.query(), query_a.as_readonly()); + bad(lens.reborrow(), query_a.as_readonly()); }) .unwrap(); } diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 9d1c5c6822afa..5f4d014d72bc1 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -1949,7 +1949,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateBorrow) { - /// assert_eq!(lens.query().single().unwrap().0, 10); + /// assert_eq!(lens.single().unwrap().0, 10); /// } /// /// // We can use the function in a system that takes the exact query. @@ -2108,7 +2108,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateBorrow) { - /// assert_eq!(lens.query().single().unwrap().0, 10); + /// assert_eq!(lens.single().unwrap().0, 10); /// } /// /// // We can use the function in a system that takes the exact query. @@ -2184,12 +2184,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateBorrow(self.world); - QueryLens { - world: self.world, - state, - last_run: self.last_run, - this_run: self.this_run, - } + // SAFETY: + // - This is memory safe because the original query had compatible access and was consumed. + // - The world matches because it was the same one used to construct self. + unsafe { Query::new(self.world, state, self.last_run, self.this_run) } } /// Gets a [`QueryLens`] with the same accesses as the existing query @@ -2238,12 +2236,12 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateBorrow /// ) { /// let mut players_transforms: QueryLens<(&Transform, &Player)> = transforms.join(&mut players); - /// for (transform, player) in &players_transforms.query() { + /// for (transform, player) in &players_transforms { /// // do something with a and b /// } /// /// let mut enemies_transforms: QueryLens<(&Transform, &Enemy)> = transforms.join(&mut enemies); - /// for (transform, enemy) in &enemies_transforms.query() { + /// for (transform, enemy) in &enemies_transforms { /// // do something with a and b /// } /// } @@ -2338,12 +2336,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateBorrow(self.world, other.state); - QueryLens { - world: self.world, - state, - last_run: self.last_run, - this_run: self.this_run, - } + // SAFETY: + // - This is memory safe because the original query had compatible access and was consumed. + // - The world matches because it was the same one used to construct self. + unsafe { Query::new(self.world, state, self.last_run, self.this_run) } } } @@ -2414,26 +2410,19 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter> Query<'w, 's, D, F> { } } -/// Type returned from [`Query::transmute_lens`] containing the new [`QueryState`]. +/// A [`Query`] with an owned [`QueryState`]. /// -/// Call [`query`](QueryLens::query) or [`into`](Into::into) to construct the resulting [`Query`] -pub struct QueryLens<'w, Q: QueryData, F: QueryFilter = ()> { - world: UnsafeWorldCell<'w>, - state: QueryState, - last_run: Tick, - this_run: Tick, -} +/// This is returned from methods like [`Query::transmute_lens`] that construct a fresh [`QueryState`]. +pub type QueryLens<'w, Q, F = ()> = Query<'w, 'w, Q, F, QueryState>; impl<'w, Q: QueryData, F: QueryFilter> QueryLens<'w, Q, F> { /// Create a [`Query`] from the underlying [`QueryState`]. + #[deprecated( + since = "0.16.0", + note = "This can usually be removed, since `QueryLens` supports all methods from `Query`. If you need to consume the resulting `Query`, call `reborrow()` instead." + )] pub fn query(&mut self) -> Query<'_, '_, Q, F> { - Query { - world: self.world, - state: &self.state, - last_run: self.last_run, - this_run: self.this_run, - marker: PhantomData, - } + self.reborrow() } } @@ -2456,7 +2445,7 @@ impl<'w, 's, Q: QueryData, F: QueryFilter> From<&'s mut QueryLens<'w, Q, F>> for Query<'s, 's, Q, F> { fn from(value: &'s mut QueryLens<'w, Q, F>) -> Query<'s, 's, Q, F> { - value.query() + value.reborrow() } } From 0a68186d91984d284f91b3d6272a3f6e7f602e5a Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Wed, 5 Mar 2025 12:41:14 -0500 Subject: [PATCH 03/18] Update doc link now that `StorageId` is `pub`. --- crates/bevy_ecs/src/query/state.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index f5d4b100b1fb8..c643b6b08dc5e 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -28,7 +28,7 @@ use super::{ /// An ID for either a table or an archetype. Used for Query iteration. /// /// Query iteration is exclusively dense (over tables) or archetypal (over archetypes) based on whether -/// the query filters are dense or not. This is represented by the [`QueryState::is_dense`] field. +/// the query filters are dense or not. This is represented by the [`QueryState::is_dense`](QueryState) field. /// /// Note that `D::IS_DENSE` and `F::IS_DENSE` have no relationship with `QueryState::is_dense` and /// any combination of their values can happen. From 49ae0f36ac4326f32d5296d3b06bcfd8d654e130 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Wed, 5 Mar 2025 15:55:14 -0500 Subject: [PATCH 04/18] Box QueryState. Use Deref instead of Borrow. --- crates/bevy_ecs/src/query/iter.rs | 77 ++++++++++----------------- crates/bevy_ecs/src/query/par_iter.rs | 32 +++++------ crates/bevy_ecs/src/query/state.rs | 11 ++-- crates/bevy_ecs/src/system/query.rs | 49 +++++------------ 4 files changed, 59 insertions(+), 110 deletions(-) diff --git a/crates/bevy_ecs/src/query/iter.rs b/crates/bevy_ecs/src/query/iter.rs index 08891df558180..a5d966985a8df 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -122,7 +122,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateBorrow world: self.world, tables: self.tables, archetypes: self.archetypes, - query_state: self.query_state.borrow(), + query_state: &self.query_state, cursor: self.cursor.reborrow(), } } @@ -214,14 +214,10 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateBorrow "TableRow is only valid up to u32::MAX" ); - D::set_table( - &mut self.cursor.fetch, - &self.query_state.borrow().fetch_state, - table, - ); + D::set_table(&mut self.cursor.fetch, &self.query_state.fetch_state, table); F::set_table( &mut self.cursor.filter, - &self.query_state.borrow().filter_state, + &self.query_state.filter_state, table, ); @@ -271,13 +267,13 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateBorrow let table = self.tables.get(archetype.table_id()).debug_checked_unwrap(); D::set_archetype( &mut self.cursor.fetch, - &self.query_state.borrow().fetch_state, + &self.query_state.fetch_state, archetype, table, ); F::set_archetype( &mut self.cursor.filter, - &self.query_state.borrow().filter_state, + &self.query_state.filter_state, archetype, table, ); @@ -349,13 +345,13 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateBorrow D::set_archetype( &mut self.cursor.fetch, - &self.query_state.borrow().fetch_state, + &self.query_state.fetch_state, archetype, table, ); F::set_archetype( &mut self.cursor.filter, - &self.query_state.borrow().filter_state, + &self.query_state.filter_state, archetype, table, ); @@ -840,10 +836,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateBorrow let world = self.world; - let query_lens_state = self - .query_state - .borrow() - .transmute_filtered::<(L, Entity), F>(world); + let query_lens_state = self.query_state.transmute_filtered::<(L, Entity), F>(world); // SAFETY: // `self.world` has permission to access the required components. @@ -882,7 +875,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateBorrow // `query_state` is the state that was passed to `QueryIterationCursor::init`. unsafe { self.cursor - .next(self.tables, self.archetypes, self.query_state.borrow()) + .next(self.tables, self.archetypes, &self.query_state) } } @@ -994,7 +987,7 @@ where last_run: Tick, this_run: Tick, ) -> Self { - let fetch = D::init_fetch(world, &query_state.borrow().fetch_state, last_run, this_run); + let fetch = D::init_fetch(world, &query_state.fetch_state, last_run, this_run); QuerySortedIter { query_state, entities: world.entities(), @@ -1029,7 +1022,7 @@ where unsafe { D::set_archetype( &mut self.fetch, - &self.query_state.borrow().fetch_state, + &self.query_state.fetch_state, archetype, table, ); @@ -1134,13 +1127,8 @@ impl< last_run: Tick, this_run: Tick, ) -> Self { - let fetch = D::init_fetch(world, &query_state.borrow().fetch_state, last_run, this_run); - let filter = F::init_fetch( - world, - &query_state.borrow().filter_state, - last_run, - this_run, - ); + let fetch = D::init_fetch(world, &query_state.fetch_state, last_run, this_run); + let filter = F::init_fetch(world, &query_state.filter_state, last_run, this_run); QueryManyIter { world, query_state, @@ -1228,7 +1216,7 @@ impl< self.archetypes, &mut self.fetch, &mut self.filter, - self.query_state.borrow(), + &self.query_state, ) .map(D::shrink) } @@ -1667,10 +1655,7 @@ impl< > { let world = self.world; - let query_lens_state = self - .query_state - .borrow() - .transmute_filtered::<(L, Entity), F>(world); + let query_lens_state = self.query_state.transmute_filtered::<(L, Entity), F>(world); // SAFETY: // `self.world` has permission to access the required components. @@ -1728,7 +1713,7 @@ impl< self.archetypes, &mut self.fetch, &mut self.filter, - self.query_state.borrow(), + &self.query_state, ) .map(D::shrink) } @@ -1753,7 +1738,7 @@ impl<'w, D: ReadOnlyQueryData, S: QueryStateBorrow, I: Iterator, I: EntitySetIterator> Iter self.0.archetypes, &mut self.0.fetch, &mut self.0.filter, - self.0.query_state.borrow(), + &self.0.query_state, ) } } @@ -1921,7 +1906,7 @@ impl<'w, D: QueryData, S: QueryStateBorrow, I: Iterator last_run: Tick, this_run: Tick, ) -> QuerySortedManyIter<'w, S, I> { - let fetch = D::init_fetch(world, &query_state.borrow().fetch_state, last_run, this_run); + let fetch = D::init_fetch(world, &query_state.fetch_state, last_run, this_run); QuerySortedManyIter { query_state, entities: world.entities(), @@ -1961,7 +1946,7 @@ impl<'w, D: QueryData, S: QueryStateBorrow, I: Iterator unsafe { D::set_archetype( &mut self.fetch, - &self.query_state.borrow().fetch_state, + &self.query_state.fetch_state, archetype, table, ); @@ -2180,15 +2165,12 @@ impl<'w, D: QueryData, S: QueryStateBorrow, const K: usize> // Make cursor in index `j` for all `j` in `[i, K)` a copy of `c` advanced `j-i+1` times. // If no such `c` exists, return `None` 'outer: for i in (0..K).rev() { - match self.cursors[i].next(self.tables, self.archetypes, self.query_state.borrow()) { + match self.cursors[i].next(self.tables, self.archetypes, &self.query_state) { Some(_) => { for j in (i + 1)..K { self.cursors[j] = self.cursors[j - 1].clone(); - match self.cursors[j].next( - self.tables, - self.archetypes, - self.query_state.borrow(), - ) { + match self.cursors[j].next(self.tables, self.archetypes, &self.query_state) + { Some(_) => {} None if i > 0 => continue 'outer, None => return None, @@ -2352,20 +2334,15 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateBorrow last_run: Tick, this_run: Tick, ) -> Self { - let fetch = D::init_fetch(world, &query_state.borrow().fetch_state, last_run, this_run); - let filter = F::init_fetch( - world, - &query_state.borrow().filter_state, - last_run, - this_run, - ); + let fetch = D::init_fetch(world, &query_state.fetch_state, last_run, this_run); + let filter = F::init_fetch(world, &query_state.filter_state, last_run, this_run); QueryIterationCursor { fetch, filter, table_entities: &[], archetype_entities: &[], storage_id_iter: query_state.storage_ids(), - is_dense: query_state.borrow().is_dense, + is_dense: query_state.is_dense, current_len: 0, current_row: 0, } diff --git a/crates/bevy_ecs/src/query/par_iter.rs b/crates/bevy_ecs/src/query/par_iter.rs index 41cda7ca83401..111ff77a9da39 100644 --- a/crates/bevy_ecs/src/query/par_iter.rs +++ b/crates/bevy_ecs/src/query/par_iter.rs @@ -94,7 +94,6 @@ impl<'w, D: QueryData, S: QueryStateBorrow> QueryParIter<'w, S> { // at the same time. unsafe { self.state - .borrow() .query_unchecked_manual_with_ticks(self.world, self.last_run, self.this_run) .into_iter() .fold(init, func); @@ -108,7 +107,6 @@ impl<'w, D: QueryData, S: QueryStateBorrow> QueryParIter<'w, S> { // SAFETY: See the safety comment above. unsafe { self.state - .borrow() .query_unchecked_manual_with_ticks(self.world, self.last_run, self.this_run) .into_iter() .fold(init, func); @@ -118,7 +116,7 @@ impl<'w, D: QueryData, S: QueryStateBorrow> QueryParIter<'w, S> { let batch_size = self.get_batch_size(thread_count).max(1); // SAFETY: See the safety comment above. unsafe { - self.state.borrow().par_fold_init_unchecked_manual( + self.state.par_fold_init_unchecked_manual( init, self.world, batch_size, @@ -135,7 +133,7 @@ impl<'w, D: QueryData, S: QueryStateBorrow> QueryParIter<'w, S> { fn get_batch_size(&self, thread_count: usize) -> usize { let max_items = || { let id_iter = self.state.storage_ids(); - if self.state.borrow().is_dense { + if self.state.is_dense { // SAFETY: We only access table metadata. let tables = unsafe { &self.world.world_metadata().storages().tables }; id_iter @@ -266,7 +264,6 @@ impl<'w, D: ReadOnlyQueryData, S: QueryStateBorrow, E: EntityBorrow + // at the same time. unsafe { self.state - .borrow() .query_unchecked_manual_with_ticks(self.world, self.last_run, self.this_run) .iter_many_inner(&self.entity_list) .fold(init, func); @@ -280,7 +277,6 @@ impl<'w, D: ReadOnlyQueryData, S: QueryStateBorrow, E: EntityBorrow + // SAFETY: See the safety comment above. unsafe { self.state - .borrow() .query_unchecked_manual_with_ticks(self.world, self.last_run, self.this_run) .iter_many_inner(&self.entity_list) .fold(init, func); @@ -290,7 +286,7 @@ impl<'w, D: ReadOnlyQueryData, S: QueryStateBorrow, E: EntityBorrow + let batch_size = self.get_batch_size(thread_count).max(1); // SAFETY: See the safety comment above. unsafe { - self.state.borrow().par_many_fold_init_unchecked_manual( + self.state.par_many_fold_init_unchecked_manual( init, self.world, &self.entity_list, @@ -422,7 +418,6 @@ impl<'w, D: QueryData, S: QueryStateBorrow, E: TrustedEntityBorrow + S // at the same time. unsafe { self.state - .borrow() .query_unchecked_manual_with_ticks(self.world, self.last_run, self.this_run) .iter_many_unique_inner(self.entity_list) .fold(init, func); @@ -436,7 +431,6 @@ impl<'w, D: QueryData, S: QueryStateBorrow, E: TrustedEntityBorrow + S // SAFETY: See the safety comment above. unsafe { self.state - .borrow() .query_unchecked_manual_with_ticks(self.world, self.last_run, self.this_run) .iter_many_unique_inner(self.entity_list) .fold(init, func); @@ -446,17 +440,15 @@ impl<'w, D: QueryData, S: QueryStateBorrow, E: TrustedEntityBorrow + S let batch_size = self.get_batch_size(thread_count).max(1); // SAFETY: See the safety comment above. unsafe { - self.state - .borrow() - .par_many_unique_fold_init_unchecked_manual( - init, - self.world, - &self.entity_list, - batch_size, - func, - self.last_run, - self.this_run, - ); + self.state.par_many_unique_fold_init_unchecked_manual( + init, + self.world, + &self.entity_list, + batch_size, + func, + self.last_run, + self.this_run, + ); } } } diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index c643b6b08dc5e..fc9ffcbec7c52 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -14,7 +14,8 @@ use crate::{ use crate::entity::{TrustedEntityBorrow, UniqueEntitySlice}; use alloc::vec::{self, Vec}; -use core::{borrow::Borrow, fmt, iter, ptr, slice}; +use bevy_platform_support::prelude::Box; +use core::{fmt, iter, ops::Deref, ptr, slice}; use fixedbitset::FixedBitSet; use log::warn; #[cfg(feature = "trace")] @@ -88,7 +89,7 @@ pub struct QueryState { } /// Abstracts over an owned or borrowed [`QueryState`]. -pub trait QueryStateBorrow: Borrow> { +pub trait QueryStateBorrow: Deref> { /// The [`QueryData`] for this `QueryState`. type Data: QueryData; @@ -117,11 +118,11 @@ pub trait QueryStateBorrow: Borrow> { fn into_readonly(self) -> Self::ReadOnly; } -impl QueryStateBorrow for QueryState { +impl QueryStateBorrow for Box> { type Data = D; type Filter = F; type StorageIter = vec::IntoIter; - type ReadOnly = QueryState; + type ReadOnly = Box>; fn storage_ids(&self) -> Self::StorageIter { // Query iteration holds both the state and the storage iterator, @@ -137,7 +138,7 @@ impl QueryStateBorrow for QueryState { } fn into_readonly(self) -> Self::ReadOnly { - self.into_readonly() + Box::new((*self).into_readonly()) } } diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 5f4d014d72bc1..da8609b20b979 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -10,6 +10,7 @@ use crate::{ }, world::unsafe_world_cell::UnsafeWorldCell, }; +use bevy_platform_support::prelude::Box; use core::{ marker::PhantomData, mem::MaybeUninit, @@ -455,7 +456,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateBorrow Query<'_, '_, NopWorldQuery, F> { - let new_state = self.state.borrow().as_nop(); + let new_state = self.state.as_nop(); // SAFETY: // - The reborrowed query is converted to read-only, so it cannot perform mutable access, // and the original query is held with a shared borrow, so it cannot perform mutable access either. @@ -545,14 +546,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateBorrow QueryParManyIter<'_, &QueryState, EntityList::Item> { QueryParManyIter { world: self.world, - state: self.state.borrow().as_readonly(), + state: self.state.as_readonly(), entity_list: entities.into_iter().collect(), last_run: self.last_run, this_run: self.this_run, @@ -1226,7 +1220,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateBorrow QueryParManyUniqueIter<'_, &QueryState, EntityList::Item> { QueryParManyUniqueIter { world: self.world, - state: self.state.borrow().as_readonly(), + state: self.state.as_readonly(), entity_list: entities.into_iter().collect(), last_run: self.last_run, this_run: self.this_run, @@ -1255,7 +1249,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateBorrow QueryParManyUniqueIter<'_, &QueryState, EntityList::Item> { QueryParManyUniqueIter { world: self.world, - state: self.state.borrow(), + state: &self.state, entity_list: entities.into_iter().collect(), last_run: self.last_run, this_run: self.this_run, @@ -1460,7 +1454,6 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateBorrow( self, ) -> QueryLens<'w, NewD, NewF> { - let state = self - .state - .borrow() - .transmute_filtered::(self.world); + let state = self.state.transmute_filtered::(self.world); // SAFETY: // - This is memory safe because the original query had compatible access and was consumed. // - The world matches because it was the same one used to construct self. - unsafe { Query::new(self.world, state, self.last_run, self.this_run) } + unsafe { Query::new(self.world, Box::new(state), self.last_run, self.this_run) } } /// Gets a [`QueryLens`] with the same accesses as the existing query @@ -2334,12 +2314,11 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateBorrow QueryLens<'w, NewD, NewF> { let state = self .state - .borrow() .join_filtered::(self.world, other.state); // SAFETY: // - This is memory safe because the original query had compatible access and was consumed. // - The world matches because it was the same one used to construct self. - unsafe { Query::new(self.world, state, self.last_run, self.this_run) } + unsafe { Query::new(self.world, Box::new(state), self.last_run, self.this_run) } } } @@ -2413,7 +2392,7 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter> Query<'w, 's, D, F> { /// A [`Query`] with an owned [`QueryState`]. /// /// This is returned from methods like [`Query::transmute_lens`] that construct a fresh [`QueryState`]. -pub type QueryLens<'w, Q, F = ()> = Query<'w, 'w, Q, F, QueryState>; +pub type QueryLens<'w, Q, F = ()> = Query<'w, 'w, Q, F, Box>>; impl<'w, Q: QueryData, F: QueryFilter> QueryLens<'w, Q, F> { /// Create a [`Query`] from the underlying [`QueryState`]. From 2d2d78d6c7b06362ff1972ac75db29894b897141 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Wed, 5 Mar 2025 15:56:49 -0500 Subject: [PATCH 05/18] Rename QueryStateBorrow to QueryStateDeref. --- crates/bevy_ecs/src/query/iter.rs | 89 +++++++++---------- crates/bevy_ecs/src/query/par_iter.rs | 14 +-- crates/bevy_ecs/src/query/state.rs | 8 +- .../src/relationship/relationship_query.rs | 22 ++--- crates/bevy_ecs/src/system/query.rs | 12 +-- 5 files changed, 71 insertions(+), 74 deletions(-) diff --git a/crates/bevy_ecs/src/query/iter.rs b/crates/bevy_ecs/src/query/iter.rs index a5d966985a8df..cdd22a6f8ecfa 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -4,7 +4,7 @@ use crate::{ bundle::Bundle, component::Tick, entity::{Entities, Entity, EntityBorrow, EntitySet, EntitySetIterator}, - query::{ArchetypeFilter, DebugCheckedUnwrap, QueryState, QueryStateBorrow, StorageId}, + query::{ArchetypeFilter, DebugCheckedUnwrap, QueryState, QueryStateDeref, StorageId}, storage::{Table, TableRow, Tables}, world::{ unsafe_world_cell::UnsafeWorldCell, EntityMut, EntityMutExcept, EntityRef, EntityRefExcept, @@ -24,7 +24,7 @@ use core::{ /// /// This struct is created by the [`Query::iter`](crate::system::Query::iter) and /// [`Query::iter_mut`](crate::system::Query::iter_mut) methods. -pub struct QueryIter<'w, S: QueryStateBorrow> { +pub struct QueryIter<'w, S: QueryStateDeref> { world: UnsafeWorldCell<'w>, tables: &'w Tables, archetypes: &'w Archetypes, @@ -32,7 +32,7 @@ pub struct QueryIter<'w, S: QueryStateBorrow> { cursor: QueryIterationCursor<'w, S>, } -impl<'w, D: QueryData, F: QueryFilter, S: QueryStateBorrow> QueryIter<'w, S> { +impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> QueryIter<'w, S> { /// # Safety /// - `world` must have permission to access any of the components registered in `query_state`. /// - `world` must be the same one used to initialize `query_state`. @@ -863,7 +863,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateBorrow } } -impl<'w, D: QueryData, F: QueryFilter, S: QueryStateBorrow> Iterator +impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> Iterator for QueryIter<'w, S> { type Item = D::Item<'w>; @@ -908,7 +908,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateBorrow } // This is correct as [`QueryIter`] always returns `None` once exhausted. -impl<'w, S: QueryStateBorrow> FusedIterator for QueryIter<'w, S> {} +impl<'w, S: QueryStateDeref> FusedIterator for QueryIter<'w, S> {} // SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. unsafe impl<'w, F: QueryFilter> EntitySetIterator for QueryIter<'w, &QueryState> {} @@ -943,13 +943,13 @@ unsafe impl<'w, F: QueryFilter, B: Bundle> EntitySetIterator { } -impl<'w, S: QueryStateBorrow> Debug for QueryIter<'w, S> { +impl<'w, S: QueryStateDeref> Debug for QueryIter<'w, S> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QueryIter").finish() } } -impl<'w, S: QueryStateBorrow + Copy> Clone for QueryIter<'w, S> { +impl<'w, S: QueryStateDeref + Copy> Clone for QueryIter<'w, S> { fn clone(&self) -> Self { self.remaining() } @@ -960,7 +960,7 @@ impl<'w, S: QueryStateBorrow + Copy> Clone for QueryIte /// This struct is created by the [`QueryIter::sort`], [`QueryIter::sort_unstable`], /// [`QueryIter::sort_by`], [`QueryIter::sort_unstable_by`], [`QueryIter::sort_by_key`], /// [`QueryIter::sort_unstable_by_key`], and [`QueryIter::sort_by_cached_key`] methods. -pub struct QuerySortedIter<'w, S: QueryStateBorrow, I> +pub struct QuerySortedIter<'w, S: QueryStateDeref, I> where I: Iterator, { @@ -972,7 +972,7 @@ where query_state: S, } -impl<'w, D: QueryData, S: QueryStateBorrow, I: Iterator> QuerySortedIter<'w, S, I> +impl<'w, D: QueryData, S: QueryStateDeref, I: Iterator> QuerySortedIter<'w, S, I> where I: Iterator, { @@ -1036,7 +1036,7 @@ where } } -impl<'w, D: QueryData, S: QueryStateBorrow, I: Iterator> Iterator +impl<'w, D: QueryData, S: QueryStateDeref, I: Iterator> Iterator for QuerySortedIter<'w, S, I> where I: Iterator, @@ -1055,7 +1055,7 @@ where } } -impl<'w, S: QueryStateBorrow, I: Iterator> DoubleEndedIterator for QuerySortedIter<'w, S, I> +impl<'w, S: QueryStateDeref, I: Iterator> DoubleEndedIterator for QuerySortedIter<'w, S, I> where I: DoubleEndedIterator, { @@ -1067,13 +1067,13 @@ where } } -impl<'w, S: QueryStateBorrow, I: Iterator> ExactSizeIterator for QuerySortedIter<'w, S, I> where +impl<'w, S: QueryStateDeref, I: Iterator> ExactSizeIterator for QuerySortedIter<'w, S, I> where I: ExactSizeIterator { } // This is correct as [`QuerySortedIter`] returns `None` once exhausted if `entity_iter` does. -impl<'w, S: QueryStateBorrow, I: Iterator> FusedIterator for QuerySortedIter<'w, S, I> where +impl<'w, S: QueryStateDeref, I: Iterator> FusedIterator for QuerySortedIter<'w, S, I> where I: FusedIterator { } @@ -1086,7 +1086,7 @@ unsafe impl<'w, F: QueryFilter, I: Iterator> EntitySetIterator { } -impl<'w, S: QueryStateBorrow, I: Iterator> Debug for QuerySortedIter<'w, S, I> { +impl<'w, S: QueryStateDeref, I: Iterator> Debug for QuerySortedIter<'w, S, I> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QuerySortedIter").finish() } @@ -1098,7 +1098,7 @@ impl<'w, S: QueryStateBorrow, I: Iterator> Debug for QuerySortedI /// Entities that don't match the query are skipped. /// /// This struct is created by the [`Query::iter_many`](crate::system::Query::iter_many) and [`Query::iter_many_mut`](crate::system::Query::iter_many_mut) methods. -pub struct QueryManyIter<'w, S: QueryStateBorrow, I: Iterator> { +pub struct QueryManyIter<'w, S: QueryStateDeref, I: Iterator> { world: UnsafeWorldCell<'w>, entity_iter: I, entities: &'w Entities, @@ -1113,7 +1113,7 @@ impl< 'w, D: QueryData, F: QueryFilter, - S: QueryStateBorrow, + S: QueryStateDeref, I: Iterator, > QueryManyIter<'w, S, I> { @@ -1693,7 +1693,7 @@ impl< impl< 'w, D: QueryData, - S: QueryStateBorrow, + S: QueryStateDeref, I: DoubleEndedIterator, > QueryManyIter<'w, S, I> { @@ -1720,7 +1720,7 @@ impl< } } -impl<'w, D: ReadOnlyQueryData, S: QueryStateBorrow, I: Iterator> +impl<'w, D: ReadOnlyQueryData, S: QueryStateDeref, I: Iterator> Iterator for QueryManyIter<'w, S, I> { type Item = D::Item<'w>; @@ -1752,7 +1752,7 @@ impl<'w, D: ReadOnlyQueryData, S: QueryStateBorrow, I: Iterator, + S: QueryStateDeref, I: DoubleEndedIterator, > DoubleEndedIterator for QueryManyIter<'w, S, I> { @@ -1776,8 +1776,8 @@ impl< } // This is correct as [`QueryManyIter`] always returns `None` once exhausted. -impl<'w, S: QueryStateBorrow, I: Iterator> - FusedIterator for QueryManyIter<'w, S, I> +impl<'w, S: QueryStateDeref, I: Iterator> FusedIterator + for QueryManyIter<'w, S, I> { } @@ -1787,7 +1787,7 @@ unsafe impl<'w, F: QueryFilter, I: EntitySetIterator> EntitySetIterator { } -impl<'w, S: QueryStateBorrow, I: Iterator> Debug for QueryManyIter<'w, S, I> { +impl<'w, S: QueryStateDeref, I: Iterator> Debug for QueryManyIter<'w, S, I> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QueryManyIter").finish() } @@ -1806,11 +1806,11 @@ impl<'w, S: QueryStateBorrow, I: Iterator> Debug for QueryMa /// [`iter_many_unique`]: crate::system::Query::iter_many /// [`iter_many_unique_mut`]: crate::system::Query::iter_many_mut /// [`Query`]: crate::system::Query -pub struct QueryManyUniqueIter<'w, S: QueryStateBorrow, I: EntitySetIterator>( +pub struct QueryManyUniqueIter<'w, S: QueryStateDeref, I: EntitySetIterator>( QueryManyIter<'w, S, I>, ); -impl<'w, D: QueryData, S: QueryStateBorrow, I: EntitySetIterator> +impl<'w, D: QueryData, S: QueryStateDeref, I: EntitySetIterator> QueryManyUniqueIter<'w, S, I> { /// # Safety @@ -1833,7 +1833,7 @@ impl<'w, D: QueryData, S: QueryStateBorrow, I: EntitySetIterator> } } -impl<'w, D: QueryData, S: QueryStateBorrow, I: EntitySetIterator> Iterator +impl<'w, D: QueryData, S: QueryStateDeref, I: EntitySetIterator> Iterator for QueryManyUniqueIter<'w, S, I> { type Item = D::Item<'w>; @@ -1861,10 +1861,7 @@ impl<'w, D: QueryData, S: QueryStateBorrow, I: EntitySetIterator> Iter } // This is correct as [`QueryManyIter`] always returns `None` once exhausted. -impl<'w, S: QueryStateBorrow, I: EntitySetIterator> FusedIterator - for QueryManyUniqueIter<'w, S, I> -{ -} +impl<'w, S: QueryStateDeref, I: EntitySetIterator> FusedIterator for QueryManyUniqueIter<'w, S, I> {} // SAFETY: Fetching unique entities maintains uniqueness. unsafe impl<'w, F: QueryFilter, I: EntitySetIterator> EntitySetIterator @@ -1872,7 +1869,7 @@ unsafe impl<'w, F: QueryFilter, I: EntitySetIterator> EntitySetIterator { } -impl<'w, S: QueryStateBorrow, I: EntitySetIterator> Debug for QueryManyUniqueIter<'w, S, I> { +impl<'w, S: QueryStateDeref, I: EntitySetIterator> Debug for QueryManyUniqueIter<'w, S, I> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QueryManyUniqueIter").finish() } @@ -1883,7 +1880,7 @@ impl<'w, S: QueryStateBorrow, I: EntitySetIterator> Debug for QueryManyUniqueIte /// This struct is created by the [`sort`](QueryManyIter), [`sort_unstable`](QueryManyIter), /// [`sort_by`](QueryManyIter), [`sort_unstable_by`](QueryManyIter), [`sort_by_key`](QueryManyIter), /// [`sort_unstable_by_key`](QueryManyIter), and [`sort_by_cached_key`](QueryManyIter) methods of [`QueryManyIter`]. -pub struct QuerySortedManyIter<'w, S: QueryStateBorrow, I: Iterator> { +pub struct QuerySortedManyIter<'w, S: QueryStateDeref, I: Iterator> { entity_iter: I, entities: &'w Entities, tables: &'w Tables, @@ -1892,7 +1889,7 @@ pub struct QuerySortedManyIter<'w, S: QueryStateBorrow, I: Iterator, I: Iterator> +impl<'w, D: QueryData, S: QueryStateDeref, I: Iterator> QuerySortedManyIter<'w, S, I> { /// # Safety @@ -1975,7 +1972,7 @@ impl<'w, D: QueryData, S: QueryStateBorrow, I: Iterator } } -impl<'w, D: QueryData, S: QueryStateBorrow, I: DoubleEndedIterator> +impl<'w, D: QueryData, S: QueryStateDeref, I: DoubleEndedIterator> QuerySortedManyIter<'w, S, I> { /// Get next result from the query @@ -1994,7 +1991,7 @@ impl<'w, D: QueryData, S: QueryStateBorrow, I: DoubleEndedIterator, I: Iterator> Iterator +impl<'w, D: ReadOnlyQueryData, S: QueryStateDeref, I: Iterator> Iterator for QuerySortedManyIter<'w, S, I> { type Item = D::Item<'w>; @@ -2013,7 +2010,7 @@ impl<'w, D: ReadOnlyQueryData, S: QueryStateBorrow, I: Iterator, I: DoubleEndedIterator> +impl<'w, S: QueryStateDeref, I: DoubleEndedIterator> DoubleEndedIterator for QuerySortedManyIter<'w, S, I> { #[inline(always)] @@ -2026,12 +2023,12 @@ impl<'w, S: QueryStateBorrow, I: DoubleEndedIterator, I: ExactSizeIterator> +impl<'w, S: QueryStateDeref, I: ExactSizeIterator> ExactSizeIterator for QuerySortedManyIter<'w, S, I> { } -impl<'w, S: QueryStateBorrow, I: Iterator> Debug for QuerySortedManyIter<'w, S, I> { +impl<'w, S: QueryStateDeref, I: Iterator> Debug for QuerySortedManyIter<'w, S, I> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QuerySortedManyIter").finish() } @@ -2100,14 +2097,14 @@ impl<'w, S: QueryStateBorrow, I: Iterator> Debug for QuerySortedM /// [`Query`]: crate::system::Query /// [`Query::iter_combinations`]: crate::system::Query::iter_combinations /// [`Query::iter_combinations_mut`]: crate::system::Query::iter_combinations_mut -pub struct QueryCombinationIter<'w, S: QueryStateBorrow, const K: usize> { +pub struct QueryCombinationIter<'w, S: QueryStateDeref, const K: usize> { tables: &'w Tables, archetypes: &'w Archetypes, query_state: S, cursors: [QueryIterationCursor<'w, S>; K], } -impl<'w, D: QueryData, S: QueryStateBorrow, const K: usize> +impl<'w, D: QueryData, S: QueryStateDeref, const K: usize> QueryCombinationIter<'w, S, K> { /// # Safety @@ -2213,7 +2210,7 @@ impl< 'w, D: ReadOnlyQueryData, F: QueryFilter, - S: QueryStateBorrow, + S: QueryStateDeref, const K: usize, > Iterator for QueryCombinationIter<'w, S, K> { @@ -2257,7 +2254,7 @@ impl< } } -impl<'w, S: QueryStateBorrow> ExactSizeIterator for QueryIter<'w, S> +impl<'w, S: QueryStateDeref> ExactSizeIterator for QueryIter<'w, S> where S::Filter: ArchetypeFilter, { @@ -2267,18 +2264,18 @@ where } // This is correct as [`QueryCombinationIter`] always returns `None` once exhausted. -impl<'w, S: QueryStateBorrow, const K: usize> FusedIterator +impl<'w, S: QueryStateDeref, const K: usize> FusedIterator for QueryCombinationIter<'w, S, K> { } -impl<'w, S: QueryStateBorrow, const K: usize> Debug for QueryCombinationIter<'w, S, K> { +impl<'w, S: QueryStateDeref, const K: usize> Debug for QueryCombinationIter<'w, S, K> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QueryCombinationIter").finish() } } -struct QueryIterationCursor<'w, S: QueryStateBorrow> { +struct QueryIterationCursor<'w, S: QueryStateDeref> { // whether the query iteration is dense or not. Mirrors QueryState's `is_dense` field. is_dense: bool, storage_id_iter: S::StorageIter, @@ -2292,7 +2289,7 @@ struct QueryIterationCursor<'w, S: QueryStateBorrow> { current_row: usize, } -impl Clone for QueryIterationCursor<'_, S> { +impl Clone for QueryIterationCursor<'_, S> { fn clone(&self) -> Self { Self { is_dense: self.is_dense, @@ -2307,7 +2304,7 @@ impl Clone for QueryIterationCursor<'_, S> { } } -impl<'w, D: QueryData, F: QueryFilter, S: QueryStateBorrow> +impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> QueryIterationCursor<'w, S> { /// # Safety diff --git a/crates/bevy_ecs/src/query/par_iter.rs b/crates/bevy_ecs/src/query/par_iter.rs index 111ff77a9da39..74005c7c34824 100644 --- a/crates/bevy_ecs/src/query/par_iter.rs +++ b/crates/bevy_ecs/src/query/par_iter.rs @@ -5,7 +5,7 @@ use crate::{ world::unsafe_world_cell::UnsafeWorldCell, }; -use super::{QueryData, QueryItem, QueryStateBorrow, ReadOnlyQueryData}; +use super::{QueryData, QueryItem, QueryStateDeref, ReadOnlyQueryData}; use alloc::vec::Vec; @@ -13,7 +13,7 @@ use alloc::vec::Vec; /// /// This struct is created by the [`Query::par_iter`](crate::system::Query::par_iter) and /// [`Query::par_iter_mut`](crate::system::Query::par_iter_mut) methods. -pub struct QueryParIter<'w, S: QueryStateBorrow> { +pub struct QueryParIter<'w, S: QueryStateDeref> { pub(crate) world: UnsafeWorldCell<'w>, pub(crate) state: S, pub(crate) last_run: Tick, @@ -21,7 +21,7 @@ pub struct QueryParIter<'w, S: QueryStateBorrow> { pub(crate) batching_strategy: BatchingStrategy, } -impl<'w, D: QueryData, S: QueryStateBorrow> QueryParIter<'w, S> { +impl<'w, D: QueryData, S: QueryStateDeref> QueryParIter<'w, S> { /// Changes the batching strategy used when iterating. /// /// For more information on how this affects the resultant iteration, see @@ -160,7 +160,7 @@ impl<'w, D: QueryData, S: QueryStateBorrow> QueryParIter<'w, S> { /// /// [`Entity`]: crate::entity::Entity /// [`Query::par_iter_many`]: crate::system::Query::par_iter_many -pub struct QueryParManyIter<'w, S: QueryStateBorrow, E: EntityBorrow> { +pub struct QueryParManyIter<'w, S: QueryStateDeref, E: EntityBorrow> { pub(crate) world: UnsafeWorldCell<'w>, pub(crate) state: S, pub(crate) entity_list: Vec, @@ -169,7 +169,7 @@ pub struct QueryParManyIter<'w, S: QueryStateBorrow, E: EntityBorrow> { pub(crate) batching_strategy: BatchingStrategy, } -impl<'w, D: ReadOnlyQueryData, S: QueryStateBorrow, E: EntityBorrow + Sync> +impl<'w, D: ReadOnlyQueryData, S: QueryStateDeref, E: EntityBorrow + Sync> QueryParManyIter<'w, S, E> { /// Changes the batching strategy used when iterating. @@ -314,7 +314,7 @@ impl<'w, D: ReadOnlyQueryData, S: QueryStateBorrow, E: EntityBorrow + /// [`EntitySet`]: crate::entity::EntitySet /// [`Query::par_iter_many_unique`]: crate::system::Query::par_iter_many_unique /// [`Query::par_iter_many_unique_mut`]: crate::system::Query::par_iter_many_unique_mut -pub struct QueryParManyUniqueIter<'w, S: QueryStateBorrow, E: TrustedEntityBorrow + Sync> { +pub struct QueryParManyUniqueIter<'w, S: QueryStateDeref, E: TrustedEntityBorrow + Sync> { pub(crate) world: UnsafeWorldCell<'w>, pub(crate) state: S, pub(crate) entity_list: UniqueEntityVec, @@ -323,7 +323,7 @@ pub struct QueryParManyUniqueIter<'w, S: QueryStateBorrow, E: TrustedEntityBorro pub(crate) batching_strategy: BatchingStrategy, } -impl<'w, D: QueryData, S: QueryStateBorrow, E: TrustedEntityBorrow + Sync> +impl<'w, D: QueryData, S: QueryStateDeref, E: TrustedEntityBorrow + Sync> QueryParManyUniqueIter<'w, S, E> { /// Changes the batching strategy used when iterating. diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index fc9ffcbec7c52..90fe0e0497401 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -89,7 +89,7 @@ pub struct QueryState { } /// Abstracts over an owned or borrowed [`QueryState`]. -pub trait QueryStateBorrow: Deref> { +pub trait QueryStateDeref: Deref> { /// The [`QueryData`] for this `QueryState`. type Data: QueryData; @@ -100,7 +100,7 @@ pub trait QueryStateBorrow: Deref> type StorageIter: Iterator + Clone + Default; /// A read-only version of the state. - type ReadOnly: QueryStateBorrow< + type ReadOnly: QueryStateDeref< Data = ::ReadOnly, Filter = Self::Filter, >; @@ -118,7 +118,7 @@ pub trait QueryStateBorrow: Deref> fn into_readonly(self) -> Self::ReadOnly; } -impl QueryStateBorrow for Box> { +impl QueryStateDeref for Box> { type Data = D; type Filter = F; type StorageIter = vec::IntoIter; @@ -142,7 +142,7 @@ impl QueryStateBorrow for Box> { } } -impl<'s, D: QueryData, F: QueryFilter> QueryStateBorrow for &'s QueryState { +impl<'s, D: QueryData, F: QueryFilter> QueryStateDeref for &'s QueryState { type Data = D; type Filter = F; type StorageIter = iter::Copied>; diff --git a/crates/bevy_ecs/src/relationship/relationship_query.rs b/crates/bevy_ecs/src/relationship/relationship_query.rs index 2781244958c53..e03087d380e07 100644 --- a/crates/bevy_ecs/src/relationship/relationship_query.rs +++ b/crates/bevy_ecs/src/relationship/relationship_query.rs @@ -1,6 +1,6 @@ use crate::{ entity::Entity, - query::{QueryData, QueryStateBorrow}, + query::{QueryData, QueryStateDeref}, relationship::{Relationship, RelationshipTarget}, system::Query, }; @@ -9,7 +9,7 @@ use smallvec::SmallVec; use super::SourceIter; -impl<'w, 's, D: QueryData, S: QueryStateBorrow> Query<'w, 's, D, S::Filter, S> { +impl<'w, 's, D: QueryData, S: QueryStateDeref> Query<'w, 's, D, S::Filter, S> { /// If the given `entity` contains the `R` [`Relationship`] component, returns the /// target entity of that relationship. pub fn related(&'w self, entity: Entity) -> Option @@ -143,7 +143,7 @@ impl<'w, 's, D: QueryData, S: QueryStateBorrow> Query<'w, 's, D, S::Fi /// An [`Iterator`] of [`Entity`]s over the descendants of an [`Entity`]. /// /// Traverses the hierarchy breadth-first. -pub struct DescendantIter<'w, 's, S: QueryStateBorrow, R: RelationshipTarget> +pub struct DescendantIter<'w, 's, S: QueryStateDeref, R: RelationshipTarget> where ::ReadOnly: QueryData = &'w R>, { @@ -151,7 +151,7 @@ where vecdeque: VecDeque, } -impl<'w, 's, S: QueryStateBorrow, R: RelationshipTarget> DescendantIter<'w, 's, S, R> +impl<'w, 's, S: QueryStateDeref, R: RelationshipTarget> DescendantIter<'w, 's, S, R> where ::ReadOnly: QueryData = &'w R>, { @@ -168,7 +168,7 @@ where } } -impl<'w, 's, S: QueryStateBorrow, R: RelationshipTarget> Iterator for DescendantIter<'w, 's, S, R> +impl<'w, 's, S: QueryStateDeref, R: RelationshipTarget> Iterator for DescendantIter<'w, 's, S, R> where ::ReadOnly: QueryData = &'w R>, { @@ -188,7 +188,7 @@ where /// An [`Iterator`] of [`Entity`]s over the descendants of an [`Entity`]. /// /// Traverses the hierarchy depth-first. -pub struct DescendantDepthFirstIter<'w, 's, S: QueryStateBorrow, R: RelationshipTarget> +pub struct DescendantDepthFirstIter<'w, 's, S: QueryStateDeref, R: RelationshipTarget> where ::ReadOnly: QueryData = &'w R>, { @@ -196,7 +196,7 @@ where stack: SmallVec<[Entity; 8]>, } -impl<'w, 's, S: QueryStateBorrow, R: RelationshipTarget> DescendantDepthFirstIter<'w, 's, S, R> +impl<'w, 's, S: QueryStateDeref, R: RelationshipTarget> DescendantDepthFirstIter<'w, 's, S, R> where ::ReadOnly: QueryData = &'w R>, SourceIter<'w, R>: DoubleEndedIterator, @@ -212,7 +212,7 @@ where } } -impl<'w, 's, S: QueryStateBorrow, R: RelationshipTarget> Iterator +impl<'w, 's, S: QueryStateDeref, R: RelationshipTarget> Iterator for DescendantDepthFirstIter<'w, 's, S, R> where ::ReadOnly: QueryData = &'w R>, @@ -232,7 +232,7 @@ where } /// An [`Iterator`] of [`Entity`]s over the ancestors of an [`Entity`]. -pub struct AncestorIter<'w, 's, S: QueryStateBorrow, R: Relationship> +pub struct AncestorIter<'w, 's, S: QueryStateDeref, R: Relationship> where ::ReadOnly: QueryData = &'w R>, { @@ -240,7 +240,7 @@ where next: Option, } -impl<'w, 's, S: QueryStateBorrow, R: Relationship> AncestorIter<'w, 's, S, R> +impl<'w, 's, S: QueryStateDeref, R: Relationship> AncestorIter<'w, 's, S, R> where ::ReadOnly: QueryData = &'w R>, { @@ -253,7 +253,7 @@ where } } -impl<'w, 's, S: QueryStateBorrow, R: Relationship> Iterator for AncestorIter<'w, 's, S, R> +impl<'w, 's, S: QueryStateDeref, R: Relationship> Iterator for AncestorIter<'w, 's, S, R> where ::ReadOnly: QueryData = &'w R>, { diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index da8609b20b979..8de403bb7d0fc 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -5,7 +5,7 @@ use crate::{ query::{ DebugCheckedUnwrap, NopWorldQuery, QueryCombinationIter, QueryData, QueryEntityError, QueryFilter, QueryIter, QueryManyIter, QueryManyUniqueIter, QueryParIter, QueryParManyIter, - QueryParManyUniqueIter, QuerySingleError, QueryState, QueryStateBorrow, ROQueryItem, + QueryParManyUniqueIter, QuerySingleError, QueryState, QueryStateDeref, ROQueryItem, ReadOnlyQueryData, }, world::unsafe_world_cell::UnsafeWorldCell, @@ -383,7 +383,7 @@ pub struct Query< 'state, D: QueryData, F: QueryFilter = (), - S: QueryStateBorrow = &'state QueryState, + S: QueryStateDeref = &'state QueryState, > { // SAFETY: Must have access to the components registered in `state`. world: UnsafeWorldCell<'world>, @@ -413,7 +413,7 @@ impl core::fmt::Debug for Query<'_, '_, D, F> { } } -impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateBorrow> +impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref> Query<'w, 's, D, F, S> { /// Creates a new query. @@ -2322,7 +2322,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateBorrow> IntoIterator +impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref> IntoIterator for Query<'w, 's, D, F, S> { type Item = D::Item<'w>; @@ -2337,7 +2337,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateBorrow> IntoIterator +impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> IntoIterator for &'w Query<'_, '_, D, F, S> { type Item = ROQueryItem<'w, D>; @@ -2348,7 +2348,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateBorrow } } -impl<'w, D: QueryData, F: QueryFilter, S: QueryStateBorrow> IntoIterator +impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> IntoIterator for &'w mut Query<'_, '_, D, F, S> { type Item = D::Item<'w>; From 4c367db02aaec05bd5609499e864e3e3a3b609fa Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Wed, 5 Mar 2025 15:58:47 -0500 Subject: [PATCH 06/18] Make QueryStateDeref an unsafe trait. --- crates/bevy_ecs/src/query/state.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index 90fe0e0497401..db5716841c68e 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -89,7 +89,13 @@ pub struct QueryState { } /// Abstracts over an owned or borrowed [`QueryState`]. -pub trait QueryStateDeref: Deref> { +/// +/// # Safety +/// +/// This must `deref` to a `QueryState` that does not change. +pub unsafe trait QueryStateDeref: + Deref> +{ /// The [`QueryData`] for this `QueryState`. type Data: QueryData; @@ -118,7 +124,8 @@ pub trait QueryStateDeref: Deref> fn into_readonly(self) -> Self::ReadOnly; } -impl QueryStateDeref for Box> { +/// SAFETY: The QueryState is owned and cannot change +unsafe impl QueryStateDeref for Box> { type Data = D; type Filter = F; type StorageIter = vec::IntoIter; @@ -142,7 +149,8 @@ impl QueryStateDeref for Box> { } } -impl<'s, D: QueryData, F: QueryFilter> QueryStateDeref for &'s QueryState { +/// SAFETY: The QueryState is borrowed for the life of the reference and cannot change +unsafe impl<'s, D: QueryData, F: QueryFilter> QueryStateDeref for &'s QueryState { type Data = D; type Filter = F; type StorageIter = iter::Copied>; From 556eced47fded1469502825de1be49e803e5d901 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Wed, 5 Mar 2025 16:36:11 -0500 Subject: [PATCH 07/18] Introduce a TrustedEntityQueryData trait so we can make a blanket `impl EntitySetIterator for QueryIter`. --- crates/bevy_ecs/src/query/fetch.rs | 34 ++++++++++++++- crates/bevy_ecs/src/query/iter.rs | 66 ++++++++++-------------------- 2 files changed, 54 insertions(+), 46 deletions(-) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index cd632f7b14f22..0c01b15c6c87a 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -3,7 +3,7 @@ use crate::{ bundle::Bundle, change_detection::{MaybeLocation, Ticks, TicksMut}, component::{Component, ComponentId, Components, Mutable, StorageType, Tick}, - entity::{Entities, Entity, EntityLocation}, + entity::{Entities, Entity, EntityLocation, TrustedEntityBorrow}, query::{Access, DebugCheckedUnwrap, FilteredAccess, WorldQuery}, storage::{ComponentSparseSet, Table, TableRow}, world::{ @@ -316,6 +316,17 @@ pub unsafe trait QueryData: WorldQuery { /// This must only be implemented for read-only [`QueryData`]'s. pub unsafe trait ReadOnlyQueryData: QueryData {} +/// A [`QueryData`] whose items can be compared as the original entity. +/// +/// # Safety +/// +/// Calling [`TrustedEntityBorrow::entity()`] on the `Item` must return the `entity` that was passed to [`QueryData::fetch()`]. +pub unsafe trait TrustedEntityQueryData: QueryData +where + for<'a> Self: QueryData: TrustedEntityBorrow>, +{ +} + /// The item type returned when a [`WorldQuery`] is iterated over pub type QueryItem<'w, Q> = ::Item<'w>; /// The read-only variant of the item type returned when a [`QueryData`] is iterated over immutably @@ -393,6 +404,9 @@ unsafe impl QueryData for Entity { /// SAFETY: access is read only unsafe impl ReadOnlyQueryData for Entity {} +/// SAFETY: `entity()` returns `self`, and `fetch` returns `entity` +unsafe impl TrustedEntityQueryData for Entity {} + /// SAFETY: /// `update_component_access` and `update_archetype_component_access` do nothing. /// This is sound because `fetch` does not access components. @@ -554,6 +568,9 @@ unsafe impl<'a> QueryData for EntityRef<'a> { /// SAFETY: access is read only unsafe impl ReadOnlyQueryData for EntityRef<'_> {} +/// SAFETY: `entity()` returns the `entity` used to get the `UnsafeEntityCell`, and `fetch` constructs that from `entity` +unsafe impl TrustedEntityQueryData for EntityRef<'_> {} + /// SAFETY: The accesses of `Self::ReadOnly` are a subset of the accesses of `Self` unsafe impl<'a> WorldQuery for EntityMut<'a> { type Fetch<'w> = UnsafeWorldCell<'w>; @@ -632,6 +649,9 @@ unsafe impl<'a> QueryData for EntityMut<'a> { } } +/// SAFETY: `entity()` returns the `entity` used to get the `UnsafeEntityCell`, and `fetch` constructs that from `entity` +unsafe impl TrustedEntityQueryData for EntityMut<'_> {} + /// 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); @@ -728,6 +748,9 @@ unsafe impl<'a> QueryData for FilteredEntityRef<'a> { /// SAFETY: Access is read-only. unsafe impl ReadOnlyQueryData for FilteredEntityRef<'_> {} +/// SAFETY: `entity()` returns the `entity` used to get the `UnsafeEntityCell`, and `fetch` constructs that from `entity` +unsafe impl TrustedEntityQueryData 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); @@ -820,6 +843,9 @@ unsafe impl<'a> QueryData for FilteredEntityMut<'a> { } } +/// SAFETY: `entity()` returns the `entity` used to get the `UnsafeEntityCell`, and `fetch` constructs that from `entity` +unsafe impl TrustedEntityQueryData for FilteredEntityMut<'_> {} + /// SAFETY: `EntityRefExcept` guards access to all components in the bundle `B` /// and populates `Access` values so that queries that conflict with this access /// are rejected. @@ -920,6 +946,9 @@ where /// components. unsafe impl<'a, B> ReadOnlyQueryData for EntityRefExcept<'a, B> where B: Bundle {} +/// SAFETY: `entity()` returns the `entity` used to get the `UnsafeEntityCell`, and `fetch` constructs that from `entity` +unsafe impl TrustedEntityQueryData for EntityRefExcept<'_, B> {} + /// SAFETY: `EntityMutExcept` guards access to all components in the bundle `B` /// and populates `Access` values so that queries that conflict with this access /// are rejected. @@ -1017,6 +1046,9 @@ where } } +/// SAFETY: `entity()` returns the `entity` used to get the `UnsafeEntityCell`, and `fetch` constructs that from `entity` +unsafe impl TrustedEntityQueryData for EntityMutExcept<'_, B> {} + /// SAFETY: /// `update_component_access` and `update_archetype_component_access` do nothing. /// This is sound because `fetch` does not access components. diff --git a/crates/bevy_ecs/src/query/iter.rs b/crates/bevy_ecs/src/query/iter.rs index cdd22a6f8ecfa..9f111ee7cf909 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -1,15 +1,14 @@ use super::{QueryData, QueryFilter, ReadOnlyQueryData, WorldQuery}; use crate::{ archetype::{Archetype, ArchetypeEntity, Archetypes}, - bundle::Bundle, component::Tick, entity::{Entities, Entity, EntityBorrow, EntitySet, EntitySetIterator}, - query::{ArchetypeFilter, DebugCheckedUnwrap, QueryState, QueryStateDeref, StorageId}, - storage::{Table, TableRow, Tables}, - world::{ - unsafe_world_cell::UnsafeWorldCell, EntityMut, EntityMutExcept, EntityRef, EntityRefExcept, - FilteredEntityMut, FilteredEntityRef, + query::{ + ArchetypeFilter, DebugCheckedUnwrap, QueryState, QueryStateDeref, StorageId, + TrustedEntityQueryData, }, + storage::{Table, TableRow, Tables}, + world::unsafe_world_cell::UnsafeWorldCell, }; use alloc::vec::Vec; use core::{ @@ -910,36 +909,10 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> // This is correct as [`QueryIter`] always returns `None` once exhausted. impl<'w, S: QueryStateDeref> FusedIterator for QueryIter<'w, S> {} -// SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. -unsafe impl<'w, F: QueryFilter> EntitySetIterator for QueryIter<'w, &QueryState> {} - -// SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. -unsafe impl<'w, F: QueryFilter> EntitySetIterator for QueryIter<'w, &QueryState, F>> {} - -// SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. -unsafe impl<'w, F: QueryFilter> EntitySetIterator for QueryIter<'w, &QueryState, F>> {} - -// SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. -unsafe impl<'w, F: QueryFilter> EntitySetIterator - for QueryIter<'w, &QueryState, F>> -{ -} - -// SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. -unsafe impl<'w, F: QueryFilter> EntitySetIterator - for QueryIter<'w, &QueryState, F>> -{ -} - -// SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. -unsafe impl<'w, F: QueryFilter, B: Bundle> EntitySetIterator - for QueryIter<'w, &QueryState, F>> -{ -} - -// SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once. -unsafe impl<'w, F: QueryFilter, B: Bundle> EntitySetIterator - for QueryIter<'w, &QueryState, F>> +// SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once, +// and [`TrustedEntityQueryData`] ensures that they return the original `Entity`. +unsafe impl<'w, S: QueryStateDeref> EntitySetIterator + for QueryIter<'w, S> { } @@ -1080,9 +1053,9 @@ impl<'w, S: QueryStateDeref, I: Iterator> FusedIterator for QuerySortedIter<'w, // SAFETY: // `I` stems from a collected and sorted `EntitySetIterator` ([`QueryIter`]). -// Fetching unique entities maintains uniqueness. -unsafe impl<'w, F: QueryFilter, I: Iterator> EntitySetIterator - for QuerySortedIter<'w, &QueryState, I> +// [`TrustedEntityQueryData`] ensures that unique items return unique `Entity`s. +unsafe impl<'w, S: QueryStateDeref, I: Iterator> + EntitySetIterator for QuerySortedIter<'w, S, I> { } @@ -1781,9 +1754,12 @@ impl<'w, S: QueryStateDeref, I: Iterator EntitySetIterator - for QueryManyIter<'w, &QueryState, I> +// SAFETY: [`TrustedEntityQueryData`] ensures that unique items return unique `Entity`s. +unsafe impl< + 'w, + S: QueryStateDeref, + I: EntitySetIterator, + > EntitySetIterator for QueryManyIter<'w, S, I> { } @@ -1863,9 +1839,9 @@ impl<'w, D: QueryData, S: QueryStateDeref, I: EntitySetIterator> Itera // This is correct as [`QueryManyIter`] always returns `None` once exhausted. impl<'w, S: QueryStateDeref, I: EntitySetIterator> FusedIterator for QueryManyUniqueIter<'w, S, I> {} -// SAFETY: Fetching unique entities maintains uniqueness. -unsafe impl<'w, F: QueryFilter, I: EntitySetIterator> EntitySetIterator - for QueryManyUniqueIter<'w, &QueryState, I> +// SAFETY: [`TrustedEntityQueryData`] ensures that unique items return unique `Entity`s. +unsafe impl<'w, S: QueryStateDeref, I: EntitySetIterator> + EntitySetIterator for QueryManyUniqueIter<'w, S, I> { } From c81671d646352b211fa46128d7b3e4e051ec4715 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Wed, 5 Mar 2025 17:31:54 -0500 Subject: [PATCH 08/18] Doc fixes. --- crates/bevy_ecs/src/query/fetch.rs | 2 +- crates/bevy_ecs/src/query/state.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 0c01b15c6c87a..08227da432ae9 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -320,7 +320,7 @@ pub unsafe trait ReadOnlyQueryData: QueryData {} /// /// # Safety /// -/// Calling [`TrustedEntityBorrow::entity()`] on the `Item` must return the `entity` that was passed to [`QueryData::fetch()`]. +/// Calling [`EntityBorrow::entity()`](crate::entity::EntityBorrow::entity) on the `Item` must return the `entity` that was passed to [`QueryData::fetch()`]. pub unsafe trait TrustedEntityQueryData: QueryData where for<'a> Self: QueryData: TrustedEntityBorrow>, diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index db5716841c68e..1f8e55838a444 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -124,7 +124,7 @@ pub unsafe trait QueryStateDeref: fn into_readonly(self) -> Self::ReadOnly; } -/// SAFETY: The QueryState is owned and cannot change +/// SAFETY: The `QueryState` is owned and cannot change unsafe impl QueryStateDeref for Box> { type Data = D; type Filter = F; @@ -149,7 +149,7 @@ unsafe impl QueryStateDeref for Box QueryStateDeref for &'s QueryState { type Data = D; type Filter = F; From e94970c09f3dc99abb988b755701fdb6e407fcfd Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Thu, 6 Mar 2025 14:05:38 -0500 Subject: [PATCH 09/18] Better docs for `TrustedEntityQueryData` from @Victoronz --- crates/bevy_ecs/src/query/fetch.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 08227da432ae9..58c75b948b6bb 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -316,11 +316,14 @@ pub unsafe trait QueryData: WorldQuery { /// This must only be implemented for read-only [`QueryData`]'s. pub unsafe trait ReadOnlyQueryData: QueryData {} -/// A [`QueryData`] whose items can be compared as the original entity. +/// A [`QueryData`] type that produces a [`TrustedEntityBorrow`] item +/// equaling the `Entity` it is addressed by. /// /// # Safety /// -/// Calling [`EntityBorrow::entity()`](crate::entity::EntityBorrow::entity) on the `Item` must return the `entity` that was passed to [`QueryData::fetch()`]. +/// [`::fetch`](QueryData::fetch) must always return an item whose `Entity` +/// equals the one the function was called with. +/// I.e.: `Self::fetch(fetch, entity, table_row).entity() == entity` always holds. pub unsafe trait TrustedEntityQueryData: QueryData where for<'a> Self: QueryData: TrustedEntityBorrow>, From 39c8c162ec6edebfa76cda527335f08c4b0f458c Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Tue, 11 Mar 2025 13:09:25 -0400 Subject: [PATCH 10/18] Use pointer casts for `Box::into_readonly()` to avoid needing to allocate a new box. --- crates/bevy_ecs/src/query/state.rs | 47 +++++++++++++++++------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index 1f8e55838a444..6bb18ca94fadd 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -145,7 +145,7 @@ unsafe impl QueryStateDeref for Box Self::ReadOnly { - Box::new((*self).into_readonly()) + self.into_readonly() } } @@ -198,26 +198,6 @@ impl QueryState { unsafe { self.as_transmuted_state::() } } - fn into_readonly(mut self) -> QueryState { - // This is not strictly necessary, since a `&QueryState` - // created using `as_readonly()` would have the full access, - // but it may avoid needing to clone the access later. - self.component_access.access_mut().clear_writes(); - QueryState { - world_id: self.world_id, - archetype_generation: self.archetype_generation, - matched_tables: self.matched_tables, - matched_archetypes: self.matched_archetypes, - component_access: self.component_access, - matched_storage_ids: self.matched_storage_ids, - is_dense: self.is_dense, - fetch_state: self.fetch_state, - filter_state: self.filter_state, - #[cfg(feature = "trace")] - par_iter_span: self.par_iter_span, - } - } - /// Converts this `QueryState` reference to a `QueryState` that does not return any data /// which can be faster. /// @@ -247,6 +227,31 @@ impl QueryState { &*ptr::from_ref(self).cast::>() } + /// Converts this `QueryState` reference to a `QueryState` that does not access anything mutably. + pub fn into_readonly(self: Box) -> Box> { + // SAFETY: invariant on `WorldQuery` trait upholds that `D::ReadOnly` and `F::ReadOnly` + // have a subset of the access, and match the exact same archetypes/tables as `D`/`F` respectively. + unsafe { self.into_transmuted_state::() } + } + + /// Converts this `QueryState` reference to any other `QueryState` with + /// the same `WorldQuery::State` associated types. + /// + /// Consider using `into_readonly` instead which is a safe function. + /// + /// # Safety + /// + /// `NewD` must have a subset of the access that `D` does and match the exact same archetypes/tables + /// `NewF` must have a subset of the access that `F` does and match the exact same archetypes/tables + pub(crate) unsafe fn into_transmuted_state< + NewD: ReadOnlyQueryData, + NewF: QueryFilter, + >( + self: Box, + ) -> Box> { + Box::from_raw(Box::into_raw(self).cast::>()) + } + /// Returns the components accessed by this query. pub fn component_access(&self) -> &FilteredAccess { &self.component_access From ddd30a5f69783db67e2448296dd0954192b10c03 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Fri, 4 Apr 2025 10:26:00 -0400 Subject: [PATCH 11/18] Fix other references to `TrustedEntityBorrow`. `cargo fmt`. --- crates/bevy_ecs/src/query/fetch.rs | 6 +++--- crates/bevy_ecs/src/query/iter.rs | 16 +++++++++++----- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 58c75b948b6bb..f0e5e958c3d53 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -3,7 +3,7 @@ use crate::{ bundle::Bundle, change_detection::{MaybeLocation, Ticks, TicksMut}, component::{Component, ComponentId, Components, Mutable, StorageType, Tick}, - entity::{Entities, Entity, EntityLocation, TrustedEntityBorrow}, + entity::{Entities, Entity, EntityEquivalent, EntityLocation}, query::{Access, DebugCheckedUnwrap, FilteredAccess, WorldQuery}, storage::{ComponentSparseSet, Table, TableRow}, world::{ @@ -316,7 +316,7 @@ pub unsafe trait QueryData: WorldQuery { /// This must only be implemented for read-only [`QueryData`]'s. pub unsafe trait ReadOnlyQueryData: QueryData {} -/// A [`QueryData`] type that produces a [`TrustedEntityBorrow`] item +/// A [`QueryData`] type that produces a [`EntityEquivalent`] item /// equaling the `Entity` it is addressed by. /// /// # Safety @@ -326,7 +326,7 @@ pub unsafe trait ReadOnlyQueryData: QueryData {} /// I.e.: `Self::fetch(fetch, entity, table_row).entity() == entity` always holds. pub unsafe trait TrustedEntityQueryData: QueryData where - for<'a> Self: QueryData: TrustedEntityBorrow>, + for<'a> Self: QueryData: EntityEquivalent>, { } diff --git a/crates/bevy_ecs/src/query/iter.rs b/crates/bevy_ecs/src/query/iter.rs index c912cd6531021..d2341a353acf9 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -1693,8 +1693,12 @@ impl< } } -impl<'w, D: ReadOnlyQueryData, S: QueryStateDeref, I: Iterator> - Iterator for QueryManyIter<'w, S, I> +impl< + 'w, + D: ReadOnlyQueryData, + S: QueryStateDeref, + I: Iterator, + > Iterator for QueryManyIter<'w, S, I> { type Item = D::Item<'w>; @@ -1749,8 +1753,8 @@ impl< } // This is correct as [`QueryManyIter`] always returns `None` once exhausted. -impl<'w, S: QueryStateDeref, I: Iterator> FusedIterator - for QueryManyIter<'w, S, I> +impl<'w, S: QueryStateDeref, I: Iterator> + FusedIterator for QueryManyIter<'w, S, I> { } @@ -1763,7 +1767,9 @@ unsafe impl< { } -impl<'w, S: QueryStateDeref, I: Iterator> Debug for QueryManyIter<'w, S, I> { +impl<'w, S: QueryStateDeref, I: Iterator> Debug + for QueryManyIter<'w, S, I> +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QueryManyIter").finish() } From 0e6102231842be69c6939ef35b80d01b67a45ec1 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Fri, 4 Apr 2025 10:26:57 -0400 Subject: [PATCH 12/18] Rename `TrustedEntityQueryData` to `EntityEquivalentQueryData`. --- crates/bevy_ecs/src/query/fetch.rs | 16 ++++++++-------- crates/bevy_ecs/src/query/iter.rs | 20 ++++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index f0e5e958c3d53..ec405b5871cc4 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -324,7 +324,7 @@ pub unsafe trait ReadOnlyQueryData: QueryData {} /// [`::fetch`](QueryData::fetch) must always return an item whose `Entity` /// equals the one the function was called with. /// I.e.: `Self::fetch(fetch, entity, table_row).entity() == entity` always holds. -pub unsafe trait TrustedEntityQueryData: QueryData +pub unsafe trait EntityEquivalentQueryData: QueryData where for<'a> Self: QueryData: EntityEquivalent>, { @@ -408,7 +408,7 @@ unsafe impl QueryData for Entity { unsafe impl ReadOnlyQueryData for Entity {} /// SAFETY: `entity()` returns `self`, and `fetch` returns `entity` -unsafe impl TrustedEntityQueryData for Entity {} +unsafe impl EntityEquivalentQueryData for Entity {} /// SAFETY: /// `update_component_access` and `update_archetype_component_access` do nothing. @@ -572,7 +572,7 @@ unsafe impl<'a> QueryData for EntityRef<'a> { unsafe impl ReadOnlyQueryData for EntityRef<'_> {} /// SAFETY: `entity()` returns the `entity` used to get the `UnsafeEntityCell`, and `fetch` constructs that from `entity` -unsafe impl TrustedEntityQueryData for EntityRef<'_> {} +unsafe impl EntityEquivalentQueryData for EntityRef<'_> {} /// SAFETY: The accesses of `Self::ReadOnly` are a subset of the accesses of `Self` unsafe impl<'a> WorldQuery for EntityMut<'a> { @@ -653,7 +653,7 @@ unsafe impl<'a> QueryData for EntityMut<'a> { } /// SAFETY: `entity()` returns the `entity` used to get the `UnsafeEntityCell`, and `fetch` constructs that from `entity` -unsafe impl TrustedEntityQueryData for EntityMut<'_> {} +unsafe impl EntityEquivalentQueryData for EntityMut<'_> {} /// SAFETY: The accesses of `Self::ReadOnly` are a subset of the accesses of `Self` unsafe impl<'a> WorldQuery for FilteredEntityRef<'a> { @@ -752,7 +752,7 @@ unsafe impl<'a> QueryData for FilteredEntityRef<'a> { unsafe impl ReadOnlyQueryData for FilteredEntityRef<'_> {} /// SAFETY: `entity()` returns the `entity` used to get the `UnsafeEntityCell`, and `fetch` constructs that from `entity` -unsafe impl TrustedEntityQueryData for FilteredEntityRef<'_> {} +unsafe impl EntityEquivalentQueryData for FilteredEntityRef<'_> {} /// SAFETY: The accesses of `Self::ReadOnly` are a subset of the accesses of `Self` unsafe impl<'a> WorldQuery for FilteredEntityMut<'a> { @@ -847,7 +847,7 @@ unsafe impl<'a> QueryData for FilteredEntityMut<'a> { } /// SAFETY: `entity()` returns the `entity` used to get the `UnsafeEntityCell`, and `fetch` constructs that from `entity` -unsafe impl TrustedEntityQueryData for FilteredEntityMut<'_> {} +unsafe impl EntityEquivalentQueryData for FilteredEntityMut<'_> {} /// SAFETY: `EntityRefExcept` guards access to all components in the bundle `B` /// and populates `Access` values so that queries that conflict with this access @@ -950,7 +950,7 @@ where unsafe impl<'a, B> ReadOnlyQueryData for EntityRefExcept<'a, B> where B: Bundle {} /// SAFETY: `entity()` returns the `entity` used to get the `UnsafeEntityCell`, and `fetch` constructs that from `entity` -unsafe impl TrustedEntityQueryData for EntityRefExcept<'_, B> {} +unsafe impl EntityEquivalentQueryData for EntityRefExcept<'_, B> {} /// SAFETY: `EntityMutExcept` guards access to all components in the bundle `B` /// and populates `Access` values so that queries that conflict with this access @@ -1050,7 +1050,7 @@ where } /// SAFETY: `entity()` returns the `entity` used to get the `UnsafeEntityCell`, and `fetch` constructs that from `entity` -unsafe impl TrustedEntityQueryData for EntityMutExcept<'_, B> {} +unsafe impl EntityEquivalentQueryData for EntityMutExcept<'_, B> {} /// SAFETY: /// `update_component_access` and `update_archetype_component_access` do nothing. diff --git a/crates/bevy_ecs/src/query/iter.rs b/crates/bevy_ecs/src/query/iter.rs index d2341a353acf9..6036b2f9c7fbd 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -4,8 +4,8 @@ use crate::{ component::Tick, entity::{ContainsEntity, Entities, Entity, EntityEquivalent, EntitySet, EntitySetIterator}, query::{ - ArchetypeFilter, DebugCheckedUnwrap, QueryState, QueryStateDeref, StorageId, - TrustedEntityQueryData, + ArchetypeFilter, DebugCheckedUnwrap, EntityEquivalentQueryData, QueryState, + QueryStateDeref, StorageId, }, storage::{Table, TableRow, Tables}, world::unsafe_world_cell::UnsafeWorldCell, @@ -910,8 +910,8 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> impl<'w, S: QueryStateDeref> FusedIterator for QueryIter<'w, S> {} // SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once, -// and [`TrustedEntityQueryData`] ensures that they return the original `Entity`. -unsafe impl<'w, S: QueryStateDeref> EntitySetIterator +// and [`EntityEquivalentQueryData`] ensures that they return the original `Entity`. +unsafe impl<'w, S: QueryStateDeref> EntitySetIterator for QueryIter<'w, S> { } @@ -1053,8 +1053,8 @@ impl<'w, S: QueryStateDeref, I: Iterator> FusedIterator for QuerySortedIter<'w, // SAFETY: // `I` stems from a collected and sorted `EntitySetIterator` ([`QueryIter`]). -// [`TrustedEntityQueryData`] ensures that unique items return unique `Entity`s. -unsafe impl<'w, S: QueryStateDeref, I: Iterator> +// [`EntityEquivalentQueryData`] ensures that unique items return unique `Entity`s. +unsafe impl<'w, S: QueryStateDeref, I: Iterator> EntitySetIterator for QuerySortedIter<'w, S, I> { } @@ -1758,10 +1758,10 @@ impl<'w, S: QueryStateDeref, I: Iterator, + S: QueryStateDeref, I: EntitySetIterator, > EntitySetIterator for QueryManyIter<'w, S, I> { @@ -1845,8 +1845,8 @@ impl<'w, D: QueryData, S: QueryStateDeref, I: EntitySetIterator> Itera // This is correct as [`QueryManyIter`] always returns `None` once exhausted. impl<'w, S: QueryStateDeref, I: EntitySetIterator> FusedIterator for QueryManyUniqueIter<'w, S, I> {} -// SAFETY: [`TrustedEntityQueryData`] ensures that unique items return unique `Entity`s. -unsafe impl<'w, S: QueryStateDeref, I: EntitySetIterator> +// SAFETY: [`EntityEquivalentQueryData`] ensures that unique items return unique `Entity`s. +unsafe impl<'w, S: QueryStateDeref, I: EntitySetIterator> EntitySetIterator for QueryManyUniqueIter<'w, S, I> { } From de747694464fe549191ca50e169717f53867e5b0 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Wed, 7 May 2025 10:04:06 -0400 Subject: [PATCH 13/18] Add migration guide. --- .../combine_query_and_query_lens.md | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 release-content/migration-guides/combine_query_and_query_lens.md diff --git a/release-content/migration-guides/combine_query_and_query_lens.md b/release-content/migration-guides/combine_query_and_query_lens.md new file mode 100644 index 0000000000000..ddf22d41aae2a --- /dev/null +++ b/release-content/migration-guides/combine_query_and_query_lens.md @@ -0,0 +1,20 @@ +--- +title: Combine `Query` and `QueryLens` +pull_requests: [18162] +--- + +The `QueryLens::query()` method has been deprecated. +The `QueryLens` type has now been combined with `Query`, so most methods can be called directly on the `QueryLens` and the call can simply be removed. +If that doesn't work and you do need a fresh `Query`, the call to `.query()` can be replaced with `.reborrow()`. + +```rust +fn with_query(query: Query<&T>) {} +fn with_lens(lens: QueryLens<&T>) -> Result { + // 0.16 + for item in lens.query().iter() {} + with_query(lens.query()); + // 0.17 + for item in lens.iter() {} + with_query(lens.reborrow()); +} +``` From fccca4daf2f267c89f969da2b976dd7e137536c3 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Wed, 7 May 2025 11:01:32 -0400 Subject: [PATCH 14/18] bevy_platform_support was renamed bevy_platform. --- crates/bevy_ecs/src/query/state.rs | 2 +- crates/bevy_ecs/src/system/query.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index 6ee6261fc23d7..b0da4676fbbc1 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -14,7 +14,7 @@ use crate::{ use crate::entity::UniqueEntityEquivalentSlice; use alloc::vec::{self, Vec}; -use bevy_platform_support::prelude::Box; +use bevy_platform::prelude::Box; use core::{fmt, iter, ops::Deref, ptr, slice}; use fixedbitset::FixedBitSet; use log::warn; diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index bbb34ba9230af..0743ae7c1c979 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -10,7 +10,7 @@ use crate::{ }, world::unsafe_world_cell::UnsafeWorldCell, }; -use bevy_platform_support::prelude::Box; +use bevy_platform::prelude::Box; use core::{ marker::PhantomData, mem::MaybeUninit, From 1bc9f75c98b81e17a18b1f60e753da6e3b3dea33 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Mon, 16 Jun 2025 20:53:26 -0400 Subject: [PATCH 15/18] Remove `'s` lifetime from `WorldQuery::Fetch`. --- crates/bevy_asset/src/asset_changed.rs | 14 +- crates/bevy_ecs/macros/src/query_data.rs | 34 ++- crates/bevy_ecs/macros/src/query_filter.rs | 5 +- crates/bevy_ecs/macros/src/world_query.rs | 36 +-- crates/bevy_ecs/src/query/fetch.rs | 269 +++++++++------------ crates/bevy_ecs/src/query/filter.rs | 100 +++----- crates/bevy_ecs/src/query/iter.rs | 16 +- crates/bevy_ecs/src/query/mod.rs | 16 +- crates/bevy_ecs/src/query/world_query.rs | 24 +- crates/bevy_render/src/sync_world.rs | 32 +-- 10 files changed, 244 insertions(+), 302 deletions(-) diff --git a/crates/bevy_asset/src/asset_changed.rs b/crates/bevy_asset/src/asset_changed.rs index db979501793a5..bd0c97739c66a 100644 --- a/crates/bevy_asset/src/asset_changed.rs +++ b/crates/bevy_asset/src/asset_changed.rs @@ -150,13 +150,11 @@ 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 Fetch<'w, 's> = AssetChangedFetch<'w, A>; + type Fetch<'w> = AssetChangedFetch<'w, A>; type State = AssetChangedState; - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fetch } @@ -165,7 +163,7 @@ unsafe impl WorldQuery for AssetChanged { state: &'s Self::State, last_run: Tick, this_run: Tick, - ) -> Self::Fetch<'w, 's> { + ) -> Self::Fetch<'w> { // SAFETY: // - `AssetChanges` is private and only accessed mutably in the `AssetEventSystems` system set. // - `resource_id` was obtained from the type ID of `AssetChanges`. @@ -204,7 +202,7 @@ unsafe impl WorldQuery for AssetChanged { const IS_DENSE: bool = <&A>::IS_DENSE; unsafe fn set_archetype<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, state: &'s Self::State, archetype: &'w Archetype, table: &'w Table, @@ -218,7 +216,7 @@ unsafe impl WorldQuery for AssetChanged { } unsafe fn set_table<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, state: &Self::State, table: &'w Table, ) { @@ -271,7 +269,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 { diff --git a/crates/bevy_ecs/macros/src/query_data.rs b/crates/bevy_ecs/macros/src/query_data.rs index 44021f27a7735..447d94d11f31e 100644 --- a/crates/bevy_ecs/macros/src/query_data.rs +++ b/crates/bevy_ecs/macros/src/query_data.rs @@ -74,13 +74,23 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream { let user_generics = ast.generics.clone(); let (user_impl_generics, user_ty_generics, user_where_clauses) = user_generics.split_for_impl(); let user_generics_with_world = { - let mut generics = ast.generics; + let mut generics = ast.generics.clone(); 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) = user_generics_with_world.split_for_impl(); + let user_generics_with_world_and_state = { + 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_and_state, + user_ty_generics_with_world_and_state, + user_where_clauses_with_world_and_state, + ) = user_generics_with_world_and_state.split_for_impl(); let struct_name = ast.ident; let read_only_struct_name = if attributes.is_mutable { @@ -165,13 +175,13 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream { &visibility, &item_struct_name, &field_types, - &user_impl_generics_with_world, + &user_impl_generics_with_world_and_state, &field_attrs, &field_visibilities, &field_idents, &user_ty_generics, - &user_ty_generics_with_world, - user_where_clauses_with_world, + &user_ty_generics_with_world_and_state, + user_where_clauses_with_world_and_state, ); let mutable_world_query_impl = world_query_impl( &path, @@ -200,13 +210,13 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream { &visibility, &read_only_item_struct_name, &read_only_field_types, - &user_impl_generics_with_world, + &user_impl_generics_with_world_and_state, &field_attrs, &field_visibilities, &field_idents, &user_ty_generics, - &user_ty_generics_with_world, - user_where_clauses_with_world, + &user_ty_generics_with_world_and_state, + user_where_clauses_with_world_and_state, ); let readonly_world_query_impl = world_query_impl( &path, @@ -257,7 +267,7 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream { for #read_only_struct_name #user_ty_generics #user_where_clauses { const IS_READ_ONLY: bool = true; type ReadOnly = #read_only_struct_name #user_ty_generics; - type Item<'__w, '__s> = #read_only_item_struct_name #user_ty_generics_with_world; + type Item<'__w, '__s> = #read_only_item_struct_name #user_ty_generics_with_world_and_state; fn shrink<'__wlong: '__wshort, '__wshort, '__s>( item: Self::Item<'__wlong, '__s> @@ -280,7 +290,7 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream { /// SAFETY: we call `fetch` for each member that implements `Fetch`. #[inline(always)] unsafe fn fetch<'__w, '__s>( - _fetch: &mut ::Fetch<'__w, '__s>, + _fetch: &mut ::Fetch<'__w>, _entity: #path::entity::Entity, _table_row: #path::storage::TableRow, ) -> Self::Item<'__w, '__s> { @@ -314,7 +324,7 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream { for #struct_name #user_ty_generics #user_where_clauses { const IS_READ_ONLY: bool = #is_read_only; type ReadOnly = #read_only_struct_name #user_ty_generics; - type Item<'__w, '__s> = #item_struct_name #user_ty_generics_with_world; + type Item<'__w, '__s> = #item_struct_name #user_ty_generics_with_world_and_state; fn shrink<'__wlong: '__wshort, '__wshort, '__s>( item: Self::Item<'__wlong, '__s> @@ -337,7 +347,7 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream { /// SAFETY: we call `fetch` for each member that implements `Fetch`. #[inline(always)] unsafe fn fetch<'__w, '__s>( - _fetch: &mut ::Fetch<'__w, '__s>, + _fetch: &mut ::Fetch<'__w>, _entity: #path::entity::Entity, _table_row: #path::storage::TableRow, ) -> Self::Item<'__w, '__s> { diff --git a/crates/bevy_ecs/macros/src/query_filter.rs b/crates/bevy_ecs/macros/src/query_filter.rs index acc5c3d41b1ba..c7ddb9cc83521 100644 --- a/crates/bevy_ecs/macros/src/query_filter.rs +++ b/crates/bevy_ecs/macros/src/query_filter.rs @@ -23,7 +23,6 @@ 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) = @@ -102,8 +101,8 @@ pub fn derive_query_filter_impl(input: TokenStream) -> TokenStream { #[allow(unused_variables)] #[inline(always)] - unsafe fn filter_fetch<'__w, '__s>( - _fetch: &mut ::Fetch<'__w, '__s>, + unsafe fn filter_fetch<'__w>( + _fetch: &mut ::Fetch<'__w>, _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 c064b05b97dbf..5a7d164b8021d 100644 --- a/crates/bevy_ecs/macros/src/world_query.rs +++ b/crates/bevy_ecs/macros/src/world_query.rs @@ -10,13 +10,13 @@ pub(crate) fn item_struct( visibility: &Visibility, item_struct_name: &Ident, field_types: &Vec, - user_impl_generics_with_world: &ImplGenerics, + user_impl_generics_with_world_and_state: &ImplGenerics, field_attrs: &Vec>, field_visibilities: &Vec, field_idents: &Vec, user_ty_generics: &TypeGenerics, - user_ty_generics_with_world: &TypeGenerics, - user_where_clauses_with_world: Option<&WhereClause>, + user_ty_generics_with_world_and_state: &TypeGenerics, + user_where_clauses_with_world_and_state: Option<&WhereClause>, ) -> proc_macro2::TokenStream { let item_attrs = quote! { #[doc = concat!( @@ -33,20 +33,20 @@ pub(crate) fn item_struct( Fields::Named(_) => quote! { #derive_macro_call #item_attrs - #visibility struct #item_struct_name #user_impl_generics_with_world #user_where_clauses_with_world { + #visibility struct #item_struct_name #user_impl_generics_with_world_and_state #user_where_clauses_with_world_and_state { #(#(#field_attrs)* #field_visibilities #field_idents: <#field_types as #path::query::QueryData>::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( + #visibility struct #item_struct_name #user_impl_generics_with_world_and_state #user_where_clauses_with_world_and_state( #( #field_visibilities <#field_types as #path::query::QueryData>::Item<'__w, '__s>, )* ); }, Fields::Unit => quote! { #item_attrs - #visibility type #item_struct_name #user_ty_generics_with_world = #struct_name #user_ty_generics; + #visibility type #item_struct_name #user_ty_generics_with_world_and_state = #struct_name #user_ty_generics; }, } } @@ -78,8 +78,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, '__s>,)* - #marker_name: (&'__w(), &'__s()), + #(#named_field_idents: <#field_types as #path::query::WorldQuery>::Fetch<'__w>,)* + #marker_name: &'__w(), } impl #user_impl_generics_with_world Clone for #fetch_struct_name #user_ty_generics_with_world @@ -87,7 +87,7 @@ pub(crate) fn world_query_impl( fn clone(&self) -> Self { Self { #(#named_field_idents: self.#named_field_idents.clone(),)* - #marker_name: (&(), &()), + #marker_name: &(), } } } @@ -96,17 +96,17 @@ pub(crate) fn world_query_impl( unsafe impl #user_impl_generics #path::query::WorldQuery for #struct_name #user_ty_generics #user_where_clauses { - type Fetch<'__w, '__s> = #fetch_struct_name #user_ty_generics_with_world; + type Fetch<'__w> = #fetch_struct_name #user_ty_generics_with_world; type State = #state_struct_name #user_ty_generics; - 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> { + 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> { #fetch_struct_name { #( #named_field_idents: <#field_types>::shrink_fetch(fetch.#named_field_idents), )* - #marker_name: (&(), &()), + #marker_name: &(), } } @@ -115,7 +115,7 @@ pub(crate) fn world_query_impl( state: &'__s Self::State, _last_run: #path::component::Tick, _this_run: #path::component::Tick, - ) -> ::Fetch<'__w, '__s> { + ) -> ::Fetch<'__w> { #fetch_struct_name { #(#named_field_idents: <#field_types>::init_fetch( @@ -125,7 +125,7 @@ pub(crate) fn world_query_impl( _this_run, ), )* - #marker_name: (&(), &()), + #marker_name: &(), } } @@ -134,7 +134,7 @@ pub(crate) fn world_query_impl( /// SAFETY: we call `set_archetype` for each member that implements `Fetch` #[inline] unsafe fn set_archetype<'__w, '__s>( - _fetch: &mut ::Fetch<'__w, '__s>, + _fetch: &mut ::Fetch<'__w>, _state: &'__s Self::State, _archetype: &'__w #path::archetype::Archetype, _table: &'__w #path::storage::Table @@ -145,7 +145,7 @@ pub(crate) fn world_query_impl( /// SAFETY: we call `set_table` for each member that implements `Fetch` #[inline] unsafe fn set_table<'__w, '__s>( - _fetch: &mut ::Fetch<'__w, '__s>, + _fetch: &mut ::Fetch<'__w>, _state: &'__s Self::State, _table: &'__w #path::storage::Table ) { diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index ba1a85cec31ee..8e8289f948f0a 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -325,7 +325,7 @@ pub unsafe trait QueryData: WorldQuery { /// `table_row` must be in the range of the current table and archetype. /// - There must not be simultaneous conflicting component access registered in `update_component_access`. unsafe fn fetch<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, entity: Entity, table_row: TableRow, ) -> Self::Item<'w, 's>; @@ -358,27 +358,24 @@ pub trait ReleaseStateQueryData: QueryData { /// `update_component_access` does nothing. /// This is sound because `fetch` does not access components. unsafe impl WorldQuery for Entity { - type Fetch<'w, 's> = (); + type Fetch<'w> = (); type State = (); - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - _: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { - } + fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {} unsafe fn init_fetch<'w, 's>( _world: UnsafeWorldCell<'w>, _state: &'s Self::State, _last_run: Tick, _this_run: Tick, - ) -> Self::Fetch<'w, 's> { + ) -> Self::Fetch<'w> { } const IS_DENSE: bool = true; #[inline] unsafe fn set_archetype<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _state: &'s Self::State, _archetype: &'w Archetype, _table: &Table, @@ -387,7 +384,7 @@ unsafe impl WorldQuery for Entity { #[inline] unsafe fn set_table<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _state: &'s Self::State, _table: &'w Table, ) { @@ -424,7 +421,7 @@ unsafe impl QueryData for Entity { #[inline(always)] unsafe fn fetch<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, entity: Entity, _table_row: TableRow, ) -> Self::Item<'w, 's> { @@ -445,12 +442,10 @@ impl ReleaseStateQueryData for Entity { /// `update_component_access` does nothing. /// This is sound because `fetch` does not access components. unsafe impl WorldQuery for EntityLocation { - type Fetch<'w, 's> = &'w Entities; + type Fetch<'w> = &'w Entities; type State = (); - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fetch } @@ -459,7 +454,7 @@ unsafe impl WorldQuery for EntityLocation { _state: &'s Self::State, _last_run: Tick, _this_run: Tick, - ) -> Self::Fetch<'w, 's> { + ) -> Self::Fetch<'w> { world.entities() } @@ -469,7 +464,7 @@ unsafe impl WorldQuery for EntityLocation { #[inline] unsafe fn set_archetype<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _state: &'s Self::State, _archetype: &'w Archetype, _table: &Table, @@ -478,7 +473,7 @@ unsafe impl WorldQuery for EntityLocation { #[inline] unsafe fn set_table<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _state: &'s Self::State, _table: &'w Table, ) { @@ -514,7 +509,7 @@ unsafe impl QueryData for EntityLocation { #[inline(always)] unsafe fn fetch<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, entity: Entity, _table_row: TableRow, ) -> Self::Item<'w, 's> { @@ -605,12 +600,10 @@ pub struct SpawnDetailsFetch<'w> { // SAFETY: // No components are accessed. unsafe impl WorldQuery for SpawnDetails { - type Fetch<'w, 's> = SpawnDetailsFetch<'w>; + type Fetch<'w> = SpawnDetailsFetch<'w>; type State = (); - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fetch } @@ -619,7 +612,7 @@ unsafe impl WorldQuery for SpawnDetails { _state: &'s Self::State, last_run: Tick, this_run: Tick, - ) -> Self::Fetch<'w, 's> { + ) -> Self::Fetch<'w> { SpawnDetailsFetch { entities: world.entities(), last_run, @@ -631,7 +624,7 @@ unsafe impl WorldQuery for SpawnDetails { #[inline] unsafe fn set_archetype<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _state: &'s Self::State, _archetype: &'w Archetype, _table: &'w Table, @@ -640,7 +633,7 @@ unsafe impl WorldQuery for SpawnDetails { #[inline] unsafe fn set_table<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _state: &'s Self::State, _table: &'w Table, ) { @@ -678,7 +671,7 @@ unsafe impl QueryData for SpawnDetails { #[inline(always)] unsafe fn fetch<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, entity: Entity, _table_row: TableRow, ) -> Self::Item<'w, 's> { @@ -721,12 +714,10 @@ pub struct EntityFetch<'w> { /// This is sound because `update_component_access` sets read access for all components and panic when appropriate. /// Filters are unchanged. unsafe impl<'a> WorldQuery for EntityRef<'a> { - type Fetch<'w, 's> = EntityFetch<'w>; + type Fetch<'w> = EntityFetch<'w>; type State = (); - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fetch } @@ -735,7 +726,7 @@ unsafe impl<'a> WorldQuery for EntityRef<'a> { _state: &'s Self::State, last_run: Tick, this_run: Tick, - ) -> Self::Fetch<'w, 's> { + ) -> Self::Fetch<'w> { EntityFetch { world, last_run, @@ -747,7 +738,7 @@ unsafe impl<'a> WorldQuery for EntityRef<'a> { #[inline] unsafe fn set_archetype<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _state: &'s Self::State, _archetype: &'w Archetype, _table: &Table, @@ -756,7 +747,7 @@ unsafe impl<'a> WorldQuery for EntityRef<'a> { #[inline] unsafe fn set_table<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _state: &'s Self::State, _table: &'w Table, ) { @@ -798,7 +789,7 @@ unsafe impl<'a> QueryData for EntityRef<'a> { #[inline(always)] unsafe fn fetch<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, entity: Entity, _table_row: TableRow, ) -> Self::Item<'w, 's> { @@ -825,12 +816,10 @@ impl ReleaseStateQueryData for EntityRef<'_> { /// SAFETY: The accesses of `Self::ReadOnly` are a subset of the accesses of `Self` unsafe impl<'a> WorldQuery for EntityMut<'a> { - type Fetch<'w, 's> = EntityFetch<'w>; + type Fetch<'w> = EntityFetch<'w>; type State = (); - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fetch } @@ -839,7 +828,7 @@ unsafe impl<'a> WorldQuery for EntityMut<'a> { _state: &'s Self::State, last_run: Tick, this_run: Tick, - ) -> Self::Fetch<'w, 's> { + ) -> Self::Fetch<'w> { EntityFetch { world, last_run, @@ -851,7 +840,7 @@ unsafe impl<'a> WorldQuery for EntityMut<'a> { #[inline] unsafe fn set_archetype<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _state: &'s Self::State, _archetype: &'w Archetype, _table: &Table, @@ -860,7 +849,7 @@ unsafe impl<'a> WorldQuery for EntityMut<'a> { #[inline] unsafe fn set_table<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _state: &'s Self::State, _table: &'w Table, ) { @@ -902,7 +891,7 @@ unsafe impl<'a> QueryData for EntityMut<'a> { #[inline(always)] unsafe fn fetch<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, entity: Entity, _table_row: TableRow, ) -> Self::Item<'w, 's> { @@ -926,12 +915,10 @@ impl ReleaseStateQueryData for EntityMut<'_> { /// SAFETY: The accesses of `Self::ReadOnly` are a subset of the accesses of `Self` unsafe impl<'a> WorldQuery for FilteredEntityRef<'a> { - type Fetch<'w, 's> = (EntityFetch<'w>, Access); + type Fetch<'w> = (EntityFetch<'w>, Access); type State = Access; - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fetch } @@ -942,7 +929,7 @@ unsafe impl<'a> WorldQuery for FilteredEntityRef<'a> { _state: &'s Self::State, last_run: Tick, this_run: Tick, - ) -> Self::Fetch<'w, 's> { + ) -> Self::Fetch<'w> { let mut access = Access::default(); access.read_all_components(); ( @@ -957,7 +944,7 @@ unsafe impl<'a> WorldQuery for FilteredEntityRef<'a> { #[inline] unsafe fn set_archetype<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, state: &'s Self::State, _: &'w Archetype, _table: &Table, @@ -966,11 +953,7 @@ unsafe impl<'a> WorldQuery for FilteredEntityRef<'a> { } #[inline] - unsafe fn set_table<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, - state: &'s Self::State, - _: &'w Table, - ) { + unsafe fn set_table<'w, 's>(fetch: &mut Self::Fetch<'w>, state: &'s Self::State, _: &'w Table) { fetch.1.clone_from(state); } @@ -1034,7 +1017,7 @@ unsafe impl<'a> QueryData for FilteredEntityRef<'a> { #[inline(always)] unsafe fn fetch<'w, 's>( - (fetch, access): &mut Self::Fetch<'w, 's>, + (fetch, access): &mut Self::Fetch<'w>, entity: Entity, _table_row: TableRow, ) -> Self::Item<'w, 's> { @@ -1055,12 +1038,10 @@ 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, 's> = (EntityFetch<'w>, Access); + type Fetch<'w> = (EntityFetch<'w>, Access); type State = Access; - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fetch } @@ -1071,7 +1052,7 @@ unsafe impl<'a> WorldQuery for FilteredEntityMut<'a> { _state: &'s Self::State, last_run: Tick, this_run: Tick, - ) -> Self::Fetch<'w, 's> { + ) -> Self::Fetch<'w> { let mut access = Access::default(); access.write_all_components(); ( @@ -1086,7 +1067,7 @@ unsafe impl<'a> WorldQuery for FilteredEntityMut<'a> { #[inline] unsafe fn set_archetype<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, state: &'s Self::State, _: &'w Archetype, _table: &Table, @@ -1095,11 +1076,7 @@ unsafe impl<'a> WorldQuery for FilteredEntityMut<'a> { } #[inline] - unsafe fn set_table<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, - state: &'s Self::State, - _: &'w Table, - ) { + unsafe fn set_table<'w, 's>(fetch: &mut Self::Fetch<'w>, state: &'s Self::State, _: &'w Table) { fetch.1.clone_from(state); } @@ -1161,7 +1138,7 @@ unsafe impl<'a> QueryData for FilteredEntityMut<'a> { #[inline(always)] unsafe fn fetch<'w, 's>( - (fetch, access): &mut Self::Fetch<'w, 's>, + (fetch, access): &mut Self::Fetch<'w>, entity: Entity, _table_row: TableRow, ) -> Self::Item<'w, 's> { @@ -1184,12 +1161,10 @@ unsafe impl<'a, B> WorldQuery for EntityRefExcept<'a, B> where B: Bundle, { - type Fetch<'w, 's> = EntityFetch<'w>; + type Fetch<'w> = EntityFetch<'w>; type State = SmallVec<[ComponentId; 4]>; - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fetch } @@ -1198,7 +1173,7 @@ where _: &'s Self::State, last_run: Tick, this_run: Tick, - ) -> Self::Fetch<'w, 's> { + ) -> Self::Fetch<'w> { EntityFetch { world, last_run, @@ -1209,14 +1184,14 @@ where const IS_DENSE: bool = true; unsafe fn set_archetype<'w, 's>( - _: &mut Self::Fetch<'w, 's>, + _: &mut Self::Fetch<'w>, _: &'s Self::State, _: &'w Archetype, _: &'w Table, ) { } - unsafe fn set_table<'w, 's>(_: &mut Self::Fetch<'w, 's>, _: &'s Self::State, _: &'w Table) {} + unsafe fn set_table<'w, 's>(_: &mut Self::Fetch<'w>, _: &'s Self::State, _: &'w Table) {} fn update_component_access( state: &Self::State, @@ -1272,7 +1247,7 @@ where } unsafe fn fetch<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, entity: Entity, _: TableRow, ) -> Self::Item<'w, 's> { @@ -1295,12 +1270,10 @@ unsafe impl<'a, B> WorldQuery for EntityMutExcept<'a, B> where B: Bundle, { - type Fetch<'w, 's> = EntityFetch<'w>; + type Fetch<'w> = EntityFetch<'w>; type State = SmallVec<[ComponentId; 4]>; - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fetch } @@ -1309,7 +1282,7 @@ where _: &'s Self::State, last_run: Tick, this_run: Tick, - ) -> Self::Fetch<'w, 's> { + ) -> Self::Fetch<'w> { EntityFetch { world, last_run, @@ -1320,14 +1293,14 @@ where const IS_DENSE: bool = true; unsafe fn set_archetype<'w, 's>( - _: &mut Self::Fetch<'w, 's>, + _: &mut Self::Fetch<'w>, _: &'s Self::State, _: &'w Archetype, _: &'w Table, ) { } - unsafe fn set_table<'w, 's>(_: &mut Self::Fetch<'w, 's>, _: &'s Self::State, _: &'w Table) {} + unsafe fn set_table<'w, 's>(_: &mut Self::Fetch<'w>, _: &'s Self::State, _: &'w Table) {} fn update_component_access( state: &Self::State, @@ -1384,7 +1357,7 @@ where } unsafe fn fetch<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, entity: Entity, _: TableRow, ) -> Self::Item<'w, 's> { @@ -1400,12 +1373,10 @@ where /// `update_component_access` does nothing. /// This is sound because `fetch` does not access components. unsafe impl WorldQuery for &Archetype { - type Fetch<'w, 's> = (&'w Entities, &'w Archetypes); + type Fetch<'w> = (&'w Entities, &'w Archetypes); type State = (); - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fetch } @@ -1414,7 +1385,7 @@ unsafe impl WorldQuery for &Archetype { _state: &'s Self::State, _last_run: Tick, _this_run: Tick, - ) -> Self::Fetch<'w, 's> { + ) -> Self::Fetch<'w> { (world.entities(), world.archetypes()) } @@ -1424,7 +1395,7 @@ unsafe impl WorldQuery for &Archetype { #[inline] unsafe fn set_archetype<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _state: &'s Self::State, _archetype: &'w Archetype, _table: &Table, @@ -1433,7 +1404,7 @@ unsafe impl WorldQuery for &Archetype { #[inline] unsafe fn set_table<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _state: &'s Self::State, _table: &'w Table, ) { @@ -1469,7 +1440,7 @@ unsafe impl QueryData for &Archetype { #[inline(always)] unsafe fn fetch<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, entity: Entity, _table_row: TableRow, ) -> Self::Item<'w, 's> { @@ -1514,12 +1485,10 @@ 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 Fetch<'w, 's> = ReadFetch<'w, T>; + type Fetch<'w> = ReadFetch<'w, T>; type State = ComponentId; - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fetch } @@ -1624,7 +1593,7 @@ unsafe impl QueryData for &T { #[inline(always)] unsafe fn fetch<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, entity: Entity, table_row: TableRow, ) -> Self::Item<'w, 's> { @@ -1691,12 +1660,10 @@ 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 Fetch<'w, 's> = RefFetch<'w, T>; + type Fetch<'w> = RefFetch<'w, T>; type State = ComponentId; - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fetch } @@ -1810,7 +1777,7 @@ unsafe impl<'__w, T: Component> QueryData for Ref<'__w, T> { #[inline(always)] unsafe fn fetch<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, entity: Entity, table_row: TableRow, ) -> Self::Item<'w, 's> { @@ -1900,12 +1867,10 @@ 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 Fetch<'w, 's> = WriteFetch<'w, T>; + type Fetch<'w> = WriteFetch<'w, T>; type State = ComponentId; - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fetch } @@ -2019,7 +1984,7 @@ unsafe impl<'__w, T: Component> QueryData for &'__w mut T #[inline(always)] unsafe fn fetch<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, entity: Entity, table_row: TableRow, ) -> Self::Item<'w, 's> { @@ -2084,12 +2049,10 @@ 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 Fetch<'w, 's> = WriteFetch<'w, T>; + type Fetch<'w> = WriteFetch<'w, T>; type State = ComponentId; - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fetch } @@ -2176,7 +2139,7 @@ unsafe impl<'__w, T: Component> QueryData for Mut<'__w, T> 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, 's>, + fetch: &mut Self::Fetch<'w>, entity: Entity, table_row: TableRow, ) -> Self::Item<'w, 's> { @@ -2191,12 +2154,12 @@ impl> ReleaseStateQueryData for Mut<'_, T> { } #[doc(hidden)] -pub struct OptionFetch<'w, 's, T: WorldQuery> { - fetch: T::Fetch<'w, 's>, +pub struct OptionFetch<'w, T: WorldQuery> { + fetch: T::Fetch<'w>, matches: bool, } -impl Clone for OptionFetch<'_, '_, T> { +impl Clone for OptionFetch<'_, T> { fn clone(&self) -> Self { Self { fetch: self.fetch.clone(), @@ -2210,12 +2173,10 @@ impl Clone for OptionFetch<'_, '_, T> { /// This is sound because `update_component_access` adds the same accesses as `T`. /// Filters are unchanged. unsafe impl WorldQuery for Option { - type Fetch<'w, 's> = OptionFetch<'w, 's, T>; + type Fetch<'w> = OptionFetch<'w, T>; type State = T::State; - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { OptionFetch { fetch: T::shrink_fetch(fetch.fetch), matches: fetch.matches, @@ -2228,7 +2189,7 @@ unsafe impl WorldQuery for Option { state: &'s T::State, last_run: Tick, this_run: Tick, - ) -> OptionFetch<'w, 's, T> { + ) -> OptionFetch<'w, T> { OptionFetch { // SAFETY: The invariants are upheld by the caller. fetch: unsafe { T::init_fetch(world, state, last_run, this_run) }, @@ -2240,7 +2201,7 @@ unsafe impl WorldQuery for Option { #[inline] unsafe fn set_archetype<'w, 's>( - fetch: &mut OptionFetch<'w, 's, T>, + fetch: &mut OptionFetch<'w, T>, state: &'s T::State, archetype: &'w Archetype, table: &'w Table, @@ -2256,7 +2217,7 @@ unsafe impl WorldQuery for Option { #[inline] unsafe fn set_table<'w, 's>( - fetch: &mut OptionFetch<'w, 's, T>, + fetch: &mut OptionFetch<'w, T>, state: &'s T::State, table: &'w Table, ) { @@ -2314,7 +2275,7 @@ unsafe impl QueryData for Option { #[inline(always)] unsafe fn fetch<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, entity: Entity, table_row: TableRow, ) -> Self::Item<'w, 's> { @@ -2409,12 +2370,10 @@ impl core::fmt::Debug for Has { /// `update_component_access` does nothing. /// This is sound because `fetch` does not access components. unsafe impl WorldQuery for Has { - type Fetch<'w, 's> = bool; + type Fetch<'w> = bool; type State = ComponentId; - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fetch } @@ -2424,7 +2383,7 @@ unsafe impl WorldQuery for Has { _state: &'s Self::State, _last_run: Tick, _this_run: Tick, - ) -> Self::Fetch<'w, 's> { + ) -> Self::Fetch<'w> { false } @@ -2437,7 +2396,7 @@ unsafe impl WorldQuery for Has { #[inline] unsafe fn set_archetype<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, state: &'s Self::State, archetype: &'w Archetype, _table: &Table, @@ -2447,7 +2406,7 @@ unsafe impl WorldQuery for Has { #[inline] unsafe fn set_table<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, state: &'s Self::State, table: &'w Table, ) { @@ -2492,7 +2451,7 @@ unsafe impl QueryData for Has { #[inline(always)] unsafe fn fetch<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, _entity: Entity, _table_row: TableRow, ) -> Self::Item<'w, 's> { @@ -2560,7 +2519,7 @@ macro_rules! impl_tuple_query_data { #[inline(always)] unsafe fn fetch<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, entity: Entity, table_row: TableRow ) -> Self::Item<'w, 's> { @@ -2614,10 +2573,10 @@ 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, 's> = ($(($name::Fetch<'w, 's>, bool),)*); + type Fetch<'w> = ($(($name::Fetch<'w>, bool),)*); type State = ($($name::State,)*); - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(fetch: Self::Fetch<'wlong, 's>) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { let ($($name,)*) = fetch; ($( ($name::shrink_fetch($name.0), $name.1), @@ -2625,7 +2584,7 @@ macro_rules! impl_anytuple_fetch { } #[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> { let ($($name,)*) = state; // SAFETY: The invariants are upheld by the caller. ($(( unsafe { $name::init_fetch(_world, $name, _last_run, _this_run) }, false),)*) @@ -2635,7 +2594,7 @@ macro_rules! impl_anytuple_fetch { #[inline] unsafe fn set_archetype<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _state: &'s Self::State, _archetype: &'w Archetype, _table: &'w Table @@ -2652,7 +2611,7 @@ macro_rules! impl_anytuple_fetch { } #[inline] - unsafe fn set_table<'w, 's>(_fetch: &mut Self::Fetch<'w, 's>, _state: &'s Self::State, _table: &'w Table) { + unsafe fn set_table<'w, 's>(_fetch: &mut Self::Fetch<'w>, _state: &'s Self::State, _table: &'w Table) { let ($($name,)*) = _fetch; let ($($state,)*) = _state; $( @@ -2735,7 +2694,7 @@ macro_rules! impl_anytuple_fetch { #[inline(always)] unsafe fn fetch<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _entity: Entity, _table_row: TableRow ) -> Self::Item<'w, 's> { @@ -2794,12 +2753,10 @@ pub(crate) struct NopWorldQuery(PhantomData); /// `update_component_access` does nothing. /// This is sound because `fetch` does not access components. unsafe impl WorldQuery for NopWorldQuery { - type Fetch<'w, 's> = (); + type Fetch<'w> = (); type State = D::State; - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - _fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(_fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { } #[inline(always)] @@ -2856,7 +2813,7 @@ unsafe impl QueryData for NopWorldQuery { #[inline(always)] unsafe fn fetch<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _entity: Entity, _table_row: TableRow, ) -> Self::Item<'w, 's> { @@ -2874,13 +2831,11 @@ impl ReleaseStateQueryData for NopWorldQuery { /// `update_component_access` does nothing. /// This is sound because `fetch` does not access components. unsafe impl WorldQuery for PhantomData { - type Fetch<'w, 's> = (); + type Fetch<'w> = (); type State = (); - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - _fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(_fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { } unsafe fn init_fetch<'w, 's>( @@ -2888,7 +2843,7 @@ unsafe impl WorldQuery for PhantomData { _state: &'s Self::State, _last_run: Tick, _this_run: Tick, - ) -> Self::Fetch<'w, 's> { + ) -> Self::Fetch<'w> { } // `PhantomData` does not match any components, so all components it matches @@ -2896,7 +2851,7 @@ unsafe impl WorldQuery for PhantomData { const IS_DENSE: bool = true; unsafe fn set_archetype<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _state: &'s Self::State, _archetype: &'w Archetype, _table: &'w Table, @@ -2904,7 +2859,7 @@ unsafe impl WorldQuery for PhantomData { } unsafe fn set_table<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _state: &'s Self::State, _table: &'w Table, ) { @@ -2938,7 +2893,7 @@ unsafe impl QueryData for PhantomData { } unsafe fn fetch<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _entity: Entity, _table_row: TableRow, ) -> Self::Item<'w, 's> { @@ -3076,12 +3031,12 @@ mod tests { /// `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 Fetch<'w> = (); type State = (); - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - _: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>( + _: Self::Fetch<'wlong>, + ) -> Self::Fetch<'wshort> { } unsafe fn init_fetch<'w, 's>( @@ -3089,14 +3044,14 @@ mod tests { _state: &'s Self::State, _last_run: Tick, _this_run: Tick, - ) -> Self::Fetch<'w, 's> { + ) -> Self::Fetch<'w> { } const IS_DENSE: bool = true; #[inline] unsafe fn set_archetype<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _state: &'s Self::State, _archetype: &'w Archetype, _table: &Table, @@ -3105,7 +3060,7 @@ mod tests { #[inline] unsafe fn set_table<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _state: &'s Self::State, _table: &'w Table, ) { @@ -3145,7 +3100,7 @@ mod tests { #[inline(always)] unsafe fn fetch<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _entity: Entity, _table_row: TableRow, ) -> Self::Item<'w, 's> { diff --git a/crates/bevy_ecs/src/query/filter.rs b/crates/bevy_ecs/src/query/filter.rs index a75acf3e97fc1..0def8b5bb5e41 100644 --- a/crates/bevy_ecs/src/query/filter.rs +++ b/crates/bevy_ecs/src/query/filter.rs @@ -103,7 +103,7 @@ pub unsafe trait QueryFilter: 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 filter_fetch( - fetch: &mut Self::Fetch<'_, '_>, + fetch: &mut Self::Fetch<'_>, entity: Entity, table_row: TableRow, ) -> bool; @@ -144,13 +144,10 @@ 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 Fetch<'w, 's> = (); + type Fetch<'w> = (); type State = ComponentId; - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - _: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { - } + fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {} #[inline] unsafe fn init_fetch( @@ -207,7 +204,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 { @@ -247,13 +244,10 @@ 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 Fetch<'w, 's> = (); + type Fetch<'w> = (); type State = ComponentId; - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - _: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { - } + fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {} #[inline] unsafe fn init_fetch( @@ -310,7 +304,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 { @@ -351,12 +345,12 @@ unsafe impl QueryFilter for Without { pub struct Or(PhantomData); #[doc(hidden)] -pub struct OrFetch<'w, 's, T: WorldQuery> { - fetch: T::Fetch<'w, 's>, +pub struct OrFetch<'w, T: WorldQuery> { + fetch: T::Fetch<'w>, matches: bool, } -impl Clone for OrFetch<'_, '_, T> { +impl Clone for OrFetch<'_, T> { fn clone(&self) -> Self { Self { fetch: self.fetch.clone(), @@ -390,10 +384,10 @@ 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, 's> = ($(OrFetch<'w, 's, $filter>,)*); + type Fetch<'w> = ($(OrFetch<'w, $filter>,)*); type State = ($($filter::State,)*); - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(fetch: Self::Fetch<'wlong, 's>) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { let ($($filter,)*) = fetch; ($( OrFetch { @@ -406,7 +400,7 @@ macro_rules! impl_or_query_filter { const IS_DENSE: bool = true $(&& $filter::IS_DENSE)*; #[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> { let ($($filter,)*) = state; ($(OrFetch { // SAFETY: The invariants are upheld by the caller. @@ -416,7 +410,7 @@ macro_rules! impl_or_query_filter { } #[inline] - unsafe fn set_table<'w, 's>(fetch: &mut Self::Fetch<'w, 's>, state: &'s Self::State, table: &'w Table) { + unsafe fn set_table<'w, 's>(fetch: &mut Self::Fetch<'w>, state: &'s Self::State, table: &'w Table) { let ($($filter,)*) = fetch; let ($($state,)*) = state; $( @@ -430,7 +424,7 @@ macro_rules! impl_or_query_filter { #[inline] unsafe fn set_archetype<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, state: &'s Self::State, archetype: &'w Archetype, table: &'w Table @@ -501,7 +495,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 { @@ -534,7 +528,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 { @@ -574,13 +568,10 @@ pub struct Allows(PhantomData); /// `update_component_access` adds an archetypal filter for `T`. /// This is sound because it doesn't affect the query unsafe impl WorldQuery for Allows { - type Fetch<'w, 's> = (); + type Fetch<'w> = (); type State = ComponentId; - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - _: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { - } + fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {} #[inline] unsafe fn init_fetch(_: UnsafeWorldCell, _: &ComponentId, _: Tick, _: Tick) {} @@ -618,7 +609,7 @@ unsafe impl QueryFilter for Allows { const IS_ARCHETYPAL: bool = true; #[inline(always)] - unsafe fn filter_fetch(_: &mut Self::Fetch<'_, '_>, _: Entity, _: TableRow) -> bool { + unsafe fn filter_fetch(_: &mut Self::Fetch<'_>, _: Entity, _: TableRow) -> bool { true } } @@ -719,12 +710,10 @@ impl Clone for AddedFetch<'_, 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 Added { - type Fetch<'w, 's> = AddedFetch<'w, T>; + type Fetch<'w> = AddedFetch<'w, T>; type State = ComponentId; - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fetch } @@ -734,8 +723,8 @@ unsafe impl WorldQuery for Added { &id: &'s ComponentId, last_run: Tick, this_run: Tick, - ) -> Self::Fetch<'w, 's> { - Self::Fetch::<'w, 's> { + ) -> Self::Fetch<'w> { + Self::Fetch::<'w> { ticks: StorageSwitch::new( || None, || { @@ -760,7 +749,7 @@ unsafe impl WorldQuery for Added { #[inline] unsafe fn set_archetype<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, component_id: &'s ComponentId, _archetype: &'w Archetype, table: &'w Table, @@ -775,7 +764,7 @@ unsafe impl WorldQuery for Added { #[inline] unsafe fn set_table<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, &component_id: &'s ComponentId, table: &'w Table, ) { @@ -818,7 +807,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 { @@ -947,12 +936,10 @@ impl Clone for ChangedFetch<'_, 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 Changed { - type Fetch<'w, 's> = ChangedFetch<'w, T>; + type Fetch<'w> = ChangedFetch<'w, T>; type State = ComponentId; - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fetch } @@ -962,8 +949,8 @@ unsafe impl WorldQuery for Changed { &id: &'s ComponentId, last_run: Tick, this_run: Tick, - ) -> Self::Fetch<'w, 's> { - Self::Fetch::<'w, 's> { + ) -> Self::Fetch<'w> { + Self::Fetch::<'w> { ticks: StorageSwitch::new( || None, || { @@ -988,7 +975,7 @@ unsafe impl WorldQuery for Changed { #[inline] unsafe fn set_archetype<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, component_id: &'s ComponentId, _archetype: &'w Archetype, table: &'w Table, @@ -1003,7 +990,7 @@ unsafe impl WorldQuery for Changed { #[inline] unsafe fn set_table<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, &component_id: &'s ComponentId, table: &'w Table, ) { @@ -1047,7 +1034,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 { @@ -1146,12 +1133,10 @@ pub struct SpawnedFetch<'w> { // SAFETY: WorldQuery impl accesses no components or component ticks unsafe impl WorldQuery for Spawned { - type Fetch<'w, 's> = SpawnedFetch<'w>; + type Fetch<'w> = SpawnedFetch<'w>; type State = (); - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { fetch } @@ -1161,7 +1146,7 @@ unsafe impl WorldQuery for Spawned { _state: &'s (), last_run: Tick, this_run: Tick, - ) -> Self::Fetch<'w, 's> { + ) -> Self::Fetch<'w> { SpawnedFetch { entities: world.entities(), last_run, @@ -1173,7 +1158,7 @@ unsafe impl WorldQuery for Spawned { #[inline] unsafe fn set_archetype<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _state: &'s (), _archetype: &'w Archetype, _table: &'w Table, @@ -1181,12 +1166,7 @@ unsafe impl WorldQuery for Spawned { } #[inline] - unsafe fn set_table<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, - _state: &'s (), - _table: &'w Table, - ) { - } + unsafe fn set_table<'w, 's>(_fetch: &mut Self::Fetch<'w>, _state: &'s (), _table: &'w Table) {} #[inline] fn update_component_access(_state: &(), _access: &mut FilteredAccess) {} @@ -1208,7 +1188,7 @@ unsafe impl QueryFilter for Spawned { #[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 a3b3d02c24d21..2cf86ea7264da 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -979,7 +979,7 @@ where entities: &'w Entities, tables: &'w Tables, archetypes: &'w Archetypes, - fetch: D::Fetch<'w, 's>, + fetch: D::Fetch<'w>, query_state: &'s QueryState, } @@ -1123,8 +1123,8 @@ pub struct QueryManyIter<'w, 's, D: QueryData, F: QueryFilter, I: Iterator, - filter: F::Fetch<'w, 's>, + fetch: D::Fetch<'w>, + filter: F::Fetch<'w>, query_state: &'s QueryState, } @@ -1171,8 +1171,8 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> entities: &'w Entities, tables: &'w Tables, archetypes: &'w Archetypes, - fetch: &mut D::Fetch<'w, 's>, - filter: &mut F::Fetch<'w, 's>, + fetch: &mut D::Fetch<'w>, + filter: &mut F::Fetch<'w>, query_state: &'s QueryState, ) -> Option> { for entity_borrow in entity_iter { @@ -1919,7 +1919,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, 's>, + fetch: D::Fetch<'w>, query_state: &'s QueryState, } @@ -2313,8 +2313,8 @@ struct QueryIterationCursor<'w, 's, D: QueryData, F: QueryFilter> { storage_id_iter: core::slice::Iter<'s, StorageId>, table_entities: &'w [Entity], archetype_entities: &'w [ArchetypeEntity], - fetch: D::Fetch<'w, 's>, - filter: F::Fetch<'w, 's>, + fetch: D::Fetch<'w>, + filter: F::Fetch<'w>, // length of the table or length of the archetype, depending on whether both `D`'s and `F`'s fetches are dense current_len: u32, // either table row or archetype index, depending on whether both `D`'s and `F`'s fetches are dense diff --git a/crates/bevy_ecs/src/query/mod.rs b/crates/bevy_ecs/src/query/mod.rs index db22c152f7894..f470ea861227c 100644 --- a/crates/bevy_ecs/src/query/mod.rs +++ b/crates/bevy_ecs/src/query/mod.rs @@ -819,12 +819,12 @@ mod tests { /// SAFETY: /// `update_component_access` adds resource read access for `R`. unsafe impl WorldQuery for ReadsRData { - type Fetch<'w, 's> = (); + type Fetch<'w> = (); type State = ComponentId; - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - _: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>( + _: Self::Fetch<'wlong>, + ) -> Self::Fetch<'wshort> { } unsafe fn init_fetch<'w, 's>( @@ -832,14 +832,14 @@ mod tests { _state: &'s Self::State, _last_run: Tick, _this_run: Tick, - ) -> Self::Fetch<'w, 's> { + ) -> Self::Fetch<'w> { } const IS_DENSE: bool = true; #[inline] unsafe fn set_archetype<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _state: &'s Self::State, _archetype: &'w Archetype, _table: &Table, @@ -848,7 +848,7 @@ mod tests { #[inline] unsafe fn set_table<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _state: &'s Self::State, _table: &'w Table, ) { @@ -894,7 +894,7 @@ mod tests { #[inline(always)] unsafe fn fetch<'w, 's>( - _fetch: &mut Self::Fetch<'w, 's>, + _fetch: &mut Self::Fetch<'w>, _entity: Entity, _table_row: TableRow, ) -> Self::Item<'w, 's> { diff --git a/crates/bevy_ecs/src/query/world_query.rs b/crates/bevy_ecs/src/query/world_query.rs index e856be76194e9..1cf6af5f7ef21 100644 --- a/crates/bevy_ecs/src/query/world_query.rs +++ b/crates/bevy_ecs/src/query/world_query.rs @@ -42,7 +42,7 @@ use variadics_please::all_tuples; /// [`QueryFilter`]: crate::query::QueryFilter pub unsafe trait WorldQuery { /// Per archetype/table state retrieved by this [`WorldQuery`] to compute [`Self::Item`](crate::query::QueryData::Item) for each entity. - type Fetch<'w, 's>: Clone; + type Fetch<'w>: 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 @@ -50,9 +50,9 @@ pub unsafe trait WorldQuery { type State: Send + Sync + Sized; /// This function manually implements subtyping for the query fetches. - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's>; + fn shrink_fetch<'wlong: 'wshort, 'wshort>( + fetch: Self::Fetch<'wlong>, + ) -> Self::Fetch<'wshort>; /// Creates a new instance of [`Self::Fetch`](WorldQuery::Fetch), /// by combining data from the [`World`] with the cached [`Self::State`](WorldQuery::State). @@ -69,7 +69,7 @@ pub unsafe trait WorldQuery { state: &'s Self::State, last_run: Tick, this_run: Tick, - ) -> Self::Fetch<'w, 's>; + ) -> Self::Fetch<'w>; /// Returns true if (and only if) every table of every archetype matched by this fetch contains /// all of the matched components. @@ -90,7 +90,7 @@ pub unsafe trait WorldQuery { /// - `table` must correspond to `archetype`. /// - `state` must be the [`State`](Self::State) that `fetch` was initialized with. unsafe fn set_archetype<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, state: &'s Self::State, archetype: &'w Archetype, table: &'w Table, @@ -104,7 +104,7 @@ 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, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, state: &'s Self::State, table: &'w Table, ); @@ -160,11 +160,11 @@ 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, 's> = ($($name::Fetch<'w, 's>,)*); + type Fetch<'w> = ($($name::Fetch<'w>,)*); type State = ($($name::State,)*); - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>(fetch: Self::Fetch<'wlong, 's>) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> { let ($($name,)*) = fetch; ($( $name::shrink_fetch($name), @@ -172,7 +172,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> { let ($($name,)*) = state; // SAFETY: The invariants are upheld by the caller. ($(unsafe { $name::init_fetch(world, $name, last_run, this_run) },)*) @@ -182,7 +182,7 @@ macro_rules! impl_tuple_world_query { #[inline] unsafe fn set_archetype<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, state: &'s Self::State, archetype: &'w Archetype, table: &'w Table @@ -194,7 +194,7 @@ macro_rules! impl_tuple_world_query { } #[inline] - unsafe fn set_table<'w, 's>(fetch: &mut Self::Fetch<'w, 's>, state: &'s Self::State, table: &'w Table) { + unsafe fn set_table<'w, 's>(fetch: &mut Self::Fetch<'w>, state: &'s Self::State, table: &'w Table) { let ($($name,)*) = fetch; let ($($state,)*) = state; // SAFETY: The invariants are upheld by the caller. diff --git a/crates/bevy_render/src/sync_world.rs b/crates/bevy_render/src/sync_world.rs index 35b500059e470..e355430908487 100644 --- a/crates/bevy_render/src/sync_world.rs +++ b/crates/bevy_render/src/sync_world.rs @@ -289,12 +289,12 @@ 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 Fetch<'w, 's> = <&'static RenderEntity as WorldQuery>::Fetch<'w, 's>; + type Fetch<'w> = <&'static RenderEntity as WorldQuery>::Fetch<'w>; type State = <&'static RenderEntity as WorldQuery>::State; - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>( + fetch: Self::Fetch<'wlong>, + ) -> Self::Fetch<'wshort> { fetch } @@ -304,7 +304,7 @@ mod render_entities_world_query_impls { component_id: &'s ComponentId, last_run: Tick, this_run: Tick, - ) -> Self::Fetch<'w, 's> { + ) -> Self::Fetch<'w> { // SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`. unsafe { <&RenderEntity as WorldQuery>::init_fetch(world, component_id, last_run, this_run) @@ -315,7 +315,7 @@ mod render_entities_world_query_impls { #[inline] unsafe fn set_archetype<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, component_id: &'s ComponentId, archetype: &'w Archetype, table: &'w Table, @@ -328,7 +328,7 @@ mod render_entities_world_query_impls { #[inline] unsafe fn set_table<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, &component_id: &'s ComponentId, table: &'w Table, ) { @@ -374,7 +374,7 @@ mod render_entities_world_query_impls { #[inline(always)] unsafe fn fetch<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, entity: Entity, table_row: TableRow, ) -> Self::Item<'w, 's> { @@ -397,12 +397,12 @@ 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 Fetch<'w, 's> = <&'static MainEntity as WorldQuery>::Fetch<'w, 's>; + type Fetch<'w> = <&'static MainEntity as WorldQuery>::Fetch<'w>; type State = <&'static MainEntity as WorldQuery>::State; - fn shrink_fetch<'wlong: 'wshort, 'wshort, 's>( - fetch: Self::Fetch<'wlong, 's>, - ) -> Self::Fetch<'wshort, 's> { + fn shrink_fetch<'wlong: 'wshort, 'wshort>( + fetch: Self::Fetch<'wlong>, + ) -> Self::Fetch<'wshort> { fetch } @@ -412,7 +412,7 @@ mod render_entities_world_query_impls { component_id: &'s ComponentId, last_run: Tick, this_run: Tick, - ) -> Self::Fetch<'w, 's> { + ) -> Self::Fetch<'w> { // SAFETY: defers to the `&T` implementation, with T set to `MainEntity`. unsafe { <&MainEntity as WorldQuery>::init_fetch(world, component_id, last_run, this_run) @@ -423,7 +423,7 @@ mod render_entities_world_query_impls { #[inline] unsafe fn set_archetype<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, component_id: &ComponentId, archetype: &'w Archetype, table: &'w Table, @@ -436,7 +436,7 @@ mod render_entities_world_query_impls { #[inline] unsafe fn set_table<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, &component_id: &'s ComponentId, table: &'w Table, ) { @@ -482,7 +482,7 @@ mod render_entities_world_query_impls { #[inline(always)] unsafe fn fetch<'w, 's>( - fetch: &mut Self::Fetch<'w, 's>, + fetch: &mut Self::Fetch<'w>, entity: Entity, table_row: TableRow, ) -> Self::Item<'w, 's> { From 66751f04cb6f8b461ce7402142d2bcc473a79adb Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Mon, 16 Jun 2025 21:28:29 -0400 Subject: [PATCH 16/18] Pass `&'s QueryState` to `fetch` and `filter_fetch`. --- crates/bevy_asset/src/asset_changed.rs | 3 +- crates/bevy_ecs/macros/src/query_data.rs | 6 +- crates/bevy_ecs/macros/src/query_filter.rs | 3 +- crates/bevy_ecs/src/query/fetch.rs | 37 +++++++-- crates/bevy_ecs/src/query/filter.rs | 26 ++++-- crates/bevy_ecs/src/query/iter.rs | 79 ++++++++++++++++--- crates/bevy_ecs/src/query/mod.rs | 6 +- crates/bevy_ecs/src/query/world_query.rs | 4 +- crates/bevy_ecs/src/system/query.rs | 14 +++- .../bevy_ecs/src/world/unsafe_world_cell.rs | 2 +- crates/bevy_render/src/sync_world.rs | 7 +- 11 files changed, 148 insertions(+), 39 deletions(-) diff --git a/crates/bevy_asset/src/asset_changed.rs b/crates/bevy_asset/src/asset_changed.rs index bd0c97739c66a..b43a8625e783d 100644 --- a/crates/bevy_asset/src/asset_changed.rs +++ b/crates/bevy_asset/src/asset_changed.rs @@ -269,6 +269,7 @@ unsafe impl QueryFilter for AssetChanged { #[inline] unsafe fn filter_fetch( + state: &Self::State, fetch: &mut Self::Fetch<'_>, entity: Entity, table_row: TableRow, @@ -276,7 +277,7 @@ unsafe impl QueryFilter for AssetChanged { fetch.inner.as_mut().is_some_and(|inner| { // SAFETY: We delegate to the inner `fetch` for `A` unsafe { - let handle = <&A>::fetch(inner, entity, table_row); + let handle = <&A>::fetch(&state.asset_id, inner, entity, table_row); fetch.check.has_changed(handle) } }) diff --git a/crates/bevy_ecs/macros/src/query_data.rs b/crates/bevy_ecs/macros/src/query_data.rs index 447d94d11f31e..910d9ce3b6893 100644 --- a/crates/bevy_ecs/macros/src/query_data.rs +++ b/crates/bevy_ecs/macros/src/query_data.rs @@ -290,12 +290,13 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream { /// SAFETY: we call `fetch` for each member that implements `Fetch`. #[inline(always)] unsafe fn fetch<'__w, '__s>( + _state: &'__s Self::State, _fetch: &mut ::Fetch<'__w>, _entity: #path::entity::Entity, _table_row: #path::storage::TableRow, ) -> Self::Item<'__w, '__s> { Self::Item { - #(#field_idents: <#read_only_field_types>::fetch(&mut _fetch.#named_field_idents, _entity, _table_row),)* + #(#field_idents: <#read_only_field_types>::fetch(&_state.#named_field_idents, &mut _fetch.#named_field_idents, _entity, _table_row),)* } } } @@ -347,12 +348,13 @@ pub fn derive_query_data_impl(input: TokenStream) -> TokenStream { /// SAFETY: we call `fetch` for each member that implements `Fetch`. #[inline(always)] unsafe fn fetch<'__w, '__s>( + _state: &'__s Self::State, _fetch: &mut ::Fetch<'__w>, _entity: #path::entity::Entity, _table_row: #path::storage::TableRow, ) -> Self::Item<'__w, '__s> { Self::Item { - #(#field_idents: <#field_types>::fetch(&mut _fetch.#named_field_idents, _entity, _table_row),)* + #(#field_idents: <#field_types>::fetch(&_state.#named_field_idents, &mut _fetch.#named_field_idents, _entity, _table_row),)* } } } diff --git a/crates/bevy_ecs/macros/src/query_filter.rs b/crates/bevy_ecs/macros/src/query_filter.rs index c7ddb9cc83521..5ae2d2325fdab 100644 --- a/crates/bevy_ecs/macros/src/query_filter.rs +++ b/crates/bevy_ecs/macros/src/query_filter.rs @@ -102,11 +102,12 @@ pub fn derive_query_filter_impl(input: TokenStream) -> TokenStream { #[allow(unused_variables)] #[inline(always)] unsafe fn filter_fetch<'__w>( + _state: &Self::State, _fetch: &mut ::Fetch<'__w>, _entity: #path::entity::Entity, _table_row: #path::storage::TableRow, ) -> bool { - true #(&& <#field_types>::filter_fetch(&mut _fetch.#named_field_idents, _entity, _table_row))* + true #(&& <#field_types>::filter_fetch(&_state.#named_field_idents, &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 8e8289f948f0a..8f7fa775a3ea5 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -325,6 +325,7 @@ pub unsafe trait QueryData: WorldQuery { /// `table_row` must be in the range of the current table and archetype. /// - There must not be simultaneous conflicting component access registered in `update_component_access`. unsafe fn fetch<'w, 's>( + state: &'s Self::State, fetch: &mut Self::Fetch<'w>, entity: Entity, table_row: TableRow, @@ -421,6 +422,7 @@ unsafe impl QueryData for Entity { #[inline(always)] unsafe fn fetch<'w, 's>( + _state: &'s Self::State, _fetch: &mut Self::Fetch<'w>, entity: Entity, _table_row: TableRow, @@ -509,6 +511,7 @@ unsafe impl QueryData for EntityLocation { #[inline(always)] unsafe fn fetch<'w, 's>( + _state: &'s Self::State, fetch: &mut Self::Fetch<'w>, entity: Entity, _table_row: TableRow, @@ -671,6 +674,7 @@ unsafe impl QueryData for SpawnDetails { #[inline(always)] unsafe fn fetch<'w, 's>( + _state: &'s Self::State, fetch: &mut Self::Fetch<'w>, entity: Entity, _table_row: TableRow, @@ -789,6 +793,7 @@ unsafe impl<'a> QueryData for EntityRef<'a> { #[inline(always)] unsafe fn fetch<'w, 's>( + _state: &'s Self::State, fetch: &mut Self::Fetch<'w>, entity: Entity, _table_row: TableRow, @@ -891,6 +896,7 @@ unsafe impl<'a> QueryData for EntityMut<'a> { #[inline(always)] unsafe fn fetch<'w, 's>( + _state: &'s Self::State, fetch: &mut Self::Fetch<'w>, entity: Entity, _table_row: TableRow, @@ -1017,6 +1023,7 @@ unsafe impl<'a> QueryData for FilteredEntityRef<'a> { #[inline(always)] unsafe fn fetch<'w, 's>( + _state: &'s Self::State, (fetch, access): &mut Self::Fetch<'w>, entity: Entity, _table_row: TableRow, @@ -1138,6 +1145,7 @@ unsafe impl<'a> QueryData for FilteredEntityMut<'a> { #[inline(always)] unsafe fn fetch<'w, 's>( + _state: &'s Self::State, (fetch, access): &mut Self::Fetch<'w>, entity: Entity, _table_row: TableRow, @@ -1247,6 +1255,7 @@ where } unsafe fn fetch<'w, 's>( + _state: &'s Self::State, fetch: &mut Self::Fetch<'w>, entity: Entity, _: TableRow, @@ -1357,6 +1366,7 @@ where } unsafe fn fetch<'w, 's>( + _state: &'s Self::State, fetch: &mut Self::Fetch<'w>, entity: Entity, _: TableRow, @@ -1440,6 +1450,7 @@ unsafe impl QueryData for &Archetype { #[inline(always)] unsafe fn fetch<'w, 's>( + _state: &'s Self::State, fetch: &mut Self::Fetch<'w>, entity: Entity, _table_row: TableRow, @@ -1593,6 +1604,7 @@ unsafe impl QueryData for &T { #[inline(always)] unsafe fn fetch<'w, 's>( + _state: &'s Self::State, fetch: &mut Self::Fetch<'w>, entity: Entity, table_row: TableRow, @@ -1777,6 +1789,7 @@ unsafe impl<'__w, T: Component> QueryData for Ref<'__w, T> { #[inline(always)] unsafe fn fetch<'w, 's>( + _state: &'s Self::State, fetch: &mut Self::Fetch<'w>, entity: Entity, table_row: TableRow, @@ -1984,6 +1997,7 @@ unsafe impl<'__w, T: Component> QueryData for &'__w mut T #[inline(always)] unsafe fn fetch<'w, 's>( + _state: &'s Self::State, fetch: &mut Self::Fetch<'w>, entity: Entity, table_row: TableRow, @@ -2137,13 +2151,14 @@ unsafe impl<'__w, T: Component> QueryData for Mut<'__w, T> #[inline(always)] // Forwarded to `&mut T` unsafe fn fetch<'w, 's>( + state: &'s Self::State, // 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>, entity: Entity, table_row: TableRow, ) -> Self::Item<'w, 's> { - <&mut T as QueryData>::fetch(fetch, entity, table_row) + <&mut T as QueryData>::fetch(state, fetch, entity, table_row) } } @@ -2275,6 +2290,7 @@ unsafe impl QueryData for Option { #[inline(always)] unsafe fn fetch<'w, 's>( + state: &'s Self::State, fetch: &mut Self::Fetch<'w>, entity: Entity, table_row: TableRow, @@ -2282,7 +2298,7 @@ unsafe impl QueryData for Option { fetch .matches // SAFETY: The invariants are upheld by the caller. - .then(|| unsafe { T::fetch(&mut fetch.fetch, entity, table_row) }) + .then(|| unsafe { T::fetch(state, &mut fetch.fetch, entity, table_row) }) } } @@ -2451,6 +2467,7 @@ unsafe impl QueryData for Has { #[inline(always)] unsafe fn fetch<'w, 's>( + _state: &'s Self::State, fetch: &mut Self::Fetch<'w>, _entity: Entity, _table_row: TableRow, @@ -2476,7 +2493,7 @@ impl ReleaseStateQueryData for Has { pub struct AnyOf(PhantomData); macro_rules! impl_tuple_query_data { - ($(#[$meta:meta])* $(($name: ident, $item: ident)),*) => { + ($(#[$meta:meta])* $(($name: ident, $item: ident, $state: ident)),*) => { #[expect( clippy::allow_attributes, reason = "This is a tuple-related macro; as such the lints below may not always apply." @@ -2519,13 +2536,15 @@ macro_rules! impl_tuple_query_data { #[inline(always)] unsafe fn fetch<'w, 's>( + state: &'s Self::State, fetch: &mut Self::Fetch<'w>, entity: Entity, table_row: TableRow ) -> Self::Item<'w, 's> { + let ($($state,)*) = state; let ($($name,)*) = fetch; // SAFETY: The invariants are upheld by the caller. - ($(unsafe { $name::fetch($name, entity, table_row) },)*) + ($(unsafe { $name::fetch($state, $name, entity, table_row) },)*) } } @@ -2694,14 +2713,16 @@ macro_rules! impl_anytuple_fetch { #[inline(always)] unsafe fn fetch<'w, 's>( + _state: &'s Self::State, _fetch: &mut Self::Fetch<'w>, _entity: Entity, _table_row: TableRow ) -> Self::Item<'w, 's> { let ($($name,)*) = _fetch; + let ($($state,)*) = _state; ($( // SAFETY: The invariants are required to be upheld by the caller. - $name.1.then(|| unsafe { $name::fetch(&mut $name.0, _entity, _table_row) }), + $name.1.then(|| unsafe { $name::fetch($state, &mut $name.0, _entity, _table_row) }), )*) } } @@ -2732,7 +2753,8 @@ all_tuples!( 0, 15, F, - i + i, + s ); all_tuples!( #[doc(fake_variadic)] @@ -2813,6 +2835,7 @@ unsafe impl QueryData for NopWorldQuery { #[inline(always)] unsafe fn fetch<'w, 's>( + _state: &'s Self::State, _fetch: &mut Self::Fetch<'w>, _entity: Entity, _table_row: TableRow, @@ -2893,6 +2916,7 @@ unsafe impl QueryData for PhantomData { } unsafe fn fetch<'w, 's>( + _state: &'s Self::State, _fetch: &mut Self::Fetch<'w>, _entity: Entity, _table_row: TableRow, @@ -3100,6 +3124,7 @@ mod tests { #[inline(always)] unsafe fn fetch<'w, 's>( + _state: &'s Self::State, _fetch: &mut Self::Fetch<'w>, _entity: Entity, _table_row: TableRow, diff --git a/crates/bevy_ecs/src/query/filter.rs b/crates/bevy_ecs/src/query/filter.rs index 0def8b5bb5e41..b1abf29a6d23d 100644 --- a/crates/bevy_ecs/src/query/filter.rs +++ b/crates/bevy_ecs/src/query/filter.rs @@ -103,6 +103,7 @@ pub unsafe trait QueryFilter: 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 filter_fetch( + state: &Self::State, fetch: &mut Self::Fetch<'_>, entity: Entity, table_row: TableRow, @@ -204,6 +205,7 @@ unsafe impl QueryFilter for With { #[inline(always)] unsafe fn filter_fetch( + _state: &Self::State, _fetch: &mut Self::Fetch<'_>, _entity: Entity, _table_row: TableRow, @@ -304,6 +306,7 @@ unsafe impl QueryFilter for Without { #[inline(always)] unsafe fn filter_fetch( + _state: &Self::State, _fetch: &mut Self::Fetch<'_>, _entity: Entity, _table_row: TableRow, @@ -495,20 +498,22 @@ macro_rules! impl_or_query_filter { #[inline(always)] unsafe fn filter_fetch( + state: &Self::State, fetch: &mut Self::Fetch<'_>, entity: Entity, table_row: TableRow ) -> bool { + let ($($state,)*) = state; let ($($filter,)*) = fetch; // SAFETY: The invariants are upheld by the caller. - false $(|| ($filter.matches && unsafe { $filter::filter_fetch(&mut $filter.fetch, entity, table_row) }))* + false $(|| ($filter.matches && unsafe { $filter::filter_fetch($state, &mut $filter.fetch, entity, table_row) }))* } } }; } macro_rules! impl_tuple_query_filter { - ($(#[$meta:meta])* $($name: ident),*) => { + ($(#[$meta:meta])* $(($name: ident, $state: ident)),*) => { #[expect( clippy::allow_attributes, reason = "This is a tuple-related macro; as such the lints below may not always apply." @@ -528,13 +533,15 @@ macro_rules! impl_tuple_query_filter { #[inline(always)] unsafe fn filter_fetch( + state: &Self::State, fetch: &mut Self::Fetch<'_>, entity: Entity, table_row: TableRow ) -> bool { + let ($($state,)*) = state; let ($($name,)*) = fetch; // SAFETY: The invariants are upheld by the caller. - true $(&& unsafe { $name::filter_fetch($name, entity, table_row) })* + true $(&& unsafe { $name::filter_fetch($state, $name, entity, table_row) })* } } @@ -546,7 +553,8 @@ all_tuples!( impl_tuple_query_filter, 0, 15, - F + F, + S ); all_tuples!( #[doc(fake_variadic)] @@ -609,7 +617,12 @@ unsafe impl QueryFilter for Allows { const IS_ARCHETYPAL: bool = true; #[inline(always)] - unsafe fn filter_fetch(_: &mut Self::Fetch<'_>, _: Entity, _: TableRow) -> bool { + unsafe fn filter_fetch( + _: &Self::State, + _: &mut Self::Fetch<'_>, + _: Entity, + _: TableRow, + ) -> bool { true } } @@ -807,6 +820,7 @@ unsafe impl QueryFilter for Added { const IS_ARCHETYPAL: bool = false; #[inline(always)] unsafe fn filter_fetch( + _state: &Self::State, fetch: &mut Self::Fetch<'_>, entity: Entity, table_row: TableRow, @@ -1034,6 +1048,7 @@ unsafe impl QueryFilter for Changed { #[inline(always)] unsafe fn filter_fetch( + _state: &Self::State, fetch: &mut Self::Fetch<'_>, entity: Entity, table_row: TableRow, @@ -1188,6 +1203,7 @@ unsafe impl QueryFilter for Spawned { #[inline(always)] unsafe fn filter_fetch( + _state: &Self::State, fetch: &mut Self::Fetch<'_>, entity: Entity, _table_row: TableRow, diff --git a/crates/bevy_ecs/src/query/iter.rs b/crates/bevy_ecs/src/query/iter.rs index 2cf86ea7264da..eb49204434b6f 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -225,14 +225,26 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { // SAFETY: set_table was called prior. // Caller assures `row` in range of the current archetype. - let fetched = unsafe { !F::filter_fetch(&mut self.cursor.filter, *entity, row) }; + let fetched = unsafe { + !F::filter_fetch( + &self.query_state.filter_state, + &mut self.cursor.filter, + *entity, + row, + ) + }; if fetched { continue; } // SAFETY: set_table was called prior. // Caller assures `row` in range of the current archetype. - let item = D::fetch(&mut self.cursor.fetch, *entity, row); + let item = D::fetch( + &self.query_state.fetch_state, + &mut self.cursor.fetch, + *entity, + row, + ); accum = func(accum, item); } @@ -283,6 +295,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { // Caller assures `index` in range of the current archetype. let fetched = unsafe { !F::filter_fetch( + &self.query_state.filter_state, &mut self.cursor.filter, archetype_entity.id(), archetype_entity.table_row(), @@ -296,6 +309,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { // Caller assures `index` in range of the current archetype. let item = unsafe { D::fetch( + &self.query_state.fetch_state, &mut self.cursor.fetch, archetype_entity.id(), archetype_entity.table_row(), @@ -356,14 +370,26 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIter<'w, 's, D, F> { // SAFETY: set_table was called prior. // Caller assures `row` in range of the current archetype. - let filter_matched = unsafe { F::filter_fetch(&mut self.cursor.filter, entity, row) }; + let filter_matched = unsafe { + F::filter_fetch( + &self.query_state.filter_state, + &mut self.cursor.filter, + entity, + row, + ) + }; if !filter_matched { continue; } // SAFETY: set_table was called prior. // Caller assures `row` in range of the current archetype. - let item = D::fetch(&mut self.cursor.fetch, entity, row); + let item = D::fetch( + &self.query_state.fetch_state, + &mut self.cursor.fetch, + entity, + row, + ); accum = func(accum, item); } @@ -1043,7 +1069,14 @@ where // SAFETY: // - set_archetype was called prior, `location.archetype_row` is an archetype index in range of the current archetype // - fetch is only called once for each entity. - unsafe { D::fetch(&mut self.fetch, entity, location.table_row) } + unsafe { + D::fetch( + &self.query_state.fetch_state, + &mut self.fetch, + entity, + location.table_row, + ) + } } } @@ -1204,11 +1237,20 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> // SAFETY: set_archetype was called prior. // `location.archetype_row` is an archetype index row in range of the current archetype, because if it was not, the match above would have `continue`d - if unsafe { F::filter_fetch(filter, entity, location.table_row) } { + if unsafe { + F::filter_fetch( + &query_state.filter_state, + filter, + entity, + location.table_row, + ) + } { // SAFETY: // - set_archetype was called prior, `location.archetype_row` is an archetype index in range of the current archetype // - fetch is only called once for each entity. - return Some(unsafe { D::fetch(fetch, entity, location.table_row) }); + return Some(unsafe { + D::fetch(&query_state.fetch_state, fetch, entity, location.table_row) + }); } } None @@ -1987,7 +2029,14 @@ impl<'w, 's, D: QueryData, F: QueryFilter, I: Iterator> // SAFETY: // - set_archetype was called prior, `location.archetype_row` is an archetype index in range of the current archetype // - fetch is only called once for each entity. - unsafe { D::fetch(&mut self.fetch, entity, location.table_row) } + unsafe { + D::fetch( + &self.query_state.fetch_state, + &mut self.fetch, + entity, + location.table_row, + ) + } } /// Get next result from the query @@ -2219,7 +2268,8 @@ impl<'w, 's, D: QueryData, F: QueryFilter, const K: usize> QueryCombinationIter< let ptr = values.as_mut_ptr().cast::>(); for (offset, cursor) in self.cursors.iter_mut().enumerate() { - ptr.add(offset).write(cursor.peek_last().unwrap()); + ptr.add(offset) + .write(cursor.peek_last(self.query_state).unwrap()); } Some(values.assume_init()) @@ -2394,7 +2444,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, query_state: &'s QueryState) -> Option> { if self.current_row > 0 { let index = self.current_row - 1; if self.is_dense { @@ -2405,6 +2455,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIterationCursor<'w, 's, D, F> { // - `*entity` and `index` are in the current table. unsafe { Some(D::fetch( + &query_state.fetch_state, &mut self.fetch, *entity, // SAFETY: This is from an exclusive range, so it can't be max. @@ -2420,6 +2471,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIterationCursor<'w, 's, D, F> { // - `archetype_entity.id()` and `archetype_entity.table_row()` are in the current archetype. unsafe { Some(D::fetch( + &query_state.fetch_state, &mut self.fetch, archetype_entity.id(), archetype_entity.table_row(), @@ -2488,7 +2540,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIterationCursor<'w, 's, D, F> { unsafe { self.table_entities.get_unchecked(self.current_row as usize) }; // SAFETY: The row is less than the u32 len, so it must not be max. let row = unsafe { TableRow::new(NonMaxU32::new_unchecked(self.current_row)) }; - if !F::filter_fetch(&mut self.filter, *entity, row) { + if !F::filter_fetch(&query_state.filter_state, &mut self.filter, *entity, row) { self.current_row += 1; continue; } @@ -2498,7 +2550,8 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIterationCursor<'w, 's, D, F> { // - `current_row` must be a table row in range of the current table, // because if it was not, then the above would have been executed. // - fetch is only called once for each `entity`. - let item = unsafe { D::fetch(&mut self.fetch, *entity, row) }; + let item = + unsafe { D::fetch(&query_state.fetch_state, &mut self.fetch, *entity, row) }; self.current_row += 1; return Some(item); @@ -2540,6 +2593,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIterationCursor<'w, 's, D, F> { .get_unchecked(self.current_row as usize) }; if !F::filter_fetch( + &query_state.filter_state, &mut self.filter, archetype_entity.id(), archetype_entity.table_row(), @@ -2555,6 +2609,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter> QueryIterationCursor<'w, 's, D, F> { // - fetch is only called once for each `archetype_entity`. let item = unsafe { D::fetch( + &query_state.fetch_state, &mut self.fetch, archetype_entity.id(), archetype_entity.table_row(), diff --git a/crates/bevy_ecs/src/query/mod.rs b/crates/bevy_ecs/src/query/mod.rs index f470ea861227c..7c1487fde4e72 100644 --- a/crates/bevy_ecs/src/query/mod.rs +++ b/crates/bevy_ecs/src/query/mod.rs @@ -822,10 +822,7 @@ mod tests { type Fetch<'w> = (); type State = ComponentId; - fn shrink_fetch<'wlong: 'wshort, 'wshort>( - _: Self::Fetch<'wlong>, - ) -> Self::Fetch<'wshort> { - } + fn shrink_fetch<'wlong: 'wshort, 'wshort>(_: Self::Fetch<'wlong>) -> Self::Fetch<'wshort> {} unsafe fn init_fetch<'w, 's>( _world: UnsafeWorldCell<'w>, @@ -894,6 +891,7 @@ mod tests { #[inline(always)] unsafe fn fetch<'w, 's>( + _state: &'s Self::State, _fetch: &mut Self::Fetch<'w>, _entity: Entity, _table_row: TableRow, diff --git a/crates/bevy_ecs/src/query/world_query.rs b/crates/bevy_ecs/src/query/world_query.rs index 1cf6af5f7ef21..1c739927acf05 100644 --- a/crates/bevy_ecs/src/query/world_query.rs +++ b/crates/bevy_ecs/src/query/world_query.rs @@ -50,9 +50,7 @@ pub unsafe trait WorldQuery { type State: Send + Sync + Sized; /// 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>(fetch: Self::Fetch<'wlong>) -> Self::Fetch<'wshort>; /// Creates a new instance of [`Self::Fetch`](WorldQuery::Fetch), /// by combining data from the [`World`] with the cached [`Self::State`](WorldQuery::State). diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 2664d3a44f616..5d41498a747ca 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -1580,8 +1580,18 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { D::set_archetype(&mut fetch, &self.state.fetch_state, archetype, table); F::set_archetype(&mut filter, &self.state.filter_state, archetype, table); - if F::filter_fetch(&mut filter, entity, location.table_row) { - Ok(D::fetch(&mut fetch, entity, location.table_row)) + if F::filter_fetch( + &self.state.filter_state, + &mut filter, + entity, + location.table_row, + ) { + Ok(D::fetch( + &self.state.fetch_state, + &mut fetch, + entity, + location.table_row, + )) } else { Err(QueryEntityError::QueryDoesNotMatch( entity, diff --git a/crates/bevy_ecs/src/world/unsafe_world_cell.rs b/crates/bevy_ecs/src/world/unsafe_world_cell.rs index 6c618a287fa1b..38d4333843999 100644 --- a/crates/bevy_ecs/src/world/unsafe_world_cell.rs +++ b/crates/bevy_ecs/src/world/unsafe_world_cell.rs @@ -1030,7 +1030,7 @@ 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. - let item = unsafe { Q::fetch(&mut fetch, self.id(), location.table_row) }; + let item = unsafe { Q::fetch(&state, &mut fetch, self.id(), location.table_row) }; Some(Q::release_state(item)) } else { None diff --git a/crates/bevy_render/src/sync_world.rs b/crates/bevy_render/src/sync_world.rs index e355430908487..b216b5fd32e3f 100644 --- a/crates/bevy_render/src/sync_world.rs +++ b/crates/bevy_render/src/sync_world.rs @@ -374,13 +374,14 @@ mod render_entities_world_query_impls { #[inline(always)] unsafe fn fetch<'w, 's>( + state: &'s Self::State, fetch: &mut Self::Fetch<'w>, entity: Entity, table_row: TableRow, ) -> Self::Item<'w, 's> { // SAFETY: defers to the `&T` implementation, with T set to `RenderEntity`. let component = - unsafe { <&RenderEntity as QueryData>::fetch(fetch, entity, table_row) }; + unsafe { <&RenderEntity as QueryData>::fetch(state, fetch, entity, table_row) }; component.id() } } @@ -482,12 +483,14 @@ mod render_entities_world_query_impls { #[inline(always)] unsafe fn fetch<'w, 's>( + state: &'s Self::State, fetch: &mut Self::Fetch<'w>, entity: Entity, table_row: TableRow, ) -> Self::Item<'w, 's> { // SAFETY: defers to the `&T` implementation, with T set to `MainEntity`. - let component = unsafe { <&MainEntity as QueryData>::fetch(fetch, entity, table_row) }; + let component = + unsafe { <&MainEntity as QueryData>::fetch(state, fetch, entity, table_row) }; component.id() } } From b9fc1ff0cb868bcfa14053f20c352b7da958786a Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Wed, 18 Jun 2025 12:42:23 -0400 Subject: [PATCH 17/18] Rework to support query data that borrows from state. Restore `'state` lifetime to iterators so they can provide it to items. Replace `QueryStateDeref` with a `ConsumableQueryState` trait that is only used in consuming query methods, and use ordinary `Deref` for borrowing methods. --- crates/bevy_ecs/src/query/fetch.rs | 10 +- crates/bevy_ecs/src/query/iter.rs | 303 +++++++++++------- crates/bevy_ecs/src/query/par_iter.rs | 40 ++- crates/bevy_ecs/src/query/state.rs | 94 ++++-- .../src/relationship/relationship_query.rs | 150 ++++++--- crates/bevy_ecs/src/system/query.rs | 199 +++++++----- 6 files changed, 505 insertions(+), 291 deletions(-) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 9e03db9d7655c..d0f2ded130bbd 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -349,7 +349,7 @@ pub unsafe trait ReadOnlyQueryData: QueryData {} /// I.e.: `Self::fetch(fetch, entity, table_row).entity() == entity` always holds. pub unsafe trait EntityEquivalentQueryData: QueryData where - for<'a> Self: QueryData: EntityEquivalent>, + for<'w, 's> Self: QueryData: EntityEquivalent>, { } @@ -752,7 +752,7 @@ unsafe impl<'a> WorldQuery for EntityRef<'a> { world, last_run, this_run, - } + } } const IS_DENSE: bool = true; @@ -858,7 +858,7 @@ unsafe impl<'a> WorldQuery for EntityMut<'a> { world, last_run, this_run, - } + } } const IS_DENSE: bool = true; @@ -1215,7 +1215,7 @@ where world, last_run, this_run, - } + } } const IS_DENSE: bool = true; @@ -1328,7 +1328,7 @@ where world, last_run, this_run, - } + } } const IS_DENSE: bool = true; diff --git a/crates/bevy_ecs/src/query/iter.rs b/crates/bevy_ecs/src/query/iter.rs index 692d1b1f2bc0b..f88cc1dde75a6 100644 --- a/crates/bevy_ecs/src/query/iter.rs +++ b/crates/bevy_ecs/src/query/iter.rs @@ -4,8 +4,8 @@ use crate::{ component::Tick, entity::{ContainsEntity, Entities, Entity, EntityEquivalent, EntitySet, EntitySetIterator}, query::{ - ArchetypeFilter, DebugCheckedUnwrap, EntityEquivalentQueryData, QueryState, - QueryStateDeref, StorageId, + ArchetypeFilter, ConsumableQueryState, DebugCheckedUnwrap, EntityEquivalentQueryData, + QueryState, StorageId, }, storage::{Table, TableRow, Tables}, world::unsafe_world_cell::UnsafeWorldCell, @@ -15,6 +15,7 @@ use core::{ cmp::Ordering, fmt::{self, Debug, Formatter}, iter::FusedIterator, + marker::PhantomData, mem::MaybeUninit, ops::Range, }; @@ -24,15 +25,17 @@ use nonmax::NonMaxU32; /// /// This struct is created by the [`Query::iter`](crate::system::Query::iter) and /// [`Query::iter_mut`](crate::system::Query::iter_mut) methods. -pub struct QueryIter<'w, S: QueryStateDeref> { +pub struct QueryIter<'w, 's, S: ConsumableQueryState<'s>> { world: UnsafeWorldCell<'w>, tables: &'w Tables, archetypes: &'w Archetypes, query_state: S, - cursor: QueryIterationCursor<'w, S>, + cursor: QueryIterationCursor<'w, 's, S>, } -impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> QueryIter<'w, S> { +impl<'w, 's, D: QueryData, F: QueryFilter, S: ConsumableQueryState<'s, Data = D, Filter = F>> + QueryIter<'w, 's, S> +{ /// # Safety /// - `world` must have permission to access any of the components registered in `query_state`. /// - `world` must be the same one used to initialize `query_state`. @@ -117,7 +120,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> /// } /// } /// ``` - pub fn remaining_mut(&mut self) -> QueryIter<'_, &QueryState> { + pub fn remaining_mut(&mut self) -> QueryIter<'_, '_, &QueryState> { QueryIter { world: self.world, tables: self.tables, @@ -240,12 +243,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> // SAFETY: set_table was called prior. // Caller assures `row` in range of the current archetype. - let item = D::fetch( - &self.query_state.fetch_state, - &mut self.cursor.fetch, - *entity, - row, - ); + let item = self.query_state.fetch(&mut self.cursor.fetch, *entity, row); accum = func(accum, item); } @@ -309,8 +307,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> // SAFETY: set_archetype was called prior, `index` is an archetype index in range of the current archetype // Caller assures `index` in range of the current archetype. let item = unsafe { - D::fetch( - &self.query_state.fetch_state, + self.query_state.fetch( &mut self.cursor.fetch, archetype_entity.id(), archetype_entity.table_row(), @@ -385,12 +382,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> // SAFETY: set_table was called prior. // Caller assures `row` in range of the current archetype. - let item = D::fetch( - &self.query_state.fetch_state, - &mut self.cursor.fetch, - entity, - row, - ); + let item = self.query_state.fetch(&mut self.cursor.fetch, entity, row); accum = func(accum, item); } @@ -513,6 +505,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> self, ) -> QuerySortedIter< 'w, + 's, S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > @@ -568,6 +561,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> self, ) -> QuerySortedIter< 'w, + 's, S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > @@ -631,6 +625,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> mut compare: impl FnMut(&L::Item<'_, '_>, &L::Item<'_, '_>) -> Ordering, ) -> QuerySortedIter< 'w, + 's, S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > { @@ -661,6 +656,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> mut compare: impl FnMut(&L::Item<'_, '_>, &L::Item<'_, '_>) -> Ordering, ) -> QuerySortedIter< 'w, + 's, S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > { @@ -751,6 +747,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> mut f: impl FnMut(&L::Item<'_, '_>) -> K, ) -> QuerySortedIter< 'w, + 's, S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > @@ -782,6 +779,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> mut f: impl FnMut(&L::Item<'_, '_>) -> K, ) -> QuerySortedIter< 'w, + 's, S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > @@ -815,6 +813,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> mut f: impl FnMut(&L::Item<'_, '_>) -> K, ) -> QuerySortedIter< 'w, + 's, S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > @@ -843,6 +842,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> f: impl FnOnce(&mut Vec<(L::Item<'_, '_>, NeutralOrd)>), ) -> QuerySortedIter< 'w, + 's, S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > { @@ -887,8 +887,8 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> } } -impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> Iterator - for QueryIter<'w, S> +impl<'w, 's, D: QueryData, F: QueryFilter, S: ConsumableQueryState<'s, Data = D, Filter = F>> + Iterator for QueryIter<'w, 's, S> { type Item = D::Item<'w, 's>; @@ -932,22 +932,24 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> } // This is correct as [`QueryIter`] always returns `None` once exhausted. -impl<'w, S: QueryStateDeref> FusedIterator for QueryIter<'w, S> {} +impl<'w, 's, S: ConsumableQueryState<'s>> FusedIterator for QueryIter<'w, 's, S> {} // SAFETY: [`QueryIter`] is guaranteed to return every matching entity once and only once, // and [`EntityEquivalentQueryData`] ensures that they return the original `Entity`. -unsafe impl<'w, S: QueryStateDeref> EntitySetIterator - for QueryIter<'w, S> +unsafe impl<'w, 's, S: ConsumableQueryState<'s, Data: EntityEquivalentQueryData>> EntitySetIterator + for QueryIter<'w, 's, S> { } -impl<'w, S: QueryStateDeref> Debug for QueryIter<'w, S> { +impl<'w, 's, S: ConsumableQueryState<'s>> Debug for QueryIter<'w, 's, S> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QueryIter").finish() } } -impl<'w, S: QueryStateDeref + Copy> Clone for QueryIter<'w, S> { +impl<'w, 's, S: ConsumableQueryState<'s, Data: ReadOnlyQueryData> + Copy> Clone + for QueryIter<'w, 's, S> +{ fn clone(&self) -> Self { self.remaining() } @@ -958,7 +960,7 @@ impl<'w, S: QueryStateDeref + Copy> Clone for QueryIter /// This struct is created by the [`QueryIter::sort`], [`QueryIter::sort_unstable`], /// [`QueryIter::sort_by`], [`QueryIter::sort_unstable_by`], [`QueryIter::sort_by_key`], /// [`QueryIter::sort_unstable_by_key`], and [`QueryIter::sort_by_cached_key`] methods. -pub struct QuerySortedIter<'w, S: QueryStateDeref, I> +pub struct QuerySortedIter<'w, 's, S: ConsumableQueryState<'s>, I> where I: Iterator, { @@ -968,9 +970,11 @@ where archetypes: &'w Archetypes, fetch: ::Fetch<'w>, query_state: S, + marker: PhantomData<&'s ()>, } -impl<'w, D: QueryData, S: QueryStateDeref, I: Iterator> QuerySortedIter<'w, S, I> +impl<'w, 's, D: QueryData, S: ConsumableQueryState<'s, Data = D>, I: Iterator> + QuerySortedIter<'w, 's, S, I> where I: Iterator, { @@ -988,6 +992,7 @@ where let fetch = D::init_fetch(world, &query_state.fetch_state, last_run, this_run); QuerySortedIter { query_state, + marker: PhantomData, entities: world.entities(), archetypes: world.archetypes(), // SAFETY: We only access table data that has been registered in `query_state`. @@ -1031,18 +1036,14 @@ where // - set_archetype was called prior, `location.archetype_row` is an archetype index in range of the current archetype // - fetch is only called once for each entity. unsafe { - D::fetch( - &self.query_state.fetch_state, - &mut self.fetch, - entity, - location.table_row, - ) - } + self.query_state + .fetch(&mut self.fetch, entity, location.table_row) + } } } -impl<'w, D: QueryData, S: QueryStateDeref, I: Iterator> Iterator - for QuerySortedIter<'w, S, I> +impl<'w, 's, D: QueryData, S: ConsumableQueryState<'s, Data = D>, I: Iterator> Iterator + for QuerySortedIter<'w, 's, S, I> where I: Iterator, { @@ -1060,7 +1061,8 @@ where } } -impl<'w, S: QueryStateDeref, I: Iterator> DoubleEndedIterator for QuerySortedIter<'w, S, I> +impl<'w, 's, S: ConsumableQueryState<'s>, I: Iterator> DoubleEndedIterator + for QuerySortedIter<'w, 's, S, I> where I: DoubleEndedIterator, { @@ -1072,26 +1074,36 @@ where } } -impl<'w, S: QueryStateDeref, I: Iterator> ExactSizeIterator for QuerySortedIter<'w, S, I> where - I: ExactSizeIterator +impl<'w, 's, S: ConsumableQueryState<'s>, I: Iterator> ExactSizeIterator + for QuerySortedIter<'w, 's, S, I> +where + I: ExactSizeIterator, { } // This is correct as [`QuerySortedIter`] returns `None` once exhausted if `entity_iter` does. -impl<'w, S: QueryStateDeref, I: Iterator> FusedIterator for QuerySortedIter<'w, S, I> where - I: FusedIterator +impl<'w, 's, S: ConsumableQueryState<'s>, I: Iterator> FusedIterator + for QuerySortedIter<'w, 's, S, I> +where + I: FusedIterator, { } // SAFETY: // `I` stems from a collected and sorted `EntitySetIterator` ([`QueryIter`]). // [`EntityEquivalentQueryData`] ensures that unique items return unique `Entity`s. -unsafe impl<'w, S: QueryStateDeref, I: Iterator> - EntitySetIterator for QuerySortedIter<'w, S, I> +unsafe impl< + 'w, + 's, + S: ConsumableQueryState<'s, Data: EntityEquivalentQueryData>, + I: Iterator, + > EntitySetIterator for QuerySortedIter<'w, 's, S, I> { } -impl<'w, S: QueryStateDeref, I: Iterator> Debug for QuerySortedIter<'w, S, I> { +impl<'w, 's, S: ConsumableQueryState<'s>, I: Iterator> Debug + for QuerySortedIter<'w, 's, S, I> +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QuerySortedIter").finish() } @@ -1103,7 +1115,7 @@ impl<'w, S: QueryStateDeref, I: Iterator> Debug for QuerySortedIt /// Entities that don't match the query are skipped. /// /// This struct is created by the [`Query::iter_many`](crate::system::Query::iter_many) and [`Query::iter_many_mut`](crate::system::Query::iter_many_mut) methods. -pub struct QueryManyIter<'w, S: QueryStateDeref, I: Iterator> { +pub struct QueryManyIter<'w, 's, S: ConsumableQueryState<'s>, I: Iterator> { world: UnsafeWorldCell<'w>, entity_iter: I, entities: &'w Entities, @@ -1112,15 +1124,17 @@ pub struct QueryManyIter<'w, S: QueryStateDeref, I: Iterator::Fetch<'w>, filter: ::Fetch<'w>, query_state: S, + marker: PhantomData<&'s ()>, } impl< 'w, + 's, D: QueryData, F: QueryFilter, - S: QueryStateDeref, + S: ConsumableQueryState<'s, Data = D, Filter = F>, I: Iterator, - > QueryManyIter<'w, S, I> + > QueryManyIter<'w, 's, S, I> { /// # Safety /// - `world` must have permission to access any of the components registered in `query_state`. @@ -1137,6 +1151,7 @@ impl< QueryManyIter { world, query_state, + marker: PhantomData, entities: world.entities(), archetypes: world.archetypes(), // SAFETY: We only access table data that has been registered in `query_state`. @@ -1164,7 +1179,7 @@ impl< archetypes: &'w Archetypes, fetch: &mut D::Fetch<'w>, filter: &mut F::Fetch<'w>, - query_state: &QueryState, + query_state: &S, ) -> Option> { for entity_borrow in entity_iter { let entity = entity_borrow.entity(); @@ -1206,9 +1221,7 @@ impl< // SAFETY: // - set_archetype was called prior, `location.archetype_row` is an archetype index in range of the current archetype // - fetch is only called once for each entity. - return Some(unsafe { - D::fetch(&query_state.fetch_state, fetch, entity, location.table_row) - }); + return Some(unsafe { query_state.fetch(fetch, entity, location.table_row) }); } } None @@ -1334,6 +1347,7 @@ impl< self, ) -> QuerySortedManyIter< 'w, + 's, S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > @@ -1390,6 +1404,7 @@ impl< self, ) -> QuerySortedManyIter< 'w, + 's, S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > @@ -1454,6 +1469,7 @@ impl< mut compare: impl FnMut(&L::Item<'_, '_>, &L::Item<'_, '_>) -> Ordering, ) -> QuerySortedManyIter< 'w, + 's, S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > { @@ -1483,6 +1499,7 @@ impl< mut compare: impl FnMut(&L::Item<'_, '_>, &L::Item<'_, '_>) -> Ordering, ) -> QuerySortedManyIter< 'w, + 's, S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > { @@ -1575,6 +1592,7 @@ impl< mut f: impl FnMut(&L::Item<'_, '_>) -> K, ) -> QuerySortedManyIter< 'w, + 's, S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > @@ -1605,6 +1623,7 @@ impl< mut f: impl FnMut(&L::Item<'_, '_>) -> K, ) -> QuerySortedManyIter< 'w, + 's, S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > @@ -1637,6 +1656,7 @@ impl< mut f: impl FnMut(&L::Item<'_, '_>) -> K, ) -> QuerySortedManyIter< 'w, + 's, S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > @@ -1664,6 +1684,7 @@ impl< f: impl FnOnce(&mut Vec<(L::Item<'_, '_>, NeutralOrd)>), ) -> QuerySortedManyIter< 'w, + 's, S, impl ExactSizeIterator + DoubleEndedIterator + FusedIterator + 'w, > { @@ -1706,10 +1727,11 @@ impl< impl< 'w, + 's, D: QueryData, - S: QueryStateDeref, + S: ConsumableQueryState<'s, Data = D>, I: DoubleEndedIterator, - > QueryManyIter<'w, S, I> + > QueryManyIter<'w, 's, S, I> { /// Get next result from the back of the query #[inline(always)] @@ -1736,10 +1758,11 @@ impl< impl< 'w, + 's, D: ReadOnlyQueryData, - S: QueryStateDeref, + S: ConsumableQueryState<'s, Data = D>, I: Iterator, - > Iterator for QueryManyIter<'w, S, I> + > Iterator for QueryManyIter<'w, 's, S, I> { type Item = D::Item<'w, 's>; @@ -1769,10 +1792,11 @@ impl< impl< 'w, + 's, D: ReadOnlyQueryData, - S: QueryStateDeref, + S: ConsumableQueryState<'s, Data = D>, I: DoubleEndedIterator, - > DoubleEndedIterator for QueryManyIter<'w, S, I> + > DoubleEndedIterator for QueryManyIter<'w, 's, S, I> { #[inline(always)] fn next_back(&mut self) -> Option { @@ -1794,22 +1818,27 @@ impl< } // This is correct as [`QueryManyIter`] always returns `None` once exhausted. -impl<'w, S: QueryStateDeref, I: Iterator> - FusedIterator for QueryManyIter<'w, S, I> +impl< + 'w, + 's, + S: ConsumableQueryState<'s, Data: ReadOnlyQueryData>, + I: Iterator, + > FusedIterator for QueryManyIter<'w, 's, S, I> { } // SAFETY: [`EntityEquivalentQueryData`] ensures that unique items return unique `Entity`s. unsafe impl< 'w, - S: QueryStateDeref, + 's, + S: ConsumableQueryState<'s, Data: EntityEquivalentQueryData + ReadOnlyQueryData>, I: EntitySetIterator, - > EntitySetIterator for QueryManyIter<'w, S, I> + > EntitySetIterator for QueryManyIter<'w, 's, S, I> { } -impl<'w, S: QueryStateDeref, I: Iterator> Debug - for QueryManyIter<'w, S, I> +impl<'w, 's, S: ConsumableQueryState<'s>, I: Iterator> Debug + for QueryManyIter<'w, 's, S, I> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QueryManyIter").finish() @@ -1829,12 +1858,12 @@ impl<'w, S: QueryStateDeref, I: Iterator> Debug /// [`iter_many_unique`]: crate::system::Query::iter_many /// [`iter_many_unique_mut`]: crate::system::Query::iter_many_mut /// [`Query`]: crate::system::Query -pub struct QueryManyUniqueIter<'w, S: QueryStateDeref, I: EntitySetIterator>( - QueryManyIter<'w, S, I>, +pub struct QueryManyUniqueIter<'w, 's, S: ConsumableQueryState<'s>, I: EntitySetIterator>( + QueryManyIter<'w, 's, S, I>, ); -impl<'w, D: QueryData, S: QueryStateDeref, I: EntitySetIterator> - QueryManyUniqueIter<'w, S, I> +impl<'w, 's, D: QueryData, S: ConsumableQueryState<'s, Data = D>, I: EntitySetIterator> + QueryManyUniqueIter<'w, 's, S, I> { /// # Safety /// - `world` must have permission to access any of the components registered in `query_state`. @@ -1856,8 +1885,8 @@ impl<'w, D: QueryData, S: QueryStateDeref, I: EntitySetIterator> } } -impl<'w, D: QueryData, S: QueryStateDeref, I: EntitySetIterator> Iterator - for QueryManyUniqueIter<'w, S, I> +impl<'w, 's, D: QueryData, S: ConsumableQueryState<'s, Data = D>, I: EntitySetIterator> Iterator + for QueryManyUniqueIter<'w, 's, S, I> { type Item = D::Item<'w, 's>; @@ -1865,7 +1894,7 @@ impl<'w, D: QueryData, S: QueryStateDeref, I: EntitySetIterator> Itera fn next(&mut self) -> Option { // SAFETY: Entities are guaranteed to be unique, thus do not alias. unsafe { - QueryManyIter::<'w, S, I>::fetch_next_aliased_unchecked( + QueryManyIter::<'w, 's, S, I>::fetch_next_aliased_unchecked( &mut self.0.entity_iter, self.0.entities, self.0.tables, @@ -1884,15 +1913,24 @@ impl<'w, D: QueryData, S: QueryStateDeref, I: EntitySetIterator> Itera } // This is correct as [`QueryManyIter`] always returns `None` once exhausted. -impl<'w, S: QueryStateDeref, I: EntitySetIterator> FusedIterator for QueryManyUniqueIter<'w, S, I> {} +impl<'w, 's, S: ConsumableQueryState<'s>, I: EntitySetIterator> FusedIterator + for QueryManyUniqueIter<'w, 's, S, I> +{ +} // SAFETY: [`EntityEquivalentQueryData`] ensures that unique items return unique `Entity`s. -unsafe impl<'w, S: QueryStateDeref, I: EntitySetIterator> - EntitySetIterator for QueryManyUniqueIter<'w, S, I> +unsafe impl< + 'w, + 's, + S: ConsumableQueryState<'s, Data: EntityEquivalentQueryData>, + I: EntitySetIterator, + > EntitySetIterator for QueryManyUniqueIter<'w, 's, S, I> { } -impl<'w, S: QueryStateDeref, I: EntitySetIterator> Debug for QueryManyUniqueIter<'w, S, I> { +impl<'w, 's, S: ConsumableQueryState<'s>, I: EntitySetIterator> Debug + for QueryManyUniqueIter<'w, 's, S, I> +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QueryManyUniqueIter").finish() } @@ -1903,17 +1941,18 @@ impl<'w, S: QueryStateDeref, I: EntitySetIterator> Debug for QueryManyUniqueIter /// This struct is created by the [`sort`](QueryManyIter), [`sort_unstable`](QueryManyIter), /// [`sort_by`](QueryManyIter), [`sort_unstable_by`](QueryManyIter), [`sort_by_key`](QueryManyIter), /// [`sort_unstable_by_key`](QueryManyIter), and [`sort_by_cached_key`](QueryManyIter) methods of [`QueryManyIter`]. -pub struct QuerySortedManyIter<'w, S: QueryStateDeref, I: Iterator> { +pub struct QuerySortedManyIter<'w, 's, S: ConsumableQueryState<'s>, I: Iterator> { entity_iter: I, entities: &'w Entities, tables: &'w Tables, archetypes: &'w Archetypes, fetch: ::Fetch<'w>, query_state: S, + marker: PhantomData<&'s ()>, } -impl<'w, D: QueryData, S: QueryStateDeref, I: Iterator> - QuerySortedManyIter<'w, S, I> +impl<'w, 's, D: QueryData, S: ConsumableQueryState<'s, Data = D>, I: Iterator> + QuerySortedManyIter<'w, 's, S, I> { /// # Safety /// - `world` must have permission to access any of the components registered in `query_state`. @@ -1925,10 +1964,11 @@ impl<'w, D: QueryData, S: QueryStateDeref, I: Iterator> entity_list: EntityList, last_run: Tick, this_run: Tick, - ) -> QuerySortedManyIter<'w, S, I> { + ) -> QuerySortedManyIter<'w, 's, S, I> { let fetch = D::init_fetch(world, &query_state.fetch_state, last_run, this_run); QuerySortedManyIter { query_state, + marker: PhantomData, entities: world.entities(), archetypes: world.archetypes(), // SAFETY: We only access table data that has been registered in `query_state`. @@ -1977,13 +2017,9 @@ impl<'w, D: QueryData, S: QueryStateDeref, I: Iterator> // - set_archetype was called prior, `location.archetype_row` is an archetype index in range of the current archetype // - fetch is only called once for each entity. unsafe { - D::fetch( - &self.query_state.fetch_state, - &mut self.fetch, - entity, - location.table_row, - ) - } + self.query_state + .fetch(&mut self.fetch, entity, location.table_row) + } } /// Get next result from the query @@ -2002,8 +2038,13 @@ impl<'w, D: QueryData, S: QueryStateDeref, I: Iterator> } } -impl<'w, D: QueryData, S: QueryStateDeref, I: DoubleEndedIterator> - QuerySortedManyIter<'w, S, I> +impl< + 'w, + 's, + D: QueryData, + S: ConsumableQueryState<'s, Data = D>, + I: DoubleEndedIterator, + > QuerySortedManyIter<'w, 's, S, I> { /// Get next result from the query #[inline(always)] @@ -2021,8 +2062,13 @@ impl<'w, D: QueryData, S: QueryStateDeref, I: DoubleEndedIterator, I: Iterator> Iterator - for QuerySortedManyIter<'w, S, I> +impl< + 'w, + 's, + D: ReadOnlyQueryData, + S: ConsumableQueryState<'s, Data = D>, + I: Iterator, + > Iterator for QuerySortedManyIter<'w, 's, S, I> { type Item = D::Item<'w, 's>; @@ -2040,8 +2086,12 @@ impl<'w, D: ReadOnlyQueryData, S: QueryStateDeref, I: Iterator, I: DoubleEndedIterator> - DoubleEndedIterator for QuerySortedManyIter<'w, S, I> +impl< + 'w, + 's, + S: ConsumableQueryState<'s, Data: ReadOnlyQueryData>, + I: DoubleEndedIterator, + > DoubleEndedIterator for QuerySortedManyIter<'w, 's, S, I> { #[inline(always)] fn next_back(&mut self) -> Option { @@ -2053,12 +2103,18 @@ impl<'w, S: QueryStateDeref, I: DoubleEndedIterator, I: ExactSizeIterator> - ExactSizeIterator for QuerySortedManyIter<'w, S, I> +impl< + 'w, + 's, + S: ConsumableQueryState<'s, Data: ReadOnlyQueryData>, + I: ExactSizeIterator, + > ExactSizeIterator for QuerySortedManyIter<'w, 's, S, I> { } -impl<'w, S: QueryStateDeref, I: Iterator> Debug for QuerySortedManyIter<'w, S, I> { +impl<'w, 's, S: ConsumableQueryState<'s>, I: Iterator> Debug + for QuerySortedManyIter<'w, 's, S, I> +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QuerySortedManyIter").finish() } @@ -2127,15 +2183,15 @@ impl<'w, S: QueryStateDeref, I: Iterator> Debug for QuerySortedMa /// [`Query`]: crate::system::Query /// [`Query::iter_combinations`]: crate::system::Query::iter_combinations /// [`Query::iter_combinations_mut`]: crate::system::Query::iter_combinations_mut -pub struct QueryCombinationIter<'w, S: QueryStateDeref, const K: usize> { +pub struct QueryCombinationIter<'w, 's, S: ConsumableQueryState<'s>, const K: usize> { tables: &'w Tables, archetypes: &'w Archetypes, query_state: S, - cursors: [QueryIterationCursor<'w, S>; K], + cursors: [QueryIterationCursor<'w, 's, S>; K], } -impl<'w, D: QueryData, S: QueryStateDeref, const K: usize> - QueryCombinationIter<'w, S, K> +impl<'w, 's, D: QueryData, S: ConsumableQueryState<'s, Data = D>, const K: usize> + QueryCombinationIter<'w, 's, S, K> { /// # Safety /// - `world` must have permission to access any of the components registered in `query_state`. @@ -2150,8 +2206,8 @@ impl<'w, D: QueryData, S: QueryStateDeref, const K: usize> // Initialize array with cursors. // There is no FromIterator on arrays, so instead initialize it manually with MaybeUninit - let mut array: MaybeUninit<[QueryIterationCursor<'w, S>; K]> = MaybeUninit::uninit(); - let ptr = array.as_mut_ptr().cast::>(); + let mut array: MaybeUninit<[QueryIterationCursor<'w, 's, S>; K]> = MaybeUninit::uninit(); + let ptr = array.as_mut_ptr().cast::>(); ptr.write(QueryIterationCursor::init( world, &query_state, @@ -2215,7 +2271,7 @@ impl<'w, D: QueryData, S: QueryStateDeref, const K: usize> let ptr = values.as_mut_ptr().cast::>(); for (offset, cursor) in self.cursors.iter_mut().enumerate() { ptr.add(offset) - .write(cursor.peek_last(self.query_state).unwrap()); + .write(cursor.peek_last(&self.query_state).unwrap()); } Some(values.assume_init()) @@ -2239,11 +2295,12 @@ impl<'w, D: QueryData, S: QueryStateDeref, const K: usize> // multiple times would allow multiple owned references to the same data to exist. impl< 'w, + 's, D: ReadOnlyQueryData, F: QueryFilter, - S: QueryStateDeref, + S: ConsumableQueryState<'s, Data = D, Filter = F>, const K: usize, - > Iterator for QueryCombinationIter<'w, S, K> + > Iterator for QueryCombinationIter<'w, 's, S, K> { type Item = [D::Item<'w, 's>; K]; @@ -2285,7 +2342,7 @@ impl< } } -impl<'w, S: QueryStateDeref> ExactSizeIterator for QueryIter<'w, S> +impl<'w, 's, S: ConsumableQueryState<'s>> ExactSizeIterator for QueryIter<'w, 's, S> where S::Filter: ArchetypeFilter, { @@ -2295,18 +2352,20 @@ where } // This is correct as [`QueryCombinationIter`] always returns `None` once exhausted. -impl<'w, S: QueryStateDeref, const K: usize> FusedIterator - for QueryCombinationIter<'w, S, K> +impl<'w, 's, S: ConsumableQueryState<'s, Data: ReadOnlyQueryData>, const K: usize> FusedIterator + for QueryCombinationIter<'w, 's, S, K> { } -impl<'w, S: QueryStateDeref, const K: usize> Debug for QueryCombinationIter<'w, S, K> { +impl<'w, 's, S: ConsumableQueryState<'s>, const K: usize> Debug + for QueryCombinationIter<'w, 's, S, K> +{ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("QueryCombinationIter").finish() } } -struct QueryIterationCursor<'w, S: QueryStateDeref> { +struct QueryIterationCursor<'w, 's, S: ConsumableQueryState<'s>> { // whether the query iteration is dense or not. Mirrors QueryState's `is_dense` field. is_dense: bool, storage_id_iter: S::StorageIter, @@ -2320,7 +2379,7 @@ struct QueryIterationCursor<'w, S: QueryStateDeref> { current_row: u32, } -impl Clone for QueryIterationCursor<'_, S> { +impl<'s, S: ConsumableQueryState<'s>> Clone for QueryIterationCursor<'_, 's, S> { fn clone(&self) -> Self { Self { is_dense: self.is_dense, @@ -2335,8 +2394,8 @@ impl Clone for QueryIterationCursor<'_, S> { } } -impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> - QueryIterationCursor<'w, S> +impl<'w, 's, D: QueryData, F: QueryFilter, S: ConsumableQueryState<'s, Data = D, Filter = F>> + QueryIterationCursor<'w, 's, S> { /// # Safety /// - `world` must have permission to access any of the components registered in `query_state`. @@ -2376,7 +2435,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> } } - fn reborrow(&mut self) -> QueryIterationCursor<'_, &'_ QueryState> { + fn reborrow(&mut self) -> QueryIterationCursor<'_, '_, &'_ QueryState> { QueryIterationCursor { is_dense: self.is_dense, fetch: D::shrink_fetch(self.fetch.clone()), @@ -2395,7 +2454,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> /// 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, query_state: &'s QueryState) -> Option> { + unsafe fn peek_last(&mut self, query_state: &S) -> Option> { if self.current_row > 0 { let index = self.current_row - 1; if self.is_dense { @@ -2405,8 +2464,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> // - `set_table` must have been called previously either in `next` or before it. // - `*entity` and `index` are in the current table. unsafe { - Some(D::fetch( - &query_state.fetch_state, + Some(query_state.fetch( &mut self.fetch, *entity, // SAFETY: This is from an exclusive range, so it can't be max. @@ -2421,8 +2479,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> // - `set_archetype` must have been called previously either in `next` or before it. // - `archetype_entity.id()` and `archetype_entity.table_row()` are in the current archetype. unsafe { - Some(D::fetch( - &query_state.fetch_state, + Some(query_state.fetch( &mut self.fetch, archetype_entity.id(), archetype_entity.table_row(), @@ -2463,7 +2520,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> &mut self, tables: &'w Tables, archetypes: &'w Archetypes, - query_state: &QueryState, + query_state: &S, ) -> Option> { if self.is_dense { loop { @@ -2501,8 +2558,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> // - `current_row` must be a table row in range of the current table, // because if it was not, then the above would have been executed. // - fetch is only called once for each `entity`. - let item = - unsafe { D::fetch(&query_state.fetch_state, &mut self.fetch, *entity, row) }; + let item = unsafe { query_state.fetch(&mut self.fetch, *entity, row) }; self.current_row += 1; return Some(item); @@ -2559,8 +2615,7 @@ impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> // because if it was not, then the if above would have been executed. // - fetch is only called once for each `archetype_entity`. let item = unsafe { - D::fetch( - &query_state.fetch_state, + query_state.fetch( &mut self.fetch, archetype_entity.id(), archetype_entity.table_row(), diff --git a/crates/bevy_ecs/src/query/par_iter.rs b/crates/bevy_ecs/src/query/par_iter.rs index 58a912678b50a..a2cdf32196b4f 100644 --- a/crates/bevy_ecs/src/query/par_iter.rs +++ b/crates/bevy_ecs/src/query/par_iter.rs @@ -1,3 +1,5 @@ +use core::marker::PhantomData; + use crate::{ batching::BatchingStrategy, component::Tick, @@ -5,7 +7,7 @@ use crate::{ world::unsafe_world_cell::UnsafeWorldCell, }; -use super::{QueryData, QueryItem, QueryStateDeref, ReadOnlyQueryData}; +use super::{ConsumableQueryState, QueryData, QueryItem, ReadOnlyQueryData}; use alloc::vec::Vec; @@ -13,15 +15,16 @@ use alloc::vec::Vec; /// /// This struct is created by the [`Query::par_iter`](crate::system::Query::par_iter) and /// [`Query::par_iter_mut`](crate::system::Query::par_iter_mut) methods. -pub struct QueryParIter<'w, S: QueryStateDeref> { +pub struct QueryParIter<'w, 's, S: ConsumableQueryState<'s>> { pub(crate) world: UnsafeWorldCell<'w>, pub(crate) state: S, + pub(crate) marker: PhantomData<&'s ()>, pub(crate) last_run: Tick, pub(crate) this_run: Tick, pub(crate) batching_strategy: BatchingStrategy, } -impl<'w, D: QueryData, S: QueryStateDeref> QueryParIter<'w, S> { +impl<'w, 's, D: QueryData, S: ConsumableQueryState<'s, Data = D>> QueryParIter<'w, 's, S> { /// Changes the batching strategy used when iterating. /// /// For more information on how this affects the resultant iteration, see @@ -39,7 +42,7 @@ impl<'w, D: QueryData, S: QueryStateDeref> QueryParIter<'w, S> { /// /// [`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)); } @@ -76,7 +79,7 @@ impl<'w, D: QueryData, S: QueryStateDeref> QueryParIter<'w, S> { #[inline] pub fn for_each_init(self, init: INIT, func: FN) where - FN: Fn(&mut T, QueryItem<'w, 's, D>) + Send + Sync + Clone, + FN: Fn(&mut T, QueryItem<'w, '_, D>) + Send + Sync + Clone, INIT: Fn() -> T + Sync + Send + Clone, { let func = |mut init, item| { @@ -161,17 +164,23 @@ impl<'w, D: QueryData, S: QueryStateDeref> QueryParIter<'w, S> { /// /// [`Entity`]: crate::entity::Entity /// [`Query::par_iter_many`]: crate::system::Query::par_iter_many -pub struct QueryParManyIter<'w, S: QueryStateDeref, E: EntityEquivalent> { +pub struct QueryParManyIter<'w, 's, S: ConsumableQueryState<'s>, E: EntityEquivalent> { pub(crate) world: UnsafeWorldCell<'w>, pub(crate) state: S, + pub(crate) marker: PhantomData<&'s ()>, pub(crate) entity_list: Vec, pub(crate) last_run: Tick, pub(crate) this_run: Tick, pub(crate) batching_strategy: BatchingStrategy, } -impl<'w, D: ReadOnlyQueryData, S: QueryStateDeref, E: EntityEquivalent + Sync> - QueryParManyIter<'w, S, E> +impl< + 'w, + 's, + D: ReadOnlyQueryData, + S: ConsumableQueryState<'s, Data = D>, + E: EntityEquivalent + Sync, + > QueryParManyIter<'w, 's, S, E> { /// Changes the batching strategy used when iterating. /// @@ -190,7 +199,7 @@ impl<'w, D: ReadOnlyQueryData, S: QueryStateDeref, E: EntityEquivalent /// /// [`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)); } @@ -247,7 +256,7 @@ impl<'w, D: ReadOnlyQueryData, S: QueryStateDeref, E: EntityEquivalent #[inline] pub fn for_each_init(self, init: INIT, func: FN) where - FN: Fn(&mut T, QueryItem<'w, 's, D>) + Send + Sync + Clone, + FN: Fn(&mut T, QueryItem<'w, '_, D>) + Send + Sync + Clone, INIT: Fn() -> T + Sync + Send + Clone, { let func = |mut init, item| { @@ -315,17 +324,18 @@ impl<'w, D: ReadOnlyQueryData, S: QueryStateDeref, E: EntityEquivalent /// [`EntitySet`]: crate::entity::EntitySet /// [`Query::par_iter_many_unique`]: crate::system::Query::par_iter_many_unique /// [`Query::par_iter_many_unique_mut`]: crate::system::Query::par_iter_many_unique_mut -pub struct QueryParManyUniqueIter<'w, S: QueryStateDeref, E: EntityEquivalent + Sync> { +pub struct QueryParManyUniqueIter<'w, 's, S: ConsumableQueryState<'s>, E: EntityEquivalent + Sync> { pub(crate) world: UnsafeWorldCell<'w>, pub(crate) state: S, + pub(crate) marker: PhantomData<&'s ()>, pub(crate) entity_list: UniqueEntityEquivalentVec, pub(crate) last_run: Tick, pub(crate) this_run: Tick, pub(crate) batching_strategy: BatchingStrategy, } -impl<'w, D: QueryData, S: QueryStateDeref, E: EntityEquivalent + Sync> - QueryParManyUniqueIter<'w, S, E> +impl<'w, 's, D: QueryData, S: ConsumableQueryState<'s, Data = D>, E: EntityEquivalent + Sync> + QueryParManyUniqueIter<'w, 's, S, E> { /// Changes the batching strategy used when iterating. /// @@ -344,7 +354,7 @@ impl<'w, D: QueryData, S: QueryStateDeref, E: EntityEquivalent + 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)); } @@ -401,7 +411,7 @@ impl<'w, D: QueryData, S: QueryStateDeref, E: EntityEquivalent + Sync> #[inline] pub fn for_each_init(self, init: INIT, func: FN) where - FN: Fn(&mut T, QueryItem<'w, 's, D>) + Send + Sync + Clone, + FN: Fn(&mut T, QueryItem<'w, '_, 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 6fe14c5b97568..28f67b34bfa79 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -5,7 +5,7 @@ use crate::{ entity_disabling::DefaultQueryFilters, prelude::FromWorld, query::{FilteredAccess, QueryCombinationIter, QueryIter, QueryParIter, WorldQuery}, - storage::{SparseSetIndex, TableId}, + storage::{SparseSetIndex, TableId, TableRow}, system::Query, world::{unsafe_world_cell::UnsafeWorldCell, World, WorldId}, }; @@ -23,7 +23,7 @@ use tracing::Span; use super::{ NopWorldQuery, QueryBuilder, QueryData, QueryEntityError, QueryFilter, QueryManyIter, - QueryManyUniqueIter, QuerySingleError, ROQueryItem, ReadOnlyQueryData, + QueryManyUniqueIter, QuerySingleError, ROQueryItem, ReadOnlyQueryData, ReleaseStateQueryData, }; /// An ID for either a table or an archetype. Used for Query iteration. @@ -88,12 +88,12 @@ pub struct QueryState { par_iter_span: Span, } -/// Abstracts over an owned or borrowed [`QueryState`]. +/// An owned or borrowed [`QueryState`] that can be consumed to query. /// -/// # Safety -/// -/// This must `deref` to a `QueryState` that does not change. -pub unsafe trait QueryStateDeref: +/// A borrowed `&QueryState` can always be consumed, +/// but an owned `Box` cannot be used +/// if the query data needs to borrow from the state. +pub trait ConsumableQueryState<'state>: Deref> { /// The [`QueryData`] for this `QueryState`. @@ -106,7 +106,8 @@ pub unsafe trait QueryStateDeref: type StorageIter: Iterator + Clone + Default; /// A read-only version of the state. - type ReadOnly: QueryStateDeref< + type ReadOnly: ConsumableQueryState< + 'state, Data = ::ReadOnly, Filter = Self::Filter, >; @@ -122,10 +123,27 @@ pub unsafe trait QueryStateDeref: /// Converts this state to a read-only version. fn into_readonly(self) -> Self::ReadOnly; + + /// Calls [`QueryData::fetch`] with the provided parameters, + /// adjusting the `'state` lifetime as necessary. + /// + /// # Safety + /// + /// It must be safe to call [`QueryData::fetch`], meaning: + /// - 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. + /// - There must not be simultaneous conflicting component access registered in `update_component_access`. + unsafe fn fetch<'w>( + &self, + fetch: &mut ::Fetch<'w>, + entity: Entity, + table_row: TableRow, + ) -> ::Item<'w, 'state>; } -/// SAFETY: The `QueryState` is owned and cannot change -unsafe impl QueryStateDeref for Box> { +impl, F: QueryFilter> + ConsumableQueryState<'static> for Box> +{ type Data = D; type Filter = F; type StorageIter = vec::IntoIter; @@ -147,10 +165,19 @@ unsafe impl QueryStateDeref for Box Self::ReadOnly { self.into_readonly() } + + unsafe fn fetch<'w>( + &self, + fetch: &mut ::Fetch<'w>, + entity: Entity, + table_row: TableRow, + ) -> ::Item<'w, 'static> { + // SAFETY: Caller ensures it is safe to call `QueryData::Fetch` + D::release_state(unsafe { D::fetch(&self.fetch_state, fetch, entity, table_row) }) + } } -/// SAFETY: The `QueryState` is borrowed for the life of the reference and cannot change -unsafe impl<'s, D: QueryData, F: QueryFilter> QueryStateDeref for &'s QueryState { +impl<'s, D: QueryData, F: QueryFilter> ConsumableQueryState<'s> for &'s QueryState { type Data = D; type Filter = F; type StorageIter = iter::Copied>; @@ -169,6 +196,16 @@ unsafe impl<'s, D: QueryData, F: QueryFilter> QueryStateDeref for &'s QueryState fn into_readonly(self) -> Self::ReadOnly { self.as_readonly() } + + unsafe fn fetch<'w>( + &self, + fetch: &mut ::Fetch<'w>, + entity: Entity, + table_row: TableRow, + ) -> ::Item<'w, 's> { + // SAFETY: Caller ensures it is safe to call `QueryData::Fetch` + unsafe { D::fetch(&self.fetch_state, fetch, entity, table_row) } + } } impl fmt::Debug for QueryState { @@ -1200,7 +1237,7 @@ impl QueryState { pub fn iter<'w, 's>( &'s mut self, world: &'w World, - ) -> QueryIter<'w, &'s QueryState> { + ) -> QueryIter<'w, 's, &'s QueryState> { self.query(world).into_iter() } @@ -1209,7 +1246,7 @@ impl QueryState { /// This iterator is always guaranteed to return results from each matching entity once and only once. /// Iteration order is not guaranteed. #[inline] - pub fn iter_mut<'w, 's>(&'s mut self, world: &'w mut World) -> QueryIter<'w, &'s Self> { + pub fn iter_mut<'w, 's>(&'s mut self, world: &'w mut World) -> QueryIter<'w, 's, &'s Self> { self.query_mut(world).into_iter() } @@ -1224,7 +1261,7 @@ impl QueryState { pub fn iter_manual<'w, 's>( &'s self, world: &'w World, - ) -> QueryIter<'w, &'s QueryState> { + ) -> QueryIter<'w, 's, &'s QueryState> { self.query_manual(world).into_iter() } @@ -1256,7 +1293,7 @@ impl QueryState { pub fn iter_combinations<'w, 's, const K: usize>( &'s mut self, world: &'w World, - ) -> QueryCombinationIter<'w, &'s QueryState, K> { + ) -> QueryCombinationIter<'w, 's, &'s QueryState, K> { self.query(world).iter_combinations_inner() } @@ -1281,7 +1318,7 @@ impl QueryState { pub fn iter_combinations_mut<'w, 's, const K: usize>( &'s mut self, world: &'w mut World, - ) -> QueryCombinationIter<'w, &'s Self, K> { + ) -> QueryCombinationIter<'w, 's, &'s Self, K> { self.query_mut(world).iter_combinations_inner() } @@ -1301,7 +1338,7 @@ impl QueryState { &'s mut self, world: &'w World, entities: EntityList, - ) -> QueryManyIter<'w, &'s QueryState, EntityList::IntoIter> { + ) -> QueryManyIter<'w, 's, &'s QueryState, EntityList::IntoIter> { self.query(world).iter_many_inner(entities) } @@ -1324,7 +1361,7 @@ impl QueryState { &'s self, world: &'w World, entities: EntityList, - ) -> QueryManyIter<'w, &'s QueryState, EntityList::IntoIter> { + ) -> QueryManyIter<'w, 's, &'s QueryState, EntityList::IntoIter> { self.query_manual(world).iter_many_inner(entities) } @@ -1337,7 +1374,7 @@ impl QueryState { &'s mut self, world: &'w mut World, entities: EntityList, - ) -> QueryManyIter<'w, &'s Self, EntityList::IntoIter> { + ) -> QueryManyIter<'w, 's, &'s Self, EntityList::IntoIter> { self.query_mut(world).iter_many_inner(entities) } @@ -1354,7 +1391,7 @@ impl QueryState { &'s mut self, world: &'w World, entities: EntityList, - ) -> QueryManyUniqueIter<'w, &'s QueryState, EntityList::IntoIter> { + ) -> QueryManyUniqueIter<'w, 's, &'s QueryState, EntityList::IntoIter> { self.query(world).iter_many_unique_inner(entities) } @@ -1378,7 +1415,7 @@ impl QueryState { &'s self, world: &'w World, entities: EntityList, - ) -> QueryManyUniqueIter<'w, &'s QueryState, EntityList::IntoIter> { + ) -> QueryManyUniqueIter<'w, 's, &'s QueryState, EntityList::IntoIter> { self.query_manual(world).iter_many_unique_inner(entities) } @@ -1391,7 +1428,7 @@ impl QueryState { &'s mut self, world: &'w mut World, entities: EntityList, - ) -> QueryManyUniqueIter<'w, &'s Self, EntityList::IntoIter> { + ) -> QueryManyUniqueIter<'w, 's, &'s Self, EntityList::IntoIter> { self.query_mut(world).iter_many_unique_inner(entities) } /// Returns an [`Iterator`] over the query results for the given [`World`]. @@ -1407,7 +1444,7 @@ impl QueryState { pub unsafe fn iter_unchecked<'w, 's>( &'s mut self, world: UnsafeWorldCell<'w>, - ) -> QueryIter<'w, &'s Self> { + ) -> QueryIter<'w, 's, &'s Self> { self.query_unchecked(world).into_iter() } @@ -1426,7 +1463,7 @@ impl QueryState { pub unsafe fn iter_combinations_unchecked<'w, 's, const K: usize>( &'s mut self, world: UnsafeWorldCell<'w>, - ) -> QueryCombinationIter<'w, &'s Self, K> { + ) -> QueryCombinationIter<'w, 's, &'s Self, K> { self.query_unchecked(world).iter_combinations_inner() } @@ -1442,7 +1479,7 @@ impl QueryState { pub fn par_iter<'w, 's>( &'s mut self, world: &'w World, - ) -> QueryParIter<'w, &'s QueryState> { + ) -> QueryParIter<'w, 's, &'s QueryState> { self.query(world).par_iter_inner() } @@ -1491,7 +1528,10 @@ impl QueryState { /// [`par_iter`]: Self::par_iter /// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool #[inline] - pub fn par_iter_mut<'w, 's>(&'s mut self, world: &'w mut World) -> QueryParIter<'w, &'s Self> { + pub fn par_iter_mut<'w, 's>( + &'s mut self, + world: &'w mut World, + ) -> QueryParIter<'w, 's, &'s Self> { self.query_mut(world).par_iter_inner() } diff --git a/crates/bevy_ecs/src/relationship/relationship_query.rs b/crates/bevy_ecs/src/relationship/relationship_query.rs index 0caf6b7fdee6a..d6827b4c94688 100644 --- a/crates/bevy_ecs/src/relationship/relationship_query.rs +++ b/crates/bevy_ecs/src/relationship/relationship_query.rs @@ -1,6 +1,8 @@ +use core::ops::Deref; + use crate::{ entity::Entity, - query::{QueryData, QueryStateDeref}, + query::{QueryData, QueryFilter, QueryState}, relationship::{Relationship, RelationshipTarget}, system::Query, }; @@ -9,12 +11,14 @@ use smallvec::SmallVec; use super::SourceIter; -impl<'w, 's, D: QueryData, S: QueryStateDeref> Query<'w, 's, D, S::Filter, S> { +impl<'w, 's, D: QueryData, F: QueryFilter, S: Deref>> + Query<'w, 's, D, F, S> +{ /// If the given `entity` contains the `R` [`Relationship`] component, returns the /// target entity of that relationship. pub fn related(&'w self, entity: Entity) -> Option where - ::ReadOnly: QueryData = &'w R>, + D::ReadOnly: QueryData = &'w R>, { self.get(entity).map(R::get).ok() } @@ -26,7 +30,7 @@ impl<'w, 's, D: QueryData, S: QueryStateDeref> Query<'w, 's, D, S::Fil entity: Entity, ) -> impl Iterator + 'w where - ::ReadOnly: QueryData = &'w R>, + D::ReadOnly: QueryData = &'w R>, { self.get(entity) .into_iter() @@ -42,7 +46,7 @@ impl<'w, 's, D: QueryData, S: QueryStateDeref> Query<'w, 's, D, S::Fil /// 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: QueryData = &'w R>, + D::ReadOnly: QueryData = &'w R>, { // Recursively search up the tree until we're out of parents match self.get(entity) { @@ -60,9 +64,9 @@ impl<'w, 's, D: QueryData, S: QueryStateDeref> Query<'w, 's, D, S::Fil pub fn iter_leaves( &'w self, entity: Entity, - ) -> impl Iterator + use<'w, 's, S, D, F> + ) -> impl Iterator + use<'w, 's, D, F, S, R> where - ::ReadOnly: QueryData = &'w R>, + D::ReadOnly: QueryData = &'w R>, SourceIter<'w, R>: DoubleEndedIterator, { self.iter_descendants_depth_first(entity).filter(|entity| { @@ -80,7 +84,7 @@ impl<'w, 's, D: QueryData, S: QueryStateDeref> Query<'w, 's, D, S::Fil entity: Entity, ) -> impl Iterator + 'w where - D::ReadOnly: QueryData = (Option<&'w R>, Option<&'w R::RelationshipTarget>)>, + D::ReadOnly: QueryData = (Option<&'w R>, Option<&'w R::RelationshipTarget>)>, { self.get(entity) .ok() @@ -101,9 +105,9 @@ impl<'w, 's, D: QueryData, S: QueryStateDeref> Query<'w, 's, D, S::Fil pub fn iter_descendants( &'w self, entity: Entity, - ) -> DescendantIter<'w, 's, S, R> + ) -> DescendantIter<'w, 's, D, F, S, R> where - D::ReadOnly: QueryData = &'w R>, + D::ReadOnly: QueryData = &'w R>, { DescendantIter::new(self, entity) } @@ -118,9 +122,9 @@ impl<'w, 's, D: QueryData, S: QueryStateDeref> Query<'w, 's, D, S::Fil pub fn iter_descendants_depth_first( &'w self, entity: Entity, - ) -> DescendantDepthFirstIter<'w, 's, S, R> + ) -> DescendantDepthFirstIter<'w, 's, D, F, S, R> where - D::ReadOnly: QueryData = &'w R>, + D::ReadOnly: QueryData = &'w R>, SourceIter<'w, R>: DoubleEndedIterator, { DescendantDepthFirstIter::new(self, entity) @@ -132,9 +136,12 @@ impl<'w, 's, D: QueryData, S: QueryStateDeref> Query<'w, 's, D, S::Fil /// /// For relationship graphs that contain loops, this could loop infinitely. /// If your relationship is not a tree (like Bevy's hierarchy), be sure to stop if you encounter a duplicate entity. - pub fn iter_ancestors(&'w self, entity: Entity) -> AncestorIter<'w, 's, S, R> + pub fn iter_ancestors( + &'w self, + entity: Entity, + ) -> AncestorIter<'w, 's, D, F, S, R> where - D::ReadOnly: QueryData = &'w R>, + D::ReadOnly: QueryData = &'w R>, { AncestorIter::new(self, entity) } @@ -143,20 +150,33 @@ impl<'w, 's, D: QueryData, S: QueryStateDeref> Query<'w, 's, D, S::Fil /// An [`Iterator`] of [`Entity`]s over the descendants of an [`Entity`]. /// /// Traverses the hierarchy breadth-first. -pub struct DescendantIter<'w, 's, S: QueryStateDeref, R: RelationshipTarget> -where - ::ReadOnly: QueryData = &'w R>, +pub struct DescendantIter< + 'w, + 's, + D: QueryData, + F: QueryFilter, + S: Deref>, + R: RelationshipTarget, +> where + D::ReadOnly: QueryData = &'w R>, { - children_query: &'w Query<'w, 's, S::Data, S::Filter, S>, + children_query: &'w Query<'w, 's, D, F, S>, vecdeque: VecDeque, } -impl<'w, 's, S: QueryStateDeref, R: RelationshipTarget> DescendantIter<'w, 's, S, R> +impl< + 'w, + 's, + D: QueryData, + F: QueryFilter, + S: Deref>, + R: RelationshipTarget, + > DescendantIter<'w, 's, D, F, S, R> where - ::ReadOnly: QueryData = &'w R>, + D::ReadOnly: QueryData = &'w R>, { /// Returns a new [`DescendantIter`]. - pub fn new(children_query: &'w Query<'w, 's, S::Data, S::Filter, S>, entity: Entity) -> Self { + pub fn new(children_query: &'w Query<'w, 's, D, F, S>, entity: Entity) -> Self { DescendantIter { children_query, vecdeque: children_query @@ -168,9 +188,16 @@ where } } -impl<'w, 's, S: QueryStateDeref, R: RelationshipTarget> Iterator for DescendantIter<'w, 's, S, R> +impl< + 'w, + 's, + D: QueryData, + F: QueryFilter, + S: Deref>, + R: RelationshipTarget, + > Iterator for DescendantIter<'w, 's, D, F, S, R> where - ::ReadOnly: QueryData = &'w R>, + D::ReadOnly: QueryData = &'w R>, { type Item = Entity; @@ -188,21 +215,34 @@ where /// An [`Iterator`] of [`Entity`]s over the descendants of an [`Entity`]. /// /// Traverses the hierarchy depth-first. -pub struct DescendantDepthFirstIter<'w, 's, S: QueryStateDeref, R: RelationshipTarget> -where - ::ReadOnly: QueryData = &'w R>, +pub struct DescendantDepthFirstIter< + 'w, + 's, + D: QueryData, + F: QueryFilter, + S: Deref>, + R: RelationshipTarget, +> where + D::ReadOnly: QueryData = &'w R>, { - children_query: &'w Query<'w, 's, S::Data, S::Filter, S>, + children_query: &'w Query<'w, 's, D, F, S>, stack: SmallVec<[Entity; 8]>, } -impl<'w, 's, S: QueryStateDeref, R: RelationshipTarget> DescendantDepthFirstIter<'w, 's, S, R> +impl< + 'w, + 's, + D: QueryData, + F: QueryFilter, + S: Deref>, + R: RelationshipTarget, + > DescendantDepthFirstIter<'w, 's, D, F, S, R> where - ::ReadOnly: QueryData = &'w R>, + D::ReadOnly: QueryData = &'w R>, SourceIter<'w, R>: DoubleEndedIterator, { /// Returns a new [`DescendantDepthFirstIter`]. - pub fn new(children_query: &'w Query<'w, 's, S::Data, S::Filter, S>, entity: Entity) -> Self { + pub fn new(children_query: &'w Query<'w, 's, D, F, S>, entity: Entity) -> Self { DescendantDepthFirstIter { children_query, stack: children_query @@ -212,10 +252,16 @@ where } } -impl<'w, 's, S: QueryStateDeref, R: RelationshipTarget> Iterator - for DescendantDepthFirstIter<'w, 's, S, R> +impl< + 'w, + 's, + D: QueryData, + F: QueryFilter, + S: Deref>, + R: RelationshipTarget, + > Iterator for DescendantDepthFirstIter<'w, 's, D, F, S, R> where - ::ReadOnly: QueryData = &'w R>, + D::ReadOnly: QueryData = &'w R>, SourceIter<'w, R>: DoubleEndedIterator, { type Item = Entity; @@ -232,20 +278,33 @@ where } /// An [`Iterator`] of [`Entity`]s over the ancestors of an [`Entity`]. -pub struct AncestorIter<'w, 's, S: QueryStateDeref, R: Relationship> -where - ::ReadOnly: QueryData = &'w R>, +pub struct AncestorIter< + 'w, + 's, + D: QueryData, + F: QueryFilter, + S: Deref>, + R: Relationship, +> where + D::ReadOnly: QueryData = &'w R>, { - parent_query: &'w Query<'w, 's, S::Data, S::Filter, S>, + parent_query: &'w Query<'w, 's, D, F, S>, next: Option, } -impl<'w, 's, S: QueryStateDeref, R: Relationship> AncestorIter<'w, 's, S, R> +impl< + 'w, + 's, + D: QueryData, + F: QueryFilter, + S: Deref>, + R: Relationship, + > AncestorIter<'w, 's, D, F, S, R> where - ::ReadOnly: QueryData = &'w R>, + D::ReadOnly: QueryData = &'w R>, { /// Returns a new [`AncestorIter`]. - pub fn new(parent_query: &'w Query<'w, 's, S::Data, S::Filter, S>, entity: Entity) -> Self { + pub fn new(parent_query: &'w Query<'w, 's, D, F, S>, entity: Entity) -> Self { AncestorIter { parent_query, next: Some(entity), @@ -253,9 +312,16 @@ where } } -impl<'w, 's, S: QueryStateDeref, R: Relationship> Iterator for AncestorIter<'w, 's, S, R> +impl< + 'w, + 's, + D: QueryData, + F: QueryFilter, + S: Deref>, + R: Relationship, + > Iterator for AncestorIter<'w, 's, D, F, S, R> where - ::ReadOnly: QueryData = &'w R>, + D::ReadOnly: QueryData = &'w R>, { type Item = Entity; diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 4120f568c40a6..6eeed0c9db91e 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -3,9 +3,9 @@ use crate::{ component::Tick, entity::{Entity, EntityDoesNotExistError, EntityEquivalent, EntitySet, UniqueEntityArray}, query::{ - DebugCheckedUnwrap, NopWorldQuery, QueryCombinationIter, QueryData, QueryEntityError, - QueryFilter, QueryIter, QueryManyIter, QueryManyUniqueIter, QueryParIter, QueryParManyIter, - QueryParManyUniqueIter, QuerySingleError, QueryState, QueryStateDeref, ROQueryItem, + ConsumableQueryState, DebugCheckedUnwrap, NopWorldQuery, QueryCombinationIter, QueryData, + QueryEntityError, QueryFilter, QueryIter, QueryManyIter, QueryManyUniqueIter, QueryParIter, + QueryParManyIter, QueryParManyUniqueIter, QuerySingleError, QueryState, ROQueryItem, ReadOnlyQueryData, }, world::unsafe_world_cell::UnsafeWorldCell, @@ -489,14 +489,16 @@ pub struct Query< 'state, D: QueryData, F: QueryFilter = (), - S: QueryStateDeref = &'state QueryState, + S: Deref> = &'state QueryState, > { // SAFETY: Must have access to the components registered in `state`. world: UnsafeWorldCell<'world>, state: S, last_run: Tick, this_run: Tick, - marker: PhantomData<&'state QueryState>, + // Note that `&'state QueryState` won't work because + // `QueryLens` uses `'static`, but `D` and `F` might not be `'static`. + marker: PhantomData<(&'state (), fn() -> QueryState)>, } impl Clone for Query<'_, '_, D, F> { @@ -519,7 +521,7 @@ impl core::fmt::Debug for Query<'_, '_, D, F> { } } -impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref> +impl<'w, 's, D: QueryData, F: QueryFilter, S: Deref>> Query<'w, 's, D, F, S> { /// Creates a new query. @@ -581,7 +583,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref Query<'w, 's, D::ReadOnly, F, S::ReadOnly> { + pub fn into_readonly(self) -> Query<'w, 's, D::ReadOnly, F, S::ReadOnly> + where + S: ConsumableQueryState<'s, Data = D, Filter = F>, + { let new_state = self.state.into_readonly(); // SAFETY: // - This is memory safe because it turns the query immutable. @@ -631,24 +636,6 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref Query<'_, '_, D, F> { - // SAFETY: - // - This is memory safe because the caller ensures that there are no conflicting references. - // - The world matches because it was the same one used to construct self. - unsafe { self.copy_unsafe() } - } - - /// Returns a new `Query` copying the access from this one. - /// The current query will still be usable while the new one exists, but must not be used in a way that violates aliasing. - /// - /// # Safety - /// - /// This function makes it possible to violate Rust's aliasing guarantees. - /// You must make sure this call does not result in a mutable or shared reference to a component with a mutable reference. - /// - /// # See also - /// - /// - [`reborrow_unsafe`](Self::reborrow_unsafe) for a safer version that constrains the returned `'w` lifetime to the length of the borrow. - unsafe fn copy_unsafe(&self) -> Query<'w, '_, D, F> { // SAFETY: // - This is memory safe because the caller ensures that there are no conflicting references. // - The world matches because it was the same one used to construct self. @@ -682,7 +669,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref QueryIter<'_, &QueryState> { + pub fn iter(&self) -> QueryIter<'_, '_, &QueryState> { self.as_readonly().into_iter() } @@ -713,7 +700,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref QueryIter<'_, &QueryState> { + pub fn iter_mut(&mut self) -> QueryIter<'_, '_, &QueryState> { self.reborrow().into_iter() } @@ -743,7 +730,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref( &self, - ) -> QueryCombinationIter<'_, &QueryState, K> { + ) -> QueryCombinationIter<'_, '_, &QueryState, K> { self.as_readonly().iter_combinations_inner() } @@ -773,7 +760,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref( &mut self, - ) -> QueryCombinationIter<'_, &QueryState, K> { + ) -> QueryCombinationIter<'_, '_, &QueryState, K> { self.reborrow().iter_combinations_inner() } @@ -802,7 +789,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref(self) -> QueryCombinationIter<'w, S, K> { + pub fn iter_combinations_inner(self) -> QueryCombinationIter<'w, 's, S, K> + where + S: ConsumableQueryState<'s, Data = D, Filter = F>, + { // SAFETY: `self.world` has permission to access the required components. unsafe { QueryCombinationIter::new(self.world, self.state, self.last_run, self.this_run) } } @@ -848,7 +838,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref>( &self, entities: EntityList, - ) -> QueryManyIter<'_, &QueryState, EntityList::IntoIter> { + ) -> QueryManyIter<'_, '_, &QueryState, EntityList::IntoIter> { self.as_readonly().iter_many_inner(entities) } @@ -893,7 +883,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref>( &mut self, entities: EntityList, - ) -> QueryManyIter<'_, &QueryState, EntityList::IntoIter> { + ) -> QueryManyIter<'_, '_, &QueryState, EntityList::IntoIter> { self.reborrow().iter_many_inner(entities) } @@ -911,7 +901,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref>( self, entities: EntityList, - ) -> QueryManyIter<'w, S, EntityList::IntoIter> { + ) -> QueryManyIter<'w, 's, S, EntityList::IntoIter> + where + S: ConsumableQueryState<'s, Data = D, Filter = F>, + { // SAFETY: `self.world` has permission to access the required components. unsafe { QueryManyIter::new( @@ -976,7 +969,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref( &self, entities: EntityList, - ) -> QueryManyUniqueIter<'_, &QueryState, EntityList::IntoIter> { + ) -> QueryManyUniqueIter<'_, '_, &QueryState, EntityList::IntoIter> { self.as_readonly().iter_many_unique_inner(entities) } @@ -1031,7 +1024,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref( &mut self, entities: EntityList, - ) -> QueryManyUniqueIter<'_, &QueryState, EntityList::IntoIter> { + ) -> QueryManyUniqueIter<'_, '_, &QueryState, EntityList::IntoIter> { self.reborrow().iter_many_unique_inner(entities) } @@ -1086,7 +1079,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref( self, entities: EntityList, - ) -> QueryManyUniqueIter<'w, S, EntityList::IntoIter> { + ) -> QueryManyUniqueIter<'w, 's, S, EntityList::IntoIter> + where + S: ConsumableQueryState<'s, Data = D, Filter = F>, + { // SAFETY: `self.world` has permission to access the required components. unsafe { QueryManyUniqueIter::new( @@ -1113,7 +1109,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref QueryIter<'_, &QueryState> { + pub unsafe fn iter_unsafe(&self) -> QueryIter<'_, '_, &QueryState> { // SAFETY: The caller promises that this will not result in multiple mutable references. unsafe { self.reborrow_unsafe() }.into_iter() } @@ -1134,7 +1130,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref( &self, - ) -> QueryCombinationIter<'_, &QueryState, K> { + ) -> QueryCombinationIter<'_, '_, &QueryState, K> { // SAFETY: The caller promises that this will not result in multiple mutable references. unsafe { self.reborrow_unsafe() }.iter_combinations_inner() } @@ -1156,7 +1152,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref>( &self, entities: EntityList, - ) -> QueryManyIter<'_, &QueryState, EntityList::IntoIter> { + ) -> QueryManyIter<'_, '_, &QueryState, EntityList::IntoIter> { // SAFETY: The caller promises that this will not result in multiple mutable references. unsafe { self.reborrow_unsafe() }.iter_many_inner(entities) } @@ -1178,7 +1174,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref( &self, entities: EntityList, - ) -> QueryManyUniqueIter<'_, &QueryState, EntityList::IntoIter> { + ) -> QueryManyUniqueIter<'_, '_, &QueryState, EntityList::IntoIter> { // SAFETY: The caller promises that this will not result in multiple mutable references. unsafe { self.reborrow_unsafe() }.iter_many_unique_inner(entities) } @@ -1199,7 +1195,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref QueryParIter<'_, &QueryState> { + pub fn par_iter(&self) -> QueryParIter<'_, '_, &QueryState> { self.as_readonly().par_iter_inner() } @@ -1234,7 +1230,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref QueryParIter<'_, &QueryState> { + pub fn par_iter_mut(&mut self) -> QueryParIter<'_, '_, &QueryState> { self.reborrow().par_iter_inner() } @@ -1265,10 +1261,14 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref QueryParIter<'w, S> { + pub fn par_iter_inner(self) -> QueryParIter<'w, 's, S> + where + S: ConsumableQueryState<'s, Data = D, Filter = F>, + { QueryParIter { world: self.world, state: self.state, + marker: PhantomData, last_run: self.last_run, this_run: self.this_run, batching_strategy: BatchingStrategy::new(), @@ -1294,10 +1294,11 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref>( &self, entities: EntityList, - ) -> QueryParManyIter<'_, &QueryState, EntityList::Item> { + ) -> QueryParManyIter<'_, '_, &QueryState, EntityList::Item> { QueryParManyIter { world: self.world, state: self.state.as_readonly(), + marker: PhantomData, entity_list: entities.into_iter().collect(), last_run: self.last_run, this_run: self.this_run, @@ -1323,10 +1324,11 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref>( &self, entities: EntityList, - ) -> QueryParManyUniqueIter<'_, &QueryState, EntityList::Item> { + ) -> QueryParManyUniqueIter<'_, '_, &QueryState, EntityList::Item> { QueryParManyUniqueIter { world: self.world, state: self.state.as_readonly(), + marker: PhantomData, entity_list: entities.into_iter().collect(), last_run: self.last_run, this_run: self.this_run, @@ -1352,10 +1354,11 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref>( &mut self, entities: EntityList, - ) -> QueryParManyUniqueIter<'_, &QueryState, EntityList::Item> { + ) -> QueryParManyUniqueIter<'_, '_, &QueryState, EntityList::Item> { QueryParManyUniqueIter { world: self.world, state: &self.state, + marker: PhantomData, entity_list: entities.into_iter().collect(), last_run: self.last_run, this_run: self.this_run, @@ -1397,7 +1400,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref Result, QueryEntityError> { + pub fn get(&self, entity: Entity) -> Result, QueryEntityError> { self.as_readonly().get_inner(entity) } @@ -1448,7 +1451,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref( &self, entities: [Entity; N], - ) -> Result<[ROQueryItem<'_, 's, D>; N], QueryEntityError> { + ) -> Result<[ROQueryItem<'_, '_, D>; N], QueryEntityError> { // Note that we call a separate `*_inner` method from `get_many_mut` // because we don't need to check for duplicates. self.as_readonly().get_many_inner(entities) @@ -1499,7 +1502,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref( &self, entities: UniqueEntityArray, - ) -> Result<[ROQueryItem<'_, 's, D>; N], QueryEntityError> { + ) -> Result<[ROQueryItem<'_, '_, D>; N], QueryEntityError> { self.as_readonly().get_many_unique_inner(entities) } @@ -1533,7 +1536,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref Result, QueryEntityError> { + pub fn get_mut(&mut self, entity: Entity) -> Result, QueryEntityError> { self.reborrow().get_inner(entity) } @@ -1548,7 +1551,29 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref Result, QueryEntityError> { + pub fn get_inner(self, entity: Entity) -> Result, QueryEntityError> + where + S: ConsumableQueryState<'s, Data = D, Filter = F>, + { + unsafe { self.get_unchecked_inner(entity) } + } + + /// Returns the query item for the given [`Entity`]. + /// + /// This is similar to [`Self::get_unchecked`], but returns results with the actual "inner" world lifetime. + /// + /// # Safety + /// + /// This function makes it possible to violate Rust's aliasing guarantees. + /// You must make sure this call does not result in multiple mutable references to the same component. + #[inline] + unsafe fn get_unchecked_inner( + &self, + entity: Entity, + ) -> Result, QueryEntityError> + where + S: ConsumableQueryState<'s, Data = D, Filter = F>, + { // SAFETY: system runs without conflicts with other systems. // same-system queries have runtime borrow checks when they conflict unsafe { @@ -1600,12 +1625,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref( &mut self, entities: [Entity; N], - ) -> Result<[D::Item<'_, 's>; N], QueryEntityError> { + ) -> Result<[D::Item<'_, '_>; N], QueryEntityError> { self.reborrow().get_many_mut_inner(entities) } @@ -1754,7 +1774,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref( &mut self, entities: UniqueEntityArray, - ) -> Result<[D::Item<'_, 's>; N], QueryEntityError> { + ) -> Result<[D::Item<'_, '_>; N], QueryEntityError> { self.reborrow().get_many_unique_inner(entities) } @@ -1773,7 +1793,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref( self, entities: [Entity; N], - ) -> Result<[D::Item<'w, 's>; N], QueryEntityError> { + ) -> Result<[D::Item<'w, 's>; N], QueryEntityError> + where + S: ConsumableQueryState<'s, Data = D, Filter = F>, + { // Verify that all entities are unique for i in 0..N { for j in 0..i { @@ -1804,6 +1827,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref Result<[D::Item<'w, 's>; N], QueryEntityError> where D: ReadOnlyQueryData, + S: ConsumableQueryState<'s, Data = D, Filter = F>, { // SAFETY: The query results are read-only, so they don't conflict if there are duplicate entities. unsafe { self.get_many_impl(entities) } @@ -1823,7 +1847,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref( self, entities: UniqueEntityArray, - ) -> Result<[D::Item<'w, 's>; N], QueryEntityError> { + ) -> Result<[D::Item<'w, 's>; N], QueryEntityError> + where + S: ConsumableQueryState<'s, Data = D, Filter = F>, + { // SAFETY: All entities are unique, so the results don't alias. unsafe { self.get_many_impl(entities.into_inner()) } } @@ -1838,12 +1865,15 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref( self, entities: [Entity; N], - ) -> Result<[D::Item<'w, 's>; N], QueryEntityError> { + ) -> Result<[D::Item<'w, 's>; N], QueryEntityError> + where + S: ConsumableQueryState<'s, Data = D, Filter = F>, + { let mut values = [(); N].map(|_| MaybeUninit::uninit()); for (value, entity) in core::iter::zip(&mut values, entities) { // SAFETY: The caller asserts that the results don't alias - let item = unsafe { self.copy_unsafe() }.get_inner(entity)?; + let item = unsafe { self.get_unchecked_inner(entity)? }; *value = MaybeUninit::new(item); } @@ -1869,7 +1899,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref Result, QueryEntityError> { + ) -> Result, QueryEntityError> { // SAFETY: The caller promises that this will not result in multiple mutable references. unsafe { self.reborrow_unsafe() }.get_inner(entity) } @@ -1905,7 +1935,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref Result, QuerySingleError> { + pub fn single(&self) -> Result, QuerySingleError> { self.as_readonly().single_inner() } @@ -1934,7 +1964,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref Result, QuerySingleError> { + pub fn single_mut(&mut self) -> Result, QuerySingleError> { self.reborrow().single_inner() } @@ -1966,7 +1996,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref Result, QuerySingleError> { + pub fn single_inner(self) -> Result, QuerySingleError> + where + S: ConsumableQueryState<'s, Data = D, Filter = F>, + { let mut query = self.into_iter(); let first = query.next(); let extra = query.next().is_some(); @@ -2473,11 +2506,11 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref> IntoIterator - for Query<'w, 's, D, F, S> +impl<'w, 's, D: QueryData, F: QueryFilter, S: ConsumableQueryState<'s, Data = D, Filter = F>> + IntoIterator for Query<'w, 's, D, F, S> { type Item = D::Item<'w, 's>; - type IntoIter = QueryIter<'w, S>; + type IntoIter = QueryIter<'w, 's, S>; fn into_iter(self) -> Self::IntoIter { // SAFETY: @@ -2488,22 +2521,22 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: QueryStateDeref> IntoIterator +impl<'w, D: QueryData, F: QueryFilter, S: Deref>> IntoIterator for &'w Query<'_, '_, D, F, S> { - type Item = ROQueryItem<'w, 's, D>; - type IntoIter = QueryIter<'w, &'w QueryState>; + type Item = ROQueryItem<'w, 'w, D>; + type IntoIter = QueryIter<'w, 'w, &'w QueryState>; fn into_iter(self) -> Self::IntoIter { self.iter() } } -impl<'w, D: QueryData, F: QueryFilter, S: QueryStateDeref> IntoIterator +impl<'w, D: QueryData, F: QueryFilter, S: Deref>> IntoIterator for &'w mut Query<'_, '_, D, F, S> { - type Item = D::Item<'w, 's>; - type IntoIter = QueryIter<'w, &'w QueryState>; + type Item = D::Item<'w, 'w>; + type IntoIter = QueryIter<'w, 'w, &'w QueryState>; fn into_iter(self) -> Self::IntoIter { self.iter_mut() @@ -2535,7 +2568,7 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter> Query<'w, 's, D, F> { /// # bevy_ecs::system::assert_is_system(report_names_system); /// ``` #[inline] - pub fn iter_inner(&self) -> QueryIter<'w, &'s QueryState> { + pub fn iter_inner(&self) -> QueryIter<'w, 's, &'s QueryState> { (*self).into_iter() } } @@ -2543,7 +2576,7 @@ impl<'w, 's, D: ReadOnlyQueryData, F: QueryFilter> Query<'w, 's, D, F> { /// A [`Query`] with an owned [`QueryState`]. /// /// This is returned from methods like [`Query::transmute_lens`] that construct a fresh [`QueryState`]. -pub type QueryLens<'w, Q, F = ()> = Query<'w, 'w, Q, F, Box>>; +pub type QueryLens<'w, Q, F = ()> = Query<'w, 'static, Q, F, Box>>; impl<'w, Q: QueryData, F: QueryFilter> QueryLens<'w, Q, F> { /// Create a [`Query`] from the underlying [`QueryState`]. @@ -2750,4 +2783,14 @@ mod tests { QueryEntityError::AliasedMutability(entities[9]) ); } + + #[test] + fn query_lens_can_be_consumed() { + let mut world = World::new(); + let lens = world + .query::() + .query(&mut world) + .transmute_lens_inner::(); + lens.single_inner().unwrap_err(); + } } From ebf1b12c9c0a4636b93ba74b1c515adc0d082560 Mon Sep 17 00:00:00 2001 From: Chris Russell <8494645+chescock@users.noreply.github.com> Date: Wed, 18 Jun 2025 13:58:10 -0400 Subject: [PATCH 18/18] Fix clippy lints. Add missing safety comment. Remove unnecessary `mut`. --- crates/bevy_ecs/src/system/query.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 6eeed0c9db91e..40a548cc53ffa 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -1555,6 +1555,8 @@ impl<'w, 's, D: QueryData, F: QueryFilter, S: Deref>> where S: ConsumableQueryState<'s, Data = D, Filter = F>, { + // SAFETY: This query has access to this item, + // and we consume the query so it is never used again. unsafe { self.get_unchecked_inner(entity) } } @@ -2789,7 +2791,7 @@ mod tests { let mut world = World::new(); let lens = world .query::() - .query(&mut world) + .query(&world) .transmute_lens_inner::(); lens.single_inner().unwrap_err(); }