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