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
24#[doc(hidden)]
29pub trait DebugCheckedUnwrap {
30 type Item;
31 unsafe fn debug_checked_unwrap(self) -> Self::Item;
38}
39
40#[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#[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#[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 let count = iterator.count();
223 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 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 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 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 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 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 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 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 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 #[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 struct ReadsRData;
819
820 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 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 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}