bevy_ecs/query/
mod.rs

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