bevy_ecs/query/
mod.rs

1//! Contains APIs for retrieving component data from the world.
2
3mod 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
24/// A debug checked version of [`Option::unwrap_unchecked`]. Will panic in
25/// debug modes if unwrapping a `None` or `Err` value in debug mode, but is
26/// equivalent to `Option::unwrap_unchecked` or `Result::unwrap_unchecked`
27/// in release mode.
28pub(crate) trait DebugCheckedUnwrap {
29    type Item;
30    /// # Panics
31    /// Panics if the value is `None` or `Err`, only in debug mode.
32    ///
33    /// # Safety
34    /// This must never be called on a `None` or `Err` value. This can
35    /// only be called on `Some` or `Ok` values.
36    unsafe fn debug_checked_unwrap(self) -> Self::Item;
37}
38
39// These two impls are explicitly split to ensure that the unreachable! macro
40// does not cause inlining to fail when compiling in release mode.
41#[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// These two impls are explicitly split to ensure that the unreachable! macro
57// does not cause inlining to fail when compiling in release mode.
58#[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// These two impls are explicitly split to ensure that the unreachable! macro
74// does not cause inlining to fail when compiling in release mode.
75#[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            // `count` tests that not only it is the expected value, but also
214            // the value is accurate to what the query returns.
215            let count = iterator.count();
216            // This will show up when one of the asserts in this function fails
217            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        // With/Without for B and C
251        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        // With/Without (And) combinations
257        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        // With/Without Or<()> combinations
263        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        // a fair amount of entities
278        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    // the order of the combinations is not guaranteed, but each unique combination is present
285    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        // Check if Added<T>, Changed<T> works
388        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        // state
739        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        // system param
753        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    // regression test for https://github.com/bevyengine/bevy/pull/8029
768    #[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}