bevy_ecs/system/
function_system.rs

1use crate::{
2    archetype::{ArchetypeComponentId, ArchetypeGeneration},
3    component::{ComponentId, Tick},
4    prelude::FromWorld,
5    query::{Access, FilteredAccessSet},
6    schedule::{InternedSystemSet, SystemSet},
7    system::{
8        check_system_change_tick, ReadOnlySystemParam, System, SystemIn, SystemInput, SystemParam,
9        SystemParamItem,
10    },
11    world::{unsafe_world_cell::UnsafeWorldCell, DeferredWorld, World, WorldId},
12};
13
14use alloc::borrow::Cow;
15use bevy_utils::all_tuples;
16use core::marker::PhantomData;
17
18#[cfg(feature = "trace")]
19use bevy_utils::tracing::{info_span, Span};
20
21use super::{In, IntoSystem, ReadOnlySystem, SystemParamBuilder};
22
23/// The metadata of a [`System`].
24#[derive(Clone)]
25pub struct SystemMeta {
26    pub(crate) name: Cow<'static, str>,
27    /// The set of component accesses for this system. This is used to determine
28    /// - soundness issues (e.g. multiple [`SystemParam`]s mutably accessing the same component)
29    /// - ambiguities in the schedule (e.g. two systems that have some sort of conflicting access)
30    pub(crate) component_access_set: FilteredAccessSet<ComponentId>,
31    /// This [`Access`] is used to determine which systems can run in parallel with each other
32    /// in the multithreaded executor.
33    ///
34    /// We use a [`ArchetypeComponentId`] as it is more precise than just checking [`ComponentId`]:
35    /// for example if you have one system with `Query<&mut T, With<A>>` and one system with `Query<&mut T, With<B>>`
36    /// they conflict if you just look at the [`ComponentId`] of `T`; but if there are no archetypes with
37    /// both `A`, `B` and `T` then in practice there's no risk of conflict. By using [`ArchetypeComponentId`]
38    /// we can be more precise because we can check if the existing archetypes of the [`World`]
39    /// cause a conflict
40    pub(crate) archetype_component_access: Access<ArchetypeComponentId>,
41    // NOTE: this must be kept private. making a SystemMeta non-send is irreversible to prevent
42    // SystemParams from overriding each other
43    is_send: bool,
44    has_deferred: bool,
45    pub(crate) last_run: Tick,
46    param_warn_policy: ParamWarnPolicy,
47    #[cfg(feature = "trace")]
48    pub(crate) system_span: Span,
49    #[cfg(feature = "trace")]
50    pub(crate) commands_span: Span,
51}
52
53impl SystemMeta {
54    pub(crate) fn new<T>() -> Self {
55        let name = core::any::type_name::<T>();
56        Self {
57            name: name.into(),
58            archetype_component_access: Access::default(),
59            component_access_set: FilteredAccessSet::default(),
60            is_send: true,
61            has_deferred: false,
62            last_run: Tick::new(0),
63            param_warn_policy: ParamWarnPolicy::Panic,
64            #[cfg(feature = "trace")]
65            system_span: info_span!("system", name = name),
66            #[cfg(feature = "trace")]
67            commands_span: info_span!("system_commands", name = name),
68        }
69    }
70
71    /// Returns the system's name
72    #[inline]
73    pub fn name(&self) -> &str {
74        &self.name
75    }
76
77    /// Sets the name of this system.
78    ///
79    /// Useful to give closure systems more readable and unique names for debugging and tracing.
80    #[inline]
81    pub fn set_name(&mut self, new_name: impl Into<Cow<'static, str>>) {
82        let new_name: Cow<'static, str> = new_name.into();
83        #[cfg(feature = "trace")]
84        {
85            let name = new_name.as_ref();
86            self.system_span = info_span!("system", name = name);
87            self.commands_span = info_span!("system_commands", name = name);
88        }
89        self.name = new_name;
90    }
91
92    /// Returns true if the system is [`Send`].
93    #[inline]
94    pub fn is_send(&self) -> bool {
95        self.is_send
96    }
97
98    /// Sets the system to be not [`Send`].
99    ///
100    /// This is irreversible.
101    #[inline]
102    pub fn set_non_send(&mut self) {
103        self.is_send = false;
104    }
105
106    /// Returns true if the system has deferred [`SystemParam`]'s
107    #[inline]
108    pub fn has_deferred(&self) -> bool {
109        self.has_deferred
110    }
111
112    /// Marks the system as having deferred buffers like [`Commands`](`super::Commands`)
113    /// This lets the scheduler insert [`apply_deferred`](`crate::prelude::apply_deferred`) systems automatically.
114    #[inline]
115    pub fn set_has_deferred(&mut self) {
116        self.has_deferred = true;
117    }
118
119    /// Changes the warn policy.
120    #[inline]
121    pub(crate) fn set_param_warn_policy(&mut self, warn_policy: ParamWarnPolicy) {
122        self.param_warn_policy = warn_policy;
123    }
124
125    /// Advances the warn policy after validation failed.
126    #[inline]
127    pub(crate) fn advance_param_warn_policy(&mut self) {
128        self.param_warn_policy.advance();
129    }
130
131    /// Emits a warning about inaccessible system param if policy allows it.
132    #[inline]
133    pub fn try_warn_param<P>(&self)
134    where
135        P: SystemParam,
136    {
137        self.param_warn_policy.try_warn::<P>(&self.name);
138    }
139
140    /// Archetype component access that is used to determine which systems can run in parallel with each other
141    /// in the multithreaded executor.
142    ///
143    /// We use an [`ArchetypeComponentId`] as it is more precise than just checking [`ComponentId`]:
144    /// for example if you have one system with `Query<&mut A, With<B>`, and one system with `Query<&mut A, Without<B>`,
145    /// they conflict if you just look at the [`ComponentId`];
146    /// but no archetype that matches the first query will match the second and vice versa,
147    /// which means there's no risk of conflict.
148    #[inline]
149    pub fn archetype_component_access(&self) -> &Access<ArchetypeComponentId> {
150        &self.archetype_component_access
151    }
152
153    /// Returns a mutable reference to the [`Access`] for [`ArchetypeComponentId`].
154    /// This is used to determine which systems can run in parallel with each other
155    /// in the multithreaded executor.
156    ///
157    /// We use an [`ArchetypeComponentId`] as it is more precise than just checking [`ComponentId`]:
158    /// for example if you have one system with `Query<&mut A, With<B>`, and one system with `Query<&mut A, Without<B>`,
159    /// they conflict if you just look at the [`ComponentId`];
160    /// but no archetype that matches the first query will match the second and vice versa,
161    /// which means there's no risk of conflict.
162    ///
163    /// # Safety
164    ///
165    /// No access can be removed from the returned [`Access`].
166    #[inline]
167    pub unsafe fn archetype_component_access_mut(&mut self) -> &mut Access<ArchetypeComponentId> {
168        &mut self.archetype_component_access
169    }
170
171    /// Returns a reference to the [`FilteredAccessSet`] for [`ComponentId`].
172    /// Used to check if systems and/or system params have conflicting access.
173    #[inline]
174    pub fn component_access_set(&self) -> &FilteredAccessSet<ComponentId> {
175        &self.component_access_set
176    }
177
178    /// Returns a mutable reference to the [`FilteredAccessSet`] for [`ComponentId`].
179    /// Used internally to statically check if systems have conflicting access.
180    ///
181    /// # Safety
182    ///
183    /// No access can be removed from the returned [`FilteredAccessSet`].
184    #[inline]
185    pub unsafe fn component_access_set_mut(&mut self) -> &mut FilteredAccessSet<ComponentId> {
186        &mut self.component_access_set
187    }
188}
189
190/// State machine for emitting warnings when [system params are invalid](System::validate_param).
191#[derive(Clone, Copy)]
192pub enum ParamWarnPolicy {
193    /// Stop app with a panic.
194    Panic,
195    /// No warning should ever be emitted.
196    Never,
197    /// The warning will be emitted once and status will update to [`Self::Never`].
198    Once,
199}
200
201impl ParamWarnPolicy {
202    /// Advances the warn policy after validation failed.
203    #[inline]
204    fn advance(&mut self) {
205        // Ignore `Panic` case, because it stops execution before this function gets called.
206        *self = Self::Never;
207    }
208
209    /// Emits a warning about inaccessible system param if policy allows it.
210    #[inline]
211    fn try_warn<P>(&self, name: &str)
212    where
213        P: SystemParam,
214    {
215        match self {
216            Self::Panic => panic!(
217                "{0} could not access system parameter {1}",
218                name,
219                disqualified::ShortName::of::<P>()
220            ),
221            Self::Once => {
222                bevy_utils::tracing::warn!(
223                    "{0} did not run because it requested inaccessible system parameter {1}",
224                    name,
225                    disqualified::ShortName::of::<P>()
226                );
227            }
228            Self::Never => {}
229        }
230    }
231}
232
233/// Trait for manipulating warn policy of systems.
234#[doc(hidden)]
235pub trait WithParamWarnPolicy<M, F>
236where
237    M: 'static,
238    F: SystemParamFunction<M>,
239    Self: Sized,
240{
241    /// Set warn policy.
242    fn with_param_warn_policy(self, warn_policy: ParamWarnPolicy) -> FunctionSystem<M, F>;
243
244    /// Warn only once about invalid system parameters.
245    fn param_warn_once(self) -> FunctionSystem<M, F> {
246        self.with_param_warn_policy(ParamWarnPolicy::Once)
247    }
248
249    /// Disable all param warnings.
250    fn never_param_warn(self) -> FunctionSystem<M, F> {
251        self.with_param_warn_policy(ParamWarnPolicy::Never)
252    }
253}
254
255impl<M, F> WithParamWarnPolicy<M, F> for F
256where
257    M: 'static,
258    F: SystemParamFunction<M>,
259{
260    fn with_param_warn_policy(self, param_warn_policy: ParamWarnPolicy) -> FunctionSystem<M, F> {
261        let mut system = IntoSystem::into_system(self);
262        system.system_meta.set_param_warn_policy(param_warn_policy);
263        system
264    }
265}
266
267// TODO: Actually use this in FunctionSystem. We should probably only do this once Systems are constructed using a World reference
268// (to avoid the need for unwrapping to retrieve SystemMeta)
269/// Holds on to persistent state required to drive [`SystemParam`] for a [`System`].
270///
271/// This is a powerful and convenient tool for working with exclusive world access,
272/// allowing you to fetch data from the [`World`] as if you were running a [`System`].
273/// However, simply calling `world::run_system(my_system)` using a [`World::run_system`](World::run_system)
274/// can be significantly simpler and ensures that change detection and command flushing work as expected.
275///
276/// Borrow-checking is handled for you, allowing you to mutably access multiple compatible system parameters at once,
277/// and arbitrary system parameters (like [`EventWriter`](crate::event::EventWriter)) can be conveniently fetched.
278///
279/// For an alternative approach to split mutable access to the world, see [`World::resource_scope`].
280///
281/// # Warning
282///
283/// [`SystemState`] values created can be cached to improve performance,
284/// and *must* be cached and reused in order for system parameters that rely on local state to work correctly.
285/// These include:
286/// - [`Added`](crate::query::Added) and [`Changed`](crate::query::Changed) query filters
287/// - [`Local`](crate::system::Local) variables that hold state
288/// - [`EventReader`](crate::event::EventReader) system parameters, which rely on a [`Local`](crate::system::Local) to track which events have been seen
289///
290/// Note that this is automatically handled for you when using a [`World::run_system`](World::run_system).
291///
292/// # Example
293///
294/// Basic usage:
295/// ```
296/// # use bevy_ecs::prelude::*;
297/// # use bevy_ecs::system::SystemState;
298/// # use bevy_ecs::event::Events;
299/// #
300/// # #[derive(Event)]
301/// # struct MyEvent;
302/// # #[derive(Resource)]
303/// # struct MyResource(u32);
304/// #
305/// # #[derive(Component)]
306/// # struct MyComponent;
307/// #
308/// // Work directly on the `World`
309/// let mut world = World::new();
310/// world.init_resource::<Events<MyEvent>>();
311///
312/// // Construct a `SystemState` struct, passing in a tuple of `SystemParam`
313/// // as if you were writing an ordinary system.
314/// let mut system_state: SystemState<(
315///     EventWriter<MyEvent>,
316///     Option<ResMut<MyResource>>,
317///     Query<&MyComponent>,
318/// )> = SystemState::new(&mut world);
319///
320/// // Use system_state.get_mut(&mut world) and unpack your system parameters into variables!
321/// // system_state.get(&world) provides read-only versions of your system parameters instead.
322/// let (event_writer, maybe_resource, query) = system_state.get_mut(&mut world);
323///
324/// // If you are using `Commands`, you can choose when you want to apply them to the world.
325/// // You need to manually call `.apply(world)` on the `SystemState` to apply them.
326/// ```
327/// Caching:
328/// ```
329/// # use bevy_ecs::prelude::*;
330/// # use bevy_ecs::system::SystemState;
331/// # use bevy_ecs::event::Events;
332/// #
333/// # #[derive(Event)]
334/// # struct MyEvent;
335/// #[derive(Resource)]
336/// struct CachedSystemState {
337///     event_state: SystemState<EventReader<'static, 'static, MyEvent>>,
338/// }
339///
340/// // Create and store a system state once
341/// let mut world = World::new();
342/// world.init_resource::<Events<MyEvent>>();
343/// let initial_state: SystemState<EventReader<MyEvent>> = SystemState::new(&mut world);
344///
345/// // The system state is cached in a resource
346/// world.insert_resource(CachedSystemState {
347///     event_state: initial_state,
348/// });
349///
350/// // Later, fetch the cached system state, saving on overhead
351/// world.resource_scope(|world, mut cached_state: Mut<CachedSystemState>| {
352///     let mut event_reader = cached_state.event_state.get_mut(world);
353///
354///     for events in event_reader.read() {
355///         println!("Hello World!");
356///     }
357/// });
358/// ```
359pub struct SystemState<Param: SystemParam + 'static> {
360    meta: SystemMeta,
361    param_state: Param::State,
362    world_id: WorldId,
363    archetype_generation: ArchetypeGeneration,
364}
365
366// Allow closure arguments to be inferred.
367// For a closure to be used as a `SystemParamFunction`, it needs to be generic in any `'w` or `'s` lifetimes.
368// Rust will only infer a closure to be generic over lifetimes if it's passed to a function with a Fn constraint.
369// So, generate a function for each arity with an explicit `FnMut` constraint to enable higher-order lifetimes,
370// along with a regular `SystemParamFunction` constraint to allow the system to be built.
371macro_rules! impl_build_system {
372    ($(#[$meta:meta])* $($param: ident),*) => {
373        $(#[$meta])*
374        impl<$($param: SystemParam),*> SystemState<($($param,)*)> {
375            /// Create a [`FunctionSystem`] from a [`SystemState`].
376            /// This method signature allows type inference of closure parameters for a system with no input.
377            /// You can use [`SystemState::build_system_with_input()`] if you have input, or [`SystemState::build_any_system()`] if you don't need type inference.
378            pub fn build_system<
379                Out: 'static,
380                Marker,
381                F: FnMut($(SystemParamItem<$param>),*) -> Out
382                    + SystemParamFunction<Marker, Param = ($($param,)*), In = (), Out = Out>
383            >
384            (
385                self,
386                func: F,
387            ) -> FunctionSystem<Marker, F>
388            {
389                self.build_any_system(func)
390            }
391
392            /// Create a [`FunctionSystem`] from a [`SystemState`].
393            /// This method signature allows type inference of closure parameters for a system with input.
394            /// You can use [`SystemState::build_system()`] if you have no input, or [`SystemState::build_any_system()`] if you don't need type inference.
395            pub fn build_system_with_input<
396                Input: SystemInput,
397                Out: 'static,
398                Marker,
399                F: FnMut(In<Input>, $(SystemParamItem<$param>),*) -> Out
400                    + SystemParamFunction<Marker, Param = ($($param,)*), In = Input, Out = Out>,
401            >(
402                self,
403                func: F,
404            ) -> FunctionSystem<Marker, F> {
405                self.build_any_system(func)
406            }
407        }
408    }
409}
410
411all_tuples!(
412    #[doc(fake_variadic)]
413    impl_build_system,
414    0,
415    16,
416    P
417);
418
419impl<Param: SystemParam> SystemState<Param> {
420    /// Creates a new [`SystemState`] with default state.
421    ///
422    /// ## Note
423    /// For users of [`SystemState::get_manual`] or [`get_manual_mut`](SystemState::get_manual_mut):
424    ///
425    /// `new` does not cache any of the world's archetypes, so you must call [`SystemState::update_archetypes`]
426    /// manually before calling `get_manual{_mut}`.
427    pub fn new(world: &mut World) -> Self {
428        let mut meta = SystemMeta::new::<Param>();
429        meta.last_run = world.change_tick().relative_to(Tick::MAX);
430        let param_state = Param::init_state(world, &mut meta);
431        Self {
432            meta,
433            param_state,
434            world_id: world.id(),
435            archetype_generation: ArchetypeGeneration::initial(),
436        }
437    }
438
439    /// Create a [`SystemState`] from a [`SystemParamBuilder`]
440    pub(crate) fn from_builder(world: &mut World, builder: impl SystemParamBuilder<Param>) -> Self {
441        let mut meta = SystemMeta::new::<Param>();
442        meta.last_run = world.change_tick().relative_to(Tick::MAX);
443        let param_state = builder.build(world, &mut meta);
444        Self {
445            meta,
446            param_state,
447            world_id: world.id(),
448            archetype_generation: ArchetypeGeneration::initial(),
449        }
450    }
451
452    /// Create a [`FunctionSystem`] from a [`SystemState`].
453    /// This method signature allows any system function, but the compiler will not perform type inference on closure parameters.
454    /// You can use [`SystemState::build_system()`] or [`SystemState::build_system_with_input()`] to get type inference on parameters.
455    pub fn build_any_system<Marker, F: SystemParamFunction<Marker, Param = Param>>(
456        self,
457        func: F,
458    ) -> FunctionSystem<Marker, F> {
459        FunctionSystem {
460            func,
461            param_state: Some(self.param_state),
462            system_meta: self.meta,
463            world_id: Some(self.world_id),
464            archetype_generation: self.archetype_generation,
465            marker: PhantomData,
466        }
467    }
468
469    /// Gets the metadata for this instance.
470    #[inline]
471    pub fn meta(&self) -> &SystemMeta {
472        &self.meta
473    }
474
475    /// Retrieve the [`SystemParam`] values. This can only be called when all parameters are read-only.
476    #[inline]
477    pub fn get<'w, 's>(&'s mut self, world: &'w World) -> SystemParamItem<'w, 's, Param>
478    where
479        Param: ReadOnlySystemParam,
480    {
481        self.validate_world(world.id());
482        self.update_archetypes(world);
483        // SAFETY: Param is read-only and doesn't allow mutable access to World.
484        // It also matches the World this SystemState was created with.
485        unsafe { self.get_unchecked_manual(world.as_unsafe_world_cell_readonly()) }
486    }
487
488    /// Retrieve the mutable [`SystemParam`] values.
489    #[inline]
490    pub fn get_mut<'w, 's>(&'s mut self, world: &'w mut World) -> SystemParamItem<'w, 's, Param> {
491        self.validate_world(world.id());
492        self.update_archetypes(world);
493        // SAFETY: World is uniquely borrowed and matches the World this SystemState was created with.
494        unsafe { self.get_unchecked_manual(world.as_unsafe_world_cell()) }
495    }
496
497    /// Applies all state queued up for [`SystemParam`] values. For example, this will apply commands queued up
498    /// by a [`Commands`](`super::Commands`) parameter to the given [`World`].
499    /// This function should be called manually after the values returned by [`SystemState::get`] and [`SystemState::get_mut`]
500    /// are finished being used.
501    pub fn apply(&mut self, world: &mut World) {
502        Param::apply(&mut self.param_state, &self.meta, world);
503    }
504
505    /// Wrapper over [`SystemParam::validate_param`].
506    ///
507    /// # Safety
508    ///
509    /// - The passed [`UnsafeWorldCell`] must have read-only access to
510    ///   world data in `archetype_component_access`.
511    /// - `world` must be the same [`World`] that was used to initialize [`state`](SystemParam::init_state).
512    pub unsafe fn validate_param(state: &Self, world: UnsafeWorldCell) -> bool {
513        // SAFETY: Delegated to existing `SystemParam` implementations.
514        unsafe { Param::validate_param(&state.param_state, &state.meta, world) }
515    }
516
517    /// Returns `true` if `world_id` matches the [`World`] that was used to call [`SystemState::new`].
518    /// Otherwise, this returns false.
519    #[inline]
520    pub fn matches_world(&self, world_id: WorldId) -> bool {
521        self.world_id == world_id
522    }
523
524    /// Asserts that the [`SystemState`] matches the provided world.
525    #[inline]
526    #[track_caller]
527    fn validate_world(&self, world_id: WorldId) {
528        #[inline(never)]
529        #[track_caller]
530        #[cold]
531        fn panic_mismatched(this: WorldId, other: WorldId) -> ! {
532            panic!("Encountered a mismatched World. This SystemState was created from {this:?}, but a method was called using {other:?}.");
533        }
534
535        if !self.matches_world(world_id) {
536            panic_mismatched(self.world_id, world_id);
537        }
538    }
539
540    /// Updates the state's internal view of the [`World`]'s archetypes. If this is not called before fetching the parameters,
541    /// the results may not accurately reflect what is in the `world`.
542    ///
543    /// This is only required if [`SystemState::get_manual`] or [`SystemState::get_manual_mut`] is being called, and it only needs to
544    /// be called if the `world` has been structurally mutated (i.e. added/removed a component or resource). Users using
545    /// [`SystemState::get`] or [`SystemState::get_mut`] do not need to call this as it will be automatically called for them.
546    #[inline]
547    pub fn update_archetypes(&mut self, world: &World) {
548        self.update_archetypes_unsafe_world_cell(world.as_unsafe_world_cell_readonly());
549    }
550
551    /// Updates the state's internal view of the `world`'s archetypes. If this is not called before fetching the parameters,
552    /// the results may not accurately reflect what is in the `world`.
553    ///
554    /// This is only required if [`SystemState::get_manual`] or [`SystemState::get_manual_mut`] is being called, and it only needs to
555    /// be called if the `world` has been structurally mutated (i.e. added/removed a component or resource). Users using
556    /// [`SystemState::get`] or [`SystemState::get_mut`] do not need to call this as it will be automatically called for them.
557    ///
558    /// # Note
559    ///
560    /// This method only accesses world metadata.
561    #[inline]
562    pub fn update_archetypes_unsafe_world_cell(&mut self, world: UnsafeWorldCell) {
563        assert_eq!(self.world_id, world.id(), "Encountered a mismatched World. A System cannot be used with Worlds other than the one it was initialized with.");
564
565        let archetypes = world.archetypes();
566        let old_generation =
567            core::mem::replace(&mut self.archetype_generation, archetypes.generation());
568
569        for archetype in &archetypes[old_generation..] {
570            // SAFETY: The assertion above ensures that the param_state was initialized from `world`.
571            unsafe { Param::new_archetype(&mut self.param_state, archetype, &mut self.meta) };
572        }
573    }
574
575    /// Retrieve the [`SystemParam`] values. This can only be called when all parameters are read-only.
576    /// This will not update the state's view of the world's archetypes automatically nor increment the
577    /// world's change tick.
578    ///
579    /// For this to return accurate results, ensure [`SystemState::update_archetypes`] is called before this
580    /// function.
581    ///
582    /// Users should strongly prefer to use [`SystemState::get`] over this function.
583    #[inline]
584    pub fn get_manual<'w, 's>(&'s mut self, world: &'w World) -> SystemParamItem<'w, 's, Param>
585    where
586        Param: ReadOnlySystemParam,
587    {
588        self.validate_world(world.id());
589        let change_tick = world.read_change_tick();
590        // SAFETY: Param is read-only and doesn't allow mutable access to World.
591        // It also matches the World this SystemState was created with.
592        unsafe { self.fetch(world.as_unsafe_world_cell_readonly(), change_tick) }
593    }
594
595    /// Retrieve the mutable [`SystemParam`] values.  This will not update the state's view of the world's archetypes
596    /// automatically nor increment the world's change tick.
597    ///
598    /// For this to return accurate results, ensure [`SystemState::update_archetypes`] is called before this
599    /// function.
600    ///
601    /// Users should strongly prefer to use [`SystemState::get_mut`] over this function.
602    #[inline]
603    pub fn get_manual_mut<'w, 's>(
604        &'s mut self,
605        world: &'w mut World,
606    ) -> SystemParamItem<'w, 's, Param> {
607        self.validate_world(world.id());
608        let change_tick = world.change_tick();
609        // SAFETY: World is uniquely borrowed and matches the World this SystemState was created with.
610        unsafe { self.fetch(world.as_unsafe_world_cell(), change_tick) }
611    }
612
613    /// Retrieve the [`SystemParam`] values. This will not update archetypes automatically.
614    ///
615    /// # Safety
616    /// This call might access any of the input parameters in a way that violates Rust's mutability rules. Make sure the data
617    /// access is safe in the context of global [`World`] access. The passed-in [`World`] _must_ be the [`World`] the [`SystemState`] was
618    /// created with.
619    #[inline]
620    pub unsafe fn get_unchecked_manual<'w, 's>(
621        &'s mut self,
622        world: UnsafeWorldCell<'w>,
623    ) -> SystemParamItem<'w, 's, Param> {
624        let change_tick = world.increment_change_tick();
625        // SAFETY: The invariants are uphold by the caller.
626        unsafe { self.fetch(world, change_tick) }
627    }
628
629    /// # Safety
630    /// This call might access any of the input parameters in a way that violates Rust's mutability rules. Make sure the data
631    /// access is safe in the context of global [`World`] access. The passed-in [`World`] _must_ be the [`World`] the [`SystemState`] was
632    /// created with.
633    #[inline]
634    unsafe fn fetch<'w, 's>(
635        &'s mut self,
636        world: UnsafeWorldCell<'w>,
637        change_tick: Tick,
638    ) -> SystemParamItem<'w, 's, Param> {
639        // SAFETY: The invariants are uphold by the caller.
640        let param =
641            unsafe { Param::get_param(&mut self.param_state, &self.meta, world, change_tick) };
642        self.meta.last_run = change_tick;
643        param
644    }
645}
646
647impl<Param: SystemParam> FromWorld for SystemState<Param> {
648    fn from_world(world: &mut World) -> Self {
649        Self::new(world)
650    }
651}
652
653/// The [`System`] counter part of an ordinary function.
654///
655/// You get this by calling [`IntoSystem::into_system`]  on a function that only accepts
656/// [`SystemParam`]s. The output of the system becomes the functions return type, while the input
657/// becomes the functions [`In`] tagged parameter or `()` if no such parameter exists.
658///
659/// [`FunctionSystem`] must be `.initialized` before they can be run.
660///
661/// The [`Clone`] implementation for [`FunctionSystem`] returns a new instance which
662/// is NOT initialized. The cloned system must also be `.initialized` before it can be run.
663pub struct FunctionSystem<Marker, F>
664where
665    F: SystemParamFunction<Marker>,
666{
667    func: F,
668    pub(crate) param_state: Option<<F::Param as SystemParam>::State>,
669    pub(crate) system_meta: SystemMeta,
670    world_id: Option<WorldId>,
671    archetype_generation: ArchetypeGeneration,
672    // NOTE: PhantomData<fn()-> T> gives this safe Send/Sync impls
673    marker: PhantomData<fn() -> Marker>,
674}
675
676impl<Marker, F> FunctionSystem<Marker, F>
677where
678    F: SystemParamFunction<Marker>,
679{
680    /// Return this system with a new name.
681    ///
682    /// Useful to give closure systems more readable and unique names for debugging and tracing.
683    pub fn with_name(mut self, new_name: impl Into<Cow<'static, str>>) -> Self {
684        self.system_meta.set_name(new_name.into());
685        self
686    }
687}
688
689// De-initializes the cloned system.
690impl<Marker, F> Clone for FunctionSystem<Marker, F>
691where
692    F: SystemParamFunction<Marker> + Clone,
693{
694    fn clone(&self) -> Self {
695        Self {
696            func: self.func.clone(),
697            param_state: None,
698            system_meta: SystemMeta::new::<F>(),
699            world_id: None,
700            archetype_generation: ArchetypeGeneration::initial(),
701            marker: PhantomData,
702        }
703    }
704}
705
706/// A marker type used to distinguish regular function systems from exclusive function systems.
707#[doc(hidden)]
708pub struct IsFunctionSystem;
709
710impl<Marker, F> IntoSystem<F::In, F::Out, (IsFunctionSystem, Marker)> for F
711where
712    Marker: 'static,
713    F: SystemParamFunction<Marker>,
714{
715    type System = FunctionSystem<Marker, F>;
716    fn into_system(func: Self) -> Self::System {
717        FunctionSystem {
718            func,
719            param_state: None,
720            system_meta: SystemMeta::new::<F>(),
721            world_id: None,
722            archetype_generation: ArchetypeGeneration::initial(),
723            marker: PhantomData,
724        }
725    }
726}
727
728impl<Marker, F> FunctionSystem<Marker, F>
729where
730    F: SystemParamFunction<Marker>,
731{
732    /// Message shown when a system isn't initialized
733    // When lines get too long, rustfmt can sometimes refuse to format them.
734    // Work around this by storing the message separately.
735    const PARAM_MESSAGE: &'static str = "System's param_state was not found. Did you forget to initialize this system before running it?";
736}
737
738impl<Marker, F> System for FunctionSystem<Marker, F>
739where
740    Marker: 'static,
741    F: SystemParamFunction<Marker>,
742{
743    type In = F::In;
744    type Out = F::Out;
745
746    #[inline]
747    fn name(&self) -> Cow<'static, str> {
748        self.system_meta.name.clone()
749    }
750
751    #[inline]
752    fn component_access(&self) -> &Access<ComponentId> {
753        self.system_meta.component_access_set.combined_access()
754    }
755
756    #[inline]
757    fn archetype_component_access(&self) -> &Access<ArchetypeComponentId> {
758        &self.system_meta.archetype_component_access
759    }
760
761    #[inline]
762    fn is_send(&self) -> bool {
763        self.system_meta.is_send
764    }
765
766    #[inline]
767    fn is_exclusive(&self) -> bool {
768        false
769    }
770
771    #[inline]
772    fn has_deferred(&self) -> bool {
773        self.system_meta.has_deferred
774    }
775
776    #[inline]
777    unsafe fn run_unsafe(
778        &mut self,
779        input: SystemIn<'_, Self>,
780        world: UnsafeWorldCell,
781    ) -> Self::Out {
782        #[cfg(feature = "trace")]
783        let _span_guard = self.system_meta.system_span.enter();
784
785        let change_tick = world.increment_change_tick();
786
787        // SAFETY:
788        // - The caller has invoked `update_archetype_component_access`, which will panic
789        //   if the world does not match.
790        // - All world accesses used by `F::Param` have been registered, so the caller
791        //   will ensure that there are no data access conflicts.
792        let params = unsafe {
793            F::Param::get_param(
794                self.param_state.as_mut().expect(Self::PARAM_MESSAGE),
795                &self.system_meta,
796                world,
797                change_tick,
798            )
799        };
800        let out = self.func.run(input, params);
801        self.system_meta.last_run = change_tick;
802        out
803    }
804
805    #[inline]
806    fn apply_deferred(&mut self, world: &mut World) {
807        let param_state = self.param_state.as_mut().expect(Self::PARAM_MESSAGE);
808        F::Param::apply(param_state, &self.system_meta, world);
809    }
810
811    #[inline]
812    fn queue_deferred(&mut self, world: DeferredWorld) {
813        let param_state = self.param_state.as_mut().expect(Self::PARAM_MESSAGE);
814        F::Param::queue(param_state, &self.system_meta, world);
815    }
816
817    #[inline]
818    unsafe fn validate_param_unsafe(&mut self, world: UnsafeWorldCell) -> bool {
819        let param_state = self.param_state.as_ref().expect(Self::PARAM_MESSAGE);
820        // SAFETY:
821        // - The caller has invoked `update_archetype_component_access`, which will panic
822        //   if the world does not match.
823        // - All world accesses used by `F::Param` have been registered, so the caller
824        //   will ensure that there are no data access conflicts.
825        let is_valid = unsafe { F::Param::validate_param(param_state, &self.system_meta, world) };
826        if !is_valid {
827            self.system_meta.advance_param_warn_policy();
828        }
829        is_valid
830    }
831
832    #[inline]
833    fn initialize(&mut self, world: &mut World) {
834        if let Some(id) = self.world_id {
835            assert_eq!(
836                id,
837                world.id(),
838                "System built with a different world than the one it was added to.",
839            );
840        } else {
841            self.world_id = Some(world.id());
842            self.param_state = Some(F::Param::init_state(world, &mut self.system_meta));
843        }
844        self.system_meta.last_run = world.change_tick().relative_to(Tick::MAX);
845    }
846
847    fn update_archetype_component_access(&mut self, world: UnsafeWorldCell) {
848        assert_eq!(self.world_id, Some(world.id()), "Encountered a mismatched World. A System cannot be used with Worlds other than the one it was initialized with.");
849        let archetypes = world.archetypes();
850        let old_generation =
851            core::mem::replace(&mut self.archetype_generation, archetypes.generation());
852
853        for archetype in &archetypes[old_generation..] {
854            let param_state = self.param_state.as_mut().unwrap();
855            // SAFETY: The assertion above ensures that the param_state was initialized from `world`.
856            unsafe { F::Param::new_archetype(param_state, archetype, &mut self.system_meta) };
857        }
858    }
859
860    #[inline]
861    fn check_change_tick(&mut self, change_tick: Tick) {
862        check_system_change_tick(
863            &mut self.system_meta.last_run,
864            change_tick,
865            self.system_meta.name.as_ref(),
866        );
867    }
868
869    fn default_system_sets(&self) -> Vec<InternedSystemSet> {
870        let set = crate::schedule::SystemTypeSet::<Self>::new();
871        vec![set.intern()]
872    }
873
874    fn get_last_run(&self) -> Tick {
875        self.system_meta.last_run
876    }
877
878    fn set_last_run(&mut self, last_run: Tick) {
879        self.system_meta.last_run = last_run;
880    }
881}
882
883/// SAFETY: `F`'s param is [`ReadOnlySystemParam`], so this system will only read from the world.
884unsafe impl<Marker, F> ReadOnlySystem for FunctionSystem<Marker, F>
885where
886    Marker: 'static,
887    F: SystemParamFunction<Marker>,
888    F::Param: ReadOnlySystemParam,
889{
890}
891
892/// A trait implemented for all functions that can be used as [`System`]s.
893///
894/// This trait can be useful for making your own systems which accept other systems,
895/// sometimes called higher order systems.
896///
897/// This should be used in combination with [`ParamSet`] when calling other systems
898/// within your system.
899/// Using [`ParamSet`] in this case avoids [`SystemParam`] collisions.
900///
901/// # Example
902///
903/// To create something like [`PipeSystem`], but in entirely safe code.
904///
905/// ```
906/// use std::num::ParseIntError;
907///
908/// use bevy_ecs::prelude::*;
909/// use bevy_ecs::system::StaticSystemInput;
910///
911/// /// Pipe creates a new system which calls `a`, then calls `b` with the output of `a`
912/// pub fn pipe<A, B, AMarker, BMarker>(
913///     mut a: A,
914///     mut b: B,
915/// ) -> impl FnMut(StaticSystemInput<A::In>, ParamSet<(A::Param, B::Param)>) -> B::Out
916/// where
917///     // We need A and B to be systems, add those bounds
918///     A: SystemParamFunction<AMarker>,
919///     B: SystemParamFunction<BMarker>,
920///     for<'a> B::In: SystemInput<Inner<'a> = A::Out>,
921/// {
922///     // The type of `params` is inferred based on the return of this function above
923///     move |StaticSystemInput(a_in), mut params| {
924///         let shared = a.run(a_in, params.p0());
925///         b.run(shared, params.p1())
926///     }
927/// }
928///
929/// // Usage example for `pipe`:
930/// fn main() {
931///     let mut world = World::default();
932///     world.insert_resource(Message("42".to_string()));
933///
934///     // pipe the `parse_message_system`'s output into the `filter_system`s input
935///     let mut piped_system = IntoSystem::into_system(pipe(parse_message, filter));
936///     piped_system.initialize(&mut world);
937///     assert_eq!(piped_system.run((), &mut world), Some(42));
938/// }
939///
940/// #[derive(Resource)]
941/// struct Message(String);
942///
943/// fn parse_message(message: Res<Message>) -> Result<usize, ParseIntError> {
944///     message.0.parse::<usize>()
945/// }
946///
947/// fn filter(In(result): In<Result<usize, ParseIntError>>) -> Option<usize> {
948///     result.ok().filter(|&n| n < 100)
949/// }
950/// ```
951/// [`PipeSystem`]: crate::system::PipeSystem
952/// [`ParamSet`]: crate::system::ParamSet
953#[diagnostic::on_unimplemented(
954    message = "`{Self}` is not a valid system",
955    label = "invalid system"
956)]
957pub trait SystemParamFunction<Marker>: Send + Sync + 'static {
958    /// The input type of this system. See [`System::In`].
959    type In: SystemInput;
960    /// The return type of this system. See [`System::Out`].
961    type Out;
962
963    /// The [`SystemParam`]/s used by this system to access the [`World`].
964    type Param: SystemParam;
965
966    /// Executes this system once. See [`System::run`] or [`System::run_unsafe`].
967    fn run(
968        &mut self,
969        input: <Self::In as SystemInput>::Inner<'_>,
970        param_value: SystemParamItem<Self::Param>,
971    ) -> Self::Out;
972}
973
974/// A marker type used to distinguish function systems with and without input.
975#[doc(hidden)]
976pub struct HasSystemInput;
977
978macro_rules! impl_system_function {
979    ($($param: ident),*) => {
980        #[allow(non_snake_case)]
981        impl<Out, Func, $($param: SystemParam),*> SystemParamFunction<fn($($param,)*) -> Out> for Func
982        where
983            Func: Send + Sync + 'static,
984            for <'a> &'a mut Func:
985                FnMut($($param),*) -> Out +
986                FnMut($(SystemParamItem<$param>),*) -> Out,
987            Out: 'static
988        {
989            type In = ();
990            type Out = Out;
991            type Param = ($($param,)*);
992            #[inline]
993            fn run(&mut self, _input: (), param_value: SystemParamItem< ($($param,)*)>) -> Out {
994                // Yes, this is strange, but `rustc` fails to compile this impl
995                // without using this function. It fails to recognize that `func`
996                // is a function, potentially because of the multiple impls of `FnMut`
997                #[allow(clippy::too_many_arguments)]
998                fn call_inner<Out, $($param,)*>(
999                    mut f: impl FnMut($($param,)*)->Out,
1000                    $($param: $param,)*
1001                )->Out{
1002                    f($($param,)*)
1003                }
1004                let ($($param,)*) = param_value;
1005                call_inner(self, $($param),*)
1006            }
1007        }
1008
1009        #[allow(non_snake_case)]
1010        impl<In, Out, Func, $($param: SystemParam),*> SystemParamFunction<(HasSystemInput, fn(In, $($param,)*) -> Out)> for Func
1011        where
1012            Func: Send + Sync + 'static,
1013            for <'a> &'a mut Func:
1014                FnMut(In, $($param),*) -> Out +
1015                FnMut(In::Param<'_>, $(SystemParamItem<$param>),*) -> Out,
1016            In: SystemInput + 'static,
1017            Out: 'static
1018        {
1019            type In = In;
1020            type Out = Out;
1021            type Param = ($($param,)*);
1022            #[inline]
1023            fn run(&mut self, input: In::Inner<'_>, param_value: SystemParamItem< ($($param,)*)>) -> Out {
1024                #[allow(clippy::too_many_arguments)]
1025                fn call_inner<In: SystemInput, Out, $($param,)*>(
1026                    mut f: impl FnMut(In::Param<'_>, $($param,)*)->Out,
1027                    input: In::Inner<'_>,
1028                    $($param: $param,)*
1029                )->Out{
1030                    f(In::wrap(input), $($param,)*)
1031                }
1032                let ($($param,)*) = param_value;
1033                call_inner(self, input, $($param),*)
1034            }
1035        }
1036    };
1037}
1038
1039// Note that we rely on the highest impl to be <= the highest order of the tuple impls
1040// of `SystemParam` created.
1041all_tuples!(impl_system_function, 0, 16, F);
1042
1043#[cfg(test)]
1044mod tests {
1045    use super::*;
1046
1047    #[test]
1048    fn into_system_type_id_consistency() {
1049        fn test<T, In: SystemInput, Out, Marker>(function: T)
1050        where
1051            T: IntoSystem<In, Out, Marker> + Copy,
1052        {
1053            fn reference_system() {}
1054
1055            use core::any::TypeId;
1056
1057            let system = IntoSystem::into_system(function);
1058
1059            assert_eq!(
1060                system.type_id(),
1061                function.system_type_id(),
1062                "System::type_id should be consistent with IntoSystem::system_type_id"
1063            );
1064
1065            assert_eq!(
1066                system.type_id(),
1067                TypeId::of::<T::System>(),
1068                "System::type_id should be consistent with TypeId::of::<T::System>()"
1069            );
1070
1071            assert_ne!(
1072                system.type_id(),
1073                IntoSystem::into_system(reference_system).type_id(),
1074                "Different systems should have different TypeIds"
1075            );
1076        }
1077
1078        fn function_system() {}
1079
1080        test(function_system);
1081    }
1082}