bevy_ecs/query/state.rs
1use crate::{
2 archetype::{Archetype, ArchetypeComponentId, ArchetypeGeneration, ArchetypeId},
3 batching::BatchingStrategy,
4 component::{ComponentId, Components, Tick},
5 entity::Entity,
6 prelude::FromWorld,
7 query::{
8 Access, DebugCheckedUnwrap, FilteredAccess, QueryCombinationIter, QueryIter, QueryParIter,
9 },
10 storage::{SparseSetIndex, TableId},
11 world::{unsafe_world_cell::UnsafeWorldCell, World, WorldId},
12};
13use bevy_utils::tracing::warn;
14#[cfg(feature = "trace")]
15use bevy_utils::tracing::Span;
16use fixedbitset::FixedBitSet;
17use std::{borrow::Borrow, fmt, mem::MaybeUninit, ptr};
18
19use super::{
20 NopWorldQuery, QueryBuilder, QueryData, QueryEntityError, QueryFilter, QueryManyIter,
21 QuerySingleError, ROQueryItem,
22};
23
24/// An ID for either a table or an archetype. Used for Query iteration.
25///
26/// Query iteration is exclusively dense (over tables) or archetypal (over archetypes) based on whether
27/// both `D::IS_DENSE` and `F::IS_DENSE` are true or not.
28///
29/// This is a union instead of an enum as the usage is determined at compile time, as all [`StorageId`]s for
30/// a [`QueryState`] will be all [`TableId`]s or all [`ArchetypeId`]s, and not a mixture of both. This
31/// removes the need for discriminator to minimize memory usage and branching during iteration, but requires
32/// a safety invariant be verified when disambiguating them.
33///
34/// # Safety
35/// Must be initialized and accessed as a [`TableId`], if both generic parameters to the query are dense.
36/// Must be initialized and accessed as an [`ArchetypeId`] otherwise.
37#[derive(Clone, Copy)]
38pub(super) union StorageId {
39 pub(super) table_id: TableId,
40 pub(super) archetype_id: ArchetypeId,
41}
42
43/// Provides scoped access to a [`World`] state according to a given [`QueryData`] and [`QueryFilter`].
44///
45/// This data is cached between system runs, and is used to:
46/// - store metadata about which [`Table`] or [`Archetype`] are matched by the query. "Matched" means
47/// that the query will iterate over the data in the matched table/archetype.
48/// - cache the [`State`] needed to compute the [`Fetch`] struct used to retrieve data
49/// from a specific [`Table`] or [`Archetype`]
50/// - build iterators that can iterate over the query results
51///
52/// [`State`]: crate::query::world_query::WorldQuery::State
53/// [`Fetch`]: crate::query::world_query::WorldQuery::Fetch
54/// [`Table`]: crate::storage::Table
55#[repr(C)]
56// SAFETY NOTE:
57// Do not add any new fields that use the `D` or `F` generic parameters as this may
58// make `QueryState::as_transmuted_state` unsound if not done with care.
59pub struct QueryState<D: QueryData, F: QueryFilter = ()> {
60 world_id: WorldId,
61 pub(crate) archetype_generation: ArchetypeGeneration,
62 /// Metadata about the [`Table`](crate::storage::Table)s matched by this query.
63 pub(crate) matched_tables: FixedBitSet,
64 /// Metadata about the [`Archetype`]s matched by this query.
65 pub(crate) matched_archetypes: FixedBitSet,
66 /// [`FilteredAccess`] computed by combining the `D` and `F` access. Used to check which other queries
67 /// this query can run in parallel with.
68 pub(crate) component_access: FilteredAccess<ComponentId>,
69 // NOTE: we maintain both a bitset and a vec because iterating the vec is faster
70 pub(super) matched_storage_ids: Vec<StorageId>,
71 pub(crate) fetch_state: D::State,
72 pub(crate) filter_state: F::State,
73 #[cfg(feature = "trace")]
74 par_iter_span: Span,
75}
76
77impl<D: QueryData, F: QueryFilter> fmt::Debug for QueryState<D, F> {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 f.debug_struct("QueryState")
80 .field("world_id", &self.world_id)
81 .field("matched_table_count", &self.matched_tables.count_ones(..))
82 .field(
83 "matched_archetype_count",
84 &self.matched_archetypes.count_ones(..),
85 )
86 .finish_non_exhaustive()
87 }
88}
89
90impl<D: QueryData, F: QueryFilter> FromWorld for QueryState<D, F> {
91 fn from_world(world: &mut World) -> Self {
92 world.query_filtered()
93 }
94}
95
96impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
97 /// Converts this `QueryState` reference to a `QueryState` that does not access anything mutably.
98 pub fn as_readonly(&self) -> &QueryState<D::ReadOnly, F> {
99 // SAFETY: invariant on `WorldQuery` trait upholds that `D::ReadOnly` and `F::ReadOnly`
100 // have a subset of the access, and match the exact same archetypes/tables as `D`/`F` respectively.
101 unsafe { self.as_transmuted_state::<D::ReadOnly, F>() }
102 }
103
104 /// Converts this `QueryState` reference to a `QueryState` that does not return any data
105 /// which can be faster.
106 ///
107 /// This doesn't use `NopWorldQuery` as it loses filter functionality, for example
108 /// `NopWorldQuery<Changed<T>>` is functionally equivalent to `With<T>`.
109 pub(crate) fn as_nop(&self) -> &QueryState<NopWorldQuery<D>, F> {
110 // SAFETY: `NopWorldQuery` doesn't have any accesses and defers to
111 // `D` for table/archetype matching
112 unsafe { self.as_transmuted_state::<NopWorldQuery<D>, F>() }
113 }
114
115 /// Converts this `QueryState` reference to any other `QueryState` with
116 /// the same `WorldQuery::State` associated types.
117 ///
118 /// Consider using `as_readonly` or `as_nop` instead which are safe functions.
119 ///
120 /// # SAFETY
121 ///
122 /// `NewD` must have a subset of the access that `D` does and match the exact same archetypes/tables
123 /// `NewF` must have a subset of the access that `F` does and match the exact same archetypes/tables
124 pub(crate) unsafe fn as_transmuted_state<
125 NewD: QueryData<State = D::State>,
126 NewF: QueryFilter<State = F::State>,
127 >(
128 &self,
129 ) -> &QueryState<NewD, NewF> {
130 &*ptr::from_ref(self).cast::<QueryState<NewD, NewF>>()
131 }
132
133 /// Returns the components accessed by this query.
134 pub fn component_access(&self) -> &FilteredAccess<ComponentId> {
135 &self.component_access
136 }
137
138 /// Returns the tables matched by this query.
139 pub fn matched_tables(&self) -> impl Iterator<Item = TableId> + '_ {
140 self.matched_tables.ones().map(TableId::from_usize)
141 }
142
143 /// Returns the archetypes matched by this query.
144 pub fn matched_archetypes(&self) -> impl Iterator<Item = ArchetypeId> + '_ {
145 self.matched_archetypes.ones().map(ArchetypeId::new)
146 }
147}
148
149impl<D: QueryData, F: QueryFilter> QueryState<D, F> {
150 /// Creates a new [`QueryState`] from a given [`World`] and inherits the result of `world.id()`.
151 pub fn new(world: &mut World) -> Self {
152 let mut state = Self::new_uninitialized(world);
153 state.update_archetypes(world);
154 state
155 }
156
157 /// Identical to `new`, but it populates the provided `access` with the matched results.
158 pub(crate) fn new_with_access(
159 world: &mut World,
160 access: &mut Access<ArchetypeComponentId>,
161 ) -> Self {
162 let mut state = Self::new_uninitialized(world);
163 for archetype in world.archetypes.iter() {
164 // SAFETY: The state was just initialized from the `world` above, and the archetypes being added
165 // come directly from the same world.
166 unsafe {
167 if state.new_archetype_internal(archetype) {
168 state.update_archetype_component_access(archetype, access);
169 }
170 }
171 }
172 state.archetype_generation = world.archetypes.generation();
173 state
174 }
175
176 /// Creates a new [`QueryState`] but does not populate it with the matched results from the World yet
177 ///
178 /// `new_archetype` and its variants must be called on all of the World's archetypes before the
179 /// state can return valid query results.
180 fn new_uninitialized(world: &mut World) -> Self {
181 let fetch_state = D::init_state(world);
182 let filter_state = F::init_state(world);
183
184 let mut component_access = FilteredAccess::default();
185 D::update_component_access(&fetch_state, &mut component_access);
186
187 // Use a temporary empty FilteredAccess for filters. This prevents them from conflicting with the
188 // main Query's `fetch_state` access. Filters are allowed to conflict with the main query fetch
189 // because they are evaluated *before* a specific reference is constructed.
190 let mut filter_component_access = FilteredAccess::default();
191 F::update_component_access(&filter_state, &mut filter_component_access);
192
193 // Merge the temporary filter access with the main access. This ensures that filter access is
194 // properly considered in a global "cross-query" context (both within systems and across systems).
195 component_access.extend(&filter_component_access);
196
197 Self {
198 world_id: world.id(),
199 archetype_generation: ArchetypeGeneration::initial(),
200 matched_storage_ids: Vec::new(),
201 fetch_state,
202 filter_state,
203 component_access,
204 matched_tables: Default::default(),
205 matched_archetypes: Default::default(),
206 #[cfg(feature = "trace")]
207 par_iter_span: bevy_utils::tracing::info_span!(
208 "par_for_each",
209 query = std::any::type_name::<D>(),
210 filter = std::any::type_name::<F>(),
211 ),
212 }
213 }
214
215 /// Creates a new [`QueryState`] from a given [`QueryBuilder`] and inherits its [`FilteredAccess`].
216 pub fn from_builder(builder: &mut QueryBuilder<D, F>) -> Self {
217 let mut fetch_state = D::init_state(builder.world_mut());
218 let filter_state = F::init_state(builder.world_mut());
219 D::set_access(&mut fetch_state, builder.access());
220
221 let mut state = Self {
222 world_id: builder.world().id(),
223 archetype_generation: ArchetypeGeneration::initial(),
224 matched_storage_ids: Vec::new(),
225 fetch_state,
226 filter_state,
227 component_access: builder.access().clone(),
228 matched_tables: Default::default(),
229 matched_archetypes: Default::default(),
230 #[cfg(feature = "trace")]
231 par_iter_span: bevy_utils::tracing::info_span!(
232 "par_for_each",
233 data = std::any::type_name::<D>(),
234 filter = std::any::type_name::<F>(),
235 ),
236 };
237 state.update_archetypes(builder.world());
238 state
239 }
240
241 /// Checks if the query is empty for the given [`World`], where the last change and current tick are given.
242 ///
243 /// This is equivalent to `self.iter().next().is_none()`, and thus the worst case runtime will be `O(n)`
244 /// where `n` is the number of *potential* matches. This can be notably expensive for queries that rely
245 /// on non-archetypal filters such as [`Added`] or [`Changed`] which must individually check each query
246 /// result for a match.
247 ///
248 /// # Panics
249 ///
250 /// If `world` does not match the one used to call `QueryState::new` for this instance.
251 ///
252 /// [`Added`]: crate::query::Added
253 /// [`Changed`]: crate::query::Changed
254 #[inline]
255 pub fn is_empty(&self, world: &World, last_run: Tick, this_run: Tick) -> bool {
256 self.validate_world(world.id());
257 // SAFETY:
258 // - We have read-only access to the entire world.
259 // - The world has been validated.
260 unsafe {
261 self.is_empty_unsafe_world_cell(
262 world.as_unsafe_world_cell_readonly(),
263 last_run,
264 this_run,
265 )
266 }
267 }
268
269 /// Returns `true` if the given [`Entity`] matches the query.
270 ///
271 /// This is always guaranteed to run in `O(1)` time.
272 #[inline]
273 pub fn contains(&self, entity: Entity, world: &World, last_run: Tick, this_run: Tick) -> bool {
274 // SAFETY: NopFetch does not access any members while &self ensures no one has exclusive access
275 unsafe {
276 self.as_nop()
277 .get_unchecked_manual(
278 world.as_unsafe_world_cell_readonly(),
279 entity,
280 last_run,
281 this_run,
282 )
283 .is_ok()
284 }
285 }
286
287 /// Checks if the query is empty for the given [`UnsafeWorldCell`].
288 ///
289 /// # Safety
290 ///
291 /// - `world` must have permission to read any components required by this instance's `F` [`QueryFilter`].
292 /// - `world` must match the one used to create this [`QueryState`].
293 #[inline]
294 pub(crate) unsafe fn is_empty_unsafe_world_cell(
295 &self,
296 world: UnsafeWorldCell,
297 last_run: Tick,
298 this_run: Tick,
299 ) -> bool {
300 // SAFETY:
301 // - The caller ensures that `world` has permission to access any data used by the filter.
302 // - The caller ensures that the world matches.
303 unsafe {
304 self.as_nop()
305 .iter_unchecked_manual(world, last_run, this_run)
306 .next()
307 .is_none()
308 }
309 }
310
311 /// Updates the state's internal view of the [`World`]'s archetypes. If this is not called before querying data,
312 /// the results may not accurately reflect what is in the `world`.
313 ///
314 /// This is only required if a `manual` method (such as [`Self::get_manual`]) is being called, and it only needs to
315 /// be called if the `world` has been structurally mutated (i.e. added/removed a component or resource). Users using
316 /// non-`manual` methods such as [`QueryState::get`] do not need to call this as it will be automatically called for them.
317 ///
318 /// If you have an [`UnsafeWorldCell`] instead of `&World`, consider using [`QueryState::update_archetypes_unsafe_world_cell`].
319 ///
320 /// # Panics
321 ///
322 /// If `world` does not match the one used to call `QueryState::new` for this instance.
323 #[inline]
324 pub fn update_archetypes(&mut self, world: &World) {
325 self.update_archetypes_unsafe_world_cell(world.as_unsafe_world_cell_readonly());
326 }
327
328 /// Updates the state's internal view of the `world`'s archetypes. If this is not called before querying data,
329 /// the results may not accurately reflect what is in the `world`.
330 ///
331 /// This is only required if a `manual` method (such as [`Self::get_manual`]) is being called, and it only needs to
332 /// be called if the `world` has been structurally mutated (i.e. added/removed a component or resource). Users using
333 /// non-`manual` methods such as [`QueryState::get`] do not need to call this as it will be automatically called for them.
334 ///
335 /// # Note
336 ///
337 /// This method only accesses world metadata.
338 ///
339 /// # Panics
340 ///
341 /// If `world` does not match the one used to call `QueryState::new` for this instance.
342 pub fn update_archetypes_unsafe_world_cell(&mut self, world: UnsafeWorldCell) {
343 self.validate_world(world.id());
344 let archetypes = world.archetypes();
345 let old_generation =
346 std::mem::replace(&mut self.archetype_generation, archetypes.generation());
347
348 for archetype in &archetypes[old_generation..] {
349 // SAFETY: The validate_world call ensures that the world is the same the QueryState
350 // was initialized from.
351 unsafe {
352 self.new_archetype_internal(archetype);
353 }
354 }
355 }
356
357 /// # Panics
358 ///
359 /// If `world_id` does not match the [`World`] used to call `QueryState::new` for this instance.
360 ///
361 /// Many unsafe query methods require the world to match for soundness. This function is the easiest
362 /// way of ensuring that it matches.
363 #[inline]
364 #[track_caller]
365 pub fn validate_world(&self, world_id: WorldId) {
366 #[inline(never)]
367 #[track_caller]
368 #[cold]
369 fn panic_mismatched(this: WorldId, other: WorldId) -> ! {
370 panic!("Encountered a mismatched World. This QueryState was created from {this:?}, but a method was called using {other:?}.");
371 }
372
373 if self.world_id != world_id {
374 panic_mismatched(self.world_id, world_id);
375 }
376 }
377
378 /// Update the current [`QueryState`] with information from the provided [`Archetype`]
379 /// (if applicable, i.e. if the archetype has any intersecting [`ComponentId`] with the current [`QueryState`]).
380 ///
381 /// The passed in `access` will be updated with any new accesses introduced by the new archetype.
382 ///
383 /// # Safety
384 /// `archetype` must be from the `World` this state was initialized from.
385 pub unsafe fn new_archetype(
386 &mut self,
387 archetype: &Archetype,
388 access: &mut Access<ArchetypeComponentId>,
389 ) {
390 // SAFETY: The caller ensures that `archetype` is from the World the state was initialized from.
391 let matches = unsafe { self.new_archetype_internal(archetype) };
392 if matches {
393 // SAFETY: The caller ensures that `archetype` is from the World the state was initialized from.
394 unsafe { self.update_archetype_component_access(archetype, access) };
395 }
396 }
397
398 /// Process the given [`Archetype`] to update internal metadata about the [`Table`](crate::storage::Table)s
399 /// and [`Archetype`]s that are matched by this query.
400 ///
401 /// Returns `true` if the given `archetype` matches the query. Otherwise, returns `false`.
402 /// If there is no match, then there is no need to update the query's [`FilteredAccess`].
403 ///
404 /// # Safety
405 /// `archetype` must be from the `World` this state was initialized from.
406 unsafe fn new_archetype_internal(&mut self, archetype: &Archetype) -> bool {
407 if D::matches_component_set(&self.fetch_state, &|id| archetype.contains(id))
408 && F::matches_component_set(&self.filter_state, &|id| archetype.contains(id))
409 && self.matches_component_set(&|id| archetype.contains(id))
410 {
411 let archetype_index = archetype.id().index();
412 if !self.matched_archetypes.contains(archetype_index) {
413 self.matched_archetypes.grow_and_insert(archetype_index);
414 if !D::IS_DENSE || !F::IS_DENSE {
415 self.matched_storage_ids.push(StorageId {
416 archetype_id: archetype.id(),
417 });
418 }
419 }
420 let table_index = archetype.table_id().as_usize();
421 if !self.matched_tables.contains(table_index) {
422 self.matched_tables.grow_and_insert(table_index);
423 if D::IS_DENSE && F::IS_DENSE {
424 self.matched_storage_ids.push(StorageId {
425 table_id: archetype.table_id(),
426 });
427 }
428 }
429 true
430 } else {
431 false
432 }
433 }
434
435 /// Returns `true` if this query matches a set of components. Otherwise, returns `false`.
436 pub fn matches_component_set(&self, set_contains_id: &impl Fn(ComponentId) -> bool) -> bool {
437 self.component_access.filter_sets.iter().any(|set| {
438 set.with
439 .ones()
440 .all(|index| set_contains_id(ComponentId::get_sparse_set_index(index)))
441 && set
442 .without
443 .ones()
444 .all(|index| !set_contains_id(ComponentId::get_sparse_set_index(index)))
445 })
446 }
447
448 /// For the given `archetype`, adds any component accessed used by this query's underlying [`FilteredAccess`] to `access`.
449 ///
450 /// The passed in `access` will be updated with any new accesses introduced by the new archetype.
451 ///
452 /// # Safety
453 /// `archetype` must be from the `World` this state was initialized from.
454 pub unsafe fn update_archetype_component_access(
455 &mut self,
456 archetype: &Archetype,
457 access: &mut Access<ArchetypeComponentId>,
458 ) {
459 self.component_access.access.reads().for_each(|id| {
460 if let Some(id) = archetype.get_archetype_component_id(id) {
461 access.add_read(id);
462 }
463 });
464 self.component_access.access.writes().for_each(|id| {
465 if let Some(id) = archetype.get_archetype_component_id(id) {
466 access.add_write(id);
467 }
468 });
469 }
470
471 /// Use this to transform a [`QueryState`] into a more generic [`QueryState`].
472 /// This can be useful for passing to another function that might take the more general form.
473 /// See [`Query::transmute_lens`](crate::system::Query::transmute_lens) for more details.
474 ///
475 /// You should not call [`update_archetypes`](Self::update_archetypes) on the returned [`QueryState`] as the result will be unpredictable.
476 /// You might end up with a mix of archetypes that only matched the original query + archetypes that only match
477 /// the new [`QueryState`]. Most of the safe methods on [`QueryState`] call [`QueryState::update_archetypes`] internally, so this
478 /// best used through a [`Query`](crate::system::Query).
479 pub fn transmute<NewD: QueryData>(&self, components: &Components) -> QueryState<NewD> {
480 self.transmute_filtered::<NewD, ()>(components)
481 }
482
483 /// Creates a new [`QueryState`] with the same underlying [`FilteredAccess`], matched tables and archetypes
484 /// as self but with a new type signature.
485 ///
486 /// Panics if `NewD` or `NewF` require accesses that this query does not have.
487 pub fn transmute_filtered<NewD: QueryData, NewF: QueryFilter>(
488 &self,
489 components: &Components,
490 ) -> QueryState<NewD, NewF> {
491 let mut component_access = FilteredAccess::default();
492 let mut fetch_state = NewD::get_state(components).expect("Could not create fetch_state, Please initialize all referenced components before transmuting.");
493 let filter_state = NewF::get_state(components).expect("Could not create filter_state, Please initialize all referenced components before transmuting.");
494
495 NewD::set_access(&mut fetch_state, &self.component_access);
496 NewD::update_component_access(&fetch_state, &mut component_access);
497
498 let mut filter_component_access = FilteredAccess::default();
499 NewF::update_component_access(&filter_state, &mut filter_component_access);
500
501 component_access.extend(&filter_component_access);
502 assert!(
503 component_access.is_subset(&self.component_access),
504 "Transmuted state for {} attempts to access terms that are not allowed by original state {}.",
505 std::any::type_name::<(NewD, NewF)>(), std::any::type_name::<(D, F)>()
506 );
507
508 QueryState {
509 world_id: self.world_id,
510 archetype_generation: self.archetype_generation,
511 matched_storage_ids: self.matched_storage_ids.clone(),
512 fetch_state,
513 filter_state,
514 component_access: self.component_access.clone(),
515 matched_tables: self.matched_tables.clone(),
516 matched_archetypes: self.matched_archetypes.clone(),
517 #[cfg(feature = "trace")]
518 par_iter_span: bevy_utils::tracing::info_span!(
519 "par_for_each",
520 query = std::any::type_name::<NewD>(),
521 filter = std::any::type_name::<NewF>(),
522 ),
523 }
524 }
525
526 /// Use this to combine two queries. The data accessed will be the intersection
527 /// of archetypes included in both queries. This can be useful for accessing a
528 /// subset of the entities between two queries.
529 ///
530 /// You should not call `update_archetypes` on the returned `QueryState` as the result
531 /// could be unpredictable. You might end up with a mix of archetypes that only matched
532 /// the original query + archetypes that only match the new `QueryState`. Most of the
533 /// safe methods on `QueryState` call [`QueryState::update_archetypes`] internally, so
534 /// this is best used through a `Query`.
535 ///
536 /// ## Performance
537 ///
538 /// This will have similar performance as constructing a new `QueryState` since much of internal state
539 /// needs to be reconstructed. But it will be a little faster as it only needs to compare the intersection
540 /// of matching archetypes rather than iterating over all archetypes.
541 ///
542 /// ## Panics
543 ///
544 /// Will panic if `NewD` contains accesses not in `Q` or `OtherQ`.
545 pub fn join<OtherD: QueryData, NewD: QueryData>(
546 &self,
547 components: &Components,
548 other: &QueryState<OtherD>,
549 ) -> QueryState<NewD, ()> {
550 self.join_filtered::<_, (), NewD, ()>(components, other)
551 }
552
553 /// Use this to combine two queries. The data accessed will be the intersection
554 /// of archetypes included in both queries.
555 ///
556 /// ## Panics
557 ///
558 /// Will panic if `NewD` or `NewF` requires accesses not in `Q` or `OtherQ`.
559 pub fn join_filtered<
560 OtherD: QueryData,
561 OtherF: QueryFilter,
562 NewD: QueryData,
563 NewF: QueryFilter,
564 >(
565 &self,
566 components: &Components,
567 other: &QueryState<OtherD, OtherF>,
568 ) -> QueryState<NewD, NewF> {
569 if self.world_id != other.world_id {
570 panic!("Joining queries initialized on different worlds is not allowed.");
571 }
572
573 let mut component_access = FilteredAccess::default();
574 let mut new_fetch_state = NewD::get_state(components)
575 .expect("Could not create fetch_state, Please initialize all referenced components before transmuting.");
576 let new_filter_state = NewF::get_state(components)
577 .expect("Could not create filter_state, Please initialize all referenced components before transmuting.");
578
579 NewD::set_access(&mut new_fetch_state, &self.component_access);
580 NewD::update_component_access(&new_fetch_state, &mut component_access);
581
582 let mut new_filter_component_access = FilteredAccess::default();
583 NewF::update_component_access(&new_filter_state, &mut new_filter_component_access);
584
585 component_access.extend(&new_filter_component_access);
586
587 let mut joined_component_access = self.component_access.clone();
588 joined_component_access.extend(&other.component_access);
589
590 assert!(
591 component_access.is_subset(&joined_component_access),
592 "Joined state for {} attempts to access terms that are not allowed by state {} joined with {}.",
593 std::any::type_name::<(NewD, NewF)>(), std::any::type_name::<(D, F)>(), std::any::type_name::<(OtherD, OtherF)>()
594 );
595
596 if self.archetype_generation != other.archetype_generation {
597 warn!("You have tried to join queries with different archetype_generations. This could lead to unpredictable results.");
598 }
599
600 // take the intersection of the matched ids
601 let mut matched_tables = self.matched_tables.clone();
602 let mut matched_archetypes = self.matched_archetypes.clone();
603 matched_tables.intersect_with(&other.matched_tables);
604 matched_archetypes.intersect_with(&other.matched_archetypes);
605 let matched_storage_ids = if NewD::IS_DENSE && NewF::IS_DENSE {
606 matched_tables
607 .ones()
608 .map(|id| StorageId {
609 table_id: TableId::from_usize(id),
610 })
611 .collect()
612 } else {
613 matched_archetypes
614 .ones()
615 .map(|id| StorageId {
616 archetype_id: ArchetypeId::new(id),
617 })
618 .collect()
619 };
620
621 QueryState {
622 world_id: self.world_id,
623 archetype_generation: self.archetype_generation,
624 matched_storage_ids,
625 fetch_state: new_fetch_state,
626 filter_state: new_filter_state,
627 component_access: joined_component_access,
628 matched_tables,
629 matched_archetypes,
630 #[cfg(feature = "trace")]
631 par_iter_span: bevy_utils::tracing::info_span!(
632 "par_for_each",
633 query = std::any::type_name::<NewD>(),
634 filter = std::any::type_name::<NewF>(),
635 ),
636 }
637 }
638
639 /// Gets the query result for the given [`World`] and [`Entity`].
640 ///
641 /// This can only be called for read-only queries, see [`Self::get_mut`] for write-queries.
642 ///
643 /// This is always guaranteed to run in `O(1)` time.
644 #[inline]
645 pub fn get<'w>(
646 &mut self,
647 world: &'w World,
648 entity: Entity,
649 ) -> Result<ROQueryItem<'w, D>, QueryEntityError> {
650 self.update_archetypes(world);
651 // SAFETY: query is read only
652 unsafe {
653 self.as_readonly().get_unchecked_manual(
654 world.as_unsafe_world_cell_readonly(),
655 entity,
656 world.last_change_tick(),
657 world.read_change_tick(),
658 )
659 }
660 }
661
662 /// Returns the read-only query results for the given array of [`Entity`].
663 ///
664 /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is
665 /// returned instead.
666 ///
667 /// Note that the unlike [`QueryState::get_many_mut`], the entities passed in do not need to be unique.
668 ///
669 /// # Examples
670 ///
671 /// ```
672 /// use bevy_ecs::prelude::*;
673 /// use bevy_ecs::query::QueryEntityError;
674 ///
675 /// #[derive(Component, PartialEq, Debug)]
676 /// struct A(usize);
677 ///
678 /// let mut world = World::new();
679 /// let entity_vec: Vec<Entity> = (0..3).map(|i|world.spawn(A(i)).id()).collect();
680 /// let entities: [Entity; 3] = entity_vec.try_into().unwrap();
681 ///
682 /// world.spawn(A(73));
683 ///
684 /// let mut query_state = world.query::<&A>();
685 ///
686 /// let component_values = query_state.get_many(&world, entities).unwrap();
687 ///
688 /// assert_eq!(component_values, [&A(0), &A(1), &A(2)]);
689 ///
690 /// let wrong_entity = Entity::from_raw(365);
691 ///
692 /// assert_eq!(query_state.get_many(&world, [wrong_entity]), Err(QueryEntityError::NoSuchEntity(wrong_entity)));
693 /// ```
694 #[inline]
695 pub fn get_many<'w, const N: usize>(
696 &mut self,
697 world: &'w World,
698 entities: [Entity; N],
699 ) -> Result<[ROQueryItem<'w, D>; N], QueryEntityError> {
700 self.update_archetypes(world);
701
702 // SAFETY:
703 // - We have read-only access to the entire world.
704 // - `update_archetypes` validates that the `World` matches.
705 unsafe {
706 self.get_many_read_only_manual(
707 world.as_unsafe_world_cell_readonly(),
708 entities,
709 world.last_change_tick(),
710 world.read_change_tick(),
711 )
712 }
713 }
714
715 /// Gets the query result for the given [`World`] and [`Entity`].
716 ///
717 /// This is always guaranteed to run in `O(1)` time.
718 #[inline]
719 pub fn get_mut<'w>(
720 &mut self,
721 world: &'w mut World,
722 entity: Entity,
723 ) -> Result<D::Item<'w>, QueryEntityError> {
724 self.update_archetypes(world);
725 let change_tick = world.change_tick();
726 let last_change_tick = world.last_change_tick();
727 // SAFETY: query has unique world access
728 unsafe {
729 self.get_unchecked_manual(
730 world.as_unsafe_world_cell(),
731 entity,
732 last_change_tick,
733 change_tick,
734 )
735 }
736 }
737
738 /// Returns the query results for the given array of [`Entity`].
739 ///
740 /// In case of a nonexisting entity or mismatched component, a [`QueryEntityError`] is
741 /// returned instead.
742 ///
743 /// ```
744 /// use bevy_ecs::prelude::*;
745 /// use bevy_ecs::query::QueryEntityError;
746 ///
747 /// #[derive(Component, PartialEq, Debug)]
748 /// struct A(usize);
749 ///
750 /// let mut world = World::new();
751 ///
752 /// let entities: Vec<Entity> = (0..3).map(|i|world.spawn(A(i)).id()).collect();
753 /// let entities: [Entity; 3] = entities.try_into().unwrap();
754 ///
755 /// world.spawn(A(73));
756 ///
757 /// let mut query_state = world.query::<&mut A>();
758 ///
759 /// let mut mutable_component_values = query_state.get_many_mut(&mut world, entities).unwrap();
760 ///
761 /// for mut a in &mut mutable_component_values {
762 /// a.0 += 5;
763 /// }
764 ///
765 /// let component_values = query_state.get_many(&world, entities).unwrap();
766 ///
767 /// assert_eq!(component_values, [&A(5), &A(6), &A(7)]);
768 ///
769 /// let wrong_entity = Entity::from_raw(57);
770 /// let invalid_entity = world.spawn_empty().id();
771 ///
772 /// assert_eq!(query_state.get_many_mut(&mut world, [wrong_entity]).unwrap_err(), QueryEntityError::NoSuchEntity(wrong_entity));
773 /// assert_eq!(query_state.get_many_mut(&mut world, [invalid_entity]).unwrap_err(), QueryEntityError::QueryDoesNotMatch(invalid_entity));
774 /// assert_eq!(query_state.get_many_mut(&mut world, [entities[0], entities[0]]).unwrap_err(), QueryEntityError::AliasedMutability(entities[0]));
775 /// ```
776 #[inline]
777 pub fn get_many_mut<'w, const N: usize>(
778 &mut self,
779 world: &'w mut World,
780 entities: [Entity; N],
781 ) -> Result<[D::Item<'w>; N], QueryEntityError> {
782 self.update_archetypes(world);
783
784 let change_tick = world.change_tick();
785 let last_change_tick = world.last_change_tick();
786 // SAFETY: method requires exclusive world access
787 // and world has been validated via update_archetypes
788 unsafe {
789 self.get_many_unchecked_manual(
790 world.as_unsafe_world_cell(),
791 entities,
792 last_change_tick,
793 change_tick,
794 )
795 }
796 }
797
798 /// Gets the query result for the given [`World`] and [`Entity`].
799 ///
800 /// This method is slightly more efficient than [`QueryState::get`] in some situations, since
801 /// it does not update this instance's internal cache. This method will return an error if `entity`
802 /// belongs to an archetype that has not been cached.
803 ///
804 /// To ensure that the cache is up to date, call [`QueryState::update_archetypes`] before this method.
805 /// The cache is also updated in [`QueryState::new`], `QueryState::get`, or any method with mutable
806 /// access to `self`.
807 ///
808 /// This can only be called for read-only queries, see [`Self::get_mut`] for mutable queries.
809 ///
810 /// This is always guaranteed to run in `O(1)` time.
811 #[inline]
812 pub fn get_manual<'w>(
813 &self,
814 world: &'w World,
815 entity: Entity,
816 ) -> Result<ROQueryItem<'w, D>, QueryEntityError> {
817 self.validate_world(world.id());
818 // SAFETY: query is read only and world is validated
819 unsafe {
820 self.as_readonly().get_unchecked_manual(
821 world.as_unsafe_world_cell_readonly(),
822 entity,
823 world.last_change_tick(),
824 world.read_change_tick(),
825 )
826 }
827 }
828
829 /// Gets the query result for the given [`World`] and [`Entity`].
830 ///
831 /// This is always guaranteed to run in `O(1)` time.
832 ///
833 /// # Safety
834 ///
835 /// This does not check for mutable query correctness. To be safe, make sure mutable queries
836 /// have unique access to the components they query.
837 #[inline]
838 pub unsafe fn get_unchecked<'w>(
839 &mut self,
840 world: UnsafeWorldCell<'w>,
841 entity: Entity,
842 ) -> Result<D::Item<'w>, QueryEntityError> {
843 self.update_archetypes_unsafe_world_cell(world);
844 self.get_unchecked_manual(world, entity, world.last_change_tick(), world.change_tick())
845 }
846
847 /// Gets the query result for the given [`World`] and [`Entity`], where the last change and
848 /// the current change tick are given.
849 ///
850 /// This is always guaranteed to run in `O(1)` time.
851 ///
852 /// # Safety
853 ///
854 /// This does not check for mutable query correctness. To be safe, make sure mutable queries
855 /// have unique access to the components they query.
856 ///
857 /// This must be called on the same `World` that the `Query` was generated from:
858 /// use `QueryState::validate_world` to verify this.
859 pub(crate) unsafe fn get_unchecked_manual<'w>(
860 &self,
861 world: UnsafeWorldCell<'w>,
862 entity: Entity,
863 last_run: Tick,
864 this_run: Tick,
865 ) -> Result<D::Item<'w>, QueryEntityError> {
866 let location = world
867 .entities()
868 .get(entity)
869 .ok_or(QueryEntityError::NoSuchEntity(entity))?;
870 if !self
871 .matched_archetypes
872 .contains(location.archetype_id.index())
873 {
874 return Err(QueryEntityError::QueryDoesNotMatch(entity));
875 }
876 let archetype = world
877 .archetypes()
878 .get(location.archetype_id)
879 .debug_checked_unwrap();
880 let mut fetch = D::init_fetch(world, &self.fetch_state, last_run, this_run);
881 let mut filter = F::init_fetch(world, &self.filter_state, last_run, this_run);
882
883 let table = world
884 .storages()
885 .tables
886 .get(location.table_id)
887 .debug_checked_unwrap();
888 D::set_archetype(&mut fetch, &self.fetch_state, archetype, table);
889 F::set_archetype(&mut filter, &self.filter_state, archetype, table);
890
891 if F::filter_fetch(&mut filter, entity, location.table_row) {
892 Ok(D::fetch(&mut fetch, entity, location.table_row))
893 } else {
894 Err(QueryEntityError::QueryDoesNotMatch(entity))
895 }
896 }
897
898 /// Gets the read-only query results for the given [`World`] and array of [`Entity`], where the last change and
899 /// the current change tick are given.
900 ///
901 /// # Safety
902 ///
903 /// * `world` must have permission to read all of the components returned from this call.
904 /// No mutable references may coexist with any of the returned references.
905 /// * This must be called on the same `World` that the `Query` was generated from:
906 /// use `QueryState::validate_world` to verify this.
907 pub(crate) unsafe fn get_many_read_only_manual<'w, const N: usize>(
908 &self,
909 world: UnsafeWorldCell<'w>,
910 entities: [Entity; N],
911 last_run: Tick,
912 this_run: Tick,
913 ) -> Result<[ROQueryItem<'w, D>; N], QueryEntityError> {
914 let mut values = [(); N].map(|_| MaybeUninit::uninit());
915
916 for (value, entity) in std::iter::zip(&mut values, entities) {
917 // SAFETY: fetch is read-only and world must be validated
918 let item = unsafe {
919 self.as_readonly()
920 .get_unchecked_manual(world, entity, last_run, this_run)?
921 };
922 *value = MaybeUninit::new(item);
923 }
924
925 // SAFETY: Each value has been fully initialized.
926 Ok(values.map(|x| unsafe { x.assume_init() }))
927 }
928
929 /// Gets the query results for the given [`World`] and array of [`Entity`], where the last change and
930 /// the current change tick are given.
931 ///
932 /// This is always guaranteed to run in `O(1)` time.
933 ///
934 /// # Safety
935 ///
936 /// This does not check for unique access to subsets of the entity-component data.
937 /// To be safe, make sure mutable queries have unique access to the components they query.
938 ///
939 /// This must be called on the same `World` that the `Query` was generated from:
940 /// use `QueryState::validate_world` to verify this.
941 pub(crate) unsafe fn get_many_unchecked_manual<'w, const N: usize>(
942 &self,
943 world: UnsafeWorldCell<'w>,
944 entities: [Entity; N],
945 last_run: Tick,
946 this_run: Tick,
947 ) -> Result<[D::Item<'w>; N], QueryEntityError> {
948 // Verify that all entities are unique
949 for i in 0..N {
950 for j in 0..i {
951 if entities[i] == entities[j] {
952 return Err(QueryEntityError::AliasedMutability(entities[i]));
953 }
954 }
955 }
956
957 let mut values = [(); N].map(|_| MaybeUninit::uninit());
958
959 for (value, entity) in std::iter::zip(&mut values, entities) {
960 let item = self.get_unchecked_manual(world, entity, last_run, this_run)?;
961 *value = MaybeUninit::new(item);
962 }
963
964 // SAFETY: Each value has been fully initialized.
965 Ok(values.map(|x| x.assume_init()))
966 }
967
968 /// Returns an [`Iterator`] over the query results for the given [`World`].
969 ///
970 /// This can only be called for read-only queries, see [`Self::iter_mut`] for write-queries.
971 #[inline]
972 pub fn iter<'w, 's>(&'s mut self, world: &'w World) -> QueryIter<'w, 's, D::ReadOnly, F> {
973 self.update_archetypes(world);
974 // SAFETY: query is read only
975 unsafe {
976 self.as_readonly().iter_unchecked_manual(
977 world.as_unsafe_world_cell_readonly(),
978 world.last_change_tick(),
979 world.read_change_tick(),
980 )
981 }
982 }
983
984 /// Returns an [`Iterator`] over the query results for the given [`World`].
985 ///
986 /// This iterator is always guaranteed to return results from each matching entity once and only once.
987 /// Iteration order is not guaranteed.
988 #[inline]
989 pub fn iter_mut<'w, 's>(&'s mut self, world: &'w mut World) -> QueryIter<'w, 's, D, F> {
990 self.update_archetypes(world);
991 let change_tick = world.change_tick();
992 let last_change_tick = world.last_change_tick();
993 // SAFETY: query has unique world access
994 unsafe {
995 self.iter_unchecked_manual(world.as_unsafe_world_cell(), last_change_tick, change_tick)
996 }
997 }
998
999 /// Returns an [`Iterator`] over the query results for the given [`World`] without updating the query's archetypes.
1000 /// Archetypes must be manually updated before by using [`Self::update_archetypes`].
1001 ///
1002 /// This iterator is always guaranteed to return results from each matching entity once and only once.
1003 /// Iteration order is not guaranteed.
1004 ///
1005 /// This can only be called for read-only queries.
1006 #[inline]
1007 pub fn iter_manual<'w, 's>(&'s self, world: &'w World) -> QueryIter<'w, 's, D::ReadOnly, F> {
1008 self.validate_world(world.id());
1009 // SAFETY: query is read only and world is validated
1010 unsafe {
1011 self.as_readonly().iter_unchecked_manual(
1012 world.as_unsafe_world_cell_readonly(),
1013 world.last_change_tick(),
1014 world.read_change_tick(),
1015 )
1016 }
1017 }
1018
1019 /// Returns an [`Iterator`] over all possible combinations of `K` query results without repetition.
1020 /// This can only be called for read-only queries.
1021 ///
1022 /// A combination is an arrangement of a collection of items where order does not matter.
1023 ///
1024 /// `K` is the number of items that make up each subset, and the number of items returned by the iterator.
1025 /// `N` is the number of total entities output by query.
1026 ///
1027 /// For example, given the list [1, 2, 3, 4], where `K` is 2, the combinations without repeats are
1028 /// [1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4].
1029 /// And in this case, `N` would be defined as 4 since the size of the input list is 4.
1030 ///
1031 /// For combinations of size `K` of query taking `N` inputs, you will get:
1032 /// - if `K == N`: one combination of all query results
1033 /// - if `K < N`: all possible `K`-sized combinations of query results, without repetition
1034 /// - if `K > N`: empty set (no `K`-sized combinations exist)
1035 ///
1036 /// The `iter_combinations` method does not guarantee order of iteration.
1037 ///
1038 /// This iterator is always guaranteed to return results from each unique pair of matching entities.
1039 /// Iteration order is not guaranteed.
1040 ///
1041 /// This can only be called for read-only queries, see [`Self::iter_combinations_mut`] for
1042 /// write-queries.
1043 #[inline]
1044 pub fn iter_combinations<'w, 's, const K: usize>(
1045 &'s mut self,
1046 world: &'w World,
1047 ) -> QueryCombinationIter<'w, 's, D::ReadOnly, F, K> {
1048 self.update_archetypes(world);
1049 // SAFETY: query is read only
1050 unsafe {
1051 self.as_readonly().iter_combinations_unchecked_manual(
1052 world.as_unsafe_world_cell_readonly(),
1053 world.last_change_tick(),
1054 world.read_change_tick(),
1055 )
1056 }
1057 }
1058
1059 /// Returns an [`Iterator`] over all possible combinations of `K` query results without repetition.
1060 ///
1061 /// A combination is an arrangement of a collection of items where order does not matter.
1062 ///
1063 /// `K` is the number of items that make up each subset, and the number of items returned by the iterator.
1064 /// `N` is the number of total entities output by query.
1065 ///
1066 /// For example, given the list [1, 2, 3, 4], where `K` is 2, the combinations without repeats are
1067 /// [1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4].
1068 /// And in this case, `N` would be defined as 4 since the size of the input list is 4.
1069 ///
1070 /// For combinations of size `K` of query taking `N` inputs, you will get:
1071 /// - if `K == N`: one combination of all query results
1072 /// - if `K < N`: all possible `K`-sized combinations of query results, without repetition
1073 /// - if `K > N`: empty set (no `K`-sized combinations exist)
1074 ///
1075 /// The `iter_combinations_mut` method does not guarantee order of iteration.
1076 #[inline]
1077 pub fn iter_combinations_mut<'w, 's, const K: usize>(
1078 &'s mut self,
1079 world: &'w mut World,
1080 ) -> QueryCombinationIter<'w, 's, D, F, K> {
1081 self.update_archetypes(world);
1082 let change_tick = world.change_tick();
1083 let last_change_tick = world.last_change_tick();
1084 // SAFETY: query has unique world access
1085 unsafe {
1086 self.iter_combinations_unchecked_manual(
1087 world.as_unsafe_world_cell(),
1088 last_change_tick,
1089 change_tick,
1090 )
1091 }
1092 }
1093
1094 /// Returns an [`Iterator`] over the read-only query items generated from an [`Entity`] list.
1095 ///
1096 /// Items are returned in the order of the list of entities.
1097 /// Entities that don't match the query are skipped.
1098 ///
1099 /// # See also
1100 ///
1101 /// - [`iter_many_mut`](Self::iter_many_mut) to get mutable query items.
1102 #[inline]
1103 pub fn iter_many<'w, 's, EntityList: IntoIterator>(
1104 &'s mut self,
1105 world: &'w World,
1106 entities: EntityList,
1107 ) -> QueryManyIter<'w, 's, D::ReadOnly, F, EntityList::IntoIter>
1108 where
1109 EntityList::Item: Borrow<Entity>,
1110 {
1111 self.update_archetypes(world);
1112 // SAFETY: query is read only
1113 unsafe {
1114 self.as_readonly().iter_many_unchecked_manual(
1115 entities,
1116 world.as_unsafe_world_cell_readonly(),
1117 world.last_change_tick(),
1118 world.read_change_tick(),
1119 )
1120 }
1121 }
1122
1123 /// Returns an [`Iterator`] over the read-only query items generated from an [`Entity`] list.
1124 ///
1125 /// Items are returned in the order of the list of entities.
1126 /// Entities that don't match the query are skipped.
1127 ///
1128 /// If `world` archetypes changed since [`Self::update_archetypes`] was last called,
1129 /// this will skip entities contained in new archetypes.
1130 ///
1131 /// This can only be called for read-only queries.
1132 ///
1133 /// # See also
1134 ///
1135 /// - [`iter_many`](Self::iter_many) to update archetypes.
1136 /// - [`iter_manual`](Self::iter_manual) to iterate over all query items.
1137 #[inline]
1138 pub fn iter_many_manual<'w, 's, EntityList: IntoIterator>(
1139 &'s self,
1140 world: &'w World,
1141 entities: EntityList,
1142 ) -> QueryManyIter<'w, 's, D::ReadOnly, F, EntityList::IntoIter>
1143 where
1144 EntityList::Item: Borrow<Entity>,
1145 {
1146 self.validate_world(world.id());
1147 // SAFETY: query is read only, world id is validated
1148 unsafe {
1149 self.as_readonly().iter_many_unchecked_manual(
1150 entities,
1151 world.as_unsafe_world_cell_readonly(),
1152 world.last_change_tick(),
1153 world.read_change_tick(),
1154 )
1155 }
1156 }
1157
1158 /// Returns an iterator over the query items generated from an [`Entity`] list.
1159 ///
1160 /// Items are returned in the order of the list of entities.
1161 /// Entities that don't match the query are skipped.
1162 #[inline]
1163 pub fn iter_many_mut<'w, 's, EntityList: IntoIterator>(
1164 &'s mut self,
1165 world: &'w mut World,
1166 entities: EntityList,
1167 ) -> QueryManyIter<'w, 's, D, F, EntityList::IntoIter>
1168 where
1169 EntityList::Item: Borrow<Entity>,
1170 {
1171 self.update_archetypes(world);
1172 let change_tick = world.change_tick();
1173 let last_change_tick = world.last_change_tick();
1174 // SAFETY: Query has unique world access.
1175 unsafe {
1176 self.iter_many_unchecked_manual(
1177 entities,
1178 world.as_unsafe_world_cell(),
1179 last_change_tick,
1180 change_tick,
1181 )
1182 }
1183 }
1184
1185 /// Returns an [`Iterator`] over the query results for the given [`World`].
1186 ///
1187 /// This iterator is always guaranteed to return results from each matching entity once and only once.
1188 /// Iteration order is not guaranteed.
1189 ///
1190 /// # Safety
1191 ///
1192 /// This does not check for mutable query correctness. To be safe, make sure mutable queries
1193 /// have unique access to the components they query.
1194 #[inline]
1195 pub unsafe fn iter_unchecked<'w, 's>(
1196 &'s mut self,
1197 world: UnsafeWorldCell<'w>,
1198 ) -> QueryIter<'w, 's, D, F> {
1199 self.update_archetypes_unsafe_world_cell(world);
1200 self.iter_unchecked_manual(world, world.last_change_tick(), world.change_tick())
1201 }
1202
1203 /// Returns an [`Iterator`] over all possible combinations of `K` query results for the
1204 /// given [`World`] without repetition.
1205 /// This can only be called for read-only queries.
1206 ///
1207 /// This iterator is always guaranteed to return results from each unique pair of matching entities.
1208 /// Iteration order is not guaranteed.
1209 ///
1210 /// # Safety
1211 ///
1212 /// This does not check for mutable query correctness. To be safe, make sure mutable queries
1213 /// have unique access to the components they query.
1214 #[inline]
1215 pub unsafe fn iter_combinations_unchecked<'w, 's, const K: usize>(
1216 &'s mut self,
1217 world: UnsafeWorldCell<'w>,
1218 ) -> QueryCombinationIter<'w, 's, D, F, K> {
1219 self.update_archetypes_unsafe_world_cell(world);
1220 self.iter_combinations_unchecked_manual(
1221 world,
1222 world.last_change_tick(),
1223 world.change_tick(),
1224 )
1225 }
1226
1227 /// Returns an [`Iterator`] for the given [`World`], where the last change and
1228 /// the current change tick are given.
1229 ///
1230 /// This iterator is always guaranteed to return results from each matching entity once and only once.
1231 /// Iteration order is not guaranteed.
1232 ///
1233 /// # Safety
1234 ///
1235 /// This does not check for mutable query correctness. To be safe, make sure mutable queries
1236 /// have unique access to the components they query.
1237 /// This does not validate that `world.id()` matches `self.world_id`. Calling this on a `world`
1238 /// with a mismatched [`WorldId`] is unsound.
1239 #[inline]
1240 pub(crate) unsafe fn iter_unchecked_manual<'w, 's>(
1241 &'s self,
1242 world: UnsafeWorldCell<'w>,
1243 last_run: Tick,
1244 this_run: Tick,
1245 ) -> QueryIter<'w, 's, D, F> {
1246 QueryIter::new(world, self, last_run, this_run)
1247 }
1248
1249 /// Returns an [`Iterator`] for the given [`World`] and list of [`Entity`]'s, where the last change and
1250 /// the current change tick are given.
1251 ///
1252 /// This iterator is always guaranteed to return results from each unique pair of matching entities.
1253 /// Iteration order is not guaranteed.
1254 ///
1255 /// # Safety
1256 ///
1257 /// This does not check for mutable query correctness. To be safe, make sure mutable queries
1258 /// have unique access to the components they query.
1259 /// This does not check for entity uniqueness
1260 /// This does not validate that `world.id()` matches `self.world_id`. Calling this on a `world`
1261 /// with a mismatched [`WorldId`] is unsound.
1262 #[inline]
1263 pub(crate) unsafe fn iter_many_unchecked_manual<'w, 's, EntityList: IntoIterator>(
1264 &'s self,
1265 entities: EntityList,
1266 world: UnsafeWorldCell<'w>,
1267 last_run: Tick,
1268 this_run: Tick,
1269 ) -> QueryManyIter<'w, 's, D, F, EntityList::IntoIter>
1270 where
1271 EntityList::Item: Borrow<Entity>,
1272 {
1273 QueryManyIter::new(world, self, entities, last_run, this_run)
1274 }
1275
1276 /// Returns an [`Iterator`] over all possible combinations of `K` query results for the
1277 /// given [`World`] without repetition.
1278 /// This can only be called for read-only queries.
1279 ///
1280 /// This iterator is always guaranteed to return results from each unique pair of matching entities.
1281 /// Iteration order is not guaranteed.
1282 ///
1283 /// # Safety
1284 ///
1285 /// This does not check for mutable query correctness. To be safe, make sure mutable queries
1286 /// have unique access to the components they query.
1287 /// This does not validate that `world.id()` matches `self.world_id`. Calling this on a `world`
1288 /// with a mismatched [`WorldId`] is unsound.
1289 #[inline]
1290 pub(crate) unsafe fn iter_combinations_unchecked_manual<'w, 's, const K: usize>(
1291 &'s self,
1292 world: UnsafeWorldCell<'w>,
1293 last_run: Tick,
1294 this_run: Tick,
1295 ) -> QueryCombinationIter<'w, 's, D, F, K> {
1296 QueryCombinationIter::new(world, self, last_run, this_run)
1297 }
1298
1299 /// Returns a parallel iterator over the query results for the given [`World`].
1300 ///
1301 /// This can only be called for read-only queries, see [`par_iter_mut`] for write-queries.
1302 ///
1303 /// Note that you must use the `for_each` method to iterate over the
1304 /// results, see [`par_iter_mut`] for an example.
1305 ///
1306 /// [`par_iter_mut`]: Self::par_iter_mut
1307 #[inline]
1308 pub fn par_iter<'w, 's>(
1309 &'s mut self,
1310 world: &'w World,
1311 ) -> QueryParIter<'w, 's, D::ReadOnly, F> {
1312 self.update_archetypes(world);
1313 QueryParIter {
1314 world: world.as_unsafe_world_cell_readonly(),
1315 state: self.as_readonly(),
1316 last_run: world.last_change_tick(),
1317 this_run: world.read_change_tick(),
1318 batching_strategy: BatchingStrategy::new(),
1319 }
1320 }
1321
1322 /// Returns a parallel iterator over the query results for the given [`World`].
1323 ///
1324 /// This can only be called for mutable queries, see [`par_iter`] for read-only-queries.
1325 ///
1326 /// # Examples
1327 ///
1328 /// ```
1329 /// use bevy_ecs::prelude::*;
1330 /// use bevy_ecs::query::QueryEntityError;
1331 ///
1332 /// #[derive(Component, PartialEq, Debug)]
1333 /// struct A(usize);
1334 ///
1335 /// # bevy_tasks::ComputeTaskPool::get_or_init(|| bevy_tasks::TaskPool::new());
1336 ///
1337 /// let mut world = World::new();
1338 ///
1339 /// # let entities: Vec<Entity> = (0..3).map(|i| world.spawn(A(i)).id()).collect();
1340 /// # let entities: [Entity; 3] = entities.try_into().unwrap();
1341 ///
1342 /// let mut query_state = world.query::<&mut A>();
1343 ///
1344 /// query_state.par_iter_mut(&mut world).for_each(|mut a| {
1345 /// a.0 += 5;
1346 /// });
1347 ///
1348 /// # let component_values = query_state.get_many(&world, entities).unwrap();
1349 ///
1350 /// # assert_eq!(component_values, [&A(5), &A(6), &A(7)]);
1351 ///
1352 /// # let wrong_entity = Entity::from_raw(57);
1353 /// # let invalid_entity = world.spawn_empty().id();
1354 ///
1355 /// # assert_eq!(query_state.get_many_mut(&mut world, [wrong_entity]).unwrap_err(), QueryEntityError::NoSuchEntity(wrong_entity));
1356 /// # assert_eq!(query_state.get_many_mut(&mut world, [invalid_entity]).unwrap_err(), QueryEntityError::QueryDoesNotMatch(invalid_entity));
1357 /// # assert_eq!(query_state.get_many_mut(&mut world, [entities[0], entities[0]]).unwrap_err(), QueryEntityError::AliasedMutability(entities[0]));
1358 /// ```
1359 ///
1360 /// # Panics
1361 /// The [`ComputeTaskPool`] is not initialized. If using this from a query that is being
1362 /// initialized and run from the ECS scheduler, this should never panic.
1363 ///
1364 /// [`par_iter`]: Self::par_iter
1365 /// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool
1366 #[inline]
1367 pub fn par_iter_mut<'w, 's>(&'s mut self, world: &'w mut World) -> QueryParIter<'w, 's, D, F> {
1368 self.update_archetypes(world);
1369 let this_run = world.change_tick();
1370 let last_run = world.last_change_tick();
1371 QueryParIter {
1372 world: world.as_unsafe_world_cell(),
1373 state: self,
1374 last_run,
1375 this_run,
1376 batching_strategy: BatchingStrategy::new(),
1377 }
1378 }
1379
1380 /// Runs `func` on each query result in parallel for the given [`World`], where the last change and
1381 /// the current change tick are given. This is faster than the equivalent
1382 /// `iter()` method, but cannot be chained like a normal [`Iterator`].
1383 ///
1384 /// # Panics
1385 /// The [`ComputeTaskPool`] is not initialized. If using this from a query that is being
1386 /// initialized and run from the ECS scheduler, this should never panic.
1387 ///
1388 /// # Safety
1389 ///
1390 /// This does not check for mutable query correctness. To be safe, make sure mutable queries
1391 /// have unique access to the components they query.
1392 /// This does not validate that `world.id()` matches `self.world_id`. Calling this on a `world`
1393 /// with a mismatched [`WorldId`] is unsound.
1394 ///
1395 /// [`ComputeTaskPool`]: bevy_tasks::ComputeTaskPool
1396 #[cfg(all(not(target_arch = "wasm32"), feature = "multi_threaded"))]
1397 pub(crate) unsafe fn par_fold_init_unchecked_manual<'w, T, FN, INIT>(
1398 &self,
1399 init_accum: INIT,
1400 world: UnsafeWorldCell<'w>,
1401 batch_size: usize,
1402 func: FN,
1403 last_run: Tick,
1404 this_run: Tick,
1405 ) where
1406 FN: Fn(T, D::Item<'w>) -> T + Send + Sync + Clone,
1407 INIT: Fn() -> T + Sync + Send + Clone,
1408 {
1409 // NOTE: If you are changing query iteration code, remember to update the following places, where relevant:
1410 // QueryIter, QueryIterationCursor, QueryManyIter, QueryCombinationIter,QueryState::par_fold_init_unchecked_manual
1411 use arrayvec::ArrayVec;
1412
1413 bevy_tasks::ComputeTaskPool::get().scope(|scope| {
1414 // SAFETY: We only access table data that has been registered in `self.archetype_component_access`.
1415 let tables = unsafe { &world.storages().tables };
1416 let archetypes = world.archetypes();
1417 let mut batch_queue = ArrayVec::new();
1418 let mut queue_entity_count = 0;
1419
1420 // submit a list of storages which smaller than batch_size as single task
1421 let submit_batch_queue = |queue: &mut ArrayVec<StorageId, 128>| {
1422 if queue.is_empty() {
1423 return;
1424 }
1425 let queue = std::mem::take(queue);
1426 let mut func = func.clone();
1427 let init_accum = init_accum.clone();
1428 scope.spawn(async move {
1429 #[cfg(feature = "trace")]
1430 let _span = self.par_iter_span.enter();
1431 let mut iter = self.iter_unchecked_manual(world, last_run, this_run);
1432 let mut accum = init_accum();
1433 for storage_id in queue {
1434 if D::IS_DENSE && F::IS_DENSE {
1435 let id = storage_id.table_id;
1436 let table = &world.storages().tables.get(id).debug_checked_unwrap();
1437 accum = iter.fold_over_table_range(
1438 accum,
1439 &mut func,
1440 table,
1441 0..table.entity_count(),
1442 );
1443 } else {
1444 let id = storage_id.archetype_id;
1445 let archetype = world.archetypes().get(id).debug_checked_unwrap();
1446 accum = iter.fold_over_archetype_range(
1447 accum,
1448 &mut func,
1449 archetype,
1450 0..archetype.len(),
1451 );
1452 }
1453 }
1454 });
1455 };
1456
1457 // submit single storage larger than batch_size
1458 let submit_single = |count, storage_id: StorageId| {
1459 for offset in (0..count).step_by(batch_size) {
1460 let mut func = func.clone();
1461 let init_accum = init_accum.clone();
1462 let len = batch_size.min(count - offset);
1463 let batch = offset..offset + len;
1464 scope.spawn(async move {
1465 #[cfg(feature = "trace")]
1466 let _span = self.par_iter_span.enter();
1467 let accum = init_accum();
1468 if D::IS_DENSE && F::IS_DENSE {
1469 let id = storage_id.table_id;
1470 let table = world.storages().tables.get(id).debug_checked_unwrap();
1471 self.iter_unchecked_manual(world, last_run, this_run)
1472 .fold_over_table_range(accum, &mut func, table, batch);
1473 } else {
1474 let id = storage_id.archetype_id;
1475 let archetype = world.archetypes().get(id).debug_checked_unwrap();
1476 self.iter_unchecked_manual(world, last_run, this_run)
1477 .fold_over_archetype_range(accum, &mut func, archetype, batch);
1478 }
1479 });
1480 }
1481 };
1482
1483 let storage_entity_count = |storage_id: StorageId| -> usize {
1484 if D::IS_DENSE && F::IS_DENSE {
1485 tables[storage_id.table_id].entity_count()
1486 } else {
1487 archetypes[storage_id.archetype_id].len()
1488 }
1489 };
1490
1491 for storage_id in &self.matched_storage_ids {
1492 let count = storage_entity_count(*storage_id);
1493
1494 // skip empty storage
1495 if count == 0 {
1496 continue;
1497 }
1498 // immediately submit large storage
1499 if count >= batch_size {
1500 submit_single(count, *storage_id);
1501 continue;
1502 }
1503 // merge small storage
1504 batch_queue.push(*storage_id);
1505 queue_entity_count += count;
1506
1507 // submit batch_queue
1508 if queue_entity_count >= batch_size || batch_queue.is_full() {
1509 submit_batch_queue(&mut batch_queue);
1510 queue_entity_count = 0;
1511 }
1512 }
1513 submit_batch_queue(&mut batch_queue);
1514 });
1515 }
1516
1517 /// Returns a single immutable query result when there is exactly one entity matching
1518 /// the query.
1519 ///
1520 /// This can only be called for read-only queries,
1521 /// see [`single_mut`](Self::single_mut) for write-queries.
1522 ///
1523 /// # Panics
1524 ///
1525 /// Panics if the number of query results is not exactly one. Use
1526 /// [`get_single`](Self::get_single) to return a `Result` instead of panicking.
1527 #[track_caller]
1528 #[inline]
1529 pub fn single<'w>(&mut self, world: &'w World) -> ROQueryItem<'w, D> {
1530 match self.get_single(world) {
1531 Ok(items) => items,
1532 Err(error) => panic!("Cannot get single mutable query result: {error}"),
1533 }
1534 }
1535
1536 /// Returns a single immutable query result when there is exactly one entity matching
1537 /// the query.
1538 ///
1539 /// This can only be called for read-only queries,
1540 /// see [`get_single_mut`](Self::get_single_mut) for write-queries.
1541 ///
1542 /// If the number of query results is not exactly one, a [`QuerySingleError`] is returned
1543 /// instead.
1544 #[inline]
1545 pub fn get_single<'w>(
1546 &mut self,
1547 world: &'w World,
1548 ) -> Result<ROQueryItem<'w, D>, QuerySingleError> {
1549 self.update_archetypes(world);
1550
1551 // SAFETY: query is read only
1552 unsafe {
1553 self.as_readonly().get_single_unchecked_manual(
1554 world.as_unsafe_world_cell_readonly(),
1555 world.last_change_tick(),
1556 world.read_change_tick(),
1557 )
1558 }
1559 }
1560
1561 /// Returns a single mutable query result when there is exactly one entity matching
1562 /// the query.
1563 ///
1564 /// # Panics
1565 ///
1566 /// Panics if the number of query results is not exactly one. Use
1567 /// [`get_single_mut`](Self::get_single_mut) to return a `Result` instead of panicking.
1568 #[track_caller]
1569 #[inline]
1570 pub fn single_mut<'w>(&mut self, world: &'w mut World) -> D::Item<'w> {
1571 // SAFETY: query has unique world access
1572 match self.get_single_mut(world) {
1573 Ok(items) => items,
1574 Err(error) => panic!("Cannot get single query result: {error}"),
1575 }
1576 }
1577
1578 /// Returns a single mutable query result when there is exactly one entity matching
1579 /// the query.
1580 ///
1581 /// If the number of query results is not exactly one, a [`QuerySingleError`] is returned
1582 /// instead.
1583 #[inline]
1584 pub fn get_single_mut<'w>(
1585 &mut self,
1586 world: &'w mut World,
1587 ) -> Result<D::Item<'w>, QuerySingleError> {
1588 self.update_archetypes(world);
1589
1590 let change_tick = world.change_tick();
1591 let last_change_tick = world.last_change_tick();
1592 // SAFETY: query has unique world access
1593 unsafe {
1594 self.get_single_unchecked_manual(
1595 world.as_unsafe_world_cell(),
1596 last_change_tick,
1597 change_tick,
1598 )
1599 }
1600 }
1601
1602 /// Returns a query result when there is exactly one entity matching the query.
1603 ///
1604 /// If the number of query results is not exactly one, a [`QuerySingleError`] is returned
1605 /// instead.
1606 ///
1607 /// # Safety
1608 ///
1609 /// This does not check for mutable query correctness. To be safe, make sure mutable queries
1610 /// have unique access to the components they query.
1611 #[inline]
1612 pub unsafe fn get_single_unchecked<'w>(
1613 &mut self,
1614 world: UnsafeWorldCell<'w>,
1615 ) -> Result<D::Item<'w>, QuerySingleError> {
1616 self.update_archetypes_unsafe_world_cell(world);
1617 self.get_single_unchecked_manual(world, world.last_change_tick(), world.change_tick())
1618 }
1619
1620 /// Returns a query result when there is exactly one entity matching the query,
1621 /// where the last change and the current change tick are given.
1622 ///
1623 /// If the number of query results is not exactly one, a [`QuerySingleError`] is returned
1624 /// instead.
1625 ///
1626 /// # Safety
1627 ///
1628 /// This does not check for mutable query correctness. To be safe, make sure mutable queries
1629 /// have unique access to the components they query.
1630 #[inline]
1631 pub unsafe fn get_single_unchecked_manual<'w>(
1632 &self,
1633 world: UnsafeWorldCell<'w>,
1634 last_run: Tick,
1635 this_run: Tick,
1636 ) -> Result<D::Item<'w>, QuerySingleError> {
1637 let mut query = self.iter_unchecked_manual(world, last_run, this_run);
1638 let first = query.next();
1639 let extra = query.next().is_some();
1640
1641 match (first, extra) {
1642 (Some(r), false) => Ok(r),
1643 (None, _) => Err(QuerySingleError::NoEntities(std::any::type_name::<Self>())),
1644 (Some(_), _) => Err(QuerySingleError::MultipleEntities(std::any::type_name::<
1645 Self,
1646 >())),
1647 }
1648 }
1649}
1650
1651impl<D: QueryData, F: QueryFilter> From<QueryBuilder<'_, D, F>> for QueryState<D, F> {
1652 fn from(mut value: QueryBuilder<D, F>) -> Self {
1653 QueryState::from_builder(&mut value)
1654 }
1655}
1656
1657#[cfg(test)]
1658mod tests {
1659 use crate as bevy_ecs;
1660 use crate::world::FilteredEntityRef;
1661 use crate::{component::Component, prelude::*, query::QueryEntityError};
1662
1663 #[test]
1664 fn get_many_unchecked_manual_uniqueness() {
1665 let mut world = World::new();
1666
1667 let entities: Vec<Entity> = (0..10).map(|_| world.spawn_empty().id()).collect();
1668
1669 let query_state = world.query::<Entity>();
1670
1671 // These don't matter for the test
1672 let last_change_tick = world.last_change_tick();
1673 let change_tick = world.change_tick();
1674
1675 // It's best to test get_many_unchecked_manual directly,
1676 // as it is shared and unsafe
1677 // We don't care about aliased mutability for the read-only equivalent
1678
1679 // SAFETY: Query does not access world data.
1680 assert!(unsafe {
1681 query_state
1682 .get_many_unchecked_manual::<10>(
1683 world.as_unsafe_world_cell_readonly(),
1684 entities.clone().try_into().unwrap(),
1685 last_change_tick,
1686 change_tick,
1687 )
1688 .is_ok()
1689 });
1690
1691 assert_eq!(
1692 // SAFETY: Query does not access world data.
1693 unsafe {
1694 query_state
1695 .get_many_unchecked_manual(
1696 world.as_unsafe_world_cell_readonly(),
1697 [entities[0], entities[0]],
1698 last_change_tick,
1699 change_tick,
1700 )
1701 .unwrap_err()
1702 },
1703 QueryEntityError::AliasedMutability(entities[0])
1704 );
1705
1706 assert_eq!(
1707 // SAFETY: Query does not access world data.
1708 unsafe {
1709 query_state
1710 .get_many_unchecked_manual(
1711 world.as_unsafe_world_cell_readonly(),
1712 [entities[0], entities[1], entities[0]],
1713 last_change_tick,
1714 change_tick,
1715 )
1716 .unwrap_err()
1717 },
1718 QueryEntityError::AliasedMutability(entities[0])
1719 );
1720
1721 assert_eq!(
1722 // SAFETY: Query does not access world data.
1723 unsafe {
1724 query_state
1725 .get_many_unchecked_manual(
1726 world.as_unsafe_world_cell_readonly(),
1727 [entities[9], entities[9]],
1728 last_change_tick,
1729 change_tick,
1730 )
1731 .unwrap_err()
1732 },
1733 QueryEntityError::AliasedMutability(entities[9])
1734 );
1735 }
1736
1737 #[test]
1738 #[should_panic]
1739 fn right_world_get() {
1740 let mut world_1 = World::new();
1741 let world_2 = World::new();
1742
1743 let mut query_state = world_1.query::<Entity>();
1744 let _panics = query_state.get(&world_2, Entity::from_raw(0));
1745 }
1746
1747 #[test]
1748 #[should_panic]
1749 fn right_world_get_many() {
1750 let mut world_1 = World::new();
1751 let world_2 = World::new();
1752
1753 let mut query_state = world_1.query::<Entity>();
1754 let _panics = query_state.get_many(&world_2, []);
1755 }
1756
1757 #[test]
1758 #[should_panic]
1759 fn right_world_get_many_mut() {
1760 let mut world_1 = World::new();
1761 let mut world_2 = World::new();
1762
1763 let mut query_state = world_1.query::<Entity>();
1764 let _panics = query_state.get_many_mut(&mut world_2, []);
1765 }
1766
1767 #[derive(Component, PartialEq, Debug)]
1768 struct A(usize);
1769
1770 #[derive(Component, PartialEq, Debug)]
1771 struct B(usize);
1772
1773 #[derive(Component, PartialEq, Debug)]
1774 struct C(usize);
1775
1776 #[test]
1777 fn can_transmute_to_more_general() {
1778 let mut world = World::new();
1779 world.spawn((A(1), B(0)));
1780
1781 let query_state = world.query::<(&A, &B)>();
1782 let mut new_query_state = query_state.transmute::<&A>(world.components());
1783 assert_eq!(new_query_state.iter(&world).len(), 1);
1784 let a = new_query_state.single(&world);
1785
1786 assert_eq!(a.0, 1);
1787 }
1788
1789 #[test]
1790 fn cannot_get_data_not_in_original_query() {
1791 let mut world = World::new();
1792 world.spawn((A(0), B(0)));
1793 world.spawn((A(1), B(0), C(0)));
1794
1795 let query_state = world.query_filtered::<(&A, &B), Without<C>>();
1796 let mut new_query_state = query_state.transmute::<&A>(world.components());
1797 // even though we change the query to not have Without<C>, we do not get the component with C.
1798 let a = new_query_state.single(&world);
1799
1800 assert_eq!(a.0, 0);
1801 }
1802
1803 #[test]
1804 fn can_transmute_empty_tuple() {
1805 let mut world = World::new();
1806 world.init_component::<A>();
1807 let entity = world.spawn(A(10)).id();
1808
1809 let q = world.query::<()>();
1810 let mut q = q.transmute::<Entity>(world.components());
1811 assert_eq!(q.single(&world), entity);
1812 }
1813
1814 #[test]
1815 fn can_transmute_immut_fetch() {
1816 let mut world = World::new();
1817 world.spawn(A(10));
1818
1819 let q = world.query::<&A>();
1820 let mut new_q = q.transmute::<Ref<A>>(world.components());
1821 assert!(new_q.single(&world).is_added());
1822
1823 let q = world.query::<Ref<A>>();
1824 let _ = q.transmute::<&A>(world.components());
1825 }
1826
1827 #[test]
1828 fn can_transmute_mut_fetch() {
1829 let mut world = World::new();
1830 world.spawn(A(0));
1831
1832 let q = world.query::<&mut A>();
1833 let _ = q.transmute::<Ref<A>>(world.components());
1834 let _ = q.transmute::<&A>(world.components());
1835 }
1836
1837 #[test]
1838 fn can_transmute_entity_mut() {
1839 let mut world = World::new();
1840 world.spawn(A(0));
1841
1842 let q: QueryState<EntityMut<'_>> = world.query::<EntityMut>();
1843 let _ = q.transmute::<EntityRef>(world.components());
1844 }
1845
1846 #[test]
1847 fn can_generalize_with_option() {
1848 let mut world = World::new();
1849 world.spawn((A(0), B(0)));
1850
1851 let query_state = world.query::<(Option<&A>, &B)>();
1852 let _ = query_state.transmute::<Option<&A>>(world.components());
1853 let _ = query_state.transmute::<&B>(world.components());
1854 }
1855
1856 #[test]
1857 #[should_panic(
1858 expected = "Transmuted state for ((&bevy_ecs::query::state::tests::A, &bevy_ecs::query::state::tests::B), ()) attempts to access terms that are not allowed by original state (&bevy_ecs::query::state::tests::A, ())."
1859 )]
1860 fn cannot_transmute_to_include_data_not_in_original_query() {
1861 let mut world = World::new();
1862 world.init_component::<A>();
1863 world.init_component::<B>();
1864 world.spawn(A(0));
1865
1866 let query_state = world.query::<&A>();
1867 let mut _new_query_state = query_state.transmute::<(&A, &B)>(world.components());
1868 }
1869
1870 #[test]
1871 #[should_panic(
1872 expected = "Transmuted state for (&mut bevy_ecs::query::state::tests::A, ()) attempts to access terms that are not allowed by original state (&bevy_ecs::query::state::tests::A, ())."
1873 )]
1874 fn cannot_transmute_immut_to_mut() {
1875 let mut world = World::new();
1876 world.spawn(A(0));
1877
1878 let query_state = world.query::<&A>();
1879 let mut _new_query_state = query_state.transmute::<&mut A>(world.components());
1880 }
1881
1882 #[test]
1883 #[should_panic(
1884 expected = "Transmuted state for (&bevy_ecs::query::state::tests::A, ()) attempts to access terms that are not allowed by original state (core::option::Option<&bevy_ecs::query::state::tests::A>, ())."
1885 )]
1886 fn cannot_transmute_option_to_immut() {
1887 let mut world = World::new();
1888 world.spawn(C(0));
1889
1890 let query_state = world.query::<Option<&A>>();
1891 let mut new_query_state = query_state.transmute::<&A>(world.components());
1892 let x = new_query_state.single(&world);
1893 assert_eq!(x.0, 1234);
1894 }
1895
1896 #[test]
1897 #[should_panic(
1898 expected = "Transmuted state for (&bevy_ecs::query::state::tests::A, ()) attempts to access terms that are not allowed by original state (bevy_ecs::world::entity_ref::EntityRef, ())."
1899 )]
1900 fn cannot_transmute_entity_ref() {
1901 let mut world = World::new();
1902 world.init_component::<A>();
1903
1904 let q = world.query::<EntityRef>();
1905 let _ = q.transmute::<&A>(world.components());
1906 }
1907
1908 #[test]
1909 fn can_transmute_filtered_entity() {
1910 let mut world = World::new();
1911 let entity = world.spawn((A(0), B(1))).id();
1912 let query = QueryState::<(Entity, &A, &B)>::new(&mut world)
1913 .transmute::<FilteredEntityRef>(world.components());
1914
1915 let mut query = query;
1916 // Our result is completely untyped
1917 let entity_ref = query.single(&world);
1918
1919 assert_eq!(entity, entity_ref.id());
1920 assert_eq!(0, entity_ref.get::<A>().unwrap().0);
1921 assert_eq!(1, entity_ref.get::<B>().unwrap().0);
1922 }
1923
1924 #[test]
1925 fn can_transmute_added() {
1926 let mut world = World::new();
1927 let entity_a = world.spawn(A(0)).id();
1928
1929 let mut query = QueryState::<(Entity, &A, Has<B>)>::new(&mut world)
1930 .transmute_filtered::<(Entity, Has<B>), Added<A>>(world.components());
1931
1932 assert_eq!((entity_a, false), query.single(&world));
1933
1934 world.clear_trackers();
1935
1936 let entity_b = world.spawn((A(0), B(0))).id();
1937 assert_eq!((entity_b, true), query.single(&world));
1938
1939 world.clear_trackers();
1940
1941 assert!(query.get_single(&world).is_err());
1942 }
1943
1944 #[test]
1945 fn can_transmute_changed() {
1946 let mut world = World::new();
1947 let entity_a = world.spawn(A(0)).id();
1948
1949 let mut detection_query = QueryState::<(Entity, &A)>::new(&mut world)
1950 .transmute_filtered::<Entity, Changed<A>>(world.components());
1951
1952 let mut change_query = QueryState::<&mut A>::new(&mut world);
1953 assert_eq!(entity_a, detection_query.single(&world));
1954
1955 world.clear_trackers();
1956
1957 assert!(detection_query.get_single(&world).is_err());
1958
1959 change_query.single_mut(&mut world).0 = 1;
1960
1961 assert_eq!(entity_a, detection_query.single(&world));
1962 }
1963
1964 #[test]
1965 #[should_panic(
1966 expected = "Transmuted state for (bevy_ecs::entity::Entity, bevy_ecs::query::filter::Changed<bevy_ecs::query::state::tests::B>) attempts to access terms that are not allowed by original state (&bevy_ecs::query::state::tests::A, ())."
1967 )]
1968 fn cannot_transmute_changed_without_access() {
1969 let mut world = World::new();
1970 world.init_component::<A>();
1971 world.init_component::<B>();
1972 let query = QueryState::<&A>::new(&mut world);
1973 let _new_query = query.transmute_filtered::<Entity, Changed<B>>(world.components());
1974 }
1975
1976 #[test]
1977 fn join() {
1978 let mut world = World::new();
1979 world.spawn(A(0));
1980 world.spawn(B(1));
1981 let entity_ab = world.spawn((A(2), B(3))).id();
1982 world.spawn((A(4), B(5), C(6)));
1983
1984 let query_1 = QueryState::<&A, Without<C>>::new(&mut world);
1985 let query_2 = QueryState::<&B, Without<C>>::new(&mut world);
1986 let mut new_query: QueryState<Entity, ()> =
1987 query_1.join_filtered(world.components(), &query_2);
1988
1989 assert_eq!(new_query.single(&world), entity_ab);
1990 }
1991
1992 #[test]
1993 fn join_with_get() {
1994 let mut world = World::new();
1995 world.spawn(A(0));
1996 world.spawn(B(1));
1997 let entity_ab = world.spawn((A(2), B(3))).id();
1998 let entity_abc = world.spawn((A(4), B(5), C(6))).id();
1999
2000 let query_1 = QueryState::<&A>::new(&mut world);
2001 let query_2 = QueryState::<&B, Without<C>>::new(&mut world);
2002 let mut new_query: QueryState<Entity, ()> =
2003 query_1.join_filtered(world.components(), &query_2);
2004
2005 assert!(new_query.get(&world, entity_ab).is_ok());
2006 // should not be able to get entity with c.
2007 assert!(new_query.get(&world, entity_abc).is_err());
2008 }
2009
2010 #[test]
2011 #[should_panic(expected = "Joined state for (&bevy_ecs::query::state::tests::C, ()) \
2012 attempts to access terms that are not allowed by state \
2013 (&bevy_ecs::query::state::tests::A, ()) joined with (&bevy_ecs::query::state::tests::B, ()).")]
2014 fn cannot_join_wrong_fetch() {
2015 let mut world = World::new();
2016 world.init_component::<C>();
2017 let query_1 = QueryState::<&A>::new(&mut world);
2018 let query_2 = QueryState::<&B>::new(&mut world);
2019 let _query: QueryState<&C> = query_1.join(world.components(), &query_2);
2020 }
2021
2022 #[test]
2023 #[should_panic(
2024 expected = "Joined state for (bevy_ecs::entity::Entity, bevy_ecs::query::filter::Changed<bevy_ecs::query::state::tests::C>) \
2025 attempts to access terms that are not allowed by state \
2026 (&bevy_ecs::query::state::tests::A, bevy_ecs::query::filter::Without<bevy_ecs::query::state::tests::C>) \
2027 joined with (&bevy_ecs::query::state::tests::B, bevy_ecs::query::filter::Without<bevy_ecs::query::state::tests::C>)."
2028 )]
2029 fn cannot_join_wrong_filter() {
2030 let mut world = World::new();
2031 let query_1 = QueryState::<&A, Without<C>>::new(&mut world);
2032 let query_2 = QueryState::<&B, Without<C>>::new(&mut world);
2033 let _: QueryState<Entity, Changed<C>> = query_1.join_filtered(world.components(), &query_2);
2034 }
2035}