@@ -945,7 +945,12 @@ impl<'w, 's, D: QueryData, F: QueryFilter, C: QueryCache> Iterator for QueryIter
945945 accum = func ( accum, item) ;
946946 }
947947
948- for id in self . cursor . storage_id_iter . clone ( ) . copied ( ) {
948+ let mut i = self . cursor . storage_index ;
949+ let len = self . cursor . storage_ids . as_ref ( ) . len ( ) ;
950+ while i < len {
951+ // Take a short-lived copy of the id to avoid holding a borrow of `self` across the call
952+ let id = self . cursor . storage_ids . as_ref ( ) [ i] ;
953+ i += 1 ;
949954 // SAFETY:
950955 // - The range(None) is equivalent to [0, storage.entity_count)
951956 accum = unsafe { self . fold_over_storage_range ( accum, & mut func, id, None ) } ;
@@ -2449,8 +2454,10 @@ impl<'w, 's, D: QueryData, F: QueryFilter, C: QueryCache, const K: usize> Debug
24492454struct QueryIterationCursor < ' w , ' s , D : QueryData , F : QueryFilter , C : QueryCache > {
24502455 // whether the query iteration is dense or not.
24512456 is_dense : bool ,
2452- storage_id_iter : core:: slice:: Iter < ' s , StorageId > ,
2453- owned_storage_ids : Option < Vec < StorageId > > ,
2457+ // Storage ids to iterate over; owned for uncached, borrowed for cached
2458+ storage_ids : Cow < ' s , [ StorageId ] > ,
2459+ // Current index into storage_ids
2460+ storage_index : usize ,
24542461 table_entities : & ' w [ Entity ] ,
24552462 archetype_entities : & ' w [ ArchetypeEntity ] ,
24562463 fetch : D :: Fetch < ' w > ,
@@ -2466,8 +2473,8 @@ impl<D: QueryData, F: QueryFilter, C: QueryCache> Clone for QueryIterationCursor
24662473 fn clone ( & self ) -> Self {
24672474 Self {
24682475 is_dense : self . is_dense ,
2469- storage_id_iter : self . storage_id_iter . clone ( ) ,
2470- owned_storage_ids : self . owned_storage_ids . clone ( ) ,
2476+ storage_ids : self . storage_ids . clone ( ) ,
2477+ storage_index : self . storage_index ,
24712478 table_entities : self . table_entities ,
24722479 archetype_entities : self . archetype_entities ,
24732480 fetch : self . fetch . clone ( ) ,
@@ -2492,7 +2499,8 @@ impl<'w, 's, D: QueryData, F: QueryFilter, C: QueryCache + 's>
24922499 this_run : Tick ,
24932500 ) -> Self {
24942501 QueryIterationCursor {
2495- storage_id_iter : [ ] . iter ( ) ,
2502+ storage_ids : Cow :: Borrowed ( & [ ] ) ,
2503+ storage_index : 0 ,
24962504 ..Self :: init ( world, query_state, last_run, this_run)
24972505 }
24982506 }
@@ -2509,27 +2517,14 @@ impl<'w, 's, D: QueryData, F: QueryFilter, C: QueryCache + 's>
25092517 let fetch = D :: init_fetch ( world, & query_state. fetch_state , last_run, this_run) ;
25102518 let filter = F :: init_fetch ( world, & query_state. filter_state , last_run, this_run) ;
25112519 let iteration_data = query_state. cache . iteration_data ( query_state, world) ;
2512- let ( owned_storage_ids, storage_id_iter) = match iteration_data. storage_ids {
2513- Cow :: Borrowed ( slice) => ( None , slice. iter ( ) ) ,
2514- Cow :: Owned ( owned) => {
2515- let owned_ids = Some ( owned) ;
2516- let slice_ptr: * const [ StorageId ] = owned_ids. as_ref ( ) . unwrap ( ) . as_slice ( ) ;
2517- // SAFETY:
2518- // - The slice pointer refers to memory owned by `owned_ids`
2519- // - `owned_ids` is moved *as a whole* into the struct below and won’t move afterward
2520- // - The struct owns `owned_ids` for the same lifetime as `ids_iter`
2521- // => Safe as long as `Cursor` isn’t moved after creation (so don’t mem::swap etc.)
2522- let ids_iter = unsafe { ( & * slice_ptr) . iter ( ) } ;
2523- ( owned_ids, ids_iter)
2524- }
2525- } ;
2520+ let storage_ids = iteration_data. storage_ids ;
25262521 QueryIterationCursor {
25272522 fetch,
25282523 filter,
25292524 table_entities : & [ ] ,
25302525 archetype_entities : & [ ] ,
2531- storage_id_iter ,
2532- owned_storage_ids ,
2526+ storage_ids ,
2527+ storage_index : 0 ,
25332528 is_dense : iteration_data. is_dense ,
25342529 current_len : 0 ,
25352530 current_row : 0 ,
@@ -2544,8 +2539,8 @@ impl<'w, 's, D: QueryData, F: QueryFilter, C: QueryCache + 's>
25442539 filter : F :: shrink_fetch ( self . filter . clone ( ) ) ,
25452540 table_entities : self . table_entities ,
25462541 archetype_entities : self . archetype_entities ,
2547- storage_id_iter : self . storage_id_iter . clone ( ) ,
2548- owned_storage_ids : self . owned_storage_ids . clone ( ) ,
2542+ storage_ids : self . storage_ids . clone ( ) ,
2543+ storage_index : self . storage_index ,
25492544 current_len : self . current_len ,
25502545 current_row : self . current_row ,
25512546 _cache : core:: marker:: PhantomData ,
@@ -2605,7 +2600,7 @@ impl<'w, 's, D: QueryData, F: QueryFilter, C: QueryCache + 's>
26052600 /// Note that if `F::IS_ARCHETYPAL`, the return value
26062601 /// will be **the exact count of remaining values**.
26072602 fn max_remaining ( & self , tables : & ' w Tables , archetypes : & ' w Archetypes ) -> u32 {
2608- let ids = self . storage_id_iter . clone ( ) ;
2603+ let ids = self . storage_ids . as_ref ( ) [ self . storage_index .. ] . iter ( ) . copied ( ) ;
26092604 let remaining_matched: u32 = if self . is_dense {
26102605 // SAFETY: The if check ensures that storage_id_iter stores TableIds
26112606 unsafe { ids. map ( |id| tables[ id. table_id ] . entity_count ( ) ) . sum ( ) }
@@ -2635,7 +2630,14 @@ impl<'w, 's, D: QueryData, F: QueryFilter, C: QueryCache + 's>
26352630 loop {
26362631 // we are on the beginning of the query, or finished processing a table, so skip to the next
26372632 if self . current_row == self . current_len {
2638- let table_id = self . storage_id_iter . next ( ) ?. table_id ;
2633+ let table_id = {
2634+ let id = * self
2635+ . storage_ids
2636+ . as_ref ( )
2637+ . get ( self . storage_index ) ?;
2638+ self . storage_index += 1 ;
2639+ id. table_id
2640+ } ;
26392641 let table = tables. get ( table_id) . debug_checked_unwrap ( ) ;
26402642 if table. is_empty ( ) {
26412643 continue ;
@@ -2676,7 +2678,14 @@ impl<'w, 's, D: QueryData, F: QueryFilter, C: QueryCache + 's>
26762678 } else {
26772679 loop {
26782680 if self . current_row == self . current_len {
2679- let archetype_id = self . storage_id_iter . next ( ) ?. archetype_id ;
2681+ let archetype_id = {
2682+ let id = * self
2683+ . storage_ids
2684+ . as_ref ( )
2685+ . get ( self . storage_index ) ?;
2686+ self . storage_index += 1 ;
2687+ id. archetype_id
2688+ } ;
26802689 let archetype = archetypes. get ( archetype_id) . debug_checked_unwrap ( ) ;
26812690 if archetype. is_empty ( ) {
26822691 continue ;
0 commit comments