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