Thanks to visit codestin.com
Credit goes to docs.rs

bevy_ecs/system/
mod.rs

1//! Tools for controlling behavior in an ECS application.
2//!
3//! Systems define how an ECS based application behaves.
4//! Systems are added to a [`Schedule`](crate::schedule::Schedule), which is then run.
5//! A system is usually written as a normal function, which is automatically converted into a system.
6//!
7//! System functions can have parameters, through which one can query and mutate Bevy ECS state.
8//! Only types that implement [`SystemParam`] can be used, automatically fetching data from
9//! the [`World`].
10//!
11//! System functions often look like this:
12//!
13//! ```
14//! # use bevy_ecs::prelude::*;
15//! #
16//! # #[derive(Component)]
17//! # struct Player { alive: bool }
18//! # #[derive(Component)]
19//! # struct Score(u32);
20//! # #[derive(Resource)]
21//! # struct Round(u32);
22//! #
23//! fn update_score_system(
24//!     mut query: Query<(&Player, &mut Score)>,
25//!     mut round: ResMut<Round>,
26//! ) {
27//!     for (player, mut score) in &mut query {
28//!         if player.alive {
29//!             score.0 += round.0;
30//!         }
31//!     }
32//!     round.0 += 1;
33//! }
34//! # bevy_ecs::system::assert_is_system(update_score_system);
35//! ```
36//!
37//! # System ordering
38//!
39//! By default, the execution of systems is parallel and not deterministic.
40//! Not all systems can run together: if a system mutably accesses data,
41//! no other system that reads or writes that data can be run at the same time.
42//! These systems are said to be **incompatible**.
43//!
44//! The relative order in which incompatible systems are run matters.
45//! When this is not specified, a **system order ambiguity** exists in your schedule.
46//! You can **explicitly order** systems:
47//!
48//! - by calling the `.before(this_system)` or `.after(that_system)` methods when adding them to your schedule
49//! - by adding them to a [`SystemSet`], and then using `.configure_sets(ThisSet.before(ThatSet))` syntax to configure many systems at once
50//! - through the use of `.add_systems((system_a, system_b, system_c).chain())`
51//!
52//! [`SystemSet`]: crate::schedule::SystemSet
53//!
54//! ## Example
55//!
56//! ```
57//! # use bevy_ecs::prelude::*;
58//! # let mut schedule = Schedule::default();
59//! # let mut world = World::new();
60//! // Configure these systems to run in order using `chain()`.
61//! schedule.add_systems((print_first, print_last).chain());
62//! // Prints "HelloWorld!"
63//! schedule.run(&mut world);
64//!
65//! // Configure this system to run in between the other two systems
66//! // using explicit dependencies.
67//! schedule.add_systems(print_mid.after(print_first).before(print_last));
68//! // Prints "Hello, World!"
69//! schedule.run(&mut world);
70//!
71//! fn print_first() {
72//!     print!("Hello");
73//! }
74//! fn print_mid() {
75//!     print!(", ");
76//! }
77//! fn print_last() {
78//!     println!("World!");
79//! }
80//! ```
81//!
82//! # System return type
83//!
84//! Systems added to a schedule through [`add_systems`](crate::schedule::Schedule) may either return
85//! empty `()` or a [`Result`](crate::error::Result). Other contexts (like one shot systems) allow
86//! systems to return arbitrary values.
87//!
88//! # System parameter list
89//! Following is the complete list of accepted types as system parameters:
90//!
91//! - [`Query`]
92//! - [`Res`] and `Option<Res>`
93//! - [`ResMut`] and `Option<ResMut>`
94//! - [`Commands`]
95//! - [`Local`]
96//! - [`MessageReader`](crate::message::MessageReader)
97//! - [`MessageWriter`](crate::message::MessageWriter)
98//! - [`NonSend`] and `Option<NonSend>`
99//! - [`NonSendMut`] and `Option<NonSendMut>`
100//! - [`RemovedComponents`](crate::lifecycle::RemovedComponents)
101//! - [`SystemName`]
102//! - [`SystemChangeTick`]
103//! - [`Archetypes`](crate::archetype::Archetypes) (Provides Archetype metadata)
104//! - [`Bundles`](crate::bundle::Bundles) (Provides Bundles metadata)
105//! - [`Components`](crate::component::Components) (Provides Components metadata)
106//! - [`Entities`](crate::entity::Entities) (Provides Entities metadata)
107//! - All tuples between 1 to 16 elements where each element implements [`SystemParam`]
108//! - [`ParamSet`]
109//! - [`()` (unit primitive type)](https://doc.rust-lang.org/stable/std/primitive.unit.html)
110//!
111//! In addition, the following parameters can be used when constructing a dynamic system with [`SystemParamBuilder`],
112//! but will only provide an empty value when used with an ordinary system:
113//!
114//! - [`FilteredResources`](crate::world::FilteredResources)
115//! - [`FilteredResourcesMut`](crate::world::FilteredResourcesMut)
116//! - [`DynSystemParam`]
117//! - [`Vec<P>`] where `P: SystemParam`
118//! - [`ParamSet<Vec<P>>`] where `P: SystemParam`
119//!
120//! [`Vec<P>`]: alloc::vec::Vec
121
122mod adapter_system;
123mod builder;
124mod combinator;
125mod commands;
126mod exclusive_function_system;
127mod exclusive_system_param;
128mod function_system;
129mod input;
130mod observer_system;
131mod query;
132mod schedule_system;
133mod system;
134mod system_name;
135mod system_param;
136mod system_registry;
137
138use core::any::TypeId;
139
140pub use adapter_system::*;
141pub use builder::*;
142pub use combinator::*;
143pub use commands::*;
144pub use exclusive_function_system::*;
145pub use exclusive_system_param::*;
146pub use function_system::*;
147pub use input::*;
148pub use observer_system::*;
149pub use query::*;
150pub use schedule_system::*;
151pub use system::*;
152pub use system_name::*;
153pub use system_param::*;
154pub use system_registry::*;
155
156use crate::world::{FromWorld, World};
157
158/// Conversion trait to turn something into a [`System`].
159///
160/// Use this to get a system from a function. Also note that every system implements this trait as
161/// well.
162///
163/// # Usage notes
164///
165/// This trait should only be used as a bound for trait implementations or as an
166/// argument to a function. If a system needs to be returned from a function or
167/// stored somewhere, use [`System`] instead of this trait.
168///
169/// # Examples
170///
171/// ```
172/// use bevy_ecs::prelude::*;
173///
174/// fn my_system_function(a_usize_local: Local<usize>) {}
175///
176/// let system = IntoSystem::into_system(my_system_function);
177/// ```
178// This trait has to be generic because we have potentially overlapping impls, in particular
179// because Rust thinks a type could impl multiple different `FnMut` combinations
180// even though none can currently
181#[diagnostic::on_unimplemented(
182    message = "`{Self}` is not a valid system with input `{In}` and output `{Out}`",
183    label = "invalid system"
184)]
185pub trait IntoSystem<In: SystemInput, Out, Marker>: Sized {
186    /// The type of [`System`] that this instance converts into.
187    type System: System<In = In, Out = Out>;
188
189    /// Turns this value into its corresponding [`System`].
190    fn into_system(this: Self) -> Self::System;
191
192    /// Pass the output of this system `A` into a second system `B`, creating a new compound system.
193    ///
194    /// The second system must have [`In<T>`](crate::system::In) as its first parameter,
195    /// where `T` is the return type of the first system.
196    fn pipe<B, BIn, BOut, MarkerB>(self, system: B) -> IntoPipeSystem<Self, B>
197    where
198        Out: 'static,
199        B: IntoSystem<BIn, BOut, MarkerB>,
200        for<'a> BIn: SystemInput<Inner<'a> = Out>,
201    {
202        IntoPipeSystem::new(self, system)
203    }
204
205    /// Pass the output of this system into the passed function `f`, creating a new system that
206    /// outputs the value returned from the function.
207    ///
208    /// ```
209    /// # use bevy_ecs::prelude::*;
210    /// # let mut schedule = Schedule::default();
211    /// // Ignores the output of a system that may fail.
212    /// schedule.add_systems(my_system.map(drop));
213    /// # let mut world = World::new();
214    /// # world.insert_resource(T);
215    /// # schedule.run(&mut world);
216    ///
217    /// # #[derive(Resource)] struct T;
218    /// # type Err = ();
219    /// fn my_system(res: Res<T>) -> Result<(), Err> {
220    ///     // ...
221    ///     # Err(())
222    /// }
223    /// ```
224    fn map<T, F>(self, f: F) -> IntoAdapterSystem<F, Self>
225    where
226        F: Send + Sync + 'static + FnMut(Out) -> T,
227    {
228        IntoAdapterSystem::new(f, self)
229    }
230
231    /// Passes a mutable reference to `value` as input to the system each run,
232    /// turning it into a system that takes no input.
233    ///
234    /// `Self` can have any [`SystemInput`] type that takes a mutable reference
235    /// to `T`, such as [`InMut`].
236    ///
237    /// # Example
238    ///
239    /// ```
240    /// # use bevy_ecs::prelude::*;
241    /// #
242    /// fn my_system(InMut(value): InMut<usize>) {
243    ///     *value += 1;
244    ///     if *value > 10 {
245    ///        println!("Value is greater than 10!");
246    ///     }
247    /// }
248    ///
249    /// # let mut schedule = Schedule::default();
250    /// schedule.add_systems(my_system.with_input(0));
251    /// # bevy_ecs::system::assert_is_system(my_system.with_input(0));
252    /// ```
253    fn with_input<T>(self, value: T) -> WithInputWrapper<Self::System, T>
254    where
255        for<'i> In: SystemInput<Inner<'i> = &'i mut T>,
256        T: Send + Sync + 'static,
257    {
258        WithInputWrapper::new(self, value)
259    }
260
261    /// Passes a mutable reference to a value of type `T` created via
262    /// [`FromWorld`] as input to the system each run, turning it into a system
263    /// that takes no input.
264    ///
265    /// `Self` can have any [`SystemInput`] type that takes a mutable reference
266    /// to `T`, such as [`InMut`].
267    ///
268    /// # Example
269    ///
270    /// ```
271    /// # use bevy_ecs::prelude::*;
272    /// #
273    /// struct MyData {
274    ///     value: usize,
275    /// }
276    ///
277    /// impl FromWorld for MyData {
278    ///     fn from_world(world: &mut World) -> Self {
279    ///         // Fetch from the world the data needed to create `MyData`
280    /// #       MyData { value: 0 }
281    ///     }
282    /// }
283    ///
284    /// fn my_system(InMut(data): InMut<MyData>) {
285    ///     data.value += 1;
286    ///     if data.value > 10 {
287    ///         println!("Value is greater than 10!");
288    ///     }
289    /// }
290    /// # let mut schedule = Schedule::default();
291    /// schedule.add_systems(my_system.with_input_from::<MyData>());
292    /// # bevy_ecs::system::assert_is_system(my_system.with_input_from::<MyData>());
293    /// ```
294    fn with_input_from<T>(self) -> WithInputFromWrapper<Self::System, T>
295    where
296        for<'i> In: SystemInput<Inner<'i> = &'i mut T>,
297        T: FromWorld + Send + Sync + 'static,
298    {
299        WithInputFromWrapper::new(self)
300    }
301
302    /// Get the [`TypeId`] of the [`System`] produced after calling [`into_system`](`IntoSystem::into_system`).
303    #[inline]
304    fn system_type_id(&self) -> TypeId {
305        TypeId::of::<Self::System>()
306    }
307}
308
309// All systems implicitly implement IntoSystem.
310impl<T: System> IntoSystem<T::In, T::Out, ()> for T {
311    type System = T;
312    fn into_system(this: Self) -> Self {
313        this
314    }
315}
316
317/// Ensure that a given function is a [system](System).
318///
319/// This should be used when writing doc examples,
320/// to confirm that systems used in an example are
321/// valid systems.
322///
323/// # Examples
324///
325/// The following example will panic when run since the
326/// system's parameters mutably access the same component
327/// multiple times.
328///
329/// ```should_panic
330/// # use bevy_ecs::{prelude::*, system::assert_is_system};
331/// #
332/// # #[derive(Component)]
333/// # struct Transform;
334/// #
335/// fn my_system(query1: Query<&mut Transform>, query2: Query<&mut Transform>) {
336///     // ...
337/// }
338///
339/// assert_is_system(my_system);
340/// ```
341pub fn assert_is_system<In: SystemInput, Out: 'static, Marker>(
342    system: impl IntoSystem<In, Out, Marker>,
343) {
344    let mut system = IntoSystem::into_system(system);
345
346    // Initialize the system, which will panic if the system has access conflicts.
347    let mut world = World::new();
348    system.initialize(&mut world);
349}
350
351/// Ensure that a given function is a [read-only system](ReadOnlySystem).
352///
353/// This should be used when writing doc examples,
354/// to confirm that systems used in an example are
355/// valid systems.
356///
357/// # Examples
358///
359/// The following example will fail to compile
360/// since the system accesses a component mutably.
361///
362/// ```compile_fail
363/// # use bevy_ecs::{prelude::*, system::assert_is_read_only_system};
364/// #
365/// # #[derive(Component)]
366/// # struct Transform;
367/// #
368/// fn my_system(query: Query<&mut Transform>) {
369///     // ...
370/// }
371///
372/// assert_is_read_only_system(my_system);
373/// ```
374pub fn assert_is_read_only_system<In, Out, Marker, S>(system: S)
375where
376    In: SystemInput,
377    Out: 'static,
378    S: IntoSystem<In, Out, Marker>,
379    S::System: ReadOnlySystem,
380{
381    assert_is_system(system);
382}
383
384/// Ensures that the provided system doesn't conflict with itself.
385///
386/// This function will panic if the provided system conflict with itself.
387///
388/// Note: this will run the system on an empty world.
389pub fn assert_system_does_not_conflict<Out, Params, S: IntoSystem<(), Out, Params>>(sys: S) {
390    let mut world = World::new();
391    let mut system = IntoSystem::into_system(sys);
392    system.initialize(&mut world);
393    system.run((), &mut world).unwrap();
394}
395
396#[cfg(test)]
397#[expect(clippy::print_stdout, reason = "Allowed in tests.")]
398mod tests {
399    use alloc::{vec, vec::Vec};
400    use bevy_utils::default;
401    use core::any::TypeId;
402    use std::println;
403
404    use crate::{
405        archetype::Archetypes,
406        bundle::Bundles,
407        change_detection::DetectChanges,
408        component::{Component, Components},
409        entity::{Entities, Entity},
410        error::Result,
411        lifecycle::RemovedComponents,
412        name::Name,
413        prelude::{Add, AnyOf, EntityRef, On},
414        query::{Added, Changed, Or, SpawnDetails, Spawned, With, Without},
415        resource::Resource,
416        schedule::{
417            common_conditions::resource_exists, ApplyDeferred, IntoScheduleConfigs, Schedule,
418            SystemCondition,
419        },
420        system::{
421            Commands, In, InMut, IntoSystem, Local, NonSend, NonSendMut, ParamSet, Query, Res,
422            ResMut, Single, StaticSystemParam, System, SystemState,
423        },
424        world::{DeferredWorld, EntityMut, FromWorld, World},
425    };
426
427    use super::ScheduleSystem;
428
429    #[derive(Resource, PartialEq, Debug)]
430    enum SystemRan {
431        Yes,
432        No,
433    }
434
435    #[derive(Component, Resource, Debug, Eq, PartialEq, Default)]
436    struct A;
437    #[derive(Component, Resource)]
438    struct B;
439    #[derive(Component, Resource)]
440    struct C;
441    #[derive(Component, Resource)]
442    struct D;
443    #[derive(Component, Resource)]
444    struct E;
445    #[derive(Component, Resource)]
446    struct F;
447
448    #[derive(Component, Debug)]
449    struct W<T>(T);
450
451    #[test]
452    fn simple_system() {
453        fn sys(query: Query<&A>) {
454            for a in &query {
455                println!("{a:?}");
456            }
457        }
458
459        let mut system = IntoSystem::into_system(sys);
460        let mut world = World::new();
461        world.spawn(A);
462
463        system.initialize(&mut world);
464        system.run((), &mut world).unwrap();
465    }
466
467    fn run_system<Marker, S: IntoScheduleConfigs<ScheduleSystem, Marker>>(
468        world: &mut World,
469        system: S,
470    ) {
471        let mut schedule = Schedule::default();
472        schedule.add_systems(system);
473        schedule.run(world);
474    }
475
476    #[test]
477    fn get_many_is_ordered() {
478        use crate::resource::Resource;
479        const ENTITIES_COUNT: usize = 1000;
480
481        #[derive(Resource)]
482        struct EntitiesArray(Vec<Entity>);
483
484        fn query_system(
485            mut ran: ResMut<SystemRan>,
486            entities_array: Res<EntitiesArray>,
487            q: Query<&W<usize>>,
488        ) {
489            let entities_array: [Entity; ENTITIES_COUNT] =
490                entities_array.0.clone().try_into().unwrap();
491
492            for (i, w) in (0..ENTITIES_COUNT).zip(q.get_many(entities_array).unwrap()) {
493                assert_eq!(i, w.0);
494            }
495
496            *ran = SystemRan::Yes;
497        }
498
499        fn query_system_mut(
500            mut ran: ResMut<SystemRan>,
501            entities_array: Res<EntitiesArray>,
502            mut q: Query<&mut W<usize>>,
503        ) {
504            let entities_array: [Entity; ENTITIES_COUNT] =
505                entities_array.0.clone().try_into().unwrap();
506
507            for (i, w) in (0..ENTITIES_COUNT).zip(q.get_many_mut(entities_array).unwrap()) {
508                assert_eq!(i, w.0);
509            }
510
511            *ran = SystemRan::Yes;
512        }
513
514        let mut world = World::default();
515        world.insert_resource(SystemRan::No);
516        let entity_ids = (0..ENTITIES_COUNT)
517            .map(|i| world.spawn(W(i)).id())
518            .collect();
519        world.insert_resource(EntitiesArray(entity_ids));
520
521        run_system(&mut world, query_system);
522        assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
523
524        world.insert_resource(SystemRan::No);
525        run_system(&mut world, query_system_mut);
526        assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
527    }
528
529    #[test]
530    fn or_param_set_system() {
531        // Regression test for issue #762
532        fn query_system(
533            mut ran: ResMut<SystemRan>,
534            mut set: ParamSet<(
535                Query<(), Or<(Changed<A>, Changed<B>)>>,
536                Query<(), Or<(Added<A>, Added<B>)>>,
537            )>,
538        ) {
539            let changed = set.p0().iter().count();
540            let added = set.p1().iter().count();
541
542            assert_eq!(changed, 1);
543            assert_eq!(added, 1);
544
545            *ran = SystemRan::Yes;
546        }
547
548        let mut world = World::default();
549        world.insert_resource(SystemRan::No);
550        world.spawn((A, B));
551
552        run_system(&mut world, query_system);
553
554        assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
555    }
556
557    #[test]
558    fn changed_resource_system() {
559        use crate::resource::Resource;
560
561        #[derive(Resource)]
562        struct Flipper(bool);
563
564        #[derive(Resource)]
565        struct Added(usize);
566
567        #[derive(Resource)]
568        struct Changed(usize);
569
570        fn incr_e_on_flip(
571            value: Res<Flipper>,
572            mut changed: ResMut<Changed>,
573            mut added: ResMut<Added>,
574        ) {
575            if value.is_added() {
576                added.0 += 1;
577            }
578
579            if value.is_changed() {
580                changed.0 += 1;
581            }
582        }
583
584        let mut world = World::default();
585        world.insert_resource(Flipper(false));
586        world.insert_resource(Added(0));
587        world.insert_resource(Changed(0));
588
589        let mut schedule = Schedule::default();
590
591        schedule.add_systems((incr_e_on_flip, ApplyDeferred, World::clear_trackers).chain());
592
593        schedule.run(&mut world);
594        assert_eq!(world.resource::<Added>().0, 1);
595        assert_eq!(world.resource::<Changed>().0, 1);
596
597        schedule.run(&mut world);
598        assert_eq!(world.resource::<Added>().0, 1);
599        assert_eq!(world.resource::<Changed>().0, 1);
600
601        world.resource_mut::<Flipper>().0 = true;
602        schedule.run(&mut world);
603        assert_eq!(world.resource::<Added>().0, 1);
604        assert_eq!(world.resource::<Changed>().0, 2);
605    }
606
607    #[test]
608    #[should_panic = "error[B0001]"]
609    fn option_has_no_filter_with() {
610        fn sys(_: Query<(Option<&A>, &mut B)>, _: Query<&mut B, Without<A>>) {}
611        let mut world = World::default();
612        run_system(&mut world, sys);
613    }
614
615    #[test]
616    fn option_doesnt_remove_unrelated_filter_with() {
617        fn sys(_: Query<(Option<&A>, &mut B, &A)>, _: Query<&mut B, Without<A>>) {}
618        let mut world = World::default();
619        run_system(&mut world, sys);
620    }
621
622    #[test]
623    fn any_of_working() {
624        fn sys(_: Query<AnyOf<(&mut A, &B)>>) {}
625        let mut world = World::default();
626        run_system(&mut world, sys);
627    }
628
629    #[test]
630    fn any_of_with_and_without_common() {
631        fn sys(_: Query<(&mut D, &C, AnyOf<(&A, &B)>)>, _: Query<&mut D, Without<C>>) {}
632        let mut world = World::default();
633        run_system(&mut world, sys);
634    }
635
636    #[test]
637    #[should_panic]
638    fn any_of_with_mut_and_ref() {
639        fn sys(_: Query<AnyOf<(&mut A, &A)>>) {}
640        let mut world = World::default();
641        run_system(&mut world, sys);
642    }
643
644    #[test]
645    #[should_panic]
646    fn any_of_with_ref_and_mut() {
647        fn sys(_: Query<AnyOf<(&A, &mut A)>>) {}
648        let mut world = World::default();
649        run_system(&mut world, sys);
650    }
651
652    #[test]
653    #[should_panic]
654    fn any_of_with_mut_and_option() {
655        fn sys(_: Query<AnyOf<(&mut A, Option<&A>)>>) {}
656        let mut world = World::default();
657        run_system(&mut world, sys);
658    }
659
660    #[test]
661    fn any_of_with_entity_and_mut() {
662        fn sys(_: Query<AnyOf<(Entity, &mut A)>>) {}
663        let mut world = World::default();
664        run_system(&mut world, sys);
665    }
666
667    #[test]
668    fn any_of_with_empty_and_mut() {
669        fn sys(_: Query<AnyOf<((), &mut A)>>) {}
670        let mut world = World::default();
671        run_system(&mut world, sys);
672    }
673
674    #[test]
675    #[should_panic = "error[B0001]"]
676    fn any_of_has_no_filter_with() {
677        fn sys(_: Query<(AnyOf<(&A, ())>, &mut B)>, _: Query<&mut B, Without<A>>) {}
678        let mut world = World::default();
679        run_system(&mut world, sys);
680    }
681
682    #[test]
683    #[should_panic]
684    fn any_of_with_conflicting() {
685        fn sys(_: Query<AnyOf<(&mut A, &mut A)>>) {}
686        let mut world = World::default();
687        run_system(&mut world, sys);
688    }
689
690    #[test]
691    fn any_of_has_filter_with_when_both_have_it() {
692        fn sys(_: Query<(AnyOf<(&A, &A)>, &mut B)>, _: Query<&mut B, Without<A>>) {}
693        let mut world = World::default();
694        run_system(&mut world, sys);
695    }
696
697    #[test]
698    fn any_of_doesnt_remove_unrelated_filter_with() {
699        fn sys(_: Query<(AnyOf<(&A, ())>, &mut B, &A)>, _: Query<&mut B, Without<A>>) {}
700        let mut world = World::default();
701        run_system(&mut world, sys);
702    }
703
704    #[test]
705    fn any_of_and_without() {
706        fn sys(_: Query<(AnyOf<(&A, &B)>, &mut C)>, _: Query<&mut C, (Without<A>, Without<B>)>) {}
707        let mut world = World::default();
708        run_system(&mut world, sys);
709    }
710
711    #[test]
712    #[should_panic = "error[B0001]"]
713    fn or_has_no_filter_with() {
714        fn sys(_: Query<&mut B, Or<(With<A>, With<B>)>>, _: Query<&mut B, Without<A>>) {}
715        let mut world = World::default();
716        run_system(&mut world, sys);
717    }
718
719    #[test]
720    fn or_has_filter_with_when_both_have_it() {
721        fn sys(_: Query<&mut B, Or<(With<A>, With<A>)>>, _: Query<&mut B, Without<A>>) {}
722        let mut world = World::default();
723        run_system(&mut world, sys);
724    }
725
726    #[test]
727    fn or_has_filter_with() {
728        fn sys(
729            _: Query<&mut C, Or<(With<A>, With<B>)>>,
730            _: Query<&mut C, (Without<A>, Without<B>)>,
731        ) {
732        }
733        let mut world = World::default();
734        run_system(&mut world, sys);
735    }
736
737    #[test]
738    fn or_expanded_with_and_without_common() {
739        fn sys(_: Query<&mut D, (With<A>, Or<(With<B>, With<C>)>)>, _: Query<&mut D, Without<A>>) {}
740        let mut world = World::default();
741        run_system(&mut world, sys);
742    }
743
744    #[test]
745    fn or_expanded_nested_with_and_without_common() {
746        fn sys(
747            _: Query<&mut E, (Or<((With<B>, With<C>), (With<C>, With<D>))>, With<A>)>,
748            _: Query<&mut E, (Without<B>, Without<D>)>,
749        ) {
750        }
751        let mut world = World::default();
752        run_system(&mut world, sys);
753    }
754
755    #[test]
756    #[should_panic = "error[B0001]"]
757    fn or_expanded_nested_with_and_disjoint_without() {
758        fn sys(
759            _: Query<&mut E, (Or<((With<B>, With<C>), (With<C>, With<D>))>, With<A>)>,
760            _: Query<&mut E, Without<D>>,
761        ) {
762        }
763        let mut world = World::default();
764        run_system(&mut world, sys);
765    }
766
767    #[test]
768    #[should_panic = "error[B0001]"]
769    fn or_expanded_nested_or_with_and_disjoint_without() {
770        fn sys(
771            _: Query<&mut D, Or<(Or<(With<A>, With<B>)>, Or<(With<A>, With<C>)>)>>,
772            _: Query<&mut D, Without<A>>,
773        ) {
774        }
775        let mut world = World::default();
776        run_system(&mut world, sys);
777    }
778
779    #[test]
780    fn or_expanded_nested_with_and_common_nested_without() {
781        fn sys(
782            _: Query<&mut D, Or<((With<A>, With<B>), (With<B>, With<C>))>>,
783            _: Query<&mut D, Or<(Without<D>, Without<B>)>>,
784        ) {
785        }
786        let mut world = World::default();
787        run_system(&mut world, sys);
788    }
789
790    #[test]
791    fn or_with_without_and_compatible_with_without() {
792        fn sys(
793            _: Query<&mut C, Or<(With<A>, Without<B>)>>,
794            _: Query<&mut C, (With<B>, Without<A>)>,
795        ) {
796        }
797        let mut world = World::default();
798        run_system(&mut world, sys);
799    }
800
801    #[test]
802    #[should_panic = "error[B0001]"]
803    fn with_and_disjoint_or_empty_without() {
804        fn sys(_: Query<&mut B, With<A>>, _: Query<&mut B, Or<((), Without<A>)>>) {}
805        let mut world = World::default();
806        run_system(&mut world, sys);
807    }
808
809    #[test]
810    #[should_panic = "error[B0001]"]
811    fn or_expanded_with_and_disjoint_nested_without() {
812        fn sys(
813            _: Query<&mut D, Or<(With<A>, With<B>)>>,
814            _: Query<&mut D, Or<(Without<A>, Without<B>)>>,
815        ) {
816        }
817        let mut world = World::default();
818        run_system(&mut world, sys);
819    }
820
821    #[test]
822    #[should_panic = "error[B0001]"]
823    fn or_expanded_nested_with_and_disjoint_nested_without() {
824        fn sys(
825            _: Query<&mut D, Or<((With<A>, With<B>), (With<B>, With<C>))>>,
826            _: Query<&mut D, Or<(Without<A>, Without<B>)>>,
827        ) {
828        }
829        let mut world = World::default();
830        run_system(&mut world, sys);
831    }
832
833    #[test]
834    fn or_doesnt_remove_unrelated_filter_with() {
835        fn sys(_: Query<&mut B, (Or<(With<A>, With<B>)>, With<A>)>, _: Query<&mut B, Without<A>>) {}
836        let mut world = World::default();
837        run_system(&mut world, sys);
838    }
839
840    #[test]
841    #[should_panic]
842    fn conflicting_query_mut_system() {
843        fn sys(_q1: Query<&mut A>, _q2: Query<&mut A>) {}
844
845        let mut world = World::default();
846        run_system(&mut world, sys);
847    }
848
849    #[test]
850    fn disjoint_query_mut_system() {
851        fn sys(_q1: Query<&mut A, With<B>>, _q2: Query<&mut A, Without<B>>) {}
852
853        let mut world = World::default();
854        run_system(&mut world, sys);
855    }
856
857    #[test]
858    fn disjoint_query_mut_read_component_system() {
859        fn sys(_q1: Query<(&mut A, &B)>, _q2: Query<&mut A, Without<B>>) {}
860
861        let mut world = World::default();
862        run_system(&mut world, sys);
863    }
864
865    #[test]
866    #[should_panic]
867    fn conflicting_query_immut_system() {
868        fn sys(_q1: Query<&A>, _q2: Query<&mut A>) {}
869
870        let mut world = World::default();
871        run_system(&mut world, sys);
872    }
873
874    #[test]
875    #[should_panic]
876    fn changed_trackers_or_conflict() {
877        fn sys(_: Query<&mut A>, _: Query<(), Or<(Changed<A>,)>>) {}
878
879        let mut world = World::default();
880        run_system(&mut world, sys);
881    }
882
883    #[test]
884    fn query_set_system() {
885        fn sys(mut _set: ParamSet<(Query<&mut A>, Query<&A>)>) {}
886        let mut world = World::default();
887        run_system(&mut world, sys);
888    }
889
890    #[test]
891    #[should_panic]
892    fn conflicting_query_with_query_set_system() {
893        fn sys(_query: Query<&mut A>, _set: ParamSet<(Query<&mut A>, Query<&B>)>) {}
894
895        let mut world = World::default();
896        run_system(&mut world, sys);
897    }
898
899    #[test]
900    #[should_panic]
901    fn conflicting_query_sets_system() {
902        fn sys(_set_1: ParamSet<(Query<&mut A>,)>, _set_2: ParamSet<(Query<&mut A>, Query<&B>)>) {}
903
904        let mut world = World::default();
905        run_system(&mut world, sys);
906    }
907
908    #[derive(Default, Resource)]
909    struct BufferRes {
910        _buffer: Vec<u8>,
911    }
912
913    fn test_for_conflicting_resources<Marker, S: IntoSystem<(), (), Marker>>(sys: S) {
914        let mut world = World::default();
915        world.insert_resource(BufferRes::default());
916        world.insert_resource(A);
917        world.insert_resource(B);
918        run_system(&mut world, sys);
919    }
920
921    #[test]
922    #[should_panic]
923    fn conflicting_system_resources() {
924        fn sys(_: ResMut<BufferRes>, _: Res<BufferRes>) {}
925        test_for_conflicting_resources(sys);
926    }
927
928    #[test]
929    #[should_panic]
930    fn conflicting_system_resources_reverse_order() {
931        fn sys(_: Res<BufferRes>, _: ResMut<BufferRes>) {}
932        test_for_conflicting_resources(sys);
933    }
934
935    #[test]
936    #[should_panic]
937    fn conflicting_system_resources_multiple_mutable() {
938        fn sys(_: ResMut<BufferRes>, _: ResMut<BufferRes>) {}
939        test_for_conflicting_resources(sys);
940    }
941
942    #[test]
943    fn nonconflicting_system_resources() {
944        fn sys(_: Local<BufferRes>, _: ResMut<BufferRes>, _: Local<A>, _: ResMut<A>) {}
945        test_for_conflicting_resources(sys);
946    }
947
948    #[test]
949    fn local_system() {
950        let mut world = World::default();
951        world.insert_resource(ProtoFoo { value: 1 });
952        world.insert_resource(SystemRan::No);
953
954        struct Foo {
955            value: u32,
956        }
957
958        #[derive(Resource)]
959        struct ProtoFoo {
960            value: u32,
961        }
962
963        impl FromWorld for Foo {
964            fn from_world(world: &mut World) -> Self {
965                Foo {
966                    value: world.resource::<ProtoFoo>().value + 1,
967                }
968            }
969        }
970
971        fn sys(local: Local<Foo>, mut system_ran: ResMut<SystemRan>) {
972            assert_eq!(local.value, 2);
973            *system_ran = SystemRan::Yes;
974        }
975
976        run_system(&mut world, sys);
977
978        // ensure the system actually ran
979        assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
980    }
981
982    #[test]
983    #[expect(
984        dead_code,
985        reason = "The `NotSend1` and `NotSend2` structs is used to verify that a system will run, even if the system params include a non-Send resource. As such, the inner value doesn't matter."
986    )]
987    fn non_send_option_system() {
988        let mut world = World::default();
989
990        world.insert_resource(SystemRan::No);
991        // Two structs are used, one which is inserted and one which is not, to verify that wrapping
992        // non-Send resources in an `Option` will allow the system to run regardless of their
993        // existence.
994        struct NotSend1(alloc::rc::Rc<i32>);
995        struct NotSend2(alloc::rc::Rc<i32>);
996        world.insert_non_send_resource(NotSend1(alloc::rc::Rc::new(0)));
997
998        fn sys(
999            op: Option<NonSend<NotSend1>>,
1000            mut _op2: Option<NonSendMut<NotSend2>>,
1001            mut system_ran: ResMut<SystemRan>,
1002        ) {
1003            op.expect("NonSend should exist");
1004            *system_ran = SystemRan::Yes;
1005        }
1006
1007        run_system(&mut world, sys);
1008        // ensure the system actually ran
1009        assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
1010    }
1011
1012    #[test]
1013    #[expect(
1014        dead_code,
1015        reason = "The `NotSend1` and `NotSend2` structs are used to verify that a system will run, even if the system params include a non-Send resource. As such, the inner value doesn't matter."
1016    )]
1017    fn non_send_system() {
1018        let mut world = World::default();
1019
1020        world.insert_resource(SystemRan::No);
1021        struct NotSend1(alloc::rc::Rc<i32>);
1022        struct NotSend2(alloc::rc::Rc<i32>);
1023
1024        world.insert_non_send_resource(NotSend1(alloc::rc::Rc::new(1)));
1025        world.insert_non_send_resource(NotSend2(alloc::rc::Rc::new(2)));
1026
1027        fn sys(
1028            _op: NonSend<NotSend1>,
1029            mut _op2: NonSendMut<NotSend2>,
1030            mut system_ran: ResMut<SystemRan>,
1031        ) {
1032            *system_ran = SystemRan::Yes;
1033        }
1034
1035        run_system(&mut world, sys);
1036        assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
1037    }
1038
1039    #[test]
1040    fn removal_tracking() {
1041        let mut world = World::new();
1042
1043        let entity_to_despawn = world.spawn(W(1)).id();
1044        let entity_to_remove_w_from = world.spawn(W(2)).id();
1045        let spurious_entity = world.spawn_empty().id();
1046
1047        // Track which entities we want to operate on
1048        #[derive(Resource)]
1049        struct Despawned(Entity);
1050        world.insert_resource(Despawned(entity_to_despawn));
1051
1052        #[derive(Resource)]
1053        struct Removed(Entity);
1054        world.insert_resource(Removed(entity_to_remove_w_from));
1055
1056        // Verify that all the systems actually ran
1057        #[derive(Default, Resource)]
1058        struct NSystems(usize);
1059        world.insert_resource(NSystems::default());
1060
1061        // First, check that removal detection is triggered if and only if we despawn an entity with the correct component
1062        world.entity_mut(entity_to_despawn).despawn();
1063        world.entity_mut(spurious_entity).despawn();
1064
1065        fn validate_despawn(
1066            mut removed_i32: RemovedComponents<W<i32>>,
1067            despawned: Res<Despawned>,
1068            mut n_systems: ResMut<NSystems>,
1069        ) {
1070            assert_eq!(
1071                removed_i32.read().collect::<Vec<_>>(),
1072                &[despawned.0],
1073                "despawning causes the correct entity to show up in the 'RemovedComponent' system parameter."
1074            );
1075
1076            n_systems.0 += 1;
1077        }
1078
1079        run_system(&mut world, validate_despawn);
1080
1081        // Reset the trackers to clear the buffer of removed components
1082        // Ordinarily, this is done in a system added by MinimalPlugins
1083        world.clear_trackers();
1084
1085        // Then, try removing a component
1086        world.spawn(W(3));
1087        world.spawn(W(4));
1088        world.entity_mut(entity_to_remove_w_from).remove::<W<i32>>();
1089
1090        fn validate_remove(
1091            mut removed_i32: RemovedComponents<W<i32>>,
1092            despawned: Res<Despawned>,
1093            removed: Res<Removed>,
1094            mut n_systems: ResMut<NSystems>,
1095        ) {
1096            // The despawned entity from the previous frame was
1097            // double buffered so we now have it in this system as well.
1098            assert_eq!(
1099                removed_i32.read().collect::<Vec<_>>(),
1100                &[despawned.0, removed.0],
1101                "removing a component causes the correct entity to show up in the 'RemovedComponent' system parameter."
1102            );
1103
1104            n_systems.0 += 1;
1105        }
1106
1107        run_system(&mut world, validate_remove);
1108
1109        // Verify that both systems actually ran
1110        assert_eq!(world.resource::<NSystems>().0, 2);
1111    }
1112
1113    #[test]
1114    fn world_collections_system() {
1115        let mut world = World::default();
1116        world.insert_resource(SystemRan::No);
1117        world.spawn((W(42), W(true)));
1118        fn sys(
1119            archetypes: &Archetypes,
1120            components: &Components,
1121            entities: &Entities,
1122            bundles: &Bundles,
1123            query: Query<Entity, With<W<i32>>>,
1124            mut system_ran: ResMut<SystemRan>,
1125        ) {
1126            assert_eq!(query.iter().count(), 1, "entity exists");
1127            for entity in &query {
1128                let location = entities.get(entity).unwrap();
1129                let archetype = archetypes.get(location.archetype_id).unwrap();
1130                let archetype_components = archetype.components();
1131                let bundle_id = bundles
1132                    .get_id(TypeId::of::<(W<i32>, W<bool>)>())
1133                    .expect("Bundle used to spawn entity should exist");
1134                let bundle_info = bundles.get(bundle_id).unwrap();
1135                let mut bundle_components = bundle_info.contributed_components().to_vec();
1136                bundle_components.sort();
1137                for component_id in &bundle_components {
1138                    assert!(
1139                        components.get_info(*component_id).is_some(),
1140                        "every bundle component exists in Components"
1141                    );
1142                }
1143                assert_eq!(
1144                    bundle_components, archetype_components,
1145                    "entity's bundle components exactly match entity's archetype components"
1146                );
1147            }
1148            *system_ran = SystemRan::Yes;
1149        }
1150
1151        run_system(&mut world, sys);
1152
1153        // ensure the system actually ran
1154        assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
1155    }
1156
1157    #[test]
1158    fn get_system_conflicts() {
1159        fn sys_x(_: Res<A>, _: Res<B>, _: Query<(&C, &D)>) {}
1160
1161        fn sys_y(_: Res<A>, _: ResMut<B>, _: Query<(&C, &mut D)>) {}
1162
1163        let mut world = World::default();
1164        let mut x = IntoSystem::into_system(sys_x);
1165        let mut y = IntoSystem::into_system(sys_y);
1166        let x_access = x.initialize(&mut world);
1167        let y_access = y.initialize(&mut world);
1168
1169        let conflicts = x_access.get_conflicts(&y_access);
1170        let b_id = world
1171            .components()
1172            .get_resource_id(TypeId::of::<B>())
1173            .unwrap();
1174        let d_id = world.components().get_id(TypeId::of::<D>()).unwrap();
1175        assert_eq!(conflicts, vec![b_id, d_id].into());
1176    }
1177
1178    #[test]
1179    fn query_is_empty() {
1180        fn without_filter(not_empty: Query<&A>, empty: Query<&B>) {
1181            assert!(!not_empty.is_empty());
1182            assert!(empty.is_empty());
1183        }
1184
1185        fn with_filter(not_empty: Query<&A, With<C>>, empty: Query<&A, With<D>>) {
1186            assert!(!not_empty.is_empty());
1187            assert!(empty.is_empty());
1188        }
1189
1190        let mut world = World::default();
1191        world.spawn(A).insert(C);
1192
1193        let mut without_filter = IntoSystem::into_system(without_filter);
1194        without_filter.initialize(&mut world);
1195        without_filter.run((), &mut world).unwrap();
1196
1197        let mut with_filter = IntoSystem::into_system(with_filter);
1198        with_filter.initialize(&mut world);
1199        with_filter.run((), &mut world).unwrap();
1200    }
1201
1202    #[test]
1203    fn can_have_16_parameters() {
1204        fn sys_x(
1205            _: Res<A>,
1206            _: Res<B>,
1207            _: Res<C>,
1208            _: Res<D>,
1209            _: Res<E>,
1210            _: Res<F>,
1211            _: Query<&A>,
1212            _: Query<&B>,
1213            _: Query<&C>,
1214            _: Query<&D>,
1215            _: Query<&E>,
1216            _: Query<&F>,
1217            _: Query<(&A, &B)>,
1218            _: Query<(&C, &D)>,
1219            _: Query<(&E, &F)>,
1220        ) {
1221        }
1222        fn sys_y(
1223            _: (
1224                Res<A>,
1225                Res<B>,
1226                Res<C>,
1227                Res<D>,
1228                Res<E>,
1229                Res<F>,
1230                Query<&A>,
1231                Query<&B>,
1232                Query<&C>,
1233                Query<&D>,
1234                Query<&E>,
1235                Query<&F>,
1236                Query<(&A, &B)>,
1237                Query<(&C, &D)>,
1238                Query<(&E, &F)>,
1239            ),
1240        ) {
1241        }
1242        let mut world = World::default();
1243        let mut x = IntoSystem::into_system(sys_x);
1244        let mut y = IntoSystem::into_system(sys_y);
1245        x.initialize(&mut world);
1246        y.initialize(&mut world);
1247    }
1248
1249    #[test]
1250    fn read_system_state() {
1251        #[derive(Eq, PartialEq, Debug, Resource)]
1252        struct A(usize);
1253
1254        #[derive(Component, Eq, PartialEq, Debug)]
1255        struct B(usize);
1256
1257        let mut world = World::default();
1258        world.insert_resource(A(42));
1259        world.spawn(B(7));
1260
1261        let mut system_state: SystemState<(
1262            Res<A>,
1263            Option<Single<&B>>,
1264            ParamSet<(Query<&C>, Query<&D>)>,
1265        )> = SystemState::new(&mut world);
1266        let (a, query, _) = system_state.get(&world);
1267        assert_eq!(*a, A(42), "returned resource matches initial value");
1268        assert_eq!(
1269            **query.unwrap(),
1270            B(7),
1271            "returned component matches initial value"
1272        );
1273    }
1274
1275    #[test]
1276    fn write_system_state() {
1277        #[derive(Resource, Eq, PartialEq, Debug)]
1278        struct A(usize);
1279
1280        #[derive(Component, Eq, PartialEq, Debug)]
1281        struct B(usize);
1282
1283        let mut world = World::default();
1284        world.insert_resource(A(42));
1285        world.spawn(B(7));
1286
1287        let mut system_state: SystemState<(ResMut<A>, Option<Single<&mut B>>)> =
1288            SystemState::new(&mut world);
1289
1290        // The following line shouldn't compile because the parameters used are not ReadOnlySystemParam
1291        // let (a, query) = system_state.get(&world);
1292
1293        let (a, query) = system_state.get_mut(&mut world);
1294        assert_eq!(*a, A(42), "returned resource matches initial value");
1295        assert_eq!(
1296            **query.unwrap(),
1297            B(7),
1298            "returned component matches initial value"
1299        );
1300    }
1301
1302    #[test]
1303    fn system_state_change_detection() {
1304        #[derive(Component, Eq, PartialEq, Debug)]
1305        struct A(usize);
1306
1307        let mut world = World::default();
1308        let entity = world.spawn(A(1)).id();
1309
1310        let mut system_state: SystemState<Option<Single<&A, Changed<A>>>> =
1311            SystemState::new(&mut world);
1312        {
1313            let query = system_state.get(&world);
1314            assert_eq!(**query.unwrap(), A(1));
1315        }
1316
1317        {
1318            let query = system_state.get(&world);
1319            assert!(query.is_none());
1320        }
1321
1322        world.entity_mut(entity).get_mut::<A>().unwrap().0 = 2;
1323        {
1324            let query = system_state.get(&world);
1325            assert_eq!(**query.unwrap(), A(2));
1326        }
1327    }
1328
1329    #[test]
1330    fn system_state_spawned() {
1331        let mut world = World::default();
1332        world.spawn_empty();
1333        let spawn_tick = world.change_tick();
1334
1335        let mut system_state: SystemState<Option<Single<SpawnDetails, Spawned>>> =
1336            SystemState::new(&mut world);
1337        {
1338            let query = system_state.get(&world);
1339            assert_eq!(query.unwrap().spawn_tick(), spawn_tick);
1340        }
1341
1342        {
1343            let query = system_state.get(&world);
1344            assert!(query.is_none());
1345        }
1346    }
1347
1348    #[test]
1349    #[should_panic]
1350    fn system_state_invalid_world() {
1351        let mut world = World::default();
1352        let mut system_state = SystemState::<Query<&A>>::new(&mut world);
1353        let mismatched_world = World::default();
1354        system_state.get(&mismatched_world);
1355    }
1356
1357    #[test]
1358    fn system_state_archetype_update() {
1359        #[derive(Component, Eq, PartialEq, Debug)]
1360        struct A(usize);
1361
1362        #[derive(Component, Eq, PartialEq, Debug)]
1363        struct B(usize);
1364
1365        let mut world = World::default();
1366        world.spawn(A(1));
1367
1368        let mut system_state = SystemState::<Query<&A>>::new(&mut world);
1369        {
1370            let query = system_state.get(&world);
1371            assert_eq!(
1372                query.iter().collect::<Vec<_>>(),
1373                vec![&A(1)],
1374                "exactly one component returned"
1375            );
1376        }
1377
1378        world.spawn((A(2), B(2)));
1379        {
1380            let query = system_state.get(&world);
1381            assert_eq!(
1382                query.iter().collect::<Vec<_>>(),
1383                vec![&A(1), &A(2)],
1384                "components from both archetypes returned"
1385            );
1386        }
1387    }
1388
1389    #[test]
1390    #[expect(
1391        dead_code,
1392        reason = "This test exists to show that read-only world-only queries can return data that lives as long as `'world`."
1393    )]
1394    fn long_life_test() {
1395        struct Holder<'w> {
1396            value: &'w A,
1397        }
1398
1399        struct State {
1400            state: SystemState<Res<'static, A>>,
1401            state_q: SystemState<Query<'static, 'static, &'static A>>,
1402        }
1403
1404        impl State {
1405            fn hold_res<'w>(&mut self, world: &'w World) -> Holder<'w> {
1406                let a = self.state.get(world);
1407                Holder {
1408                    value: a.into_inner(),
1409                }
1410            }
1411            fn hold_component<'w>(&mut self, world: &'w World, entity: Entity) -> Holder<'w> {
1412                let q = self.state_q.get(world);
1413                let a = q.get_inner(entity).unwrap();
1414                Holder { value: a }
1415            }
1416            fn hold_components<'w>(&mut self, world: &'w World) -> Vec<Holder<'w>> {
1417                let mut components = Vec::new();
1418                let q = self.state_q.get(world);
1419                for a in q.iter_inner() {
1420                    components.push(Holder { value: a });
1421                }
1422                components
1423            }
1424        }
1425    }
1426
1427    #[test]
1428    fn immutable_mut_test() {
1429        #[derive(Component, Eq, PartialEq, Debug, Clone, Copy)]
1430        struct A(usize);
1431
1432        let mut world = World::default();
1433        world.spawn(A(1));
1434        world.spawn(A(2));
1435
1436        let mut system_state = SystemState::<Query<&mut A>>::new(&mut world);
1437        {
1438            let mut query = system_state.get_mut(&mut world);
1439            assert_eq!(
1440                query.iter_mut().map(|m| *m).collect::<Vec<A>>(),
1441                vec![A(1), A(2)],
1442                "both components returned by iter_mut of &mut"
1443            );
1444            assert_eq!(
1445                query.iter().collect::<Vec<&A>>(),
1446                vec![&A(1), &A(2)],
1447                "both components returned by iter of &mut"
1448            );
1449        }
1450    }
1451
1452    #[test]
1453    fn convert_mut_to_immut() {
1454        {
1455            let mut world = World::new();
1456
1457            fn mutable_query(mut query: Query<&mut A>) {
1458                for _ in &mut query {}
1459
1460                immutable_query(query.as_readonly());
1461            }
1462
1463            fn immutable_query(_: Query<&A>) {}
1464
1465            let mut sys = IntoSystem::into_system(mutable_query);
1466            sys.initialize(&mut world);
1467        }
1468
1469        {
1470            let mut world = World::new();
1471
1472            fn mutable_query(mut query: Query<Option<&mut A>>) {
1473                for _ in &mut query {}
1474
1475                immutable_query(query.as_readonly());
1476            }
1477
1478            fn immutable_query(_: Query<Option<&A>>) {}
1479
1480            let mut sys = IntoSystem::into_system(mutable_query);
1481            sys.initialize(&mut world);
1482        }
1483
1484        {
1485            let mut world = World::new();
1486
1487            fn mutable_query(mut query: Query<(&mut A, &B)>) {
1488                for _ in &mut query {}
1489
1490                immutable_query(query.as_readonly());
1491            }
1492
1493            fn immutable_query(_: Query<(&A, &B)>) {}
1494
1495            let mut sys = IntoSystem::into_system(mutable_query);
1496            sys.initialize(&mut world);
1497        }
1498
1499        {
1500            let mut world = World::new();
1501
1502            fn mutable_query(mut query: Query<(&mut A, &mut B)>) {
1503                for _ in &mut query {}
1504
1505                immutable_query(query.as_readonly());
1506            }
1507
1508            fn immutable_query(_: Query<(&A, &B)>) {}
1509
1510            let mut sys = IntoSystem::into_system(mutable_query);
1511            sys.initialize(&mut world);
1512        }
1513
1514        {
1515            let mut world = World::new();
1516
1517            fn mutable_query(mut query: Query<(&mut A, &mut B), With<C>>) {
1518                for _ in &mut query {}
1519
1520                immutable_query(query.as_readonly());
1521            }
1522
1523            fn immutable_query(_: Query<(&A, &B), With<C>>) {}
1524
1525            let mut sys = IntoSystem::into_system(mutable_query);
1526            sys.initialize(&mut world);
1527        }
1528
1529        {
1530            let mut world = World::new();
1531
1532            fn mutable_query(mut query: Query<(&mut A, &mut B), Without<C>>) {
1533                for _ in &mut query {}
1534
1535                immutable_query(query.as_readonly());
1536            }
1537
1538            fn immutable_query(_: Query<(&A, &B), Without<C>>) {}
1539
1540            let mut sys = IntoSystem::into_system(mutable_query);
1541            sys.initialize(&mut world);
1542        }
1543
1544        {
1545            let mut world = World::new();
1546
1547            fn mutable_query(mut query: Query<(&mut A, &mut B), Added<C>>) {
1548                for _ in &mut query {}
1549
1550                immutable_query(query.as_readonly());
1551            }
1552
1553            fn immutable_query(_: Query<(&A, &B), Added<C>>) {}
1554
1555            let mut sys = IntoSystem::into_system(mutable_query);
1556            sys.initialize(&mut world);
1557        }
1558
1559        {
1560            let mut world = World::new();
1561
1562            fn mutable_query(mut query: Query<(&mut A, &mut B), Changed<C>>) {
1563                for _ in &mut query {}
1564
1565                immutable_query(query.as_readonly());
1566            }
1567
1568            fn immutable_query(_: Query<(&A, &B), Changed<C>>) {}
1569
1570            let mut sys = IntoSystem::into_system(mutable_query);
1571            sys.initialize(&mut world);
1572        }
1573
1574        {
1575            let mut world = World::new();
1576
1577            fn mutable_query(mut query: Query<(&mut A, &mut B, SpawnDetails), Spawned>) {
1578                for _ in &mut query {}
1579
1580                immutable_query(query.as_readonly());
1581            }
1582
1583            fn immutable_query(_: Query<(&A, &B, SpawnDetails), Spawned>) {}
1584
1585            let mut sys = IntoSystem::into_system(mutable_query);
1586            sys.initialize(&mut world);
1587        }
1588    }
1589
1590    #[test]
1591    fn commands_param_set() {
1592        // Regression test for #4676
1593        let mut world = World::new();
1594        let entity = world.spawn_empty().id();
1595
1596        run_system(
1597            &mut world,
1598            move |mut commands_set: ParamSet<(Commands, Commands)>| {
1599                commands_set.p0().entity(entity).insert(A);
1600                commands_set.p1().entity(entity).insert(B);
1601            },
1602        );
1603
1604        let entity = world.entity(entity);
1605        assert!(entity.contains::<A>());
1606        assert!(entity.contains::<B>());
1607    }
1608
1609    #[test]
1610    fn into_iter_impl() {
1611        let mut world = World::new();
1612        world.spawn(W(42u32));
1613        run_system(&mut world, |mut q: Query<&mut W<u32>>| {
1614            for mut a in &mut q {
1615                assert_eq!(a.0, 42);
1616                a.0 = 0;
1617            }
1618            for a in &q {
1619                assert_eq!(a.0, 0);
1620            }
1621        });
1622    }
1623
1624    #[test]
1625    #[should_panic]
1626    fn assert_system_does_not_conflict() {
1627        fn system(_query: Query<(&mut W<u32>, &mut W<u32>)>) {}
1628        super::assert_system_does_not_conflict(system);
1629    }
1630
1631    #[test]
1632    #[should_panic]
1633    fn assert_world_and_entity_mut_system_does_conflict_first() {
1634        fn system(_query: &World, _q2: Query<EntityMut>) {}
1635        super::assert_system_does_not_conflict(system);
1636    }
1637
1638    #[test]
1639    #[should_panic]
1640    fn assert_world_and_entity_mut_system_does_conflict_second() {
1641        fn system(_: Query<EntityMut>, _: &World) {}
1642        super::assert_system_does_not_conflict(system);
1643    }
1644
1645    #[test]
1646    #[should_panic]
1647    fn assert_entity_ref_and_entity_mut_system_does_conflict() {
1648        fn system(_query: Query<EntityRef>, _q2: Query<EntityMut>) {}
1649        super::assert_system_does_not_conflict(system);
1650    }
1651
1652    #[test]
1653    #[should_panic]
1654    fn assert_entity_mut_system_does_conflict() {
1655        fn system(_query: Query<EntityMut>, _q2: Query<EntityMut>) {}
1656        super::assert_system_does_not_conflict(system);
1657    }
1658
1659    #[test]
1660    #[should_panic]
1661    fn assert_deferred_world_and_entity_ref_system_does_conflict_first() {
1662        fn system(_world: DeferredWorld, _query: Query<EntityRef>) {}
1663        super::assert_system_does_not_conflict(system);
1664    }
1665
1666    #[test]
1667    #[should_panic]
1668    fn assert_deferred_world_and_entity_ref_system_does_conflict_second() {
1669        fn system(_query: Query<EntityRef>, _world: DeferredWorld) {}
1670        super::assert_system_does_not_conflict(system);
1671    }
1672
1673    #[test]
1674    fn assert_deferred_world_and_empty_query_does_not_conflict_first() {
1675        fn system(_world: DeferredWorld, _query: Query<Entity>) {}
1676        super::assert_system_does_not_conflict(system);
1677    }
1678
1679    #[test]
1680    fn assert_deferred_world_and_empty_query_does_not_conflict_second() {
1681        fn system(_query: Query<Entity>, _world: DeferredWorld) {}
1682        super::assert_system_does_not_conflict(system);
1683    }
1684
1685    #[test]
1686    #[should_panic]
1687    fn panic_inside_system() {
1688        let mut world = World::new();
1689        let system: fn() = || {
1690            panic!("this system panics");
1691        };
1692        run_system(&mut world, system);
1693    }
1694
1695    #[test]
1696    fn assert_systems() {
1697        use core::str::FromStr;
1698
1699        use crate::{prelude::*, system::assert_is_system};
1700
1701        /// Mocks a system that returns a value of type `T`.
1702        fn returning<T>() -> T {
1703            unimplemented!()
1704        }
1705
1706        /// Mocks an exclusive system that takes an input and returns an output.
1707        fn exclusive_in_out<A, B>(_: In<A>, _: &mut World) -> B {
1708            unimplemented!()
1709        }
1710
1711        fn static_system_param(_: StaticSystemParam<Query<'static, 'static, &W<u32>>>) {
1712            unimplemented!()
1713        }
1714
1715        fn exclusive_with_state(
1716            _: &mut World,
1717            _: Local<bool>,
1718            _: (&mut QueryState<&W<i32>>, &mut SystemState<Query<&W<u32>>>),
1719            _: (),
1720        ) {
1721            unimplemented!()
1722        }
1723
1724        fn not(In(val): In<bool>) -> bool {
1725            !val
1726        }
1727
1728        assert_is_system(returning::<Result<u32, std::io::Error>>.map(Result::unwrap));
1729        assert_is_system(returning::<Option<()>>.map(drop));
1730        assert_is_system(returning::<&str>.map(u64::from_str).map(Result::unwrap));
1731        assert_is_system(static_system_param);
1732        assert_is_system(
1733            exclusive_in_out::<(), Result<(), std::io::Error>>.map(|_out| {
1734                #[cfg(feature = "trace")]
1735                if let Err(error) = _out {
1736                    tracing::error!("{}", error);
1737                }
1738            }),
1739        );
1740        assert_is_system(exclusive_with_state);
1741        assert_is_system(returning::<bool>.pipe(exclusive_in_out::<bool, ()>));
1742
1743        returning::<()>.run_if(returning::<bool>.pipe(not));
1744    }
1745
1746    #[test]
1747    fn pipe_change_detection() {
1748        #[derive(Resource, Default)]
1749        struct Flag;
1750
1751        #[derive(Default)]
1752        struct Info {
1753            // If true, the respective system will mutate `Flag`.
1754            do_first: bool,
1755            do_second: bool,
1756
1757            // Will be set to true if the respective system saw that `Flag` changed.
1758            first_flag: bool,
1759            second_flag: bool,
1760        }
1761
1762        fn first(In(mut info): In<Info>, mut flag: ResMut<Flag>) -> Info {
1763            if flag.is_changed() {
1764                info.first_flag = true;
1765            }
1766            if info.do_first {
1767                *flag = Flag;
1768            }
1769
1770            info
1771        }
1772
1773        fn second(In(mut info): In<Info>, mut flag: ResMut<Flag>) -> Info {
1774            if flag.is_changed() {
1775                info.second_flag = true;
1776            }
1777            if info.do_second {
1778                *flag = Flag;
1779            }
1780
1781            info
1782        }
1783
1784        let mut world = World::new();
1785        world.init_resource::<Flag>();
1786        let mut sys = IntoSystem::into_system(first.pipe(second));
1787        sys.initialize(&mut world);
1788
1789        sys.run(default(), &mut world).unwrap();
1790
1791        // The second system should observe a change made in the first system.
1792        let info = sys
1793            .run(
1794                Info {
1795                    do_first: true,
1796                    ..default()
1797                },
1798                &mut world,
1799            )
1800            .unwrap();
1801        assert!(!info.first_flag);
1802        assert!(info.second_flag);
1803
1804        // When a change is made in the second system, the first system
1805        // should observe it the next time they are run.
1806        let info1 = sys
1807            .run(
1808                Info {
1809                    do_second: true,
1810                    ..default()
1811                },
1812                &mut world,
1813            )
1814            .unwrap();
1815        let info2 = sys.run(default(), &mut world).unwrap();
1816        assert!(!info1.first_flag);
1817        assert!(!info1.second_flag);
1818        assert!(info2.first_flag);
1819        assert!(!info2.second_flag);
1820    }
1821
1822    #[test]
1823    fn test_combinator_clone() {
1824        let mut world = World::new();
1825        #[derive(Resource)]
1826        struct A;
1827        #[derive(Resource)]
1828        struct B;
1829        #[derive(Resource, PartialEq, Eq, Debug)]
1830        struct C(i32);
1831
1832        world.insert_resource(A);
1833        world.insert_resource(C(0));
1834        let mut sched = Schedule::default();
1835        sched.add_systems(
1836            (
1837                |mut res: ResMut<C>| {
1838                    res.0 += 1;
1839                },
1840                |mut res: ResMut<C>| {
1841                    res.0 += 2;
1842                },
1843            )
1844                .distributive_run_if(resource_exists::<A>.or(resource_exists::<B>)),
1845        );
1846        sched.initialize(&mut world).unwrap();
1847        sched.run(&mut world);
1848        assert_eq!(world.get_resource(), Some(&C(3)));
1849    }
1850
1851    #[test]
1852    #[should_panic(
1853        expected = "Encountered an error in system `bevy_ecs::system::tests::simple_fallible_system::sys`: error"
1854    )]
1855    fn simple_fallible_system() {
1856        fn sys() -> Result {
1857            Err("error")?;
1858            Ok(())
1859        }
1860
1861        let mut world = World::new();
1862        run_system(&mut world, sys);
1863    }
1864
1865    #[test]
1866    #[should_panic(
1867        expected = "Encountered an error in system `bevy_ecs::system::tests::simple_fallible_exclusive_system::sys`: error"
1868    )]
1869    fn simple_fallible_exclusive_system() {
1870        fn sys(_world: &mut World) -> Result {
1871            Err("error")?;
1872            Ok(())
1873        }
1874
1875        let mut world = World::new();
1876        run_system(&mut world, sys);
1877    }
1878
1879    // Regression test for
1880    // https://github.com/bevyengine/bevy/issues/18778
1881    //
1882    // Dear rustc team, please reach out if you encounter this
1883    // in a crater run and we can work something out!
1884    //
1885    // These todo! macro calls should never be removed;
1886    // they're intended to demonstrate real-world usage
1887    // in a way that's clearer than simply calling `panic!`
1888    //
1889    // Because type inference behaves differently for functions and closures,
1890    // we need to test both, in addition to explicitly annotating the return type
1891    // to ensure that there are no upstream regressions there.
1892    #[test]
1893    fn nondiverging_never_trait_impls() {
1894        // This test is a compilation test:
1895        // no meaningful logic is ever actually evaluated.
1896        // It is simply intended to check that the correct traits are implemented
1897        // when todo! or similar nondiverging panics are used.
1898        let mut world = World::new();
1899        let mut schedule = Schedule::default();
1900
1901        fn sys(_query: Query<&Name>) {
1902            todo!()
1903        }
1904
1905        schedule.add_systems(sys);
1906        schedule.add_systems(|_query: Query<&Name>| {});
1907        schedule.add_systems(|_query: Query<&Name>| todo!());
1908        schedule.add_systems(|_query: Query<&Name>| -> () { todo!() });
1909
1910        fn obs(_event: On<Add, Name>) {
1911            todo!()
1912        }
1913
1914        world.add_observer(obs);
1915        world.add_observer(|_event: On<Add, Name>| {});
1916        world.add_observer(|_event: On<Add, Name>| todo!());
1917        world.add_observer(|_event: On<Add, Name>| -> () { todo!() });
1918
1919        fn my_command(_world: &mut World) {
1920            todo!()
1921        }
1922
1923        world.commands().queue(my_command);
1924        world.commands().queue(|_world: &mut World| {});
1925        world.commands().queue(|_world: &mut World| todo!());
1926        world
1927            .commands()
1928            .queue(|_world: &mut World| -> () { todo!() });
1929    }
1930
1931    #[test]
1932    fn with_input() {
1933        fn sys(InMut(v): InMut<usize>) {
1934            *v += 1;
1935        }
1936
1937        let mut world = World::new();
1938        let mut system = IntoSystem::into_system(sys.with_input(42));
1939        system.initialize(&mut world);
1940        system.run((), &mut world).unwrap();
1941        assert_eq!(*system.value(), 43);
1942    }
1943
1944    #[test]
1945    fn with_input_from() {
1946        struct TestData(usize);
1947
1948        impl FromWorld for TestData {
1949            fn from_world(_world: &mut World) -> Self {
1950                Self(5)
1951            }
1952        }
1953
1954        fn sys(InMut(v): InMut<TestData>) {
1955            v.0 += 1;
1956        }
1957
1958        let mut world = World::new();
1959        let mut system = IntoSystem::into_system(sys.with_input_from::<TestData>());
1960        assert!(system.value().is_none());
1961        system.initialize(&mut world);
1962        assert!(system.value().is_some());
1963        system.run((), &mut world).unwrap();
1964        assert_eq!(system.value().unwrap().0, 6);
1965    }
1966}