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