Skip to main content

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>`] and [`SmallVec<[P, N]>`](smallvec::SmallVec) 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, NestedQuery, 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, ExclusiveMarker, In, InMut, IntoSystem, Local, NonSend, NonSendMut, ParamSet,
422            Query, Res, 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, Debug, Eq, PartialEq, Default)]
436    struct A;
437    #[derive(Component)]
438    struct B;
439    #[derive(Component)]
440    struct C;
441    #[derive(Component)]
442    struct D;
443    #[derive(Component)]
444    struct E;
445    #[derive(Component)]
446    struct F;
447
448    #[derive(Resource)]
449    struct ResA;
450    #[derive(Resource)]
451    struct ResB;
452    #[derive(Resource)]
453    struct ResC;
454    #[derive(Resource)]
455    struct ResD;
456    #[derive(Resource)]
457    struct ResE;
458    #[derive(Resource)]
459    struct ResF;
460
461    #[derive(Component, Debug)]
462    struct W<T>(T);
463
464    #[test]
465    fn simple_system() {
466        fn sys(query: Query<&A>) {
467            for a in &query {
468                println!("{a:?}");
469            }
470        }
471
472        let mut system = IntoSystem::into_system(sys);
473        let mut world = World::new();
474        world.spawn(A);
475
476        system.initialize(&mut world);
477        system.run((), &mut world).unwrap();
478    }
479
480    fn run_system<Marker, S: IntoScheduleConfigs<ScheduleSystem, Marker>>(
481        world: &mut World,
482        system: S,
483    ) {
484        let mut schedule = Schedule::default();
485        schedule.add_systems(system);
486        schedule.run(world);
487    }
488
489    #[test]
490    fn get_many_is_ordered() {
491        use crate::resource::Resource;
492        const ENTITIES_COUNT: usize = 1000;
493
494        #[derive(Resource)]
495        struct EntitiesArray(Vec<Entity>);
496
497        fn query_system(
498            mut ran: ResMut<SystemRan>,
499            entities_array: Res<EntitiesArray>,
500            q: Query<&W<usize>>,
501        ) {
502            let entities_array: [Entity; ENTITIES_COUNT] =
503                entities_array.0.clone().try_into().unwrap();
504
505            for (i, w) in (0..ENTITIES_COUNT).zip(q.get_many(entities_array).unwrap()) {
506                assert_eq!(i, w.0);
507            }
508
509            *ran = SystemRan::Yes;
510        }
511
512        fn query_system_mut(
513            mut ran: ResMut<SystemRan>,
514            entities_array: Res<EntitiesArray>,
515            mut q: Query<&mut W<usize>>,
516        ) {
517            let entities_array: [Entity; ENTITIES_COUNT] =
518                entities_array.0.clone().try_into().unwrap();
519
520            for (i, w) in (0..ENTITIES_COUNT).zip(q.get_many_mut(entities_array).unwrap()) {
521                assert_eq!(i, w.0);
522            }
523
524            *ran = SystemRan::Yes;
525        }
526
527        let mut world = World::default();
528        world.insert_resource(SystemRan::No);
529        let entity_ids = (0..ENTITIES_COUNT)
530            .map(|i| world.spawn(W(i)).id())
531            .collect();
532        world.insert_resource(EntitiesArray(entity_ids));
533
534        run_system(&mut world, query_system);
535        assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
536
537        world.insert_resource(SystemRan::No);
538        run_system(&mut world, query_system_mut);
539        assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
540    }
541
542    #[test]
543    fn or_param_set_system() {
544        // Regression test for issue #762
545        fn query_system(
546            mut ran: ResMut<SystemRan>,
547            mut set: ParamSet<(
548                Query<(), Or<(Changed<A>, Changed<B>)>>,
549                Query<(), Or<(Added<A>, Added<B>)>>,
550            )>,
551        ) {
552            let changed = set.p0().iter().count();
553            let added = set.p1().iter().count();
554
555            assert_eq!(changed, 1);
556            assert_eq!(added, 1);
557
558            *ran = SystemRan::Yes;
559        }
560
561        let mut world = World::default();
562        world.insert_resource(SystemRan::No);
563        world.spawn((A, B));
564
565        run_system(&mut world, query_system);
566
567        assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
568    }
569
570    #[test]
571    fn changed_resource_system() {
572        use crate::resource::Resource;
573
574        #[derive(Resource)]
575        struct Flipper(bool);
576
577        #[derive(Resource)]
578        struct Added(usize);
579
580        #[derive(Resource)]
581        struct Changed(usize);
582
583        fn incr_e_on_flip(
584            value: Res<Flipper>,
585            mut changed: ResMut<Changed>,
586            mut added: ResMut<Added>,
587        ) {
588            if value.is_added() {
589                added.0 += 1;
590            }
591
592            if value.is_changed() {
593                changed.0 += 1;
594            }
595        }
596
597        let mut world = World::default();
598        world.insert_resource(Flipper(false));
599        world.insert_resource(Added(0));
600        world.insert_resource(Changed(0));
601
602        let mut schedule = Schedule::default();
603
604        schedule.add_systems((incr_e_on_flip, ApplyDeferred, World::clear_trackers).chain());
605
606        schedule.run(&mut world);
607        assert_eq!(world.resource::<Added>().0, 1);
608        assert_eq!(world.resource::<Changed>().0, 1);
609
610        schedule.run(&mut world);
611        assert_eq!(world.resource::<Added>().0, 1);
612        assert_eq!(world.resource::<Changed>().0, 1);
613
614        world.resource_mut::<Flipper>().0 = true;
615        schedule.run(&mut world);
616        assert_eq!(world.resource::<Added>().0, 1);
617        assert_eq!(world.resource::<Changed>().0, 2);
618    }
619
620    #[test]
621    #[should_panic = "error[B0001]"]
622    fn option_has_no_filter_with() {
623        fn sys(_: Query<(Option<&A>, &mut B)>, _: Query<&mut B, Without<A>>) {}
624        let mut world = World::default();
625        run_system(&mut world, sys);
626    }
627
628    #[test]
629    fn option_doesnt_remove_unrelated_filter_with() {
630        fn sys(_: Query<(Option<&A>, &mut B, &A)>, _: Query<&mut B, Without<A>>) {}
631        let mut world = World::default();
632        run_system(&mut world, sys);
633    }
634
635    #[test]
636    fn any_of_working() {
637        fn sys(_: Query<AnyOf<(&mut A, &B)>>) {}
638        let mut world = World::default();
639        run_system(&mut world, sys);
640    }
641
642    #[test]
643    fn any_of_with_and_without_common() {
644        fn sys(_: Query<(&mut D, &C, AnyOf<(&A, &B)>)>, _: Query<&mut D, Without<C>>) {}
645        let mut world = World::default();
646        run_system(&mut world, sys);
647    }
648
649    #[test]
650    #[should_panic]
651    fn any_of_with_mut_and_ref() {
652        fn sys(_: Query<AnyOf<(&mut A, &A)>>) {}
653        let mut world = World::default();
654        run_system(&mut world, sys);
655    }
656
657    #[test]
658    #[should_panic]
659    fn any_of_with_ref_and_mut() {
660        fn sys(_: Query<AnyOf<(&A, &mut A)>>) {}
661        let mut world = World::default();
662        run_system(&mut world, sys);
663    }
664
665    #[test]
666    #[should_panic]
667    fn any_of_with_mut_and_option() {
668        fn sys(_: Query<AnyOf<(&mut A, Option<&A>)>>) {}
669        let mut world = World::default();
670        run_system(&mut world, sys);
671    }
672
673    #[test]
674    fn any_of_with_entity_and_mut() {
675        fn sys(_: Query<AnyOf<(Entity, &mut A)>>) {}
676        let mut world = World::default();
677        run_system(&mut world, sys);
678    }
679
680    #[test]
681    fn any_of_with_empty_and_mut() {
682        fn sys(_: Query<AnyOf<((), &mut A)>>) {}
683        let mut world = World::default();
684        run_system(&mut world, sys);
685    }
686
687    #[test]
688    #[should_panic = "error[B0001]"]
689    fn any_of_has_no_filter_with() {
690        fn sys(_: Query<(AnyOf<(&A, ())>, &mut B)>, _: Query<&mut B, Without<A>>) {}
691        let mut world = World::default();
692        run_system(&mut world, sys);
693    }
694
695    #[test]
696    #[should_panic]
697    fn any_of_with_conflicting() {
698        fn sys(_: Query<AnyOf<(&mut A, &mut A)>>) {}
699        let mut world = World::default();
700        run_system(&mut world, sys);
701    }
702
703    #[test]
704    fn any_of_has_filter_with_when_both_have_it() {
705        fn sys(_: Query<(AnyOf<(&A, &A)>, &mut B)>, _: Query<&mut B, Without<A>>) {}
706        let mut world = World::default();
707        run_system(&mut world, sys);
708    }
709
710    #[test]
711    fn any_of_doesnt_remove_unrelated_filter_with() {
712        fn sys(_: Query<(AnyOf<(&A, ())>, &mut B, &A)>, _: Query<&mut B, Without<A>>) {}
713        let mut world = World::default();
714        run_system(&mut world, sys);
715    }
716
717    #[test]
718    fn any_of_and_without() {
719        fn sys(_: Query<(AnyOf<(&A, &B)>, &mut C)>, _: Query<&mut C, (Without<A>, Without<B>)>) {}
720        let mut world = World::default();
721        run_system(&mut world, sys);
722    }
723
724    #[test]
725    #[should_panic = "error[B0001]"]
726    fn or_has_no_filter_with() {
727        fn sys(_: Query<&mut B, Or<(With<A>, With<B>)>>, _: Query<&mut B, Without<A>>) {}
728        let mut world = World::default();
729        run_system(&mut world, sys);
730    }
731
732    #[test]
733    fn or_has_filter_with_when_both_have_it() {
734        fn sys(_: Query<&mut B, Or<(With<A>, With<A>)>>, _: Query<&mut B, Without<A>>) {}
735        let mut world = World::default();
736        run_system(&mut world, sys);
737    }
738
739    #[test]
740    fn or_has_filter_with() {
741        fn sys(
742            _: Query<&mut C, Or<(With<A>, With<B>)>>,
743            _: Query<&mut C, (Without<A>, Without<B>)>,
744        ) {
745        }
746        let mut world = World::default();
747        run_system(&mut world, sys);
748    }
749
750    #[test]
751    fn or_expanded_with_and_without_common() {
752        fn sys(_: Query<&mut D, (With<A>, Or<(With<B>, With<C>)>)>, _: Query<&mut D, Without<A>>) {}
753        let mut world = World::default();
754        run_system(&mut world, sys);
755    }
756
757    #[test]
758    fn or_expanded_nested_with_and_without_common() {
759        fn sys(
760            _: Query<&mut E, (Or<((With<B>, With<C>), (With<C>, With<D>))>, With<A>)>,
761            _: Query<&mut E, (Without<B>, Without<D>)>,
762        ) {
763        }
764        let mut world = World::default();
765        run_system(&mut world, sys);
766    }
767
768    #[test]
769    #[should_panic = "error[B0001]"]
770    fn or_expanded_nested_with_and_disjoint_without() {
771        fn sys(
772            _: Query<&mut E, (Or<((With<B>, With<C>), (With<C>, With<D>))>, With<A>)>,
773            _: Query<&mut E, Without<D>>,
774        ) {
775        }
776        let mut world = World::default();
777        run_system(&mut world, sys);
778    }
779
780    #[test]
781    #[should_panic = "error[B0001]"]
782    fn or_expanded_nested_or_with_and_disjoint_without() {
783        fn sys(
784            _: Query<&mut D, Or<(Or<(With<A>, With<B>)>, Or<(With<A>, With<C>)>)>>,
785            _: Query<&mut D, Without<A>>,
786        ) {
787        }
788        let mut world = World::default();
789        run_system(&mut world, sys);
790    }
791
792    #[test]
793    fn or_expanded_nested_with_and_common_nested_without() {
794        fn sys(
795            _: Query<&mut D, Or<((With<A>, With<B>), (With<B>, With<C>))>>,
796            _: Query<&mut D, Or<(Without<D>, Without<B>)>>,
797        ) {
798        }
799        let mut world = World::default();
800        run_system(&mut world, sys);
801    }
802
803    #[test]
804    fn or_with_without_and_compatible_with_without() {
805        fn sys(
806            _: Query<&mut C, Or<(With<A>, Without<B>)>>,
807            _: Query<&mut C, (With<B>, Without<A>)>,
808        ) {
809        }
810        let mut world = World::default();
811        run_system(&mut world, sys);
812    }
813
814    #[test]
815    #[should_panic = "error[B0001]"]
816    fn with_and_disjoint_or_empty_without() {
817        fn sys(_: Query<&mut B, With<A>>, _: Query<&mut B, Or<((), Without<A>)>>) {}
818        let mut world = World::default();
819        run_system(&mut world, sys);
820    }
821
822    #[test]
823    #[should_panic = "error[B0001]"]
824    fn or_expanded_with_and_disjoint_nested_without() {
825        fn sys(
826            _: Query<&mut D, Or<(With<A>, With<B>)>>,
827            _: Query<&mut D, Or<(Without<A>, Without<B>)>>,
828        ) {
829        }
830        let mut world = World::default();
831        run_system(&mut world, sys);
832    }
833
834    #[test]
835    #[should_panic = "error[B0001]"]
836    fn or_expanded_nested_with_and_disjoint_nested_without() {
837        fn sys(
838            _: Query<&mut D, Or<((With<A>, With<B>), (With<B>, With<C>))>>,
839            _: Query<&mut D, Or<(Without<A>, Without<B>)>>,
840        ) {
841        }
842        let mut world = World::default();
843        run_system(&mut world, sys);
844    }
845
846    #[test]
847    fn or_doesnt_remove_unrelated_filter_with() {
848        fn sys(_: Query<&mut B, (Or<(With<A>, With<B>)>, With<A>)>, _: Query<&mut B, Without<A>>) {}
849        let mut world = World::default();
850        run_system(&mut world, sys);
851    }
852
853    #[test]
854    #[should_panic]
855    fn conflicting_query_mut_system() {
856        fn sys(_q1: Query<&mut A>, _q2: Query<&mut A>) {}
857
858        let mut world = World::default();
859        run_system(&mut world, sys);
860    }
861
862    #[test]
863    fn disjoint_query_mut_system() {
864        fn sys(_q1: Query<&mut A, With<B>>, _q2: Query<&mut A, Without<B>>) {}
865
866        let mut world = World::default();
867        run_system(&mut world, sys);
868    }
869
870    #[test]
871    fn disjoint_query_mut_read_component_system() {
872        fn sys(_q1: Query<(&mut A, &B)>, _q2: Query<&mut A, Without<B>>) {}
873
874        let mut world = World::default();
875        run_system(&mut world, sys);
876    }
877
878    #[test]
879    #[should_panic]
880    fn conflicting_query_immut_system() {
881        fn sys(_q1: Query<&A>, _q2: Query<&mut A>) {}
882
883        let mut world = World::default();
884        run_system(&mut world, sys);
885    }
886
887    #[test]
888    #[should_panic]
889    fn changed_trackers_or_conflict() {
890        fn sys(_: Query<&mut A>, _: Query<(), Or<(Changed<A>,)>>) {}
891
892        let mut world = World::default();
893        run_system(&mut world, sys);
894    }
895
896    #[test]
897    #[should_panic = "error[B0001]"]
898    fn nested_query_conflicts_with_main_query() {
899        fn sys(_: Query<(&mut A, NestedQuery<&A>)>) {}
900
901        let mut world = World::default();
902        run_system(&mut world, sys);
903    }
904
905    #[test]
906    #[should_panic = "error[B0001]"]
907    fn nested_query_conflicts_with_earlier_query() {
908        fn sys(_: Query<&mut A>, _: Query<NestedQuery<&A>>) {}
909
910        let mut world = World::default();
911        run_system(&mut world, sys);
912    }
913
914    #[test]
915    #[should_panic = "error[B0001]"]
916    fn nested_query_conflicts_with_later_query() {
917        fn sys(_: Query<NestedQuery<&A>>, _: Query<&mut A>) {}
918
919        let mut world = World::default();
920        run_system(&mut world, sys);
921    }
922
923    #[test]
924    fn query_set_system() {
925        fn sys(mut _set: ParamSet<(Query<&mut A>, Query<&A>)>) {}
926        let mut world = World::default();
927        run_system(&mut world, sys);
928    }
929
930    #[test]
931    #[should_panic]
932    fn conflicting_query_with_query_set_system() {
933        fn sys(_query: Query<&mut A>, _set: ParamSet<(Query<&mut A>, Query<&B>)>) {}
934
935        let mut world = World::default();
936        run_system(&mut world, sys);
937    }
938
939    #[test]
940    #[should_panic]
941    fn conflicting_query_sets_system() {
942        fn sys(_set_1: ParamSet<(Query<&mut A>,)>, _set_2: ParamSet<(Query<&mut A>, Query<&B>)>) {}
943
944        let mut world = World::default();
945        run_system(&mut world, sys);
946    }
947
948    #[derive(Default, Resource)]
949    struct BufferRes {
950        _buffer: Vec<u8>,
951    }
952
953    fn test_for_conflicting_resources<Marker, S: IntoSystem<(), (), Marker>>(sys: S) {
954        let mut world = World::default();
955        world.insert_resource(BufferRes::default());
956        world.insert_resource(ResA);
957        world.insert_resource(ResB);
958        run_system(&mut world, sys);
959    }
960
961    #[test]
962    #[should_panic]
963    fn conflicting_system_resources() {
964        fn sys(_: ResMut<BufferRes>, _: Res<BufferRes>) {}
965        test_for_conflicting_resources(sys);
966    }
967
968    #[test]
969    #[should_panic]
970    fn conflicting_system_resources_reverse_order() {
971        fn sys(_: Res<BufferRes>, _: ResMut<BufferRes>) {}
972        test_for_conflicting_resources(sys);
973    }
974
975    #[test]
976    #[should_panic]
977    fn conflicting_system_resources_multiple_mutable() {
978        fn sys(_: ResMut<BufferRes>, _: ResMut<BufferRes>) {}
979        test_for_conflicting_resources(sys);
980    }
981
982    #[test]
983    fn nonconflicting_system_resources() {
984        fn sys(_: Local<BufferRes>, _: ResMut<BufferRes>, _: Local<A>, _: ResMut<ResA>) {}
985        test_for_conflicting_resources(sys);
986    }
987
988    #[test]
989    fn local_system() {
990        let mut world = World::default();
991        world.insert_resource(ProtoFoo { value: 1 });
992        world.insert_resource(SystemRan::No);
993
994        struct Foo {
995            value: u32,
996        }
997
998        #[derive(Resource)]
999        struct ProtoFoo {
1000            value: u32,
1001        }
1002
1003        impl FromWorld for Foo {
1004            fn from_world(world: &mut World) -> Self {
1005                Foo {
1006                    value: world.resource::<ProtoFoo>().value + 1,
1007                }
1008            }
1009        }
1010
1011        fn sys(local: Local<Foo>, mut system_ran: ResMut<SystemRan>) {
1012            assert_eq!(local.value, 2);
1013            *system_ran = SystemRan::Yes;
1014        }
1015
1016        run_system(&mut world, sys);
1017
1018        // ensure the system actually ran
1019        assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
1020    }
1021
1022    #[test]
1023    #[expect(
1024        dead_code,
1025        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."
1026    )]
1027    fn non_send_option_system() {
1028        let mut world = World::default();
1029
1030        world.insert_resource(SystemRan::No);
1031        // Two structs are used, one which is inserted and one which is not, to verify that wrapping
1032        // non-Send resources in an `Option` will allow the system to run regardless of their
1033        // existence.
1034        struct NotSend1(alloc::rc::Rc<i32>);
1035        struct NotSend2(alloc::rc::Rc<i32>);
1036        world.insert_non_send(NotSend1(alloc::rc::Rc::new(0)));
1037
1038        fn sys(
1039            op: Option<NonSend<NotSend1>>,
1040            mut _op2: Option<NonSendMut<NotSend2>>,
1041            mut system_ran: ResMut<SystemRan>,
1042        ) {
1043            op.expect("NonSend should exist");
1044            *system_ran = SystemRan::Yes;
1045        }
1046
1047        run_system(&mut world, sys);
1048        // ensure the system actually ran
1049        assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
1050    }
1051
1052    #[test]
1053    #[expect(
1054        dead_code,
1055        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."
1056    )]
1057    fn non_send_system() {
1058        let mut world = World::default();
1059
1060        world.insert_resource(SystemRan::No);
1061        struct NotSend1(alloc::rc::Rc<i32>);
1062        struct NotSend2(alloc::rc::Rc<i32>);
1063
1064        world.insert_non_send(NotSend1(alloc::rc::Rc::new(1)));
1065        world.insert_non_send(NotSend2(alloc::rc::Rc::new(2)));
1066
1067        fn sys(
1068            _op: NonSend<NotSend1>,
1069            mut _op2: NonSendMut<NotSend2>,
1070            mut system_ran: ResMut<SystemRan>,
1071        ) {
1072            *system_ran = SystemRan::Yes;
1073        }
1074
1075        run_system(&mut world, sys);
1076        assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
1077    }
1078
1079    #[test]
1080    fn function_system_as_exclusive() {
1081        let mut world = World::default();
1082
1083        world.insert_resource(SystemRan::No);
1084
1085        fn sys(_marker: ExclusiveMarker, mut system_ran: ResMut<SystemRan>) {
1086            *system_ran = SystemRan::Yes;
1087        }
1088
1089        let mut sys = IntoSystem::into_system(sys);
1090        sys.initialize(&mut world);
1091        assert!(sys.is_exclusive());
1092
1093        run_system(&mut world, sys);
1094        assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
1095    }
1096
1097    #[test]
1098    fn removal_tracking() {
1099        let mut world = World::new();
1100
1101        let entity_to_despawn = world.spawn(W(1)).id();
1102        let entity_to_remove_w_from = world.spawn(W(2)).id();
1103        let spurious_entity = world.spawn_empty().id();
1104
1105        // Track which entities we want to operate on
1106        #[derive(Resource)]
1107        struct Despawned(Entity);
1108        world.insert_resource(Despawned(entity_to_despawn));
1109
1110        #[derive(Resource)]
1111        struct Removed(Entity);
1112        world.insert_resource(Removed(entity_to_remove_w_from));
1113
1114        // Verify that all the systems actually ran
1115        #[derive(Default, Resource)]
1116        struct NSystems(usize);
1117        world.insert_resource(NSystems::default());
1118
1119        // First, check that removal detection is triggered if and only if we despawn an entity with the correct component
1120        world.entity_mut(entity_to_despawn).despawn();
1121        world.entity_mut(spurious_entity).despawn();
1122
1123        fn validate_despawn(
1124            mut removed_i32: RemovedComponents<W<i32>>,
1125            despawned: Res<Despawned>,
1126            mut n_systems: ResMut<NSystems>,
1127        ) {
1128            assert_eq!(
1129                removed_i32.read().collect::<Vec<_>>(),
1130                &[despawned.0],
1131                "despawning causes the correct entity to show up in the 'RemovedComponent' system parameter."
1132            );
1133
1134            n_systems.0 += 1;
1135        }
1136
1137        run_system(&mut world, validate_despawn);
1138
1139        // Reset the trackers to clear the buffer of removed components
1140        // Ordinarily, this is done in a system added by MinimalPlugins
1141        world.clear_trackers();
1142
1143        // Then, try removing a component
1144        world.spawn(W(3));
1145        world.spawn(W(4));
1146        world.entity_mut(entity_to_remove_w_from).remove::<W<i32>>();
1147
1148        fn validate_remove(
1149            mut removed_i32: RemovedComponents<W<i32>>,
1150            despawned: Res<Despawned>,
1151            removed: Res<Removed>,
1152            mut n_systems: ResMut<NSystems>,
1153        ) {
1154            // The despawned entity from the previous frame was
1155            // double buffered so we now have it in this system as well.
1156            assert_eq!(
1157                removed_i32.read().collect::<Vec<_>>(),
1158                &[despawned.0, removed.0],
1159                "removing a component causes the correct entity to show up in the 'RemovedComponent' system parameter."
1160            );
1161
1162            n_systems.0 += 1;
1163        }
1164
1165        run_system(&mut world, validate_remove);
1166
1167        // Verify that both systems actually ran
1168        assert_eq!(world.resource::<NSystems>().0, 2);
1169    }
1170
1171    #[test]
1172    fn world_collections_system() {
1173        let mut world = World::default();
1174        world.insert_resource(SystemRan::No);
1175        world.spawn((W(42), W(true)));
1176        fn sys(
1177            archetypes: &Archetypes,
1178            components: &Components,
1179            entities: &Entities,
1180            bundles: &Bundles,
1181            query: Query<Entity, With<W<i32>>>,
1182            mut system_ran: ResMut<SystemRan>,
1183        ) {
1184            assert_eq!(query.iter().count(), 1, "entity exists");
1185            for entity in &query {
1186                let location = entities.get_spawned(entity).unwrap();
1187                let archetype = archetypes.get(location.archetype_id).unwrap();
1188                let archetype_components = archetype.components();
1189                let bundle_id = bundles
1190                    .get_id(TypeId::of::<(W<i32>, W<bool>)>())
1191                    .expect("Bundle used to spawn entity should exist");
1192                let bundle_info = bundles.get(bundle_id).unwrap();
1193                let mut bundle_components = bundle_info.contributed_components().to_vec();
1194                bundle_components.sort();
1195                for component_id in &bundle_components {
1196                    assert!(
1197                        components.get_info(*component_id).is_some(),
1198                        "every bundle component exists in Components"
1199                    );
1200                }
1201                assert_eq!(
1202                    bundle_components, archetype_components,
1203                    "entity's bundle components exactly match entity's archetype components"
1204                );
1205            }
1206            *system_ran = SystemRan::Yes;
1207        }
1208
1209        run_system(&mut world, sys);
1210
1211        // ensure the system actually ran
1212        assert_eq!(*world.resource::<SystemRan>(), SystemRan::Yes);
1213    }
1214
1215    #[test]
1216    fn get_system_conflicts() {
1217        fn sys_x(_: Res<ResA>, _: Res<ResB>, _: Query<(&C, &D)>) {}
1218
1219        fn sys_y(_: Res<ResA>, _: ResMut<ResB>, _: Query<(&C, &mut D)>) {}
1220
1221        let mut world = World::default();
1222        let mut x = IntoSystem::into_system(sys_x);
1223        let mut y = IntoSystem::into_system(sys_y);
1224        let x_access = x.initialize(&mut world);
1225        let y_access = y.initialize(&mut world);
1226
1227        let conflicts = x_access.get_conflicts(&y_access);
1228        let b_id = world.components().get_id(TypeId::of::<ResB>()).unwrap();
1229        let d_id = world.components().get_id(TypeId::of::<D>()).unwrap();
1230        assert_eq!(conflicts, vec![b_id, d_id].into());
1231    }
1232
1233    #[test]
1234    fn query_is_empty() {
1235        fn without_filter(not_empty: Query<&A>, empty: Query<&B>) {
1236            assert!(!not_empty.is_empty());
1237            assert!(empty.is_empty());
1238        }
1239
1240        fn with_filter(not_empty: Query<&A, With<C>>, empty: Query<&A, With<D>>) {
1241            assert!(!not_empty.is_empty());
1242            assert!(empty.is_empty());
1243        }
1244
1245        let mut world = World::default();
1246        world.spawn(A).insert(C);
1247
1248        let mut without_filter = IntoSystem::into_system(without_filter);
1249        without_filter.initialize(&mut world);
1250        without_filter.run((), &mut world).unwrap();
1251
1252        let mut with_filter = IntoSystem::into_system(with_filter);
1253        with_filter.initialize(&mut world);
1254        with_filter.run((), &mut world).unwrap();
1255    }
1256
1257    #[test]
1258    fn can_have_16_parameters() {
1259        fn sys_x(
1260            _: Res<ResA>,
1261            _: Res<ResB>,
1262            _: Res<ResC>,
1263            _: Res<ResD>,
1264            _: Res<ResE>,
1265            _: Res<ResF>,
1266            _: Query<&A>,
1267            _: Query<&B>,
1268            _: Query<&C>,
1269            _: Query<&D>,
1270            _: Query<&E>,
1271            _: Query<&F>,
1272            _: Query<(&A, &B)>,
1273            _: Query<(&C, &D)>,
1274            _: Query<(&E, &F)>,
1275        ) {
1276        }
1277        fn sys_y(
1278            _: (
1279                Res<ResA>,
1280                Res<ResB>,
1281                Res<ResC>,
1282                Res<ResD>,
1283                Res<ResE>,
1284                Res<ResF>,
1285                Query<&A>,
1286                Query<&B>,
1287                Query<&C>,
1288                Query<&D>,
1289                Query<&E>,
1290                Query<&F>,
1291                Query<(&A, &B)>,
1292                Query<(&C, &D)>,
1293                Query<(&E, &F)>,
1294            ),
1295        ) {
1296        }
1297        let mut world = World::default();
1298        let mut x = IntoSystem::into_system(sys_x);
1299        let mut y = IntoSystem::into_system(sys_y);
1300        x.initialize(&mut world);
1301        y.initialize(&mut world);
1302    }
1303
1304    #[test]
1305    fn read_system_state() {
1306        #[derive(Eq, PartialEq, Debug, Resource)]
1307        struct A(usize);
1308
1309        #[derive(Component, Eq, PartialEq, Debug)]
1310        struct B(usize);
1311
1312        let mut world = World::default();
1313        world.insert_resource(A(42));
1314        world.spawn(B(7));
1315
1316        let mut system_state: SystemState<(
1317            Res<A>,
1318            Option<Single<&B>>,
1319            ParamSet<(Query<&C>, Query<&D>)>,
1320        )> = SystemState::new(&mut world);
1321        let (a, query, _) = system_state.get(&world).unwrap();
1322        assert_eq!(*a, A(42), "returned resource matches initial value");
1323        assert_eq!(
1324            **query.unwrap(),
1325            B(7),
1326            "returned component matches initial value"
1327        );
1328    }
1329
1330    #[test]
1331    fn write_system_state() {
1332        #[derive(Resource, Eq, PartialEq, Debug)]
1333        struct A(usize);
1334
1335        #[derive(Component, Eq, PartialEq, Debug)]
1336        struct B(usize);
1337
1338        let mut world = World::default();
1339        world.insert_resource(A(42));
1340        world.spawn(B(7));
1341
1342        let mut system_state: SystemState<(ResMut<A>, Option<Single<&mut B>>)> =
1343            SystemState::new(&mut world);
1344
1345        // The following line shouldn't compile because the parameters used are not ReadOnlySystemParam
1346        // let (a, query) = system_state.get(&world);
1347
1348        let (a, query) = system_state.get_mut(&mut world).unwrap();
1349        assert_eq!(*a, A(42), "returned resource matches initial value");
1350        assert_eq!(
1351            **query.unwrap(),
1352            B(7),
1353            "returned component matches initial value"
1354        );
1355    }
1356
1357    #[test]
1358    fn system_state_change_detection() {
1359        #[derive(Component, Eq, PartialEq, Debug)]
1360        struct A(usize);
1361
1362        let mut world = World::default();
1363        let entity = world.spawn(A(1)).id();
1364
1365        let mut system_state: SystemState<Option<Single<&A, Changed<A>>>> =
1366            SystemState::new(&mut world);
1367        {
1368            let query = system_state.get(&world).unwrap();
1369            assert_eq!(**query.unwrap(), A(1));
1370        }
1371
1372        {
1373            let query = system_state.get(&world).unwrap();
1374            assert!(query.is_none());
1375        }
1376
1377        world.entity_mut(entity).get_mut::<A>().unwrap().0 = 2;
1378        {
1379            let query = system_state.get(&world).unwrap();
1380            assert_eq!(**query.unwrap(), A(2));
1381        }
1382    }
1383
1384    #[test]
1385    fn system_state_spawned() {
1386        let mut world = World::default();
1387        world.spawn(A);
1388        let spawn_tick = world.change_tick();
1389
1390        let mut system_state: SystemState<Option<Single<(&A, SpawnDetails), Spawned>>> =
1391            SystemState::new(&mut world);
1392        {
1393            let query = system_state.get(&world).unwrap();
1394            assert_eq!(query.unwrap().1.spawn_tick(), spawn_tick);
1395        }
1396
1397        {
1398            let query = system_state.get(&world).unwrap();
1399            assert!(query.is_none());
1400        }
1401    }
1402
1403    #[test]
1404    #[should_panic]
1405    fn system_state_invalid_world() {
1406        let mut world = World::default();
1407        let mut system_state = SystemState::<Query<&A>>::new(&mut world);
1408        let mismatched_world = World::default();
1409        system_state.get(&mismatched_world).unwrap();
1410    }
1411
1412    #[test]
1413    fn system_state_archetype_update() {
1414        #[derive(Component, Eq, PartialEq, Debug)]
1415        struct A(usize);
1416
1417        #[derive(Component, Eq, PartialEq, Debug)]
1418        struct B(usize);
1419
1420        let mut world = World::default();
1421        world.spawn(A(1));
1422
1423        let mut system_state = SystemState::<Query<&A>>::new(&mut world);
1424        {
1425            let query = system_state.get(&world).unwrap();
1426            assert_eq!(
1427                query.iter().collect::<Vec<_>>(),
1428                vec![&A(1)],
1429                "exactly one component returned"
1430            );
1431        }
1432
1433        world.spawn((A(2), B(2)));
1434        {
1435            let query = system_state.get(&world).unwrap();
1436            assert_eq!(
1437                query.iter().collect::<Vec<_>>(),
1438                vec![&A(1), &A(2)],
1439                "components from both archetypes returned"
1440            );
1441        }
1442    }
1443
1444    #[test]
1445    #[expect(
1446        dead_code,
1447        reason = "This test exists to show that read-only world-only queries can return data that lives as long as `'world`."
1448    )]
1449    fn long_life_test() {
1450        struct ResourceHolder<'w> {
1451            value: &'w ResA,
1452        }
1453
1454        struct Holder<'w> {
1455            value: &'w A,
1456        }
1457
1458        struct State {
1459            state: SystemState<Res<'static, ResA>>,
1460            state_q: SystemState<Query<'static, 'static, &'static A>>,
1461        }
1462
1463        impl State {
1464            fn hold_res<'w>(&mut self, world: &'w World) -> ResourceHolder<'w> {
1465                let a = self.state.get(world).unwrap();
1466                ResourceHolder {
1467                    value: a.into_inner(),
1468                }
1469            }
1470            fn hold_component<'w>(&mut self, world: &'w World, entity: Entity) -> Holder<'w> {
1471                let q = self.state_q.get(world).unwrap();
1472                let a = q.get_inner(entity).unwrap();
1473                Holder { value: a }
1474            }
1475            fn hold_components<'w>(&mut self, world: &'w World) -> Vec<Holder<'w>> {
1476                let mut components = Vec::new();
1477                let q = self.state_q.get(world).unwrap();
1478                for a in q.iter_inner() {
1479                    components.push(Holder { value: a });
1480                }
1481                components
1482            }
1483        }
1484    }
1485
1486    #[test]
1487    fn immutable_mut_test() {
1488        #[derive(Component, Eq, PartialEq, Debug, Clone, Copy)]
1489        struct A(usize);
1490
1491        let mut world = World::default();
1492        world.spawn(A(1));
1493        world.spawn(A(2));
1494
1495        let mut system_state = SystemState::<Query<&mut A>>::new(&mut world);
1496        {
1497            let mut query = system_state.get_mut(&mut world).unwrap();
1498            assert_eq!(
1499                query.iter_mut().map(|m| *m).collect::<Vec<A>>(),
1500                vec![A(1), A(2)],
1501                "both components returned by iter_mut of &mut"
1502            );
1503            assert_eq!(
1504                query.iter().collect::<Vec<&A>>(),
1505                vec![&A(1), &A(2)],
1506                "both components returned by iter of &mut"
1507            );
1508        }
1509    }
1510
1511    #[test]
1512    fn convert_mut_to_immut() {
1513        {
1514            let mut world = World::new();
1515
1516            fn mutable_query(mut query: Query<&mut A>) {
1517                for _ in &mut query {}
1518
1519                immutable_query(query.as_readonly());
1520            }
1521
1522            fn immutable_query(_: Query<&A>) {}
1523
1524            let mut sys = IntoSystem::into_system(mutable_query);
1525            sys.initialize(&mut world);
1526        }
1527
1528        {
1529            let mut world = World::new();
1530
1531            fn mutable_query(mut query: Query<Option<&mut A>>) {
1532                for _ in &mut query {}
1533
1534                immutable_query(query.as_readonly());
1535            }
1536
1537            fn immutable_query(_: Query<Option<&A>>) {}
1538
1539            let mut sys = IntoSystem::into_system(mutable_query);
1540            sys.initialize(&mut world);
1541        }
1542
1543        {
1544            let mut world = World::new();
1545
1546            fn mutable_query(mut query: Query<(&mut A, &B)>) {
1547                for _ in &mut query {}
1548
1549                immutable_query(query.as_readonly());
1550            }
1551
1552            fn immutable_query(_: Query<(&A, &B)>) {}
1553
1554            let mut sys = IntoSystem::into_system(mutable_query);
1555            sys.initialize(&mut world);
1556        }
1557
1558        {
1559            let mut world = World::new();
1560
1561            fn mutable_query(mut query: Query<(&mut A, &mut B)>) {
1562                for _ in &mut query {}
1563
1564                immutable_query(query.as_readonly());
1565            }
1566
1567            fn immutable_query(_: Query<(&A, &B)>) {}
1568
1569            let mut sys = IntoSystem::into_system(mutable_query);
1570            sys.initialize(&mut world);
1571        }
1572
1573        {
1574            let mut world = World::new();
1575
1576            fn mutable_query(mut query: Query<(&mut A, &mut B), With<C>>) {
1577                for _ in &mut query {}
1578
1579                immutable_query(query.as_readonly());
1580            }
1581
1582            fn immutable_query(_: Query<(&A, &B), With<C>>) {}
1583
1584            let mut sys = IntoSystem::into_system(mutable_query);
1585            sys.initialize(&mut world);
1586        }
1587
1588        {
1589            let mut world = World::new();
1590
1591            fn mutable_query(mut query: Query<(&mut A, &mut B), Without<C>>) {
1592                for _ in &mut query {}
1593
1594                immutable_query(query.as_readonly());
1595            }
1596
1597            fn immutable_query(_: Query<(&A, &B), Without<C>>) {}
1598
1599            let mut sys = IntoSystem::into_system(mutable_query);
1600            sys.initialize(&mut world);
1601        }
1602
1603        {
1604            let mut world = World::new();
1605
1606            fn mutable_query(mut query: Query<(&mut A, &mut B), Added<C>>) {
1607                for _ in &mut query {}
1608
1609                immutable_query(query.as_readonly());
1610            }
1611
1612            fn immutable_query(_: Query<(&A, &B), Added<C>>) {}
1613
1614            let mut sys = IntoSystem::into_system(mutable_query);
1615            sys.initialize(&mut world);
1616        }
1617
1618        {
1619            let mut world = World::new();
1620
1621            fn mutable_query(mut query: Query<(&mut A, &mut B), Changed<C>>) {
1622                for _ in &mut query {}
1623
1624                immutable_query(query.as_readonly());
1625            }
1626
1627            fn immutable_query(_: Query<(&A, &B), Changed<C>>) {}
1628
1629            let mut sys = IntoSystem::into_system(mutable_query);
1630            sys.initialize(&mut world);
1631        }
1632
1633        {
1634            let mut world = World::new();
1635
1636            fn mutable_query(mut query: Query<(&mut A, &mut B, SpawnDetails), Spawned>) {
1637                for _ in &mut query {}
1638
1639                immutable_query(query.as_readonly());
1640            }
1641
1642            fn immutable_query(_: Query<(&A, &B, SpawnDetails), Spawned>) {}
1643
1644            let mut sys = IntoSystem::into_system(mutable_query);
1645            sys.initialize(&mut world);
1646        }
1647    }
1648
1649    #[test]
1650    fn commands_param_set() {
1651        // Regression test for #4676
1652        let mut world = World::new();
1653        let entity = world.spawn_empty().id();
1654
1655        run_system(
1656            &mut world,
1657            move |mut commands_set: ParamSet<(Commands, Commands)>| {
1658                commands_set.p0().entity(entity).insert(A);
1659                commands_set.p1().entity(entity).insert(B);
1660            },
1661        );
1662
1663        let entity = world.entity(entity);
1664        assert!(entity.contains::<A>());
1665        assert!(entity.contains::<B>());
1666    }
1667
1668    #[test]
1669    fn into_iter_impl() {
1670        let mut world = World::new();
1671        world.spawn(W(42u32));
1672        run_system(&mut world, |mut q: Query<&mut W<u32>>| {
1673            for mut a in &mut q {
1674                assert_eq!(a.0, 42);
1675                a.0 = 0;
1676            }
1677            for a in &q {
1678                assert_eq!(a.0, 0);
1679            }
1680        });
1681    }
1682
1683    #[test]
1684    #[should_panic]
1685    fn assert_system_does_not_conflict() {
1686        fn system(_query: Query<(&mut W<u32>, &mut W<u32>)>) {}
1687        super::assert_system_does_not_conflict(system);
1688    }
1689
1690    #[test]
1691    #[should_panic]
1692    fn assert_world_and_entity_mut_system_does_conflict_first() {
1693        fn system(_query: &World, _q2: Query<EntityMut>) {}
1694        super::assert_system_does_not_conflict(system);
1695    }
1696
1697    #[test]
1698    #[should_panic]
1699    fn assert_world_and_entity_mut_system_does_conflict_second() {
1700        fn system(_: Query<EntityMut>, _: &World) {}
1701        super::assert_system_does_not_conflict(system);
1702    }
1703
1704    #[test]
1705    #[should_panic]
1706    fn assert_entity_ref_and_entity_mut_system_does_conflict() {
1707        fn system(_query: Query<EntityRef>, _q2: Query<EntityMut>) {}
1708        super::assert_system_does_not_conflict(system);
1709    }
1710
1711    #[test]
1712    #[should_panic]
1713    fn assert_entity_mut_system_does_conflict() {
1714        fn system(_query: Query<EntityMut>, _q2: Query<EntityMut>) {}
1715        super::assert_system_does_not_conflict(system);
1716    }
1717
1718    #[test]
1719    #[should_panic]
1720    fn assert_deferred_world_and_entity_ref_system_does_conflict_first() {
1721        fn system(_world: DeferredWorld, _query: Query<EntityRef>) {}
1722        super::assert_system_does_not_conflict(system);
1723    }
1724
1725    #[test]
1726    #[should_panic]
1727    fn assert_deferred_world_and_entity_ref_system_does_conflict_second() {
1728        fn system(_query: Query<EntityRef>, _world: DeferredWorld) {}
1729        super::assert_system_does_not_conflict(system);
1730    }
1731
1732    #[test]
1733    fn assert_deferred_world_and_empty_query_does_not_conflict_first() {
1734        fn system(_world: DeferredWorld, _query: Query<Entity>) {}
1735        super::assert_system_does_not_conflict(system);
1736    }
1737
1738    #[test]
1739    fn assert_deferred_world_and_empty_query_does_not_conflict_second() {
1740        fn system(_query: Query<Entity>, _world: DeferredWorld) {}
1741        super::assert_system_does_not_conflict(system);
1742    }
1743
1744    #[test]
1745    #[should_panic]
1746    fn panic_inside_system() {
1747        let mut world = World::new();
1748        let system: fn() = || {
1749            panic!("this system panics");
1750        };
1751        run_system(&mut world, system);
1752    }
1753
1754    #[test]
1755    fn assert_systems() {
1756        use core::str::FromStr;
1757
1758        use crate::{prelude::*, system::assert_is_system};
1759
1760        /// Mocks a system that returns a value of type `T`.
1761        fn returning<T>() -> T {
1762            unimplemented!()
1763        }
1764
1765        /// Mocks an exclusive system that takes an input and returns an output.
1766        fn exclusive_in_out<A, B>(_: In<A>, _: &mut World) -> B {
1767            unimplemented!()
1768        }
1769
1770        fn static_system_param(_: StaticSystemParam<Query<'static, 'static, &W<u32>>>) {
1771            unimplemented!()
1772        }
1773
1774        fn exclusive_with_state(
1775            _: &mut World,
1776            _: Local<bool>,
1777            _: (&mut QueryState<&W<i32>>, &mut SystemState<Query<&W<u32>>>),
1778            _: (),
1779        ) {
1780            unimplemented!()
1781        }
1782
1783        fn not(In(val): In<bool>) -> bool {
1784            !val
1785        }
1786
1787        assert_is_system(returning::<Result<u32, std::io::Error>>.map(Result::unwrap));
1788        assert_is_system(returning::<Option<()>>.map(drop));
1789        assert_is_system(returning::<&str>.map(u64::from_str).map(Result::unwrap));
1790        assert_is_system(static_system_param);
1791        assert_is_system(
1792            exclusive_in_out::<(), Result<(), std::io::Error>>.map(|_out| {
1793                #[cfg(feature = "trace")]
1794                if let Err(error) = _out {
1795                    tracing::error!("{}", error);
1796                }
1797            }),
1798        );
1799        assert_is_system(exclusive_with_state);
1800        assert_is_system(returning::<bool>.pipe(exclusive_in_out::<bool, ()>));
1801
1802        returning::<()>.run_if(returning::<bool>.pipe(not));
1803    }
1804
1805    #[test]
1806    fn pipe_change_detection() {
1807        #[derive(Resource, Default)]
1808        struct Flag;
1809
1810        #[derive(Default)]
1811        struct Info {
1812            // If true, the respective system will mutate `Flag`.
1813            do_first: bool,
1814            do_second: bool,
1815
1816            // Will be set to true if the respective system saw that `Flag` changed.
1817            first_flag: bool,
1818            second_flag: bool,
1819        }
1820
1821        fn first(In(mut info): In<Info>, mut flag: ResMut<Flag>) -> Info {
1822            if flag.is_changed() {
1823                info.first_flag = true;
1824            }
1825            if info.do_first {
1826                *flag = Flag;
1827            }
1828
1829            info
1830        }
1831
1832        fn second(In(mut info): In<Info>, mut flag: ResMut<Flag>) -> Info {
1833            if flag.is_changed() {
1834                info.second_flag = true;
1835            }
1836            if info.do_second {
1837                *flag = Flag;
1838            }
1839
1840            info
1841        }
1842
1843        let mut world = World::new();
1844        world.init_resource::<Flag>();
1845        let mut sys = IntoSystem::into_system(first.pipe(second));
1846        sys.initialize(&mut world);
1847
1848        sys.run(default(), &mut world).unwrap();
1849
1850        // The second system should observe a change made in the first system.
1851        let info = sys
1852            .run(
1853                Info {
1854                    do_first: true,
1855                    ..default()
1856                },
1857                &mut world,
1858            )
1859            .unwrap();
1860        assert!(!info.first_flag);
1861        assert!(info.second_flag);
1862
1863        // When a change is made in the second system, the first system
1864        // should observe it the next time they are run.
1865        let info1 = sys
1866            .run(
1867                Info {
1868                    do_second: true,
1869                    ..default()
1870                },
1871                &mut world,
1872            )
1873            .unwrap();
1874        let info2 = sys.run(default(), &mut world).unwrap();
1875        assert!(!info1.first_flag);
1876        assert!(!info1.second_flag);
1877        assert!(info2.first_flag);
1878        assert!(!info2.second_flag);
1879    }
1880
1881    #[test]
1882    fn test_combinator_clone() {
1883        let mut world = World::new();
1884        #[derive(Resource)]
1885        struct A;
1886        #[derive(Resource)]
1887        struct B;
1888        #[derive(Resource, PartialEq, Eq, Debug)]
1889        struct C(i32);
1890
1891        world.insert_resource(A);
1892        world.insert_resource(C(0));
1893        let mut sched = Schedule::default();
1894        sched.add_systems(
1895            (
1896                |mut res: ResMut<C>| {
1897                    res.0 += 1;
1898                },
1899                |mut res: ResMut<C>| {
1900                    res.0 += 2;
1901                },
1902            )
1903                .distributive_run_if(resource_exists::<A>.or_eager(resource_exists::<B>)),
1904        );
1905        sched.initialize(&mut world).unwrap();
1906        sched.run(&mut world);
1907        assert_eq!(world.get_resource(), Some(&C(3)));
1908    }
1909
1910    #[test]
1911    #[cfg_attr(not(feature = "debug"), ignore)]
1912    #[should_panic(
1913        expected = "Encountered an error in system `bevy_ecs::system::tests::simple_fallible_system::sys`: error"
1914    )]
1915    fn simple_fallible_system() {
1916        fn sys() -> Result {
1917            Err("error")?;
1918            Ok(())
1919        }
1920
1921        let mut world = World::new();
1922        run_system(&mut world, sys);
1923    }
1924
1925    #[test]
1926    #[cfg_attr(not(feature = "debug"), ignore)]
1927    #[should_panic(
1928        expected = "Encountered an error in system `bevy_ecs::system::tests::simple_fallible_exclusive_system::sys`: error"
1929    )]
1930    fn simple_fallible_exclusive_system() {
1931        fn sys(_world: &mut World) -> Result {
1932            Err("error")?;
1933            Ok(())
1934        }
1935
1936        let mut world = World::new();
1937        run_system(&mut world, sys);
1938    }
1939
1940    // Regression test for
1941    // https://github.com/bevyengine/bevy/issues/18778
1942    //
1943    // Dear rustc team, please reach out if you encounter this
1944    // in a crater run and we can work something out!
1945    //
1946    // These todo! macro calls should never be removed;
1947    // they're intended to demonstrate real-world usage
1948    // in a way that's clearer than simply calling `panic!`
1949    //
1950    // Because type inference behaves differently for functions and closures,
1951    // we need to test both, in addition to explicitly annotating the return type
1952    // to ensure that there are no upstream regressions there.
1953    #[test]
1954    fn nondiverging_never_trait_impls() {
1955        // This test is a compilation test:
1956        // no meaningful logic is ever actually evaluated.
1957        // It is simply intended to check that the correct traits are implemented
1958        // when todo! or similar nondiverging panics are used.
1959        let mut world = World::new();
1960        let mut schedule = Schedule::default();
1961
1962        fn sys(_query: Query<&Name>) {
1963            todo!()
1964        }
1965
1966        schedule.add_systems(sys);
1967        schedule.add_systems(|_query: Query<&Name>| {});
1968        schedule.add_systems(|_query: Query<&Name>| todo!());
1969        schedule.add_systems(|_query: Query<&Name>| -> () { todo!() });
1970
1971        fn obs(_event: On<Add, Name>) {
1972            todo!()
1973        }
1974
1975        world.add_observer(obs);
1976        world.add_observer(|_event: On<Add, Name>| {});
1977        world.add_observer(|_event: On<Add, Name>| todo!());
1978        world.add_observer(|_event: On<Add, Name>| -> () { todo!() });
1979
1980        fn my_command(_world: &mut World) {
1981            todo!()
1982        }
1983
1984        world.commands().queue(my_command);
1985        world.commands().queue(|_world: &mut World| {});
1986        world.commands().queue(|_world: &mut World| todo!());
1987        world
1988            .commands()
1989            .queue(|_world: &mut World| -> () { todo!() });
1990    }
1991
1992    #[test]
1993    fn with_input() {
1994        fn sys(InMut(v): InMut<usize>) {
1995            *v += 1;
1996        }
1997
1998        let mut world = World::new();
1999        let mut system = IntoSystem::into_system(sys.with_input(42));
2000        system.initialize(&mut world);
2001        system.run((), &mut world).unwrap();
2002        assert_eq!(*system.value(), 43);
2003    }
2004
2005    #[test]
2006    fn with_input_from() {
2007        struct TestData(usize);
2008
2009        impl FromWorld for TestData {
2010            fn from_world(_world: &mut World) -> Self {
2011                Self(5)
2012            }
2013        }
2014
2015        fn sys(InMut(v): InMut<TestData>) {
2016            v.0 += 1;
2017        }
2018
2019        let mut world = World::new();
2020        let mut system = IntoSystem::into_system(sys.with_input_from::<TestData>());
2021        assert!(system.value().is_none());
2022        system.initialize(&mut world);
2023        assert!(system.value().is_some());
2024        system.run((), &mut world).unwrap();
2025        assert_eq!(system.value().unwrap().0, 6);
2026    }
2027}