Implement iter() for mutable Queries (#2305)
A sample implementation of how to have `iter()` work on mutable queries without breaking aliasing rules. # Objective - Fixes #753 ## Solution - Added a ReadOnlyFetch to WorldQuery that is the `&T` version of `&mut T` that is used to specify the return type for read only operations like `iter()`. - ~~As the comment suggests specifying the bound doesn't work due to restrictions on defining recursive implementations (like `Or`). However bounds on the functions are fine~~ Never mind I misread how `Or` was constructed, bounds now exist. - Note that the only mutable one has a new `Fetch` for readonly as the `State` has to be the same for any of this to work Co-authored-by: Carter Anderson <mcanders1@gmail.com>
This commit is contained in:
		
							parent
							
								
									5fe73be2b5
								
							
						
					
					
						commit
						274ace790b
					
				@ -43,6 +43,8 @@ use std::{
 | 
			
		||||
pub trait WorldQuery {
 | 
			
		||||
    type Fetch: for<'world, 'state> Fetch<'world, 'state, State = Self::State>;
 | 
			
		||||
    type State: FetchState;
 | 
			
		||||
    type ReadOnlyFetch: for<'world, 'state> Fetch<'world, 'state, State = Self::State>
 | 
			
		||||
        + ReadOnlyFetch;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub type QueryItem<'w, 's, Q> = <<Q as WorldQuery>::Fetch as Fetch<'w, 's>>::Item;
 | 
			
		||||
@ -136,6 +138,7 @@ pub unsafe trait ReadOnlyFetch {}
 | 
			
		||||
impl WorldQuery for Entity {
 | 
			
		||||
    type Fetch = EntityFetch;
 | 
			
		||||
    type State = EntityState;
 | 
			
		||||
    type ReadOnlyFetch = EntityFetch;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// The [`Fetch`] of [`Entity`].
 | 
			
		||||
@ -222,6 +225,7 @@ impl<'w, 's> Fetch<'w, 's> for EntityFetch {
 | 
			
		||||
impl<T: Component> WorldQuery for &T {
 | 
			
		||||
    type Fetch = ReadFetch<T>;
 | 
			
		||||
    type State = ReadState<T>;
 | 
			
		||||
    type ReadOnlyFetch = ReadFetch<T>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// The [`FetchState`] of `&T`.
 | 
			
		||||
@ -376,6 +380,7 @@ impl<'w, 's, T: Component> Fetch<'w, 's> for ReadFetch<T> {
 | 
			
		||||
impl<T: Component> WorldQuery for &mut T {
 | 
			
		||||
    type Fetch = WriteFetch<T>;
 | 
			
		||||
    type State = WriteState<T>;
 | 
			
		||||
    type ReadOnlyFetch = ReadOnlyWriteFetch<T>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// The [`Fetch`] of `&mut T`.
 | 
			
		||||
@ -403,6 +408,28 @@ impl<T> Clone for WriteFetch<T> {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// The [`ReadOnlyFetch`] of `&mut T`.
 | 
			
		||||
pub struct ReadOnlyWriteFetch<T> {
 | 
			
		||||
    table_components: NonNull<T>,
 | 
			
		||||
    entities: *const Entity,
 | 
			
		||||
    entity_table_rows: *const usize,
 | 
			
		||||
    sparse_set: *const ComponentSparseSet,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// SAFETY: access is read only
 | 
			
		||||
unsafe impl<T> ReadOnlyFetch for ReadOnlyWriteFetch<T> {}
 | 
			
		||||
 | 
			
		||||
impl<T> Clone for ReadOnlyWriteFetch<T> {
 | 
			
		||||
    fn clone(&self) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            table_components: self.table_components,
 | 
			
		||||
            entities: self.entities,
 | 
			
		||||
            entity_table_rows: self.entity_table_rows,
 | 
			
		||||
            sparse_set: self.sparse_set,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// The [`FetchState`] of `&mut T`.
 | 
			
		||||
pub struct WriteState<T> {
 | 
			
		||||
    component_id: ComponentId,
 | 
			
		||||
@ -555,9 +582,88 @@ impl<'w, 's, T: Component> Fetch<'w, 's> for WriteFetch<T> {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'w, 's, T: Component> Fetch<'w, 's> for ReadOnlyWriteFetch<T> {
 | 
			
		||||
    type Item = &'w T;
 | 
			
		||||
    type State = WriteState<T>;
 | 
			
		||||
 | 
			
		||||
    const IS_DENSE: bool = {
 | 
			
		||||
        match T::Storage::STORAGE_TYPE {
 | 
			
		||||
            StorageType::Table => true,
 | 
			
		||||
            StorageType::SparseSet => false,
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    unsafe fn init(
 | 
			
		||||
        world: &World,
 | 
			
		||||
        state: &Self::State,
 | 
			
		||||
        _last_change_tick: u32,
 | 
			
		||||
        _change_tick: u32,
 | 
			
		||||
    ) -> Self {
 | 
			
		||||
        let mut value = Self {
 | 
			
		||||
            table_components: NonNull::dangling(),
 | 
			
		||||
            entities: ptr::null::<Entity>(),
 | 
			
		||||
            entity_table_rows: ptr::null::<usize>(),
 | 
			
		||||
            sparse_set: ptr::null::<ComponentSparseSet>(),
 | 
			
		||||
        };
 | 
			
		||||
        if T::Storage::STORAGE_TYPE == StorageType::SparseSet {
 | 
			
		||||
            value.sparse_set = world
 | 
			
		||||
                .storages()
 | 
			
		||||
                .sparse_sets
 | 
			
		||||
                .get(state.component_id)
 | 
			
		||||
                .unwrap();
 | 
			
		||||
        }
 | 
			
		||||
        value
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn set_archetype(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        state: &Self::State,
 | 
			
		||||
        archetype: &Archetype,
 | 
			
		||||
        tables: &Tables,
 | 
			
		||||
    ) {
 | 
			
		||||
        match T::Storage::STORAGE_TYPE {
 | 
			
		||||
            StorageType::Table => {
 | 
			
		||||
                self.entity_table_rows = archetype.entity_table_rows().as_ptr();
 | 
			
		||||
                let column = tables[archetype.table_id()]
 | 
			
		||||
                    .get_column(state.component_id)
 | 
			
		||||
                    .unwrap();
 | 
			
		||||
                self.table_components = column.get_data_ptr().cast::<T>();
 | 
			
		||||
            }
 | 
			
		||||
            StorageType::SparseSet => self.entities = archetype.entities().as_ptr(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn set_table(&mut self, state: &Self::State, table: &Table) {
 | 
			
		||||
        let column = table.get_column(state.component_id).unwrap();
 | 
			
		||||
        self.table_components = column.get_data_ptr().cast::<T>();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn archetype_fetch(&mut self, archetype_index: usize) -> Self::Item {
 | 
			
		||||
        match T::Storage::STORAGE_TYPE {
 | 
			
		||||
            StorageType::Table => {
 | 
			
		||||
                let table_row = *self.entity_table_rows.add(archetype_index);
 | 
			
		||||
                &*self.table_components.as_ptr().add(table_row)
 | 
			
		||||
            }
 | 
			
		||||
            StorageType::SparseSet => {
 | 
			
		||||
                let entity = *self.entities.add(archetype_index);
 | 
			
		||||
                &*(*self.sparse_set).get(entity).unwrap().cast::<T>()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn table_fetch(&mut self, table_row: usize) -> Self::Item {
 | 
			
		||||
        &*self.table_components.as_ptr().add(table_row)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: WorldQuery> WorldQuery for Option<T> {
 | 
			
		||||
    type Fetch = OptionFetch<T::Fetch>;
 | 
			
		||||
    type State = OptionState<T::State>;
 | 
			
		||||
    type ReadOnlyFetch = OptionFetch<T::ReadOnlyFetch>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// The [`Fetch`] of `Option<T>`.
 | 
			
		||||
@ -733,6 +839,7 @@ impl<T: Component> ChangeTrackers<T> {
 | 
			
		||||
impl<T: Component> WorldQuery for ChangeTrackers<T> {
 | 
			
		||||
    type Fetch = ChangeTrackersFetch<T>;
 | 
			
		||||
    type State = ChangeTrackersState<T>;
 | 
			
		||||
    type ReadOnlyFetch = ChangeTrackersFetch<T>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// The [`FetchState`] of [`ChangeTrackers`].
 | 
			
		||||
@ -983,6 +1090,7 @@ macro_rules! impl_tuple_fetch {
 | 
			
		||||
        impl<$($name: WorldQuery),*> WorldQuery for ($($name,)*) {
 | 
			
		||||
            type Fetch = ($($name::Fetch,)*);
 | 
			
		||||
            type State = ($($name::State,)*);
 | 
			
		||||
            type ReadOnlyFetch = ($($name::ReadOnlyFetch,)*);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// SAFETY: each item in the tuple is read only
 | 
			
		||||
@ -992,3 +1100,45 @@ macro_rules! impl_tuple_fetch {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
all_tuples!(impl_tuple_fetch, 0, 15, F, S);
 | 
			
		||||
 | 
			
		||||
/// [`Fetch`] that does not actually fetch anything
 | 
			
		||||
///
 | 
			
		||||
/// Mostly useful when something is generic over the Fetch and you don't want to fetch as you will discard the result
 | 
			
		||||
pub struct NopFetch<State> {
 | 
			
		||||
    state: PhantomData<State>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'w, 's, State: FetchState> Fetch<'w, 's> for NopFetch<State> {
 | 
			
		||||
    type Item = ();
 | 
			
		||||
    type State = State;
 | 
			
		||||
 | 
			
		||||
    const IS_DENSE: bool = true;
 | 
			
		||||
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    unsafe fn init(
 | 
			
		||||
        _world: &World,
 | 
			
		||||
        _state: &Self::State,
 | 
			
		||||
        _last_change_tick: u32,
 | 
			
		||||
        _change_tick: u32,
 | 
			
		||||
    ) -> Self {
 | 
			
		||||
        Self { state: PhantomData }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    unsafe fn set_archetype(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        _state: &Self::State,
 | 
			
		||||
        _archetype: &Archetype,
 | 
			
		||||
        _tables: &Tables,
 | 
			
		||||
    ) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    unsafe fn set_table(&mut self, _state: &Self::State, _table: &Table) {}
 | 
			
		||||
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    unsafe fn archetype_fetch(&mut self, _archetype_index: usize) -> Self::Item {}
 | 
			
		||||
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    unsafe fn table_fetch(&mut self, _table_row: usize) -> Self::Item {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@ use crate::{
 | 
			
		||||
    archetype::{Archetype, ArchetypeComponentId},
 | 
			
		||||
    component::{Component, ComponentId, ComponentStorage, ComponentTicks, StorageType},
 | 
			
		||||
    entity::Entity,
 | 
			
		||||
    query::{Access, Fetch, FetchState, FilteredAccess, WorldQuery},
 | 
			
		||||
    query::{Access, Fetch, FetchState, FilteredAccess, ReadOnlyFetch, WorldQuery},
 | 
			
		||||
    storage::{ComponentSparseSet, Table, Tables},
 | 
			
		||||
    world::World,
 | 
			
		||||
};
 | 
			
		||||
@ -72,6 +72,7 @@ pub struct With<T>(PhantomData<T>);
 | 
			
		||||
impl<T: Component> WorldQuery for With<T> {
 | 
			
		||||
    type Fetch = WithFetch<T>;
 | 
			
		||||
    type State = WithState<T>;
 | 
			
		||||
    type ReadOnlyFetch = WithFetch<T>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// The [`Fetch`] of [`With`].
 | 
			
		||||
@ -162,6 +163,9 @@ impl<'w, 's, T: Component> Fetch<'w, 's> for WithFetch<T> {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SAFETY: no component access or archetype component access
 | 
			
		||||
unsafe impl<T> ReadOnlyFetch for WithFetch<T> {}
 | 
			
		||||
 | 
			
		||||
/// Filter that selects entities without a component `T`.
 | 
			
		||||
///
 | 
			
		||||
/// This is the negation of [`With`].
 | 
			
		||||
@ -191,6 +195,7 @@ pub struct Without<T>(PhantomData<T>);
 | 
			
		||||
impl<T: Component> WorldQuery for Without<T> {
 | 
			
		||||
    type Fetch = WithoutFetch<T>;
 | 
			
		||||
    type State = WithoutState<T>;
 | 
			
		||||
    type ReadOnlyFetch = WithoutFetch<T>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// The [`Fetch`] of [`Without`].
 | 
			
		||||
@ -281,6 +286,9 @@ impl<'w, 's, T: Component> Fetch<'w, 's> for WithoutFetch<T> {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SAFETY: no component access or archetype component access
 | 
			
		||||
unsafe impl<T> ReadOnlyFetch for WithoutFetch<T> {}
 | 
			
		||||
 | 
			
		||||
/// A filter that tests if any of the given filters apply.
 | 
			
		||||
///
 | 
			
		||||
/// This is useful for example if a system with multiple components in a query only wants to run
 | 
			
		||||
@ -338,12 +346,15 @@ macro_rules! impl_query_filter_tuple {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        impl<$($filter: WorldQuery),*> WorldQuery for Or<($($filter,)*)>
 | 
			
		||||
            where $($filter::Fetch: FilterFetch),*
 | 
			
		||||
            where $($filter::Fetch: FilterFetch, $filter::ReadOnlyFetch: FilterFetch),*
 | 
			
		||||
        {
 | 
			
		||||
            type Fetch = Or<($(OrFetch<$filter::Fetch>,)*)>;
 | 
			
		||||
            type State = Or<($($filter::State,)*)>;
 | 
			
		||||
            type ReadOnlyFetch = Or<($(OrFetch<$filter::ReadOnlyFetch>,)*)>;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// SAFETY: this only works using the filter which doesn't write
 | 
			
		||||
        unsafe impl<$($filter: FilterFetch + ReadOnlyFetch),*> ReadOnlyFetch for Or<($(OrFetch<$filter>,)*)> {}
 | 
			
		||||
 | 
			
		||||
        #[allow(unused_variables)]
 | 
			
		||||
        #[allow(non_snake_case)]
 | 
			
		||||
@ -464,9 +475,9 @@ macro_rules! impl_tick_filter {
 | 
			
		||||
        impl<T: Component> WorldQuery for $name<T> {
 | 
			
		||||
            type Fetch = $fetch_name<T>;
 | 
			
		||||
            type State = $state_name<T>;
 | 
			
		||||
            type ReadOnlyFetch = $fetch_name<T>;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // SAFETY: this reads the T component. archetype component access and component access are updated to reflect that
 | 
			
		||||
        unsafe impl<T: Component> FetchState for $state_name<T> {
 | 
			
		||||
            fn init(world: &mut World) -> Self {
 | 
			
		||||
@ -572,6 +583,9 @@ macro_rules! impl_tick_filter {
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// SAFETY: read-only access
 | 
			
		||||
        unsafe impl<T: Component> ReadOnlyFetch for $fetch_name<T> {}
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,13 +4,13 @@ use crate::{
 | 
			
		||||
    storage::{TableId, Tables},
 | 
			
		||||
    world::World,
 | 
			
		||||
};
 | 
			
		||||
use std::mem::MaybeUninit;
 | 
			
		||||
use std::{marker::PhantomData, mem::MaybeUninit};
 | 
			
		||||
 | 
			
		||||
/// An [`Iterator`] over query results of a [`Query`](crate::system::Query).
 | 
			
		||||
///
 | 
			
		||||
/// 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, Q: WorldQuery, F: WorldQuery>
 | 
			
		||||
pub struct QueryIter<'w, 's, Q: WorldQuery, QF: Fetch<'w, 's, State = Q::State>, F: WorldQuery>
 | 
			
		||||
where
 | 
			
		||||
    F::Fetch: FilterFetch,
 | 
			
		||||
{
 | 
			
		||||
@ -20,15 +20,16 @@ where
 | 
			
		||||
    world: &'w World,
 | 
			
		||||
    table_id_iter: std::slice::Iter<'s, TableId>,
 | 
			
		||||
    archetype_id_iter: std::slice::Iter<'s, ArchetypeId>,
 | 
			
		||||
    fetch: Q::Fetch,
 | 
			
		||||
    fetch: QF,
 | 
			
		||||
    filter: F::Fetch,
 | 
			
		||||
    current_len: usize,
 | 
			
		||||
    current_index: usize,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'w, 's, Q: WorldQuery, F: WorldQuery> QueryIter<'w, 's, Q, F>
 | 
			
		||||
impl<'w, 's, Q: WorldQuery, QF, F: WorldQuery> QueryIter<'w, 's, Q, QF, F>
 | 
			
		||||
where
 | 
			
		||||
    F::Fetch: FilterFetch,
 | 
			
		||||
    QF: Fetch<'w, 's, State = Q::State>,
 | 
			
		||||
{
 | 
			
		||||
    /// # Safety
 | 
			
		||||
    /// This does not check for mutable query correctness. To be safe, make sure mutable queries
 | 
			
		||||
@ -41,7 +42,7 @@ where
 | 
			
		||||
        last_change_tick: u32,
 | 
			
		||||
        change_tick: u32,
 | 
			
		||||
    ) -> Self {
 | 
			
		||||
        let fetch = <Q::Fetch as Fetch>::init(
 | 
			
		||||
        let fetch = QF::init(
 | 
			
		||||
            world,
 | 
			
		||||
            &query_state.fetch_state,
 | 
			
		||||
            last_change_tick,
 | 
			
		||||
@ -67,69 +68,14 @@ where
 | 
			
		||||
            current_index: 0,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Consumes `self` and returns true if there were no elements remaining in this iterator.
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    pub(crate) fn none_remaining(mut self) -> bool {
 | 
			
		||||
        // NOTE: this mimics the behavior of `QueryIter::next()`, except that it
 | 
			
		||||
        // never gets a `Self::Item`.
 | 
			
		||||
        unsafe {
 | 
			
		||||
            if Q::Fetch::IS_DENSE && F::Fetch::IS_DENSE {
 | 
			
		||||
                loop {
 | 
			
		||||
                    if self.current_index == self.current_len {
 | 
			
		||||
                        let table_id = match self.table_id_iter.next() {
 | 
			
		||||
                            Some(table_id) => table_id,
 | 
			
		||||
                            None => return true,
 | 
			
		||||
                        };
 | 
			
		||||
                        let table = &self.tables[*table_id];
 | 
			
		||||
                        self.filter.set_table(&self.query_state.filter_state, table);
 | 
			
		||||
                        self.current_len = table.len();
 | 
			
		||||
                        self.current_index = 0;
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if !self.filter.table_filter_fetch(self.current_index) {
 | 
			
		||||
                        self.current_index += 1;
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                loop {
 | 
			
		||||
                    if self.current_index == self.current_len {
 | 
			
		||||
                        let archetype_id = match self.archetype_id_iter.next() {
 | 
			
		||||
                            Some(archetype_id) => archetype_id,
 | 
			
		||||
                            None => return true,
 | 
			
		||||
                        };
 | 
			
		||||
                        let archetype = &self.archetypes[*archetype_id];
 | 
			
		||||
                        self.filter.set_archetype(
 | 
			
		||||
                            &self.query_state.filter_state,
 | 
			
		||||
                            archetype,
 | 
			
		||||
                            self.tables,
 | 
			
		||||
                        );
 | 
			
		||||
                        self.current_len = archetype.len();
 | 
			
		||||
                        self.current_index = 0;
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if !self.filter.archetype_filter_fetch(self.current_index) {
 | 
			
		||||
                        self.current_index += 1;
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'w, 's, Q: WorldQuery, F: WorldQuery> Iterator for QueryIter<'w, 's, Q, F>
 | 
			
		||||
impl<'w, 's, Q: WorldQuery, QF, F: WorldQuery> Iterator for QueryIter<'w, 's, Q, QF, F>
 | 
			
		||||
where
 | 
			
		||||
    F::Fetch: FilterFetch,
 | 
			
		||||
    QF: Fetch<'w, 's, State = Q::State>,
 | 
			
		||||
{
 | 
			
		||||
    type Item = <Q::Fetch as Fetch<'w, 's>>::Item;
 | 
			
		||||
    type Item = QF::Item;
 | 
			
		||||
 | 
			
		||||
    // NOTE: If you are changing query iteration code, remember to update the following places, where relevant:
 | 
			
		||||
    // QueryIter, QueryIterationCursor, QueryState::for_each_unchecked_manual, QueryState::par_for_each_unchecked_manual
 | 
			
		||||
@ -137,7 +83,7 @@ where
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    fn next(&mut self) -> Option<Self::Item> {
 | 
			
		||||
        unsafe {
 | 
			
		||||
            if Q::Fetch::IS_DENSE && F::Fetch::IS_DENSE {
 | 
			
		||||
            if QF::IS_DENSE && F::Fetch::IS_DENSE {
 | 
			
		||||
                loop {
 | 
			
		||||
                    if self.current_index == self.current_len {
 | 
			
		||||
                        let table_id = self.table_id_iter.next()?;
 | 
			
		||||
@ -207,19 +153,22 @@ where
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct QueryCombinationIter<'w, 's, Q: WorldQuery, F: WorldQuery, const K: usize>
 | 
			
		||||
pub struct QueryCombinationIter<'w, 's, Q: WorldQuery, QF, F: WorldQuery, const K: usize>
 | 
			
		||||
where
 | 
			
		||||
    QF: Fetch<'w, 's, State = Q::State>,
 | 
			
		||||
    F::Fetch: FilterFetch,
 | 
			
		||||
{
 | 
			
		||||
    tables: &'w Tables,
 | 
			
		||||
    archetypes: &'w Archetypes,
 | 
			
		||||
    query_state: &'s QueryState<Q, F>,
 | 
			
		||||
    world: &'w World,
 | 
			
		||||
    cursors: [QueryIterationCursor<'s, Q, F>; K],
 | 
			
		||||
    cursors: [QueryIterationCursor<'w, 's, Q, QF, F>; K],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'w, 's, Q: WorldQuery, F: WorldQuery, const K: usize> QueryCombinationIter<'w, 's, Q, F, K>
 | 
			
		||||
impl<'w, 's, Q: WorldQuery, QF, F: WorldQuery, const K: usize>
 | 
			
		||||
    QueryCombinationIter<'w, 's, Q, QF, F, K>
 | 
			
		||||
where
 | 
			
		||||
    QF: Fetch<'w, 's, State = Q::State>,
 | 
			
		||||
    F::Fetch: FilterFetch,
 | 
			
		||||
{
 | 
			
		||||
    /// # Safety
 | 
			
		||||
@ -237,7 +186,7 @@ where
 | 
			
		||||
        // There is no FromIterator on arrays, so instead initialize it manually with MaybeUninit
 | 
			
		||||
 | 
			
		||||
        // TODO: use MaybeUninit::uninit_array if it stabilizes
 | 
			
		||||
        let mut cursors: [MaybeUninit<QueryIterationCursor<'s, Q, F>>; K] =
 | 
			
		||||
        let mut cursors: [MaybeUninit<QueryIterationCursor<'w, 's, Q, QF, F>>; K] =
 | 
			
		||||
            MaybeUninit::uninit().assume_init();
 | 
			
		||||
        for (i, cursor) in cursors.iter_mut().enumerate() {
 | 
			
		||||
            match i {
 | 
			
		||||
@ -257,8 +206,8 @@ where
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // TODO: use MaybeUninit::array_assume_init if it stabilizes
 | 
			
		||||
        let cursors: [QueryIterationCursor<'s, Q, F>; K] =
 | 
			
		||||
            (&cursors as *const _ as *const [QueryIterationCursor<'s, Q, F>; K]).read();
 | 
			
		||||
        let cursors: [QueryIterationCursor<'w, 's, Q, QF, F>; K] =
 | 
			
		||||
            (&cursors as *const _ as *const [QueryIterationCursor<'w, 's, Q, QF, F>; K]).read();
 | 
			
		||||
 | 
			
		||||
        QueryCombinationIter {
 | 
			
		||||
            world,
 | 
			
		||||
@ -275,11 +224,9 @@ where
 | 
			
		||||
    /// references to the same component, leading to unique reference aliasing.
 | 
			
		||||
    ///.
 | 
			
		||||
    /// It is always safe for shared access.
 | 
			
		||||
    unsafe fn fetch_next_aliased_unchecked<'a>(
 | 
			
		||||
        &mut self,
 | 
			
		||||
    ) -> Option<[<Q::Fetch as Fetch<'a, 's>>::Item; K]>
 | 
			
		||||
    unsafe fn fetch_next_aliased_unchecked(&mut self) -> Option<[QF::Item; K]>
 | 
			
		||||
    where
 | 
			
		||||
        Q::Fetch: Clone,
 | 
			
		||||
        QF: Clone,
 | 
			
		||||
        F::Fetch: Clone,
 | 
			
		||||
    {
 | 
			
		||||
        if K == 0 {
 | 
			
		||||
@ -307,25 +254,23 @@ where
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // TODO: use MaybeUninit::uninit_array if it stabilizes
 | 
			
		||||
        let mut values: [MaybeUninit<<Q::Fetch as Fetch<'a, 's>>::Item>; K] =
 | 
			
		||||
            MaybeUninit::uninit().assume_init();
 | 
			
		||||
        let mut values: [MaybeUninit<QF::Item>; K] = MaybeUninit::uninit().assume_init();
 | 
			
		||||
 | 
			
		||||
        for (value, cursor) in values.iter_mut().zip(&mut self.cursors) {
 | 
			
		||||
            value.as_mut_ptr().write(cursor.peek_last().unwrap());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // TODO: use MaybeUninit::array_assume_init if it stabilizes
 | 
			
		||||
        let values: [<Q::Fetch as Fetch<'a, 's>>::Item; K] =
 | 
			
		||||
            (&values as *const _ as *const [<Q::Fetch as Fetch<'a, 's>>::Item; K]).read();
 | 
			
		||||
        let values: [QF::Item; K] = (&values as *const _ as *const [QF::Item; K]).read();
 | 
			
		||||
 | 
			
		||||
        Some(values)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Get next combination of queried components
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn fetch_next(&mut self) -> Option<[<Q::Fetch as Fetch<'_, 's>>::Item; K]>
 | 
			
		||||
    pub fn fetch_next(&mut self) -> Option<[QF::Item; K]>
 | 
			
		||||
    where
 | 
			
		||||
        Q::Fetch: Clone,
 | 
			
		||||
        QF: Clone,
 | 
			
		||||
        F::Fetch: Clone,
 | 
			
		||||
    {
 | 
			
		||||
        // safety: we are limiting the returned reference to self,
 | 
			
		||||
@ -338,13 +283,13 @@ where
 | 
			
		||||
// 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, Q: WorldQuery, F: WorldQuery, const K: usize> Iterator
 | 
			
		||||
    for QueryCombinationIter<'w, 's, Q, F, K>
 | 
			
		||||
impl<'w, 's, Q: WorldQuery, QF, F: WorldQuery, const K: usize> Iterator
 | 
			
		||||
    for QueryCombinationIter<'w, 's, Q, QF, F, K>
 | 
			
		||||
where
 | 
			
		||||
    Q::Fetch: Clone + ReadOnlyFetch,
 | 
			
		||||
    QF: Fetch<'w, 's, State = Q::State> + Clone + ReadOnlyFetch,
 | 
			
		||||
    F::Fetch: Clone + FilterFetch + ReadOnlyFetch,
 | 
			
		||||
{
 | 
			
		||||
    type Item = [<Q::Fetch as Fetch<'w, 's>>::Item; K];
 | 
			
		||||
    type Item = [QF::Item; K];
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
    fn next(&mut self) -> Option<Self::Item> {
 | 
			
		||||
@ -388,7 +333,10 @@ where
 | 
			
		||||
// (2) each archetype pre-computes length
 | 
			
		||||
// (3) there are no per-entity filters
 | 
			
		||||
// TODO: add an ArchetypeOnlyFilter that enables us to implement this for filters like With<T>
 | 
			
		||||
impl<'w, 's, Q: WorldQuery> ExactSizeIterator for QueryIter<'w, 's, Q, ()> {
 | 
			
		||||
impl<'w, 's, Q: WorldQuery, QF> ExactSizeIterator for QueryIter<'w, 's, Q, QF, ()>
 | 
			
		||||
where
 | 
			
		||||
    QF: Fetch<'w, 's, State = Q::State>,
 | 
			
		||||
{
 | 
			
		||||
    fn len(&self) -> usize {
 | 
			
		||||
        self.query_state
 | 
			
		||||
            .matched_archetypes
 | 
			
		||||
@ -398,18 +346,25 @@ impl<'w, 's, Q: WorldQuery> ExactSizeIterator for QueryIter<'w, 's, Q, ()> {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct QueryIterationCursor<'s, Q: WorldQuery, F: WorldQuery> {
 | 
			
		||||
struct QueryIterationCursor<
 | 
			
		||||
    'w,
 | 
			
		||||
    's,
 | 
			
		||||
    Q: WorldQuery,
 | 
			
		||||
    QF: Fetch<'w, 's, State = Q::State>,
 | 
			
		||||
    F: WorldQuery,
 | 
			
		||||
> {
 | 
			
		||||
    table_id_iter: std::slice::Iter<'s, TableId>,
 | 
			
		||||
    archetype_id_iter: std::slice::Iter<'s, ArchetypeId>,
 | 
			
		||||
    fetch: Q::Fetch,
 | 
			
		||||
    fetch: QF,
 | 
			
		||||
    filter: F::Fetch,
 | 
			
		||||
    current_len: usize,
 | 
			
		||||
    current_index: usize,
 | 
			
		||||
    phantom: PhantomData<&'w Q>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'s, Q: WorldQuery, F: WorldQuery> Clone for QueryIterationCursor<'s, Q, F>
 | 
			
		||||
impl<'w, 's, Q: WorldQuery, QF, F: WorldQuery> Clone for QueryIterationCursor<'w, 's, Q, QF, F>
 | 
			
		||||
where
 | 
			
		||||
    Q::Fetch: Clone,
 | 
			
		||||
    QF: Fetch<'w, 's, State = Q::State> + Clone,
 | 
			
		||||
    F::Fetch: Clone,
 | 
			
		||||
{
 | 
			
		||||
    fn clone(&self) -> Self {
 | 
			
		||||
@ -420,12 +375,14 @@ where
 | 
			
		||||
            filter: self.filter.clone(),
 | 
			
		||||
            current_len: self.current_len,
 | 
			
		||||
            current_index: self.current_index,
 | 
			
		||||
            phantom: PhantomData,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'s, Q: WorldQuery, F: WorldQuery> QueryIterationCursor<'s, Q, F>
 | 
			
		||||
impl<'w, 's, Q: WorldQuery, QF, F: WorldQuery> QueryIterationCursor<'w, 's, Q, QF, F>
 | 
			
		||||
where
 | 
			
		||||
    QF: Fetch<'w, 's, State = Q::State>,
 | 
			
		||||
    F::Fetch: FilterFetch,
 | 
			
		||||
{
 | 
			
		||||
    unsafe fn init_empty(
 | 
			
		||||
@ -447,7 +404,7 @@ where
 | 
			
		||||
        last_change_tick: u32,
 | 
			
		||||
        change_tick: u32,
 | 
			
		||||
    ) -> Self {
 | 
			
		||||
        let fetch = <Q::Fetch as Fetch>::init(
 | 
			
		||||
        let fetch = QF::init(
 | 
			
		||||
            world,
 | 
			
		||||
            &query_state.fetch_state,
 | 
			
		||||
            last_change_tick,
 | 
			
		||||
@ -466,14 +423,15 @@ where
 | 
			
		||||
            archetype_id_iter: query_state.matched_archetype_ids.iter(),
 | 
			
		||||
            current_len: 0,
 | 
			
		||||
            current_index: 0,
 | 
			
		||||
            phantom: PhantomData,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// retrieve item returned from most recent `next` call again.
 | 
			
		||||
    #[inline]
 | 
			
		||||
    unsafe fn peek_last<'w>(&mut self) -> Option<<Q::Fetch as Fetch<'w, 's>>::Item> {
 | 
			
		||||
    unsafe fn peek_last(&mut self) -> Option<QF::Item> {
 | 
			
		||||
        if self.current_index > 0 {
 | 
			
		||||
            if Q::Fetch::IS_DENSE && F::Fetch::IS_DENSE {
 | 
			
		||||
            if QF::IS_DENSE && F::Fetch::IS_DENSE {
 | 
			
		||||
                Some(self.fetch.table_fetch(self.current_index - 1))
 | 
			
		||||
            } else {
 | 
			
		||||
                Some(self.fetch.archetype_fetch(self.current_index - 1))
 | 
			
		||||
@ -487,13 +445,13 @@ where
 | 
			
		||||
    // QueryIter, QueryIterationCursor, QueryState::for_each_unchecked_manual, QueryState::par_for_each_unchecked_manual
 | 
			
		||||
    // We can't currently reuse QueryIterationCursor in QueryIter for performance reasons. See #1763 for context.
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    unsafe fn next<'w>(
 | 
			
		||||
    unsafe fn next(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        tables: &'w Tables,
 | 
			
		||||
        archetypes: &'w Archetypes,
 | 
			
		||||
        query_state: &'s QueryState<Q, F>,
 | 
			
		||||
    ) -> Option<<Q::Fetch as Fetch<'w, 's>>::Item> {
 | 
			
		||||
        if Q::Fetch::IS_DENSE && F::Fetch::IS_DENSE {
 | 
			
		||||
    ) -> Option<QF::Item> {
 | 
			
		||||
        if QF::IS_DENSE && F::Fetch::IS_DENSE {
 | 
			
		||||
            loop {
 | 
			
		||||
                if self.current_index == self.current_len {
 | 
			
		||||
                    let table_id = self.table_id_iter.next()?;
 | 
			
		||||
 | 
			
		||||
@ -3,8 +3,8 @@ use crate::{
 | 
			
		||||
    component::ComponentId,
 | 
			
		||||
    entity::Entity,
 | 
			
		||||
    query::{
 | 
			
		||||
        Access, Fetch, FetchState, FilterFetch, FilteredAccess, QueryCombinationIter, QueryIter,
 | 
			
		||||
        ReadOnlyFetch, WorldQuery,
 | 
			
		||||
        Access, Fetch, FetchState, FilterFetch, FilteredAccess, NopFetch, QueryCombinationIter,
 | 
			
		||||
        QueryIter, WorldQuery,
 | 
			
		||||
    },
 | 
			
		||||
    storage::TableId,
 | 
			
		||||
    world::{World, WorldId},
 | 
			
		||||
@ -73,11 +73,11 @@ where
 | 
			
		||||
    /// Checks if the query is empty for the given [`World`], where the last change and current tick are given.
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn is_empty(&self, world: &World, last_change_tick: u32, change_tick: u32) -> bool {
 | 
			
		||||
        // SAFE: the iterator is instantly consumed via `none_remaining` and the implementation of
 | 
			
		||||
        // `QueryIter::none_remaining` never creates any references to the `<Q::Fetch as Fetch<'w>>::Item`.
 | 
			
		||||
        // SAFE: NopFetch does not access any members while &self ensures no one has exclusive access
 | 
			
		||||
        unsafe {
 | 
			
		||||
            self.iter_unchecked_manual(world, last_change_tick, change_tick)
 | 
			
		||||
                .none_remaining()
 | 
			
		||||
            self.iter_unchecked_manual::<NopFetch<Q::State>>(world, last_change_tick, change_tick)
 | 
			
		||||
                .next()
 | 
			
		||||
                .is_none()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -139,12 +139,17 @@ where
 | 
			
		||||
        &'s mut self,
 | 
			
		||||
        world: &'w World,
 | 
			
		||||
        entity: Entity,
 | 
			
		||||
    ) -> Result<<Q::Fetch as Fetch<'w, 's>>::Item, QueryEntityError>
 | 
			
		||||
    where
 | 
			
		||||
        Q::Fetch: ReadOnlyFetch,
 | 
			
		||||
    {
 | 
			
		||||
    ) -> Result<<Q::ReadOnlyFetch as Fetch<'w, 's>>::Item, QueryEntityError> {
 | 
			
		||||
        self.update_archetypes(world);
 | 
			
		||||
        // SAFETY: query is read only
 | 
			
		||||
        unsafe { self.get_unchecked(world, entity) }
 | 
			
		||||
        unsafe {
 | 
			
		||||
            self.get_unchecked_manual::<Q::ReadOnlyFetch>(
 | 
			
		||||
                world,
 | 
			
		||||
                entity,
 | 
			
		||||
                world.last_change_tick(),
 | 
			
		||||
                world.read_change_tick(),
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Gets the query result for the given [`World`] and [`Entity`].
 | 
			
		||||
@ -154,8 +159,16 @@ where
 | 
			
		||||
        world: &'w mut World,
 | 
			
		||||
        entity: Entity,
 | 
			
		||||
    ) -> Result<<Q::Fetch as Fetch<'w, 's>>::Item, QueryEntityError> {
 | 
			
		||||
        self.update_archetypes(world);
 | 
			
		||||
        // SAFETY: query has unique world access
 | 
			
		||||
        unsafe { self.get_unchecked(world, entity) }
 | 
			
		||||
        unsafe {
 | 
			
		||||
            self.get_unchecked_manual::<Q::Fetch>(
 | 
			
		||||
                world,
 | 
			
		||||
                entity,
 | 
			
		||||
                world.last_change_tick(),
 | 
			
		||||
                world.read_change_tick(),
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline]
 | 
			
		||||
@ -163,14 +176,11 @@ where
 | 
			
		||||
        &'s self,
 | 
			
		||||
        world: &'w World,
 | 
			
		||||
        entity: Entity,
 | 
			
		||||
    ) -> Result<<Q::Fetch as Fetch<'w, 's>>::Item, QueryEntityError>
 | 
			
		||||
    where
 | 
			
		||||
        Q::Fetch: ReadOnlyFetch,
 | 
			
		||||
    {
 | 
			
		||||
    ) -> Result<<Q::ReadOnlyFetch as Fetch<'w, 's>>::Item, QueryEntityError> {
 | 
			
		||||
        self.validate_world(world);
 | 
			
		||||
        // SAFETY: query is read only and world is validated
 | 
			
		||||
        unsafe {
 | 
			
		||||
            self.get_unchecked_manual(
 | 
			
		||||
            self.get_unchecked_manual::<Q::ReadOnlyFetch>(
 | 
			
		||||
                world,
 | 
			
		||||
                entity,
 | 
			
		||||
                world.last_change_tick(),
 | 
			
		||||
@ -192,7 +202,7 @@ where
 | 
			
		||||
        entity: Entity,
 | 
			
		||||
    ) -> Result<<Q::Fetch as Fetch<'w, 's>>::Item, QueryEntityError> {
 | 
			
		||||
        self.update_archetypes(world);
 | 
			
		||||
        self.get_unchecked_manual(
 | 
			
		||||
        self.get_unchecked_manual::<Q::Fetch>(
 | 
			
		||||
            world,
 | 
			
		||||
            entity,
 | 
			
		||||
            world.last_change_tick(),
 | 
			
		||||
@ -207,13 +217,13 @@ where
 | 
			
		||||
    ///
 | 
			
		||||
    /// This does not check for mutable query correctness. To be safe, make sure mutable queries
 | 
			
		||||
    /// have unique access to the components they query.
 | 
			
		||||
    pub unsafe fn get_unchecked_manual<'w, 's>(
 | 
			
		||||
    pub(crate) unsafe fn get_unchecked_manual<'w, 's, QF: Fetch<'w, 's, State = Q::State>>(
 | 
			
		||||
        &'s self,
 | 
			
		||||
        world: &'w World,
 | 
			
		||||
        entity: Entity,
 | 
			
		||||
        last_change_tick: u32,
 | 
			
		||||
        change_tick: u32,
 | 
			
		||||
    ) -> Result<<Q::Fetch as Fetch<'w, 's>>::Item, QueryEntityError> {
 | 
			
		||||
    ) -> Result<QF::Item, QueryEntityError> {
 | 
			
		||||
        let location = world
 | 
			
		||||
            .entities
 | 
			
		||||
            .get(entity)
 | 
			
		||||
@ -225,8 +235,7 @@ where
 | 
			
		||||
            return Err(QueryEntityError::QueryDoesNotMatch);
 | 
			
		||||
        }
 | 
			
		||||
        let archetype = &world.archetypes[location.archetype_id];
 | 
			
		||||
        let mut fetch =
 | 
			
		||||
            <Q::Fetch as Fetch>::init(world, &self.fetch_state, last_change_tick, change_tick);
 | 
			
		||||
        let mut fetch = QF::init(world, &self.fetch_state, last_change_tick, change_tick);
 | 
			
		||||
        let mut filter =
 | 
			
		||||
            <F::Fetch as Fetch>::init(world, &self.filter_state, last_change_tick, change_tick);
 | 
			
		||||
 | 
			
		||||
@ -243,19 +252,28 @@ where
 | 
			
		||||
    ///
 | 
			
		||||
    /// 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, Q, F>
 | 
			
		||||
    where
 | 
			
		||||
        Q::Fetch: ReadOnlyFetch,
 | 
			
		||||
    {
 | 
			
		||||
    pub fn iter<'w, 's>(
 | 
			
		||||
        &'s mut self,
 | 
			
		||||
        world: &'w World,
 | 
			
		||||
    ) -> QueryIter<'w, 's, Q, Q::ReadOnlyFetch, F> {
 | 
			
		||||
        // SAFETY: query is read only
 | 
			
		||||
        unsafe { self.iter_unchecked(world) }
 | 
			
		||||
        unsafe {
 | 
			
		||||
            self.update_archetypes(world);
 | 
			
		||||
            self.iter_unchecked_manual(world, world.last_change_tick(), world.read_change_tick())
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns an [`Iterator`] over the query results for the given [`World`].
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn iter_mut<'w, 's>(&'s mut self, world: &'w mut World) -> QueryIter<'w, 's, Q, F> {
 | 
			
		||||
    pub fn iter_mut<'w, 's>(
 | 
			
		||||
        &'s mut self,
 | 
			
		||||
        world: &'w mut World,
 | 
			
		||||
    ) -> QueryIter<'w, 's, Q, Q::Fetch, F> {
 | 
			
		||||
        // SAFETY: query has unique world access
 | 
			
		||||
        unsafe { self.iter_unchecked(world) }
 | 
			
		||||
        unsafe {
 | 
			
		||||
            self.update_archetypes(world);
 | 
			
		||||
            self.iter_unchecked_manual(world, world.last_change_tick(), world.read_change_tick())
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns an [`Iterator`] over all possible combinations of `K` query results without repetition.
 | 
			
		||||
@ -269,10 +287,10 @@ where
 | 
			
		||||
    /// This can only be called for read-only queries, see [`Self::iter_combinations_mut`] for
 | 
			
		||||
    /// write-queries.
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn iter_manual<'w, 's>(&'s self, world: &'w World) -> QueryIter<'w, 's, Q, F>
 | 
			
		||||
    where
 | 
			
		||||
        Q::Fetch: ReadOnlyFetch,
 | 
			
		||||
    {
 | 
			
		||||
    pub fn iter_manual<'w, 's>(
 | 
			
		||||
        &'s self,
 | 
			
		||||
        world: &'w World,
 | 
			
		||||
    ) -> QueryIter<'w, 's, Q, Q::ReadOnlyFetch, F> {
 | 
			
		||||
        self.validate_world(world);
 | 
			
		||||
        // SAFETY: query is read only and world is validated
 | 
			
		||||
        unsafe {
 | 
			
		||||
@ -294,12 +312,16 @@ where
 | 
			
		||||
    pub fn iter_combinations<'w, 's, const K: usize>(
 | 
			
		||||
        &'s mut self,
 | 
			
		||||
        world: &'w World,
 | 
			
		||||
    ) -> QueryCombinationIter<'w, 's, Q, F, K>
 | 
			
		||||
    where
 | 
			
		||||
        Q::Fetch: ReadOnlyFetch,
 | 
			
		||||
    {
 | 
			
		||||
    ) -> QueryCombinationIter<'w, 's, Q, Q::ReadOnlyFetch, F, K> {
 | 
			
		||||
        // SAFE: query is read only
 | 
			
		||||
        unsafe { self.iter_combinations_unchecked(world) }
 | 
			
		||||
        unsafe {
 | 
			
		||||
            self.update_archetypes(world);
 | 
			
		||||
            self.iter_combinations_unchecked_manual(
 | 
			
		||||
                world,
 | 
			
		||||
                world.last_change_tick(),
 | 
			
		||||
                world.read_change_tick(),
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Iterates over all possible combinations of `K` query results for the given [`World`]
 | 
			
		||||
@ -313,9 +335,16 @@ where
 | 
			
		||||
    pub fn iter_combinations_mut<'w, 's, const K: usize>(
 | 
			
		||||
        &'s mut self,
 | 
			
		||||
        world: &'w mut World,
 | 
			
		||||
    ) -> QueryCombinationIter<'w, 's, Q, F, K> {
 | 
			
		||||
    ) -> QueryCombinationIter<'w, 's, Q, Q::Fetch, F, K> {
 | 
			
		||||
        // SAFE: query has unique world access
 | 
			
		||||
        unsafe { self.iter_combinations_unchecked(world) }
 | 
			
		||||
        unsafe {
 | 
			
		||||
            self.update_archetypes(world);
 | 
			
		||||
            self.iter_combinations_unchecked_manual(
 | 
			
		||||
                world,
 | 
			
		||||
                world.last_change_tick(),
 | 
			
		||||
                world.read_change_tick(),
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns an [`Iterator`] over the query results for the given [`World`].
 | 
			
		||||
@ -328,7 +357,7 @@ where
 | 
			
		||||
    pub unsafe fn iter_unchecked<'w, 's>(
 | 
			
		||||
        &'s mut self,
 | 
			
		||||
        world: &'w World,
 | 
			
		||||
    ) -> QueryIter<'w, 's, Q, F> {
 | 
			
		||||
    ) -> QueryIter<'w, 's, Q, Q::Fetch, F> {
 | 
			
		||||
        self.update_archetypes(world);
 | 
			
		||||
        self.iter_unchecked_manual(world, world.last_change_tick(), world.read_change_tick())
 | 
			
		||||
    }
 | 
			
		||||
@ -345,7 +374,7 @@ where
 | 
			
		||||
    pub unsafe fn iter_combinations_unchecked<'w, 's, const K: usize>(
 | 
			
		||||
        &'s mut self,
 | 
			
		||||
        world: &'w World,
 | 
			
		||||
    ) -> QueryCombinationIter<'w, 's, Q, F, K> {
 | 
			
		||||
    ) -> QueryCombinationIter<'w, 's, Q, Q::Fetch, F, K> {
 | 
			
		||||
        self.update_archetypes(world);
 | 
			
		||||
        self.iter_combinations_unchecked_manual(
 | 
			
		||||
            world,
 | 
			
		||||
@ -364,12 +393,12 @@ where
 | 
			
		||||
    /// This does not validate that `world.id()` matches `self.world_id`. Calling this on a `world`
 | 
			
		||||
    /// with a mismatched WorldId is unsound.
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub(crate) unsafe fn iter_unchecked_manual<'w, 's>(
 | 
			
		||||
    pub(crate) unsafe fn iter_unchecked_manual<'w, 's, QF: Fetch<'w, 's, State = Q::State>>(
 | 
			
		||||
        &'s self,
 | 
			
		||||
        world: &'w World,
 | 
			
		||||
        last_change_tick: u32,
 | 
			
		||||
        change_tick: u32,
 | 
			
		||||
    ) -> QueryIter<'w, 's, Q, F> {
 | 
			
		||||
    ) -> QueryIter<'w, 's, Q, QF, F> {
 | 
			
		||||
        QueryIter::new(world, self, last_change_tick, change_tick)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -384,12 +413,17 @@ where
 | 
			
		||||
    /// This does not validate that `world.id()` matches `self.world_id`. Calling this on a `world`
 | 
			
		||||
    /// with a mismatched WorldId is unsound.
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub(crate) unsafe fn iter_combinations_unchecked_manual<'w, 's, const K: usize>(
 | 
			
		||||
    pub(crate) unsafe fn iter_combinations_unchecked_manual<
 | 
			
		||||
        'w,
 | 
			
		||||
        's,
 | 
			
		||||
        QF: Fetch<'w, 's, State = Q::State>,
 | 
			
		||||
        const K: usize,
 | 
			
		||||
    >(
 | 
			
		||||
        &'s self,
 | 
			
		||||
        world: &'w World,
 | 
			
		||||
        last_change_tick: u32,
 | 
			
		||||
        change_tick: u32,
 | 
			
		||||
    ) -> QueryCombinationIter<'w, 's, Q, F, K> {
 | 
			
		||||
    ) -> QueryCombinationIter<'w, 's, Q, QF, F, K> {
 | 
			
		||||
        QueryCombinationIter::new(world, self, last_change_tick, change_tick)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -398,30 +432,40 @@ where
 | 
			
		||||
    ///
 | 
			
		||||
    /// This can only be called for read-only queries, see [`Self::for_each_mut`] for write-queries.
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn for_each<'w, 's>(
 | 
			
		||||
    pub fn for_each<'w, 's, FN: FnMut(<Q::ReadOnlyFetch as Fetch<'w, 's>>::Item)>(
 | 
			
		||||
        &'s mut self,
 | 
			
		||||
        world: &'w World,
 | 
			
		||||
        func: impl FnMut(<Q::Fetch as Fetch<'w, 's>>::Item),
 | 
			
		||||
    ) where
 | 
			
		||||
        Q::Fetch: ReadOnlyFetch,
 | 
			
		||||
    {
 | 
			
		||||
        func: FN,
 | 
			
		||||
    ) {
 | 
			
		||||
        // SAFETY: query is read only
 | 
			
		||||
        unsafe {
 | 
			
		||||
            self.for_each_unchecked(world, func);
 | 
			
		||||
            self.update_archetypes(world);
 | 
			
		||||
            self.for_each_unchecked_manual::<Q::ReadOnlyFetch, FN>(
 | 
			
		||||
                world,
 | 
			
		||||
                func,
 | 
			
		||||
                world.last_change_tick(),
 | 
			
		||||
                world.read_change_tick(),
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Runs `func` on each query result for the given [`World`]. This is faster than the equivalent
 | 
			
		||||
    /// iter_mut() method, but cannot be chained like a normal [`Iterator`].
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn for_each_mut<'w, 's>(
 | 
			
		||||
    pub fn for_each_mut<'w, 's, FN: FnMut(<Q::Fetch as Fetch<'w, 's>>::Item)>(
 | 
			
		||||
        &'s mut self,
 | 
			
		||||
        world: &'w mut World,
 | 
			
		||||
        func: impl FnMut(<Q::Fetch as Fetch<'w, 's>>::Item),
 | 
			
		||||
        func: FN,
 | 
			
		||||
    ) {
 | 
			
		||||
        // SAFETY: query has unique world access
 | 
			
		||||
        unsafe {
 | 
			
		||||
            self.for_each_unchecked(world, func);
 | 
			
		||||
            self.update_archetypes(world);
 | 
			
		||||
            self.for_each_unchecked_manual::<Q::Fetch, FN>(
 | 
			
		||||
                world,
 | 
			
		||||
                func,
 | 
			
		||||
                world.last_change_tick(),
 | 
			
		||||
                world.read_change_tick(),
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -435,13 +479,13 @@ where
 | 
			
		||||
    /// This does not check for mutable query correctness. To be safe, make sure mutable queries
 | 
			
		||||
    /// have unique access to the components they query.
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub unsafe fn for_each_unchecked<'w, 's>(
 | 
			
		||||
    pub unsafe fn for_each_unchecked<'w, 's, FN: FnMut(<Q::Fetch as Fetch<'w, 's>>::Item)>(
 | 
			
		||||
        &'s mut self,
 | 
			
		||||
        world: &'w World,
 | 
			
		||||
        func: impl FnMut(<Q::Fetch as Fetch<'w, 's>>::Item),
 | 
			
		||||
        func: FN,
 | 
			
		||||
    ) {
 | 
			
		||||
        self.update_archetypes(world);
 | 
			
		||||
        self.for_each_unchecked_manual(
 | 
			
		||||
        self.for_each_unchecked_manual::<Q::Fetch, FN>(
 | 
			
		||||
            world,
 | 
			
		||||
            func,
 | 
			
		||||
            world.last_change_tick(),
 | 
			
		||||
@ -454,33 +498,55 @@ where
 | 
			
		||||
    /// This can only be called for read-only queries, see [`Self::par_for_each_mut`] for
 | 
			
		||||
    /// write-queries.
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn par_for_each<'w, 's>(
 | 
			
		||||
    pub fn par_for_each<
 | 
			
		||||
        'w,
 | 
			
		||||
        's,
 | 
			
		||||
        FN: Fn(<Q::ReadOnlyFetch as Fetch<'w, 's>>::Item) + Send + Sync + Clone,
 | 
			
		||||
    >(
 | 
			
		||||
        &'s mut self,
 | 
			
		||||
        world: &'w World,
 | 
			
		||||
        task_pool: &TaskPool,
 | 
			
		||||
        batch_size: usize,
 | 
			
		||||
        func: impl Fn(<Q::Fetch as Fetch<'w, 's>>::Item) + Send + Sync + Clone,
 | 
			
		||||
    ) where
 | 
			
		||||
        Q::Fetch: ReadOnlyFetch,
 | 
			
		||||
    {
 | 
			
		||||
        func: FN,
 | 
			
		||||
    ) {
 | 
			
		||||
        // SAFETY: query is read only
 | 
			
		||||
        unsafe {
 | 
			
		||||
            self.par_for_each_unchecked(world, task_pool, batch_size, func);
 | 
			
		||||
            self.update_archetypes(world);
 | 
			
		||||
            self.par_for_each_unchecked_manual::<Q::ReadOnlyFetch, FN>(
 | 
			
		||||
                world,
 | 
			
		||||
                task_pool,
 | 
			
		||||
                batch_size,
 | 
			
		||||
                func,
 | 
			
		||||
                world.last_change_tick(),
 | 
			
		||||
                world.read_change_tick(),
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Runs `func` on each query result in parallel using the given `task_pool`.
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn par_for_each_mut<'w, 's>(
 | 
			
		||||
    pub fn par_for_each_mut<
 | 
			
		||||
        'w,
 | 
			
		||||
        's,
 | 
			
		||||
        FN: Fn(<Q::Fetch as Fetch<'w, 's>>::Item) + Send + Sync + Clone,
 | 
			
		||||
    >(
 | 
			
		||||
        &'s mut self,
 | 
			
		||||
        world: &'w mut World,
 | 
			
		||||
        task_pool: &TaskPool,
 | 
			
		||||
        batch_size: usize,
 | 
			
		||||
        func: impl Fn(<Q::Fetch as Fetch<'w, 's>>::Item) + Send + Sync + Clone,
 | 
			
		||||
        func: FN,
 | 
			
		||||
    ) {
 | 
			
		||||
        // SAFETY: query has unique world access
 | 
			
		||||
        unsafe {
 | 
			
		||||
            self.par_for_each_unchecked(world, task_pool, batch_size, func);
 | 
			
		||||
            self.update_archetypes(world);
 | 
			
		||||
            self.par_for_each_unchecked_manual::<Q::Fetch, FN>(
 | 
			
		||||
                world,
 | 
			
		||||
                task_pool,
 | 
			
		||||
                batch_size,
 | 
			
		||||
                func,
 | 
			
		||||
                world.last_change_tick(),
 | 
			
		||||
                world.read_change_tick(),
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -493,15 +559,19 @@ where
 | 
			
		||||
    /// This does not check for mutable query correctness. To be safe, make sure mutable queries
 | 
			
		||||
    /// have unique access to the components they query.
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub unsafe fn par_for_each_unchecked<'w, 's>(
 | 
			
		||||
    pub unsafe fn par_for_each_unchecked<
 | 
			
		||||
        'w,
 | 
			
		||||
        's,
 | 
			
		||||
        FN: Fn(<Q::Fetch as Fetch<'w, 's>>::Item) + Send + Sync + Clone,
 | 
			
		||||
    >(
 | 
			
		||||
        &'s mut self,
 | 
			
		||||
        world: &'w World,
 | 
			
		||||
        task_pool: &TaskPool,
 | 
			
		||||
        batch_size: usize,
 | 
			
		||||
        func: impl Fn(<Q::Fetch as Fetch<'w, 's>>::Item) + Send + Sync + Clone,
 | 
			
		||||
        func: FN,
 | 
			
		||||
    ) {
 | 
			
		||||
        self.update_archetypes(world);
 | 
			
		||||
        self.par_for_each_unchecked_manual(
 | 
			
		||||
        self.par_for_each_unchecked_manual::<Q::Fetch, FN>(
 | 
			
		||||
            world,
 | 
			
		||||
            task_pool,
 | 
			
		||||
            batch_size,
 | 
			
		||||
@ -521,17 +591,21 @@ where
 | 
			
		||||
    /// have unique access to the components they query.
 | 
			
		||||
    /// This does not validate that `world.id()` matches `self.world_id`. Calling this on a `world`
 | 
			
		||||
    /// with a mismatched WorldId is unsound.
 | 
			
		||||
    pub(crate) unsafe fn for_each_unchecked_manual<'w, 's>(
 | 
			
		||||
    pub(crate) unsafe fn for_each_unchecked_manual<
 | 
			
		||||
        'w,
 | 
			
		||||
        's,
 | 
			
		||||
        QF: Fetch<'w, 's, State = Q::State>,
 | 
			
		||||
        FN: FnMut(QF::Item),
 | 
			
		||||
    >(
 | 
			
		||||
        &'s self,
 | 
			
		||||
        world: &'w World,
 | 
			
		||||
        mut func: impl FnMut(<Q::Fetch as Fetch<'w, 's>>::Item),
 | 
			
		||||
        mut func: FN,
 | 
			
		||||
        last_change_tick: u32,
 | 
			
		||||
        change_tick: u32,
 | 
			
		||||
    ) {
 | 
			
		||||
        // NOTE: If you are changing query iteration code, remember to update the following places, where relevant:
 | 
			
		||||
        // QueryIter, QueryIterationCursor, QueryState::for_each_unchecked_manual, QueryState::par_for_each_unchecked_manual
 | 
			
		||||
        let mut fetch =
 | 
			
		||||
            <Q::Fetch as Fetch>::init(world, &self.fetch_state, last_change_tick, change_tick);
 | 
			
		||||
        let mut fetch = QF::init(world, &self.fetch_state, last_change_tick, change_tick);
 | 
			
		||||
        let mut filter =
 | 
			
		||||
            <F::Fetch as Fetch>::init(world, &self.filter_state, last_change_tick, change_tick);
 | 
			
		||||
        if Q::Fetch::IS_DENSE && F::Fetch::IS_DENSE {
 | 
			
		||||
@ -577,19 +651,24 @@ where
 | 
			
		||||
    /// have unique access to the components they query.
 | 
			
		||||
    /// This does not validate that `world.id()` matches `self.world_id`. Calling this on a `world`
 | 
			
		||||
    /// with a mismatched WorldId is unsound.
 | 
			
		||||
    pub unsafe fn par_for_each_unchecked_manual<'w, 's>(
 | 
			
		||||
    pub(crate) unsafe fn par_for_each_unchecked_manual<
 | 
			
		||||
        'w,
 | 
			
		||||
        's,
 | 
			
		||||
        QF: Fetch<'w, 's, State = Q::State>,
 | 
			
		||||
        FN: Fn(QF::Item) + Send + Sync + Clone,
 | 
			
		||||
    >(
 | 
			
		||||
        &'s self,
 | 
			
		||||
        world: &'w World,
 | 
			
		||||
        task_pool: &TaskPool,
 | 
			
		||||
        batch_size: usize,
 | 
			
		||||
        func: impl Fn(<Q::Fetch as Fetch<'w, 's>>::Item) + Send + Sync + Clone,
 | 
			
		||||
        func: FN,
 | 
			
		||||
        last_change_tick: u32,
 | 
			
		||||
        change_tick: u32,
 | 
			
		||||
    ) {
 | 
			
		||||
        // NOTE: If you are changing query iteration code, remember to update the following places, where relevant:
 | 
			
		||||
        // QueryIter, QueryIterationCursor, QueryState::for_each_unchecked_manual, QueryState::par_for_each_unchecked_manual
 | 
			
		||||
        task_pool.scope(|scope| {
 | 
			
		||||
            if Q::Fetch::IS_DENSE && F::Fetch::IS_DENSE {
 | 
			
		||||
            if QF::IS_DENSE && F::Fetch::IS_DENSE {
 | 
			
		||||
                let tables = &world.storages().tables;
 | 
			
		||||
                for table_id in self.matched_table_ids.iter() {
 | 
			
		||||
                    let table = &tables[*table_id];
 | 
			
		||||
@ -597,12 +676,8 @@ where
 | 
			
		||||
                    while offset < table.len() {
 | 
			
		||||
                        let func = func.clone();
 | 
			
		||||
                        scope.spawn(async move {
 | 
			
		||||
                            let mut fetch = <Q::Fetch as Fetch>::init(
 | 
			
		||||
                                world,
 | 
			
		||||
                                &self.fetch_state,
 | 
			
		||||
                                last_change_tick,
 | 
			
		||||
                                change_tick,
 | 
			
		||||
                            );
 | 
			
		||||
                            let mut fetch =
 | 
			
		||||
                                QF::init(world, &self.fetch_state, last_change_tick, change_tick);
 | 
			
		||||
                            let mut filter = <F::Fetch as Fetch>::init(
 | 
			
		||||
                                world,
 | 
			
		||||
                                &self.filter_state,
 | 
			
		||||
@ -633,12 +708,8 @@ where
 | 
			
		||||
                    while offset < archetype.len() {
 | 
			
		||||
                        let func = func.clone();
 | 
			
		||||
                        scope.spawn(async move {
 | 
			
		||||
                            let mut fetch = <Q::Fetch as Fetch>::init(
 | 
			
		||||
                                world,
 | 
			
		||||
                                &self.fetch_state,
 | 
			
		||||
                                last_change_tick,
 | 
			
		||||
                                change_tick,
 | 
			
		||||
                            );
 | 
			
		||||
                            let mut fetch =
 | 
			
		||||
                                QF::init(world, &self.fetch_state, last_change_tick, change_tick);
 | 
			
		||||
                            let mut filter = <F::Fetch as Fetch>::init(
 | 
			
		||||
                                world,
 | 
			
		||||
                                &self.filter_state,
 | 
			
		||||
 | 
			
		||||
@ -785,4 +785,29 @@ mod tests {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn immutable_mut_test() {
 | 
			
		||||
        #[derive(Component, Eq, PartialEq, Debug, Clone, Copy)]
 | 
			
		||||
        struct A(usize);
 | 
			
		||||
 | 
			
		||||
        let mut world = World::default();
 | 
			
		||||
        world.spawn().insert(A(1));
 | 
			
		||||
        world.spawn().insert(A(2));
 | 
			
		||||
 | 
			
		||||
        let mut system_state = SystemState::<Query<&mut A>>::new(&mut world);
 | 
			
		||||
        {
 | 
			
		||||
            let mut query = system_state.get_mut(&mut world);
 | 
			
		||||
            assert_eq!(
 | 
			
		||||
                query.iter_mut().map(|m| *m).collect::<Vec<A>>(),
 | 
			
		||||
                vec![A(1), A(2)],
 | 
			
		||||
                "both components returned by iter_mut of &mut"
 | 
			
		||||
            );
 | 
			
		||||
            assert_eq!(
 | 
			
		||||
                query.iter().collect::<Vec<&A>>(),
 | 
			
		||||
                vec![&A(1), &A(2)],
 | 
			
		||||
                "both components returned by iter of &mut"
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -3,7 +3,7 @@ use crate::{
 | 
			
		||||
    entity::Entity,
 | 
			
		||||
    query::{
 | 
			
		||||
        Fetch, FilterFetch, QueryCombinationIter, QueryEntityError, QueryIter, QueryState,
 | 
			
		||||
        ReadOnlyFetch, WorldQuery,
 | 
			
		||||
        WorldQuery,
 | 
			
		||||
    },
 | 
			
		||||
    world::{Mut, World},
 | 
			
		||||
};
 | 
			
		||||
@ -277,8 +277,8 @@ where
 | 
			
		||||
 | 
			
		||||
    /// Returns an [`Iterator`] over the query results.
 | 
			
		||||
    ///
 | 
			
		||||
    /// This can only be called for read-only queries (due to the [`ReadOnlyFetch`] trait
 | 
			
		||||
    /// bound). See [`Self::iter_mut`] for queries that contain at least one mutable component.
 | 
			
		||||
    /// This can only return immutable data (mutable data will be cast to an immutable form).
 | 
			
		||||
    /// See [`Self::iter_mut`] for queries that contain at least one mutable component.
 | 
			
		||||
    ///
 | 
			
		||||
    /// # Example
 | 
			
		||||
    ///
 | 
			
		||||
@ -299,10 +299,7 @@ where
 | 
			
		||||
    /// # report_names_system.system();
 | 
			
		||||
    /// ```
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn iter(&'s self) -> QueryIter<'w, 's, Q, F>
 | 
			
		||||
    where
 | 
			
		||||
        Q::Fetch: ReadOnlyFetch,
 | 
			
		||||
    {
 | 
			
		||||
    pub fn iter(&'s self) -> QueryIter<'w, 's, Q, Q::ReadOnlyFetch, F> {
 | 
			
		||||
        // SAFE: system runs without conflicts with other systems.
 | 
			
		||||
        // same-system queries have runtime borrow checks when they conflict
 | 
			
		||||
        unsafe {
 | 
			
		||||
@ -332,7 +329,7 @@ where
 | 
			
		||||
    /// # gravity_system.system();
 | 
			
		||||
    /// ```
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn iter_mut(&mut self) -> QueryIter<'_, '_, Q, F> {
 | 
			
		||||
    pub fn iter_mut(&mut self) -> QueryIter<'_, '_, Q, Q::Fetch, F> {
 | 
			
		||||
        // SAFE: system runs without conflicts with other systems.
 | 
			
		||||
        // same-system queries have runtime borrow checks when they conflict
 | 
			
		||||
        unsafe {
 | 
			
		||||
@ -342,17 +339,16 @@ where
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns an [`Iterator`] over all possible combinations of `K` query results without repetition.
 | 
			
		||||
    /// This can only be called for read-only queries
 | 
			
		||||
    /// This can only return immutable data
 | 
			
		||||
    ///
 | 
			
		||||
    ///  For permutations of size K of query returning N results, you will get:
 | 
			
		||||
    /// - if K == N: one permutation of all query results
 | 
			
		||||
    /// - if K < N: all possible K-sized combinations of query results, without repetition
 | 
			
		||||
    /// - if K > N: empty set (no K-sized combinations exist)
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn iter_combinations<const K: usize>(&self) -> QueryCombinationIter<'_, '_, Q, F, K>
 | 
			
		||||
    where
 | 
			
		||||
        Q::Fetch: ReadOnlyFetch,
 | 
			
		||||
    {
 | 
			
		||||
    pub fn iter_combinations<const K: usize>(
 | 
			
		||||
        &self,
 | 
			
		||||
    ) -> QueryCombinationIter<'_, '_, Q, Q::ReadOnlyFetch, F, K> {
 | 
			
		||||
        // SAFE: system runs without conflicts with other systems.
 | 
			
		||||
        // same-system queries have runtime borrow checks when they conflict
 | 
			
		||||
        unsafe {
 | 
			
		||||
@ -389,7 +385,7 @@ where
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn iter_combinations_mut<const K: usize>(
 | 
			
		||||
        &mut self,
 | 
			
		||||
    ) -> QueryCombinationIter<'_, '_, Q, F, K> {
 | 
			
		||||
    ) -> QueryCombinationIter<'_, '_, Q, Q::Fetch, F, K> {
 | 
			
		||||
        // SAFE: system runs without conflicts with other systems.
 | 
			
		||||
        // same-system queries have runtime borrow checks when they conflict
 | 
			
		||||
        unsafe {
 | 
			
		||||
@ -408,7 +404,7 @@ where
 | 
			
		||||
    /// 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]
 | 
			
		||||
    pub unsafe fn iter_unsafe(&self) -> QueryIter<'_, '_, Q, F> {
 | 
			
		||||
    pub unsafe fn iter_unsafe(&'s self) -> QueryIter<'w, 's, Q, Q::Fetch, F> {
 | 
			
		||||
        // SEMI-SAFE: system runs without conflicts with other systems.
 | 
			
		||||
        // same-system queries have runtime borrow checks when they conflict
 | 
			
		||||
        self.state
 | 
			
		||||
@ -424,7 +420,7 @@ where
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub unsafe fn iter_combinations_unsafe<const K: usize>(
 | 
			
		||||
        &self,
 | 
			
		||||
    ) -> QueryCombinationIter<'_, '_, Q, F, K> {
 | 
			
		||||
    ) -> QueryCombinationIter<'_, '_, Q, Q::Fetch, F, K> {
 | 
			
		||||
        // SEMI-SAFE: system runs without conflicts with other systems.
 | 
			
		||||
        // same-system queries have runtime borrow checks when they conflict
 | 
			
		||||
        self.state.iter_combinations_unchecked_manual(
 | 
			
		||||
@ -437,7 +433,7 @@ where
 | 
			
		||||
    /// Runs `f` on each query result. This is faster than the equivalent iter() method, but cannot
 | 
			
		||||
    /// be chained like a normal [`Iterator`].
 | 
			
		||||
    ///
 | 
			
		||||
    /// This can only be called for read-only queries, see [`Self::for_each_mut`] for write-queries.
 | 
			
		||||
    /// This can only pass in immutable data, see [`Self::for_each_mut`] for mutable access.
 | 
			
		||||
    ///
 | 
			
		||||
    /// # Example
 | 
			
		||||
    ///
 | 
			
		||||
@ -458,19 +454,17 @@ where
 | 
			
		||||
    /// # report_names_system.system();
 | 
			
		||||
    /// ```
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn for_each(&'s self, f: impl FnMut(<Q::Fetch as Fetch<'w, 's>>::Item))
 | 
			
		||||
    where
 | 
			
		||||
        Q::Fetch: ReadOnlyFetch,
 | 
			
		||||
    {
 | 
			
		||||
    pub fn for_each<FN: FnMut(<Q::ReadOnlyFetch as Fetch<'w, 's>>::Item)>(&'s self, f: FN) {
 | 
			
		||||
        // SAFE: system runs without conflicts with other systems.
 | 
			
		||||
        // same-system queries have runtime borrow checks when they conflict
 | 
			
		||||
        unsafe {
 | 
			
		||||
            self.state.for_each_unchecked_manual(
 | 
			
		||||
                self.world,
 | 
			
		||||
                f,
 | 
			
		||||
                self.last_change_tick,
 | 
			
		||||
                self.change_tick,
 | 
			
		||||
            )
 | 
			
		||||
            self.state
 | 
			
		||||
                .for_each_unchecked_manual::<Q::ReadOnlyFetch, FN>(
 | 
			
		||||
                    self.world,
 | 
			
		||||
                    f,
 | 
			
		||||
                    self.last_change_tick,
 | 
			
		||||
                    self.change_tick,
 | 
			
		||||
                )
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -496,11 +490,11 @@ where
 | 
			
		||||
    /// # gravity_system.system();
 | 
			
		||||
    /// ```
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn for_each_mut<'a>(&'a mut self, f: impl FnMut(<Q::Fetch as Fetch<'a, 'a>>::Item)) {
 | 
			
		||||
    pub fn for_each_mut<'a, FN: FnMut(<Q::Fetch as Fetch<'a, 'a>>::Item)>(&'a mut self, f: FN) {
 | 
			
		||||
        // SAFE: system runs without conflicts with other systems. same-system queries have runtime
 | 
			
		||||
        // borrow checks when they conflict
 | 
			
		||||
        unsafe {
 | 
			
		||||
            self.state.for_each_unchecked_manual(
 | 
			
		||||
            self.state.for_each_unchecked_manual::<Q::Fetch, FN>(
 | 
			
		||||
                self.world,
 | 
			
		||||
                f,
 | 
			
		||||
                self.last_change_tick,
 | 
			
		||||
@ -511,43 +505,42 @@ where
 | 
			
		||||
 | 
			
		||||
    /// Runs `f` on each query result in parallel using the given task pool.
 | 
			
		||||
    ///
 | 
			
		||||
    /// This can only be called for read-only queries, see [`Self::par_for_each_mut`] for
 | 
			
		||||
    /// write-queries.
 | 
			
		||||
    /// This can only be called for immutable data, see [`Self::par_for_each_mut`] for
 | 
			
		||||
    /// mutable access.
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn par_for_each(
 | 
			
		||||
    pub fn par_for_each<FN: Fn(<Q::ReadOnlyFetch as Fetch<'w, 's>>::Item) + Send + Sync + Clone>(
 | 
			
		||||
        &'s self,
 | 
			
		||||
        task_pool: &TaskPool,
 | 
			
		||||
        batch_size: usize,
 | 
			
		||||
        f: impl Fn(<Q::Fetch as Fetch<'w, 's>>::Item) + Send + Sync + Clone,
 | 
			
		||||
    ) where
 | 
			
		||||
        Q::Fetch: ReadOnlyFetch,
 | 
			
		||||
    {
 | 
			
		||||
        f: FN,
 | 
			
		||||
    ) {
 | 
			
		||||
        // SAFE: system runs without conflicts with other systems. same-system queries have runtime
 | 
			
		||||
        // borrow checks when they conflict
 | 
			
		||||
        unsafe {
 | 
			
		||||
            self.state.par_for_each_unchecked_manual(
 | 
			
		||||
                self.world,
 | 
			
		||||
                task_pool,
 | 
			
		||||
                batch_size,
 | 
			
		||||
                f,
 | 
			
		||||
                self.last_change_tick,
 | 
			
		||||
                self.change_tick,
 | 
			
		||||
            )
 | 
			
		||||
            self.state
 | 
			
		||||
                .par_for_each_unchecked_manual::<Q::ReadOnlyFetch, FN>(
 | 
			
		||||
                    self.world,
 | 
			
		||||
                    task_pool,
 | 
			
		||||
                    batch_size,
 | 
			
		||||
                    f,
 | 
			
		||||
                    self.last_change_tick,
 | 
			
		||||
                    self.change_tick,
 | 
			
		||||
                )
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Runs `f` on each query result in parallel using the given task pool.
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn par_for_each_mut<'a>(
 | 
			
		||||
    pub fn par_for_each_mut<'a, FN: Fn(<Q::Fetch as Fetch<'a, 'a>>::Item) + Send + Sync + Clone>(
 | 
			
		||||
        &'a mut self,
 | 
			
		||||
        task_pool: &TaskPool,
 | 
			
		||||
        batch_size: usize,
 | 
			
		||||
        f: impl Fn(<Q::Fetch as Fetch<'a, 'a>>::Item) + Send + Sync + Clone,
 | 
			
		||||
        f: FN,
 | 
			
		||||
    ) {
 | 
			
		||||
        // SAFE: system runs without conflicts with other systems. same-system queries have runtime
 | 
			
		||||
        // borrow checks when they conflict
 | 
			
		||||
        unsafe {
 | 
			
		||||
            self.state.par_for_each_unchecked_manual(
 | 
			
		||||
            self.state.par_for_each_unchecked_manual::<Q::Fetch, FN>(
 | 
			
		||||
                self.world,
 | 
			
		||||
                task_pool,
 | 
			
		||||
                batch_size,
 | 
			
		||||
@ -563,8 +556,8 @@ where
 | 
			
		||||
    /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is
 | 
			
		||||
    /// returned instead.
 | 
			
		||||
    ///
 | 
			
		||||
    /// This can only be called for read-only queries (due to the [`ReadOnlyFetch`] trait bound).
 | 
			
		||||
    /// see [`get_mut`](Self::get_mut) for queries that contain at least one mutable component.
 | 
			
		||||
    /// This can only return immutable data (mutable data will be cast to an immutable form).
 | 
			
		||||
    /// See [`get_mut`](Self::get_mut) for queries that contain at least one mutable component.
 | 
			
		||||
    ///
 | 
			
		||||
    /// # Example
 | 
			
		||||
    ///
 | 
			
		||||
@ -593,14 +586,11 @@ where
 | 
			
		||||
    pub fn get(
 | 
			
		||||
        &'s self,
 | 
			
		||||
        entity: Entity,
 | 
			
		||||
    ) -> Result<<Q::Fetch as Fetch<'w, 's>>::Item, QueryEntityError>
 | 
			
		||||
    where
 | 
			
		||||
        Q::Fetch: ReadOnlyFetch,
 | 
			
		||||
    {
 | 
			
		||||
    ) -> Result<<Q::ReadOnlyFetch as Fetch<'w, 's>>::Item, QueryEntityError> {
 | 
			
		||||
        // SAFE: system runs without conflicts with other systems.
 | 
			
		||||
        // same-system queries have runtime borrow checks when they conflict
 | 
			
		||||
        unsafe {
 | 
			
		||||
            self.state.get_unchecked_manual(
 | 
			
		||||
            self.state.get_unchecked_manual::<Q::ReadOnlyFetch>(
 | 
			
		||||
                self.world,
 | 
			
		||||
                entity,
 | 
			
		||||
                self.last_change_tick,
 | 
			
		||||
@ -641,7 +631,7 @@ where
 | 
			
		||||
        // SAFE: system runs without conflicts with other systems.
 | 
			
		||||
        // same-system queries have runtime borrow checks when they conflict
 | 
			
		||||
        unsafe {
 | 
			
		||||
            self.state.get_unchecked_manual(
 | 
			
		||||
            self.state.get_unchecked_manual::<Q::Fetch>(
 | 
			
		||||
                self.world,
 | 
			
		||||
                entity,
 | 
			
		||||
                self.last_change_tick,
 | 
			
		||||
@ -661,13 +651,17 @@ where
 | 
			
		||||
    /// this call does not result in multiple mutable references to the same component
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub unsafe fn get_unchecked(
 | 
			
		||||
        &self,
 | 
			
		||||
        &'s self,
 | 
			
		||||
        entity: Entity,
 | 
			
		||||
    ) -> Result<<Q::Fetch as Fetch>::Item, QueryEntityError> {
 | 
			
		||||
    ) -> Result<<Q::Fetch as Fetch<'w, 's>>::Item, QueryEntityError> {
 | 
			
		||||
        // SEMI-SAFE: system runs without conflicts with other systems.
 | 
			
		||||
        // same-system queries have runtime borrow checks when they conflict
 | 
			
		||||
        self.state
 | 
			
		||||
            .get_unchecked_manual(self.world, entity, self.last_change_tick, self.change_tick)
 | 
			
		||||
        self.state.get_unchecked_manual::<Q::Fetch>(
 | 
			
		||||
            self.world,
 | 
			
		||||
            entity,
 | 
			
		||||
            self.last_change_tick,
 | 
			
		||||
            self.change_tick,
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns a reference to the [`Entity`]'s [`Component`] of the given type.
 | 
			
		||||
@ -800,9 +794,8 @@ where
 | 
			
		||||
    /// Returns a single immutable query result when there is exactly one entity matching
 | 
			
		||||
    /// the query.
 | 
			
		||||
    ///
 | 
			
		||||
    /// This can only be called for read-only queries (due to the [`ReadOnlyFetch`] trait
 | 
			
		||||
    /// bound). Use [`single_mut`](Self::single_mut) for queries that contain at least one
 | 
			
		||||
    /// mutable component.
 | 
			
		||||
    /// This can only return immutable data. Use [`single_mut`](Self::single_mut) for
 | 
			
		||||
    /// queries that contain at least one mutable component.
 | 
			
		||||
    ///
 | 
			
		||||
    /// # Example
 | 
			
		||||
    ///
 | 
			
		||||
@ -824,19 +817,15 @@ where
 | 
			
		||||
    /// Panics if the number of query results is not exactly one. Use
 | 
			
		||||
    /// [`get_single`](Self::get_single) to return a `Result` instead of panicking.
 | 
			
		||||
    #[track_caller]
 | 
			
		||||
    pub fn single(&'s self) -> <Q::Fetch as Fetch<'w, 's>>::Item
 | 
			
		||||
    where
 | 
			
		||||
        Q::Fetch: ReadOnlyFetch,
 | 
			
		||||
    {
 | 
			
		||||
    pub fn single(&'s self) -> <Q::ReadOnlyFetch as Fetch<'w, 's>>::Item {
 | 
			
		||||
        self.get_single().unwrap()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Returns a single immutable query result when there is exactly one entity matching
 | 
			
		||||
    /// the query.
 | 
			
		||||
    ///
 | 
			
		||||
    /// This can only be called for read-only queries (due to the [`ReadOnlyFetch`] trait
 | 
			
		||||
    /// bound). Use [`get_single_mut`](Self::get_single_mut) for queries that contain at least one
 | 
			
		||||
    /// mutable component.
 | 
			
		||||
    /// This can only return immutable data. Use [`get_single_mut`](Self::get_single_mut)
 | 
			
		||||
    /// for queries that contain at least one mutable component.
 | 
			
		||||
    ///
 | 
			
		||||
    /// If the number of query results is not exactly one, a [`QuerySingleError`] is returned
 | 
			
		||||
    /// instead.
 | 
			
		||||
@ -863,10 +852,9 @@ where
 | 
			
		||||
    /// }
 | 
			
		||||
    /// # player_scoring_system.system();
 | 
			
		||||
    /// ```
 | 
			
		||||
    pub fn get_single(&'s self) -> Result<<Q::Fetch as Fetch<'w, 's>>::Item, QuerySingleError>
 | 
			
		||||
    where
 | 
			
		||||
        Q::Fetch: ReadOnlyFetch,
 | 
			
		||||
    {
 | 
			
		||||
    pub fn get_single(
 | 
			
		||||
        &'s self,
 | 
			
		||||
    ) -> Result<<Q::ReadOnlyFetch as Fetch<'w, 's>>::Item, QuerySingleError> {
 | 
			
		||||
        let mut query = self.iter();
 | 
			
		||||
        let first = query.next();
 | 
			
		||||
        let extra = query.next().is_some();
 | 
			
		||||
@ -970,8 +958,6 @@ where
 | 
			
		||||
    /// ```
 | 
			
		||||
    #[inline]
 | 
			
		||||
    pub fn is_empty(&self) -> bool {
 | 
			
		||||
        // TODO: This code can be replaced with `self.iter().next().is_none()` if/when
 | 
			
		||||
        // we sort out how to convert "write" queries to "read" queries.
 | 
			
		||||
        self.state
 | 
			
		||||
            .is_empty(self.world, self.last_change_tick, self.change_tick)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,28 @@
 | 
			
		||||
use bevy_ecs::prelude::*;
 | 
			
		||||
use bevy_ecs::system::SystemState;
 | 
			
		||||
 | 
			
		||||
#[derive(Component, Eq, PartialEq, Debug, Clone, Copy)]
 | 
			
		||||
struct A(usize);
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    let mut world = World::default();
 | 
			
		||||
    world.spawn().insert(A(1));
 | 
			
		||||
    world.spawn().insert(A(2));
 | 
			
		||||
 | 
			
		||||
    let mut system_state = SystemState::<Query<&mut A>>::new(&mut world);
 | 
			
		||||
    {
 | 
			
		||||
        let mut query = system_state.get_mut(&mut world);
 | 
			
		||||
        let mut_vec = query.iter_mut().collect::<Vec<bevy_ecs::prelude::Mut<A>>>();
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            // this should fail to compile due to the later use of mut_vec
 | 
			
		||||
            query.iter().collect::<Vec<&A>>(),
 | 
			
		||||
            vec![&A(1), &A(2)],
 | 
			
		||||
            "both components returned by iter of &mut"
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            mut_vec.iter().map(|m| **m).collect::<Vec<A>>(),
 | 
			
		||||
            vec![A(1), A(2)],
 | 
			
		||||
            "both components returned by iter_mut of &mut"
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,11 @@
 | 
			
		||||
error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable
 | 
			
		||||
  --> tests/ui/system_state_iter_mut_overlap_safety.rs:18:13
 | 
			
		||||
   |
 | 
			
		||||
15 |         let mut_vec = query.iter_mut().collect::<Vec<bevy_ecs::prelude::Mut<A>>>();
 | 
			
		||||
   |                       ----- mutable borrow occurs here
 | 
			
		||||
...
 | 
			
		||||
18 |             query.iter().collect::<Vec<&A>>(),
 | 
			
		||||
   |             ^^^^^ immutable borrow occurs here
 | 
			
		||||
...
 | 
			
		||||
23 |             mut_vec.iter().map(|m| **m).collect::<Vec<A>>(),
 | 
			
		||||
   |             ------- mutable borrow later used here
 | 
			
		||||
@ -8,7 +8,7 @@ use bevy_asset::{Asset, Handle};
 | 
			
		||||
use bevy_ecs::{
 | 
			
		||||
    component::Component,
 | 
			
		||||
    prelude::*,
 | 
			
		||||
    query::{FilterFetch, QueryItem, ReadOnlyFetch, WorldQuery},
 | 
			
		||||
    query::{FilterFetch, QueryItem, WorldQuery},
 | 
			
		||||
    system::{
 | 
			
		||||
        lifetimeless::{Read, SCommands, SQuery},
 | 
			
		||||
        RunSystem, SystemParamItem,
 | 
			
		||||
@ -141,7 +141,6 @@ impl<C, F> Default for ExtractComponentPlugin<C, F> {
 | 
			
		||||
 | 
			
		||||
impl<C: ExtractComponent> Plugin for ExtractComponentPlugin<C>
 | 
			
		||||
where
 | 
			
		||||
    <C::Query as WorldQuery>::Fetch: ReadOnlyFetch,
 | 
			
		||||
    <C::Filter as WorldQuery>::Fetch: FilterFetch,
 | 
			
		||||
{
 | 
			
		||||
    fn build(&self, app: &mut App) {
 | 
			
		||||
@ -167,7 +166,6 @@ pub struct ExtractComponentSystem<C: ExtractComponent>(PhantomData<C>);
 | 
			
		||||
impl<C: ExtractComponent> RunSystem for ExtractComponentSystem<C>
 | 
			
		||||
where
 | 
			
		||||
    <C::Filter as WorldQuery>::Fetch: FilterFetch,
 | 
			
		||||
    <C::Query as WorldQuery>::Fetch: ReadOnlyFetch,
 | 
			
		||||
{
 | 
			
		||||
    type Param = (
 | 
			
		||||
        SCommands,
 | 
			
		||||
@ -176,9 +174,9 @@ where
 | 
			
		||||
        SQuery<(Entity, C::Query), C::Filter>,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    fn run((mut commands, mut previous_len, query): SystemParamItem<Self::Param>) {
 | 
			
		||||
    fn run((mut commands, mut previous_len, mut query): SystemParamItem<Self::Param>) {
 | 
			
		||||
        let mut values = Vec::with_capacity(*previous_len);
 | 
			
		||||
        for (entity, query_item) in query.iter() {
 | 
			
		||||
        for (entity, query_item) in query.iter_mut() {
 | 
			
		||||
            values.push((entity, (C::extract_component(query_item),)));
 | 
			
		||||
        }
 | 
			
		||||
        *previous_len = values.len();
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user