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