1#![expect(
2 unsafe_op_in_unsafe_fn,
3 reason = "See #11590. To be removed once all applicable unsafe code has an unsafe block with a safety comment."
4)]
5
6mod access;
9mod access_iter;
10mod builder;
11mod error;
12mod fetch;
13mod filter;
14mod iter;
15mod par_iter;
16mod state;
17mod world_query;
18
19pub use access::*;
20pub use access_iter::*;
21pub use bevy_ecs_macros::{QueryData, QueryFilter};
22pub use builder::*;
23pub use error::*;
24pub use fetch::*;
25pub use filter::*;
26pub use iter::*;
27pub use par_iter::*;
28pub use state::*;
29pub use world_query::*;
30
31#[doc(hidden)]
36pub trait DebugCheckedUnwrap {
37 type Item;
38 unsafe fn debug_checked_unwrap(self) -> Self::Item;
45}
46
47#[cfg(debug_assertions)]
50impl<T> DebugCheckedUnwrap for Option<T> {
51 type Item = T;
52
53 #[inline(always)]
54 #[track_caller]
55 unsafe fn debug_checked_unwrap(self) -> Self::Item {
56 if let Some(inner) = self {
57 inner
58 } else {
59 unreachable!()
60 }
61 }
62}
63
64#[cfg(debug_assertions)]
67impl<T, U> DebugCheckedUnwrap for Result<T, U> {
68 type Item = T;
69
70 #[inline(always)]
71 #[track_caller]
72 unsafe fn debug_checked_unwrap(self) -> Self::Item {
73 if let Ok(inner) = self {
74 inner
75 } else {
76 unreachable!()
77 }
78 }
79}
80
81#[cfg(not(debug_assertions))]
84impl<T, U> DebugCheckedUnwrap for Result<T, U> {
85 type Item = T;
86
87 #[inline(always)]
88 #[track_caller]
89 unsafe fn debug_checked_unwrap(self) -> Self::Item {
90 if let Ok(inner) = self {
91 inner
92 } else {
93 core::hint::unreachable_unchecked()
94 }
95 }
96}
97
98#[cfg(not(debug_assertions))]
99impl<T> DebugCheckedUnwrap for Option<T> {
100 type Item = T;
101
102 #[inline(always)]
103 unsafe fn debug_checked_unwrap(self) -> Self::Item {
104 if let Some(inner) = self {
105 inner
106 } else {
107 core::hint::unreachable_unchecked()
108 }
109 }
110}
111
112#[cfg(test)]
113#[expect(clippy::print_stdout, reason = "Allowed in tests.")]
114mod tests {
115 use crate::{
116 component::Component,
117 prelude::{AnyOf, Changed, Entity, Or, QueryState, With, Without},
118 query::{
119 ArchetypeFilter, ArchetypeQueryData, Has, QueryCombinationIter, QueryData, QueryFilter,
120 ReadOnlyQueryData,
121 },
122 schedule::{IntoScheduleConfigs, Schedule},
123 system::{IntoSystem, Query, System, SystemState},
124 world::World,
125 };
126 use alloc::{vec, vec::Vec};
127 use core::{any::type_name, fmt::Debug, hash::Hash};
128 use std::{collections::HashSet, println};
129
130 #[derive(Component, Debug, Hash, Eq, PartialEq, Clone, Copy, PartialOrd, Ord)]
131 struct A(usize);
132 #[derive(Component, Debug, Hash, Eq, PartialEq, Clone, Copy)]
133 struct B(usize);
134 #[derive(Component, Debug, Eq, PartialEq, Clone, Copy)]
135 struct C(usize);
136 #[derive(Component, Debug, Eq, PartialEq, Clone, Copy)]
137 struct D(usize);
138
139 #[derive(Component, Debug, Hash, Eq, PartialEq, Clone, Copy, PartialOrd, Ord)]
140 #[component(storage = "SparseSet")]
141 struct Sparse(usize);
142
143 #[test]
144 fn query() {
145 let mut world = World::new();
146 world.spawn((A(1), B(1)));
147 world.spawn(A(2));
148 let values = world.query::<&A>().iter(&world).collect::<HashSet<&A>>();
149 assert!(values.contains(&A(1)));
150 assert!(values.contains(&A(2)));
151
152 for (_a, mut b) in world.query::<(&A, &mut B)>().iter_mut(&mut world) {
153 b.0 = 3;
154 }
155 let values = world.query::<&B>().iter(&world).collect::<Vec<&B>>();
156 assert_eq!(values, vec![&B(3)]);
157 }
158
159 #[test]
160 #[cfg_attr(miri, ignore = "This test takes ~170s on CI")]
161 fn query_filtered_exactsizeiterator_len() {
162 fn choose(n: usize, k: usize) -> usize {
163 if n == 0 || k == 0 || n < k {
164 return 0;
165 }
166 let ks = 1..=k;
167 let ns = (n - k + 1..=n).rev();
168 ks.zip(ns).fold(1, |acc, (k, n)| acc * n / k)
169 }
170 fn assert_combination<D, F, const K: usize>(world: &mut World, expected_size: usize)
171 where
172 D: ReadOnlyQueryData + ArchetypeQueryData,
173 F: ArchetypeFilter,
174 {
175 let mut query = world.query_filtered::<D, F>();
176 let query_type = type_name::<QueryCombinationIter<D, F, K>>();
177 let iter = query.iter_combinations::<K>(world);
178 assert_all_sizes_iterator_equal(iter, expected_size, 0, query_type);
179 let iter = query.iter_combinations::<K>(world);
180 assert_all_sizes_iterator_equal(iter, expected_size, 1, query_type);
181 let iter = query.iter_combinations::<K>(world);
182 assert_all_sizes_iterator_equal(iter, expected_size, 5, query_type);
183 }
184 fn assert_all_sizes_equal<D, F>(world: &mut World, expected_size: usize)
185 where
186 D: ReadOnlyQueryData + ArchetypeQueryData,
187 F: ArchetypeFilter,
188 {
189 let mut query = world.query_filtered::<D, F>();
190 let query_type = type_name::<QueryState<D, F>>();
191 assert_all_exact_sizes_iterator_equal(query.iter(world), expected_size, 0, query_type);
192 assert_all_exact_sizes_iterator_equal(query.iter(world), expected_size, 1, query_type);
193 assert_all_exact_sizes_iterator_equal(query.iter(world), expected_size, 5, query_type);
194
195 let expected = expected_size;
196 assert_combination::<D, F, 1>(world, choose(expected, 1));
197 assert_combination::<D, F, 2>(world, choose(expected, 2));
198 assert_combination::<D, F, 5>(world, choose(expected, 5));
199 assert_combination::<D, F, 43>(world, choose(expected, 43));
200 assert_combination::<D, F, 64>(world, choose(expected, 64));
201 }
202 fn assert_all_exact_sizes_iterator_equal(
203 iterator: impl ExactSizeIterator,
204 expected_size: usize,
205 skip: usize,
206 query_type: &'static str,
207 ) {
208 let len = iterator.len();
209 println!("len: {len}");
210 assert_all_sizes_iterator_equal(iterator, expected_size, skip, query_type);
211 assert_eq!(len, expected_size);
212 }
213 fn assert_all_sizes_iterator_equal(
214 mut iterator: impl Iterator,
215 expected_size: usize,
216 skip: usize,
217 query_type: &'static str,
218 ) {
219 let expected_size = expected_size.saturating_sub(skip);
220 for _ in 0..skip {
221 iterator.next();
222 }
223 let size_hint_0 = iterator.size_hint().0;
224 let size_hint_1 = iterator.size_hint().1;
225 let count = iterator.count();
228 println!(
230 "query declared sizes: \n\
231 for query: {query_type} \n\
232 expected: {expected_size} \n\
233 size_hint().0: {size_hint_0} \n\
234 size_hint().1: {size_hint_1:?} \n\
235 count(): {count}"
236 );
237 assert_eq!(size_hint_0, expected_size);
238 assert_eq!(size_hint_1, Some(expected_size));
239 assert_eq!(count, expected_size);
240 }
241
242 let mut world = World::new();
243 world.spawn((A(1), B(1)));
244 world.spawn(A(2));
245 world.spawn(A(3));
246
247 assert_all_sizes_equal::<&A, With<B>>(&mut world, 1);
248 assert_all_sizes_equal::<&A, Without<B>>(&mut world, 2);
249
250 let mut world = World::new();
251 world.spawn((A(1), B(1), C(1)));
252 world.spawn((A(2), B(2)));
253 world.spawn((A(3), B(3)));
254 world.spawn((A(4), C(4)));
255 world.spawn((A(5), C(5)));
256 world.spawn((A(6), C(6)));
257 world.spawn(A(7));
258 world.spawn(A(8));
259 world.spawn(A(9));
260 world.spawn(A(10));
261
262 assert_all_sizes_equal::<&A, With<B>>(&mut world, 3);
264 assert_all_sizes_equal::<&A, With<C>>(&mut world, 4);
265 assert_all_sizes_equal::<&A, Without<B>>(&mut world, 7);
266 assert_all_sizes_equal::<&A, Without<C>>(&mut world, 6);
267
268 assert_all_sizes_equal::<&A, (With<B>, With<C>)>(&mut world, 1);
270 assert_all_sizes_equal::<&A, (With<B>, Without<C>)>(&mut world, 2);
271 assert_all_sizes_equal::<&A, (Without<B>, With<C>)>(&mut world, 3);
272 assert_all_sizes_equal::<&A, (Without<B>, Without<C>)>(&mut world, 4);
273
274 assert_all_sizes_equal::<&A, Or<(With<B>, With<C>)>>(&mut world, 6);
276 assert_all_sizes_equal::<&A, Or<(With<B>, Without<C>)>>(&mut world, 7);
277 assert_all_sizes_equal::<&A, Or<(Without<B>, With<C>)>>(&mut world, 8);
278 assert_all_sizes_equal::<&A, Or<(Without<B>, Without<C>)>>(&mut world, 9);
279 assert_all_sizes_equal::<&A, (Or<(With<B>,)>, Or<(With<C>,)>)>(&mut world, 1);
280 assert_all_sizes_equal::<&A, Or<(Or<(With<B>, With<C>)>, With<D>)>>(&mut world, 6);
281
282 for i in 11..14 {
283 world.spawn((A(i), D(i)));
284 }
285
286 assert_all_sizes_equal::<&A, Or<(Or<(With<B>, With<C>)>, With<D>)>>(&mut world, 9);
287 assert_all_sizes_equal::<&A, Or<(Or<(With<B>, With<C>)>, Without<D>)>>(&mut world, 10);
288
289 for i in 14..20 {
291 world.spawn((C(i), D(i)));
292 }
293 assert_all_sizes_equal::<Entity, (With<C>, With<D>)>(&mut world, 6);
294 }
295
296 fn check_combinations<T: Ord + Hash + Debug, const K: usize>(
298 values: HashSet<[&T; K]>,
299 expected: HashSet<[&T; K]>,
300 ) {
301 values.iter().for_each(|pair| {
302 let mut sorted = *pair;
303 sorted.sort();
304 assert!(expected.contains(&sorted),
305 "the results of iter_combinations should contain this combination {:?}. Expected: {:?}, got: {:?}",
306 &sorted, &expected, &values);
307 });
308 }
309
310 #[test]
311 fn query_iter_combinations() {
312 let mut world = World::new();
313
314 world.spawn((A(1), B(1)));
315 world.spawn(A(2));
316 world.spawn(A(3));
317 world.spawn(A(4));
318
319 let values: HashSet<[&A; 2]> = world.query::<&A>().iter_combinations(&world).collect();
320 check_combinations(
321 values,
322 HashSet::from([
323 [&A(1), &A(2)],
324 [&A(1), &A(3)],
325 [&A(1), &A(4)],
326 [&A(2), &A(3)],
327 [&A(2), &A(4)],
328 [&A(3), &A(4)],
329 ]),
330 );
331 let mut a_query = world.query::<&A>();
332
333 let values: HashSet<[&A; 3]> = a_query.iter_combinations(&world).collect();
334 check_combinations(
335 values,
336 HashSet::from([
337 [&A(1), &A(2), &A(3)],
338 [&A(1), &A(2), &A(4)],
339 [&A(1), &A(3), &A(4)],
340 [&A(2), &A(3), &A(4)],
341 ]),
342 );
343
344 let mut b_query = world.query::<&B>();
345 assert_eq!(
346 b_query.iter_combinations::<2>(&world).size_hint(),
347 (0, Some(0))
348 );
349 let values: Vec<[&B; 2]> = b_query.iter_combinations(&world).collect();
350 assert_eq!(values, Vec::<[&B; 2]>::new());
351 }
352
353 #[test]
354 fn query_filtered_iter_combinations() {
355 use bevy_ecs::query::{Added, Or, With, Without};
356
357 let mut world = World::new();
358
359 world.spawn((A(1), B(1)));
360 world.spawn(A(2));
361 world.spawn(A(3));
362 world.spawn(A(4));
363
364 let mut a_wout_b = world.query_filtered::<&A, Without<B>>();
365 let values: HashSet<[&A; 2]> = a_wout_b.iter_combinations(&world).collect();
366 check_combinations(
367 values,
368 HashSet::from([[&A(2), &A(3)], [&A(2), &A(4)], [&A(3), &A(4)]]),
369 );
370
371 let values: HashSet<[&A; 3]> = a_wout_b.iter_combinations(&world).collect();
372 check_combinations(values, HashSet::from([[&A(2), &A(3), &A(4)]]));
373
374 let mut query = world.query_filtered::<&A, Or<(With<A>, With<B>)>>();
375 let values: HashSet<[&A; 2]> = query.iter_combinations(&world).collect();
376 check_combinations(
377 values,
378 HashSet::from([
379 [&A(1), &A(2)],
380 [&A(1), &A(3)],
381 [&A(1), &A(4)],
382 [&A(2), &A(3)],
383 [&A(2), &A(4)],
384 [&A(3), &A(4)],
385 ]),
386 );
387
388 let mut query = world.query_filtered::<&mut A, Without<B>>();
389 let mut combinations = query.iter_combinations_mut(&mut world);
390 while let Some([mut a, mut b, mut c]) = combinations.fetch_next() {
391 a.0 += 10;
392 b.0 += 100;
393 c.0 += 1000;
394 }
395
396 let values: HashSet<[&A; 3]> = a_wout_b.iter_combinations(&world).collect();
397 check_combinations(values, HashSet::from([[&A(12), &A(103), &A(1004)]]));
398
399 let mut world = World::new();
401
402 world.spawn((A(1), B(1)));
403 world.spawn((A(2), B(2)));
404 world.spawn((A(3), B(3)));
405 world.spawn((A(4), B(4)));
406
407 let mut query_added = world.query_filtered::<&A, Added<A>>();
408
409 world.clear_trackers();
410 world.spawn(A(5));
411
412 assert_eq!(query_added.iter_combinations::<2>(&world).count(), 0);
413
414 world.clear_trackers();
415 world.spawn(A(6));
416 world.spawn(A(7));
417
418 assert_eq!(query_added.iter_combinations::<2>(&world).count(), 1);
419
420 world.clear_trackers();
421 world.spawn(A(8));
422 world.spawn(A(9));
423 world.spawn(A(10));
424
425 assert_eq!(query_added.iter_combinations::<2>(&world).count(), 3);
426 }
427
428 #[test]
429 fn query_iter_combinations_sparse() {
430 let mut world = World::new();
431
432 world.spawn_batch((1..=4).map(Sparse));
433
434 let values: HashSet<[&Sparse; 3]> =
435 world.query::<&Sparse>().iter_combinations(&world).collect();
436 check_combinations(
437 values,
438 HashSet::from([
439 [&Sparse(1), &Sparse(2), &Sparse(3)],
440 [&Sparse(1), &Sparse(2), &Sparse(4)],
441 [&Sparse(1), &Sparse(3), &Sparse(4)],
442 [&Sparse(2), &Sparse(3), &Sparse(4)],
443 ]),
444 );
445 }
446
447 #[test]
448 fn get_many_only_mut_checks_duplicates() {
449 let mut world = World::new();
450 let id = world.spawn(A(10)).id();
451 let mut query_state = world.query::<&mut A>();
452 let mut query = query_state.query_mut(&mut world);
453 let result = query.get_many([id, id]);
454 assert_eq!(result, Ok([&A(10), &A(10)]));
455 let mut_result = query.get_many_mut([id, id]);
456 assert!(mut_result.is_err());
457 }
458
459 #[test]
460 fn multi_storage_query() {
461 let mut world = World::new();
462
463 world.spawn((Sparse(1), B(2)));
464 world.spawn(Sparse(2));
465
466 let values = world
467 .query::<&Sparse>()
468 .iter(&world)
469 .collect::<HashSet<&Sparse>>();
470 assert!(values.contains(&Sparse(1)));
471 assert!(values.contains(&Sparse(2)));
472
473 for (_a, mut b) in world.query::<(&Sparse, &mut B)>().iter_mut(&mut world) {
474 b.0 = 3;
475 }
476
477 let values = world.query::<&B>().iter(&world).collect::<Vec<&B>>();
478 assert_eq!(values, vec![&B(3)]);
479 }
480
481 #[test]
482 fn any_query() {
483 let mut world = World::new();
484
485 world.spawn((A(1), B(2)));
486 world.spawn(A(2));
487 world.spawn(C(3));
488
489 let values: Vec<(Option<&A>, Option<&B>)> =
490 world.query::<AnyOf<(&A, &B)>>().iter(&world).collect();
491
492 assert_eq!(
493 values,
494 vec![(Some(&A(1)), Some(&B(2))), (Some(&A(2)), None),]
495 );
496 }
497
498 #[test]
499 fn has_query() {
500 let mut world = World::new();
501
502 world.spawn((A(1), B(1)));
503 world.spawn(A(2));
504 world.spawn((A(3), B(1)));
505 world.spawn(A(4));
506
507 let values: HashSet<(&A, bool)> = world.query::<(&A, Has<B>)>().iter(&world).collect();
508
509 assert!(values.contains(&(&A(1), true)));
510 assert!(values.contains(&(&A(2), false)));
511 assert!(values.contains(&(&A(3), true)));
512 assert!(values.contains(&(&A(4), false)));
513 }
514
515 #[test]
516 #[should_panic]
517 fn self_conflicting_worldquery() {
518 #[derive(QueryData)]
519 #[query_data(mutable)]
520 struct SelfConflicting {
521 a: &'static mut A,
522 b: &'static mut A,
523 }
524
525 let mut world = World::new();
526 world.query::<SelfConflicting>();
527 }
528
529 #[test]
530 fn derived_worldqueries() {
531 let mut world = World::new();
532
533 world.spawn((A(10), B(18), C(3), Sparse(4)));
534
535 world.spawn((A(101), B(148), C(13)));
536 world.spawn((A(51), B(46), Sparse(72)));
537 world.spawn((A(398), C(6), Sparse(9)));
538 world.spawn((B(11), C(28), Sparse(92)));
539
540 world.spawn((C(18348), Sparse(101)));
541 world.spawn((B(839), Sparse(5)));
542 world.spawn((B(6721), C(122)));
543 world.spawn((A(220), Sparse(63)));
544 world.spawn((A(1092), C(382)));
545 world.spawn((A(2058), B(3019)));
546
547 world.spawn((B(38), C(8), Sparse(100)));
548 world.spawn((A(111), C(52), Sparse(1)));
549 world.spawn((A(599), B(39), Sparse(13)));
550 world.spawn((A(55), B(66), C(77)));
551
552 world.spawn_empty();
553
554 {
555 #[derive(QueryData)]
556 struct CustomAB {
557 a: &'static A,
558 b: &'static B,
559 }
560
561 let custom_param_data = world
562 .query::<CustomAB>()
563 .iter(&world)
564 .map(|item| (*item.a, *item.b))
565 .collect::<Vec<_>>();
566 let normal_data = world
567 .query::<(&A, &B)>()
568 .iter(&world)
569 .map(|(a, b)| (*a, *b))
570 .collect::<Vec<_>>();
571 assert_eq!(custom_param_data, normal_data);
572 }
573
574 {
575 #[derive(QueryData)]
576 struct FancyParam {
577 e: Entity,
578 b: &'static B,
579 opt: Option<&'static Sparse>,
580 }
581
582 let custom_param_data = world
583 .query::<FancyParam>()
584 .iter(&world)
585 .map(|fancy| (fancy.e, *fancy.b, fancy.opt.copied()))
586 .collect::<Vec<_>>();
587 let normal_data = world
588 .query::<(Entity, &B, Option<&Sparse>)>()
589 .iter(&world)
590 .map(|(e, b, opt)| (e, *b, opt.copied()))
591 .collect::<Vec<_>>();
592 assert_eq!(custom_param_data, normal_data);
593 }
594
595 {
596 #[derive(QueryData)]
597 struct MaybeBSparse {
598 blah: Option<(&'static B, &'static Sparse)>,
599 }
600 #[derive(QueryData)]
601 struct MatchEverything {
602 abcs: AnyOf<(&'static A, &'static B, &'static C)>,
603 opt_bsparse: MaybeBSparse,
604 }
605
606 let custom_param_data = world
607 .query::<MatchEverything>()
608 .iter(&world)
609 .map(
610 |MatchEverythingItem {
611 abcs: (a, b, c),
612 opt_bsparse: MaybeBSparseItem { blah: bsparse },
613 }| {
614 (
615 (a.copied(), b.copied(), c.copied()),
616 bsparse.map(|(b, sparse)| (*b, *sparse)),
617 )
618 },
619 )
620 .collect::<Vec<_>>();
621 let normal_data = world
622 .query::<(AnyOf<(&A, &B, &C)>, Option<(&B, &Sparse)>)>()
623 .iter(&world)
624 .map(|((a, b, c), bsparse)| {
625 (
626 (a.copied(), b.copied(), c.copied()),
627 bsparse.map(|(b, sparse)| (*b, *sparse)),
628 )
629 })
630 .collect::<Vec<_>>();
631 assert_eq!(custom_param_data, normal_data);
632 }
633
634 {
635 #[derive(QueryFilter)]
636 struct AOrBFilter {
637 a: Or<(With<A>, With<B>)>,
638 }
639 #[derive(QueryFilter)]
640 struct NoSparseThatsSlow {
641 no: Without<Sparse>,
642 }
643
644 let custom_param_entities = world
645 .query_filtered::<Entity, (AOrBFilter, NoSparseThatsSlow)>()
646 .iter(&world)
647 .collect::<Vec<_>>();
648 let normal_entities = world
649 .query_filtered::<Entity, (Or<(With<A>, With<B>)>, Without<Sparse>)>()
650 .iter(&world)
651 .collect::<Vec<_>>();
652 assert_eq!(custom_param_entities, normal_entities);
653 }
654
655 {
656 #[derive(QueryFilter)]
657 struct CSparseFilter {
658 tuple_structs_pls: With<C>,
659 ugh: With<Sparse>,
660 }
661
662 let custom_param_entities = world
663 .query_filtered::<Entity, CSparseFilter>()
664 .iter(&world)
665 .collect::<Vec<_>>();
666 let normal_entities = world
667 .query_filtered::<Entity, (With<C>, With<Sparse>)>()
668 .iter(&world)
669 .collect::<Vec<_>>();
670 assert_eq!(custom_param_entities, normal_entities);
671 }
672
673 {
674 #[derive(QueryFilter)]
675 struct WithoutComps {
676 _1: Without<A>,
677 _2: Without<B>,
678 _3: Without<C>,
679 }
680
681 let custom_param_entities = world
682 .query_filtered::<Entity, WithoutComps>()
683 .iter(&world)
684 .collect::<Vec<_>>();
685 let normal_entities = world
686 .query_filtered::<Entity, (Without<A>, Without<B>, Without<C>)>()
687 .iter(&world)
688 .collect::<Vec<_>>();
689 assert_eq!(custom_param_entities, normal_entities);
690 }
691
692 {
693 #[derive(QueryData)]
694 struct IterCombAB {
695 a: &'static A,
696 b: &'static B,
697 }
698
699 let custom_param_data = world
700 .query::<IterCombAB>()
701 .iter_combinations::<2>(&world)
702 .map(|[item0, item1]| [(*item0.a, *item0.b), (*item1.a, *item1.b)])
703 .collect::<Vec<_>>();
704 let normal_data = world
705 .query::<(&A, &B)>()
706 .iter_combinations(&world)
707 .map(|[(a0, b0), (a1, b1)]| [(*a0, *b0), (*a1, *b1)])
708 .collect::<Vec<_>>();
709 assert_eq!(custom_param_data, normal_data);
710 }
711 }
712
713 #[test]
714 fn many_entities() {
715 let mut world = World::new();
716 world.spawn((A(0), B(0)));
717 world.spawn((A(0), B(0)));
718 world.spawn(A(0));
719 world.spawn(B(0));
720 {
721 fn system(has_a: Query<Entity, With<A>>, has_a_and_b: Query<(&A, &B)>) {
722 assert_eq!(has_a_and_b.iter_many(&has_a).count(), 2);
723 }
724 let mut system = IntoSystem::into_system(system);
725 system.initialize(&mut world);
726 system.run((), &mut world).unwrap();
727 }
728 {
729 fn system(has_a: Query<Entity, With<A>>, mut b_query: Query<&mut B>) {
730 let mut iter = b_query.iter_many_mut(&has_a);
731 while let Some(mut b) = iter.fetch_next() {
732 b.0 = 1;
733 }
734 }
735 let mut system = IntoSystem::into_system(system);
736 system.initialize(&mut world);
737 system.run((), &mut world).unwrap();
738 }
739 {
740 fn system(query: Query<(Option<&A>, &B)>) {
741 for (maybe_a, b) in &query {
742 match maybe_a {
743 Some(_) => assert_eq!(b.0, 1),
744 None => assert_eq!(b.0, 0),
745 }
746 }
747 }
748 let mut system = IntoSystem::into_system(system);
749 system.initialize(&mut world);
750 system.run((), &mut world).unwrap();
751 }
752 }
753
754 #[test]
755 fn mut_to_immut_query_methods_have_immut_item() {
756 #[derive(Component)]
757 struct Foo;
758
759 let mut world = World::new();
760 let e = world.spawn(Foo).id();
761
762 let mut q = world.query::<&mut Foo>();
764 let _: Option<&Foo> = q.iter(&world).next();
765 let _: Option<[&Foo; 2]> = q.iter_combinations::<2>(&world).next();
766 let _: Option<&Foo> = q.iter_manual(&world).next();
767 let _: Option<&Foo> = q.iter_many(&world, [e]).next();
768 q.iter(&world).for_each(|_: &Foo| ());
769
770 let _: Option<&Foo> = q.get(&world, e).ok();
771 let _: Option<&Foo> = q.get_manual(&world, e).ok();
772 let _: Option<[&Foo; 1]> = q.get_many(&world, [e]).ok();
773 let _: Option<&Foo> = q.single(&world).ok();
774 let _: &Foo = q.single(&world).unwrap();
775
776 let mut q = SystemState::<Query<&mut Foo>>::new(&mut world);
778 let q = q.get_mut(&mut world).unwrap();
779 let _: Option<&Foo> = q.iter().next();
780 let _: Option<[&Foo; 2]> = q.iter_combinations::<2>().next();
781 let _: Option<&Foo> = q.iter_many([e]).next();
782 q.iter().for_each(|_: &Foo| ());
783
784 let _: Option<&Foo> = q.get(e).ok();
785 let _: Option<[&Foo; 1]> = q.get_many([e]).ok();
786 let _: Option<&Foo> = q.single().ok();
787 let _: &Foo = q.single().unwrap();
788 }
789
790 #[test]
792 fn par_iter_mut_change_detection() {
793 let mut world = World::new();
794 world.spawn((A(1), B(1)));
795
796 fn propagate_system(mut query: Query<(&A, &mut B), Changed<A>>) {
797 query.par_iter_mut().for_each(|(a, mut b)| {
798 b.0 = a.0;
799 });
800 }
801
802 fn modify_system(mut query: Query<&mut A>) {
803 for mut a in &mut query {
804 a.0 = 2;
805 }
806 }
807
808 let mut schedule = Schedule::default();
809 schedule.add_systems((propagate_system, modify_system).chain());
810 schedule.run(&mut world);
811 world.clear_trackers();
812 schedule.run(&mut world);
813 world.clear_trackers();
814
815 let values = world.query::<&B>().iter(&world).collect::<Vec<&B>>();
816 assert_eq!(values, vec![&B(2)]);
817 }
818
819 #[test]
821 #[rustfmt::skip]
823 fn query_data_derive_where_clause() {
824 #[derive(QueryData)]
825 struct QueryDataA<C>
826 where
827 C: Component,
828 {
829 component: &'static C,
830 }
831
832 #[derive(QueryData)]
833 struct QueryDataB<C>(&'static C)
834 where
835 C: Component;
836 }
837
838 #[test]
840 fn query_data_derive_contiguous_tuple() {
841 #[derive(QueryData)]
842 #[query_data(contiguous(mutable))]
843 struct QueryDataA(Entity, &'static A);
844
845 #[derive(QueryData)]
846 #[query_data(contiguous(all))]
847 struct QueryDataB<C>(&'static C)
848 where
849 C: Component + PartialEq;
850
851 let mut world = World::new();
852 let _ = world.query::<QueryDataA>().contiguous_iter_mut(&mut world);
853 let _ = world.query::<QueryDataB<D>>().contiguous_iter(&world);
854 }
855
856 #[test]
858 fn query_data_derive_empty() {
859 #[derive(QueryData)]
860 struct QueryDataA {}
861
862 #[derive(QueryData)]
863 struct QueryDataB();
864
865 #[derive(QueryData)]
866 #[query_data(mutable)]
867 struct QueryDataC {}
868
869 #[derive(QueryData)]
870 #[query_data(mutable)]
871 struct QueryDataD();
872
873 #[derive(QueryData)]
874 #[query_data(contiguous(immutable))]
875 struct QueryDataE {}
876
877 #[derive(QueryData)]
878 #[query_data(contiguous(immutable))]
879 struct QueryDataF();
880
881 #[derive(QueryData)]
882 #[query_data(mutable, contiguous(immutable))]
883 struct QueryDataG {}
884
885 #[derive(QueryData)]
886 #[query_data(mutable, contiguous(immutable))]
887 struct QueryDataH();
888
889 #[derive(QueryData)]
890 #[query_data(contiguous(mutable))]
891 struct QueryDataI {}
892
893 #[derive(QueryData)]
894 #[query_data(contiguous(mutable))]
895 struct QueryDataJ();
896
897 #[derive(QueryData)]
898 #[query_data(mutable, contiguous(mutable))]
899 struct QueryDataK {}
900
901 #[derive(QueryData)]
902 #[query_data(mutable, contiguous(mutable))]
903 struct QueryDataL();
904
905 #[derive(QueryData)]
906 #[query_data(contiguous(all))]
907 struct QueryDataM {}
908
909 #[derive(QueryData)]
910 #[query_data(contiguous(all))]
911 struct QueryDataN();
912
913 #[derive(QueryData)]
914 #[query_data(mutable, contiguous(all))]
915 struct QueryDataO {}
916
917 #[derive(QueryData)]
918 #[query_data(mutable, contiguous(all))]
919 struct QueryDataP();
920 }
921}