bevy_ecs/query/
mod.rs

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