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