diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index d68c64375e2e5..88dd33f4ca4d8 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -309,8 +309,16 @@ pub trait WorldQuery { + ReadOnlyFetch; } +/// The item type returned when you iterate a [`Query`](crate::system::Query) or [`QueryState`](crate::query::QueryState) +/// +/// Unlike [`ReadOnlyQueryItem`], this type may allow mutable access to the component data. pub type QueryItem<'w, 's, Q> = <::Fetch as Fetch<'w, 's>>::Item; +/// The item type returned when you iterate a [`Query`](crate::system::Query) or [`QueryState`](crate::query::QueryState) +/// +/// Unlike [`QueryItem`], this type only permits immutable access to the component data. +pub type ReadOnlyQueryItem<'w, 's, Q> = <::ReadOnlyFetch as Fetch<'w, 's>>::Item; + /// Types that implement this trait are responsible for fetching query items from tables or /// archetypes. /// diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index f675de4d89a1d..1859fc0391d55 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -4,7 +4,7 @@ use crate::{ entity::Entity, query::{ Access, Fetch, FetchState, FilterFetch, FilteredAccess, NopFetch, QueryCombinationIter, - QueryIter, WorldQuery, + QueryItem, QueryIter, ReadOnlyQueryItem, WorldQuery, }, storage::TableId, world::{World, WorldId}, @@ -140,7 +140,7 @@ where &'s mut self, world: &'w World, entity: Entity, - ) -> Result<>::Item, QueryEntityError> { + ) -> Result, QueryEntityError> { self.update_archetypes(world); // SAFETY: query is read only unsafe { @@ -159,7 +159,7 @@ where &'s mut self, world: &'w mut World, entity: Entity, - ) -> Result<>::Item, QueryEntityError> { + ) -> Result, QueryEntityError> { self.update_archetypes(world); // SAFETY: query has unique world access unsafe { @@ -177,7 +177,7 @@ where &'s self, world: &'w World, entity: Entity, - ) -> Result<>::Item, QueryEntityError> { + ) -> Result, QueryEntityError> { self.validate_world(world); // SAFETY: query is read only and world is validated unsafe { @@ -201,7 +201,7 @@ where &'s mut self, world: &'w World, entity: Entity, - ) -> Result<>::Item, QueryEntityError> { + ) -> Result, QueryEntityError> { self.update_archetypes(world); self.get_unchecked_manual::( world, @@ -427,7 +427,7 @@ 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, FN: FnMut(>::Item)>( + pub fn for_each<'w, 's, FN: FnMut(ReadOnlyQueryItem<'w, 's, Q>)>( &'s mut self, world: &'w World, func: FN, @@ -447,7 +447,7 @@ where /// 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, FN: FnMut(>::Item)>( + pub fn for_each_mut<'w, 's, FN: FnMut(QueryItem<'w, 's, Q>)>( &'s mut self, world: &'w mut World, func: FN, @@ -467,14 +467,12 @@ where /// Runs `func` on each query result for the given [`World`]. 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. - /// /// # Safety /// /// 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, FN: FnMut(>::Item)>( + pub unsafe fn for_each_unchecked<'w, 's, FN: FnMut(QueryItem<'w, 's, Q>)>( &'s mut self, world: &'w World, func: FN, @@ -493,11 +491,7 @@ 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, - FN: Fn(>::Item) + Send + Sync + Clone, - >( + pub fn par_for_each<'w, 's, FN: Fn(ReadOnlyQueryItem<'w, 's, Q>) + Send + Sync + Clone>( &'s mut self, world: &'w World, task_pool: &TaskPool, @@ -520,11 +514,7 @@ where /// Runs `func` on each query result in parallel using the given `task_pool`. #[inline] - pub fn par_for_each_mut< - 'w, - 's, - FN: Fn(>::Item) + Send + Sync + Clone, - >( + pub fn par_for_each_mut<'w, 's, FN: Fn(QueryItem<'w, 's, Q>) + Send + Sync + Clone>( &'s mut self, world: &'w mut World, task_pool: &TaskPool, @@ -557,7 +547,7 @@ where pub unsafe fn par_for_each_unchecked< 'w, 's, - FN: Fn(>::Item) + Send + Sync + Clone, + FN: Fn(QueryItem<'w, 's, Q>) + Send + Sync + Clone, >( &'s mut self, world: &'w World, diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 349121b06bd87..f8a48e30c0859 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -2,8 +2,8 @@ use crate::{ component::Component, entity::Entity, query::{ - Fetch, FilterFetch, NopFetch, QueryCombinationIter, QueryEntityError, QueryIter, - QueryState, ReadOnlyFetch, WorldQuery, + FilterFetch, NopFetch, QueryCombinationIter, QueryEntityError, QueryItem, QueryIter, + QueryState, ReadOnlyFetch, ReadOnlyQueryItem, WorldQuery, }, world::{Mut, World}, }; @@ -454,10 +454,7 @@ where /// # bevy_ecs::system::assert_is_system(report_names_system); /// ``` #[inline] - pub fn for_each<'this>( - &'this self, - f: impl FnMut(>::Item), - ) { + pub fn for_each<'this>(&'this self, f: impl FnMut(ReadOnlyQueryItem<'this, 's, Q>)) { // SAFE: system runs without conflicts with other systems. // same-system queries have runtime borrow checks when they conflict unsafe { @@ -492,7 +489,7 @@ where /// # bevy_ecs::system::assert_is_system(gravity_system); /// ``` #[inline] - pub fn for_each_mut<'a, FN: FnMut(>::Item)>(&'a mut self, f: FN) { + pub fn for_each_mut<'a, FN: FnMut(QueryItem<'a, 'a, Q>)>(&'a mut self, f: FN) { // SAFE: system runs without conflicts with other systems. same-system queries have runtime // borrow checks when they conflict unsafe { @@ -530,7 +527,7 @@ where &'this self, task_pool: &TaskPool, batch_size: usize, - f: impl Fn(>::Item) + Send + Sync + Clone, + f: impl Fn(ReadOnlyQueryItem<'this, 's, Q>) + Send + Sync + Clone, ) { // SAFE: system runs without conflicts with other systems. same-system queries have runtime // borrow checks when they conflict @@ -550,7 +547,7 @@ where /// Runs `f` on each query result in parallel using the given [`TaskPool`]. /// See [`Self::par_for_each`] for more details. #[inline] - pub fn par_for_each_mut<'a, FN: Fn(>::Item) + Send + Sync + Clone>( + pub fn par_for_each_mut<'a, FN: Fn(QueryItem<'a, 'a, Q>) + Send + Sync + Clone>( &'a mut self, task_pool: &TaskPool, batch_size: usize, @@ -602,10 +599,7 @@ where /// # bevy_ecs::system::assert_is_system(print_selected_character_name_system); /// ``` #[inline] - pub fn get( - &self, - entity: Entity, - ) -> Result<>::Item, QueryEntityError> { + pub fn get(&self, entity: Entity) -> Result, QueryEntityError> { // SAFE: system runs without conflicts with other systems. // same-system queries have runtime borrow checks when they conflict unsafe { @@ -643,10 +637,7 @@ where /// # bevy_ecs::system::assert_is_system(poison_system); /// ``` #[inline] - pub fn get_mut( - &mut self, - entity: Entity, - ) -> Result<::Item, QueryEntityError> { + pub fn get_mut(&mut self, entity: Entity) -> Result, QueryEntityError> { // SAFE: system runs without conflicts with other systems. // same-system queries have runtime borrow checks when they conflict unsafe { @@ -672,7 +663,7 @@ where pub unsafe fn get_unchecked( &'s self, entity: Entity, - ) -> Result<>::Item, QueryEntityError> { + ) -> Result, 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::( @@ -836,7 +827,7 @@ 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(&self) -> >::Item { + pub fn single(&self) -> ReadOnlyQueryItem { self.get_single().unwrap() } @@ -871,9 +862,7 @@ where /// } /// # bevy_ecs::system::assert_is_system(player_scoring_system); /// ``` - pub fn get_single( - &self, - ) -> Result<>::Item, QuerySingleError> { + pub fn get_single(&self) -> Result, QuerySingleError> { let mut query = self.iter(); let first = query.next(); let extra = query.next().is_some(); @@ -912,7 +901,7 @@ where /// Panics if the number of query results is not exactly one. Use /// [`get_single_mut`](Self::get_single_mut) to return a `Result` instead of panicking. #[track_caller] - pub fn single_mut(&mut self) -> >::Item { + pub fn single_mut(&mut self) -> QueryItem { self.get_single_mut().unwrap() } @@ -938,9 +927,7 @@ where /// } /// # bevy_ecs::system::assert_is_system(regenerate_player_health_system); /// ``` - pub fn get_single_mut( - &mut self, - ) -> Result<>::Item, QuerySingleError> { + pub fn get_single_mut(&mut self) -> Result, QuerySingleError> { let mut query = self.iter_mut(); let first = query.next(); let extra = query.next().is_some(); @@ -1081,7 +1068,7 @@ where pub fn get_inner( &'s self, entity: Entity, - ) -> Result<>::Item, QueryEntityError> { + ) -> Result, QueryEntityError> { // SAFE: system runs without conflicts with other systems. // same-system queries have runtime borrow checks when they conflict unsafe {