From 879b170f2893c41203411811922df2c987be62b9 Mon Sep 17 00:00:00 2001 From: James Liu Date: Mon, 11 Mar 2024 11:17:46 -0700 Subject: [PATCH] Mention in docs about the query iteration order and result uniqueness. (#12400) # Objective Fix #10876. Improve `Query` and `QueryState`'s docs. ## Solution Explicitly denote that Query is always guaranteed to return results from all matching entities once and only once for each entity, and that iteration order is not guaranteed in any way. --- crates/bevy_ecs/src/query/state.rs | 24 +++++++++++++++++ crates/bevy_ecs/src/system/query.rs | 41 ++++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index 3eb76d3d3df75..8abd77d00d091 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -730,6 +730,9 @@ impl QueryState { } /// Returns an [`Iterator`] over the query results for the given [`World`]. + /// + /// This iterator is always guaranteed to return results from each matching entity once and only once. + /// Iteration order is not guaranteed. #[inline] pub fn iter_mut<'w, 's>(&'s mut self, world: &'w mut World) -> QueryIter<'w, 's, D, F> { self.update_archetypes(world); @@ -744,6 +747,9 @@ impl QueryState { /// Returns an [`Iterator`] over the query results for the given [`World`] without updating the query's archetypes. /// Archetypes must be manually updated before by using [`Self::update_archetypes`]. /// + /// This iterator is always guaranteed to return results from each matching entity once and only once. + /// Iteration order is not guaranteed. + /// /// This can only be called for read-only queries. #[inline] pub fn iter_manual<'w, 's>(&'s self, world: &'w World) -> QueryIter<'w, 's, D::ReadOnly, F> { @@ -777,6 +783,9 @@ impl QueryState { /// /// The `iter_combinations` method does not guarantee order of iteration. /// + /// This iterator is always guaranteed to return results from each unique pair of matching entities. + /// Iteration order is not guaranteed. + /// /// This can only be called for read-only queries, see [`Self::iter_combinations_mut`] for /// write-queries. #[inline] @@ -923,6 +932,9 @@ impl QueryState { /// Returns an [`Iterator`] over the query results for the given [`World`]. /// + /// This iterator is always guaranteed to return results from each matching entity once and only once. + /// Iteration order is not guaranteed. + /// /// # Safety /// /// This does not check for mutable query correctness. To be safe, make sure mutable queries @@ -940,6 +952,9 @@ impl QueryState { /// given [`World`] without repetition. /// This can only be called for read-only queries. /// + /// This iterator is always guaranteed to return results from each unique pair of matching entities. + /// Iteration order is not guaranteed. + /// /// # Safety /// /// This does not check for mutable query correctness. To be safe, make sure mutable queries @@ -960,6 +975,9 @@ impl QueryState { /// Returns an [`Iterator`] for the given [`World`], where the last change and /// the current change tick are given. /// + /// This iterator is always guaranteed to return results from each matching entity once and only once. + /// Iteration order is not guaranteed. + /// /// # Safety /// /// This does not check for mutable query correctness. To be safe, make sure mutable queries @@ -979,6 +997,9 @@ impl QueryState { /// Returns an [`Iterator`] for the given [`World`] and list of [`Entity`]'s, where the last change and /// the current change tick are given. /// + /// This iterator is always guaranteed to return results from each unique pair of matching entities. + /// Iteration order is not guaranteed. + /// /// # Safety /// /// This does not check for mutable query correctness. To be safe, make sure mutable queries @@ -1004,6 +1025,9 @@ impl QueryState { /// given [`World`] without repetition. /// This can only be called for read-only queries. /// + /// This iterator is always guaranteed to return results from each unique pair of matching entities. + /// Iteration order is not guaranteed. + /// /// # Safety /// /// This does not check for mutable query correctness. To be safe, make sure mutable queries diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 773a0c0e3aff4..db34e2513e0ea 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -407,6 +407,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// Returns an [`Iterator`] over the read-only query items. /// + /// This iterator is always guaranteed to return results from each matching entity once and only once. + /// Iteration order is not guaranteed. + /// /// # Example /// /// Here, the `report_names_system` iterates over the `Player` component of every entity that contains it: @@ -442,6 +445,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// Returns an [`Iterator`] over the query items. /// + /// This iterator is always guaranteed to return results from each matching entity once and only once. + /// Iteration order is not guaranteed. + /// /// # Example /// /// Here, the `gravity_system` updates the `Velocity` component of every entity that contains it: @@ -474,6 +480,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// Returns a [`QueryCombinationIter`] over all combinations of `K` read-only query items without repetition. /// + /// This iterator is always guaranteed to return results from each unique pair of matching entities. + /// Iteration order is not guaranteed. + /// /// # Example /// /// ``` @@ -509,6 +518,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// Returns a [`QueryCombinationIter`] over all combinations of `K` query items without repetition. /// + /// This iterator is always guaranteed to return results from each unique pair of matching entities. + /// Iteration order is not guaranteed. + /// /// # Example /// /// ``` @@ -539,8 +551,8 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// Returns an [`Iterator`] over the read-only query items generated from an [`Entity`] list. /// - /// Items are returned in the order of the list of entities. - /// Entities that don't match the query are skipped. + /// Items are returned in the order of the list of entities, and may not be unique if the input + /// doesnn't guarantee uniqueness. Entities that don't match the query are skipped. /// /// # Example /// @@ -596,8 +608,8 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// Returns an iterator over the query items generated from an [`Entity`] list. /// - /// Items are returned in the order of the list of entities. - /// Entities that don't match the query are skipped. + /// Items are returned in the order of the list of entities, and may not be unique if the input + /// doesnn't guarantee uniqueness. Entities that don't match the query are skipped. /// /// # Examples /// @@ -648,6 +660,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// Returns an [`Iterator`] over the query items. /// + /// This iterator is always guaranteed to return results from each matching entity once and only once. + /// Iteration order is not guaranteed. + /// /// # Safety /// /// This function makes it possible to violate Rust's aliasing guarantees. @@ -669,6 +684,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// Iterates over all possible combinations of `K` query items without repetition. /// + /// This iterator is always guaranteed to return results from each unique pair of matching entities. + /// Iteration order is not guaranteed. + /// /// # Safety /// /// This allows aliased mutability. @@ -692,6 +710,9 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// Returns an [`Iterator`] over the query items generated from an [`Entity`] list. /// + /// Items are returned in the order of the list of entities, and may not be unique if the input + /// doesnn't guarantee uniqueness. Entities that don't match the query are skipped. + /// /// # Safety /// /// This allows aliased mutability and does not check for entity uniqueness. @@ -723,6 +744,12 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// Returns a parallel iterator over the query results for the given [`World`]. /// + /// This parallel iterator is always guaranteed to return results from each matching entity once and + /// only once. Iteration order and thread assignment is not guaranteed. + /// + /// If the `multithreaded` feature is disabled, iterating with this operates identically to [`Iterator::for_each`] + /// on [`QueryIter`]. + /// /// This can only be called for read-only queries, see [`par_iter_mut`] for write-queries. /// /// Note that you must use the `for_each` method to iterate over the @@ -743,6 +770,12 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> { /// Returns a parallel iterator over the query results for the given [`World`]. /// + /// This parallel iterator is always guaranteed to return results from each matching entity once and + /// only once. Iteration order and thread assignment is not guaranteed. + /// + /// If the `multithreaded` feature is disabled, iterating with this operates identically to [`Iterator::for_each`] + /// on [`QueryIter`]. + /// /// This can only be called for mutable queries, see [`par_iter`] for read-only-queries. /// /// # Example