Skip to content

Commit a6e37e7

Browse files
authored
Add QueryState::contains, document complexity, and make as_nop pub(crate) (#12776)
# Objective Fixes #12752. Fixes #12750. Document the runtime complexity of all of the `O(1)` operations on the individual APIs. ## Solution * Mirror `Query::contains` onto `QueryState::contains` * Make `QueryState::as_nop` pub(crate) * Make `NopWorldQuery` pub(crate) * Document all of the O(1) operations on Query and QueryState.
1 parent 476e296 commit a6e37e7

File tree

3 files changed

+40
-2
lines changed

3 files changed

+40
-2
lines changed

crates/bevy_ecs/src/query/fetch.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1809,7 +1809,7 @@ all_tuples!(impl_anytuple_fetch, 0, 15, F, S);
18091809
/// [`WorldQuery`] used to nullify queries by turning `Query<D>` into `Query<NopWorldQuery<D>>`
18101810
///
18111811
/// This will rarely be useful to consumers of `bevy_ecs`.
1812-
pub struct NopWorldQuery<D: QueryData>(PhantomData<D>);
1812+
pub(crate) struct NopWorldQuery<D: QueryData>(PhantomData<D>);
18131813

18141814
/// SAFETY:
18151815
/// `update_component_access` and `update_archetype_component_access` do nothing.

crates/bevy_ecs/src/query/state.rs

+31-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
8686
///
8787
/// This doesn't use `NopWorldQuery` as it loses filter functionality, for example
8888
/// `NopWorldQuery<Changed<T>>` is functionally equivalent to `With<T>`.
89-
pub fn as_nop(&self) -> &QueryState<NopWorldQuery<D>, F> {
89+
pub(crate) fn as_nop(&self) -> &QueryState<NopWorldQuery<D>, F> {
9090
// SAFETY: `NopWorldQuery` doesn't have any accesses and defers to
9191
// `D` for table/archetype matching
9292
unsafe { self.as_transmuted_state::<NopWorldQuery<D>, F>() }
@@ -244,6 +244,24 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
244244
}
245245
}
246246

247+
/// Returns `true` if the given [`Entity`] matches the query.
248+
///
249+
/// This is always guaranteed to run in `O(1)` time.
250+
#[inline]
251+
pub fn contains(&self, entity: Entity, world: &World, last_run: Tick, this_run: Tick) -> bool {
252+
// SAFETY: NopFetch does not access any members while &self ensures no one has exclusive access
253+
unsafe {
254+
self.as_nop()
255+
.get_unchecked_manual(
256+
world.as_unsafe_world_cell_readonly(),
257+
entity,
258+
last_run,
259+
this_run,
260+
)
261+
.is_ok()
262+
}
263+
}
264+
247265
/// Checks if the query is empty for the given [`UnsafeWorldCell`].
248266
///
249267
/// # Safety
@@ -570,6 +588,8 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
570588
/// Gets the query result for the given [`World`] and [`Entity`].
571589
///
572590
/// This can only be called for read-only queries, see [`Self::get_mut`] for write-queries.
591+
///
592+
/// This is always guaranteed to run in `O(1)` time.
573593
#[inline]
574594
pub fn get<'w>(
575595
&mut self,
@@ -642,6 +662,8 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
642662
}
643663

644664
/// Gets the query result for the given [`World`] and [`Entity`].
665+
///
666+
/// This is always guaranteed to run in `O(1)` time.
645667
#[inline]
646668
pub fn get_mut<'w>(
647669
&mut self,
@@ -733,6 +755,8 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
733755
/// access to `self`.
734756
///
735757
/// This can only be called for read-only queries, see [`Self::get_mut`] for mutable queries.
758+
///
759+
/// This is always guaranteed to run in `O(1)` time.
736760
#[inline]
737761
pub fn get_manual<'w>(
738762
&self,
@@ -753,6 +777,8 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
753777

754778
/// Gets the query result for the given [`World`] and [`Entity`].
755779
///
780+
/// This is always guaranteed to run in `O(1)` time.
781+
///
756782
/// # Safety
757783
///
758784
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
@@ -770,6 +796,8 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
770796
/// Gets the query result for the given [`World`] and [`Entity`], where the last change and
771797
/// the current change tick are given.
772798
///
799+
/// This is always guaranteed to run in `O(1)` time.
800+
///
773801
/// # Safety
774802
///
775803
/// This does not check for mutable query correctness. To be safe, make sure mutable queries
@@ -850,6 +878,8 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
850878
/// Gets the query results for the given [`World`] and array of [`Entity`], where the last change and
851879
/// the current change tick are given.
852880
///
881+
/// This is always guaranteed to run in `O(1)` time.
882+
///
853883
/// # Safety
854884
///
855885
/// This does not check for unique access to subsets of the entity-component data.

crates/bevy_ecs/src/system/query.rs

+8
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,8 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
813813
///
814814
/// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is returned instead.
815815
///
816+
/// This is always guaranteed to run in `O(1)` time.
817+
///
816818
/// # Example
817819
///
818820
/// Here, `get` is used to retrieve the exact query item of the entity specified by the `SelectedCharacter` resource.
@@ -931,6 +933,8 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
931933
///
932934
/// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is returned instead.
933935
///
936+
/// This is always guaranteed to run in `O(1)` time.
937+
///
934938
/// # Example
935939
///
936940
/// Here, `get_mut` is used to retrieve the exact query item of the entity specified by the `PoisonedCharacter` resource.
@@ -1045,6 +1049,8 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
10451049
///
10461050
/// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is returned instead.
10471051
///
1052+
/// This is always guaranteed to run in `O(1)` time.
1053+
///
10481054
/// # Safety
10491055
///
10501056
/// This function makes it possible to violate Rust's aliasing guarantees.
@@ -1248,6 +1254,8 @@ impl<'w, 's, D: QueryData, F: QueryFilter> Query<'w, 's, D, F> {
12481254

12491255
/// Returns `true` if the given [`Entity`] matches the query.
12501256
///
1257+
/// This is always guaranteed to run in `O(1)` time.
1258+
///
12511259
/// # Example
12521260
///
12531261
/// ```

0 commit comments

Comments
 (0)