1mod 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
24pub(crate) trait DebugCheckedUnwrap {
29 type Item;
30 unsafe fn debug_checked_unwrap(self) -> Self::Item;
37}
38
39#[cfg(debug_assertions)]
42impl<T> DebugCheckedUnwrap for Option<T> {
43 type Item = T;
44
45 #[inline(always)]
46 #[track_caller]
47 unsafe fn debug_checked_unwrap(self) -> Self::Item {
48 if let Some(inner) = self {
49 inner
50 } else {
51 unreachable!()
52 }
53 }
54}
55
56#[cfg(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#[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 let count = iterator.count();
222 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 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 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 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 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 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 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 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 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 #[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 struct ReadsRData;
818
819 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 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 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}