bevy_ecs/system/
function_system.rs

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