bevy_ecs/system/
system_param.rs

1pub use crate::change_detection::{NonSendMut, Res, ResMut};
2use crate::{
3    archetype::{Archetype, Archetypes},
4    bundle::Bundles,
5    change_detection::{MaybeLocation, Ticks, TicksMut},
6    component::{ComponentId, ComponentTicks, Components, Tick},
7    entity::Entities,
8    query::{
9        Access, FilteredAccess, FilteredAccessSet, QueryData, QueryFilter, QuerySingleError,
10        QueryState, ReadOnlyQueryData,
11    },
12    resource::Resource,
13    storage::ResourceData,
14    system::{Query, Single, SystemMeta},
15    world::{
16        unsafe_world_cell::UnsafeWorldCell, DeferredWorld, FilteredResources, FilteredResourcesMut,
17        FromWorld, World,
18    },
19};
20use alloc::{
21    borrow::{Cow, ToOwned},
22    boxed::Box,
23    vec::Vec,
24};
25pub use bevy_ecs_macros::SystemParam;
26use bevy_ptr::UnsafeCellDeref;
27use bevy_utils::synccell::SyncCell;
28use core::{
29    any::Any,
30    fmt::{Debug, Display},
31    marker::PhantomData,
32    ops::{Deref, DerefMut},
33    panic::Location,
34};
35use disqualified::ShortName;
36use thiserror::Error;
37
38use super::Populated;
39use variadics_please::{all_tuples, all_tuples_enumerated};
40
41/// A parameter that can be used in a [`System`](super::System).
42///
43/// # Derive
44///
45/// This trait can be derived with the [`derive@super::SystemParam`] macro.
46/// This macro only works if each field on the derived struct implements [`SystemParam`].
47/// Note: There are additional requirements on the field types.
48/// See the *Generic `SystemParam`s* section for details and workarounds of the probable
49/// cause if this derive causes an error to be emitted.
50///
51/// Derived `SystemParam` structs may have two lifetimes: `'w` for data stored in the [`World`],
52/// and `'s` for data stored in the parameter's state.
53///
54/// The following list shows the most common [`SystemParam`]s and which lifetime they require
55///
56/// ```
57/// # use bevy_ecs::prelude::*;
58/// # #[derive(Resource)]
59/// # struct SomeResource;
60/// # #[derive(Event)]
61/// # struct SomeEvent;
62/// # #[derive(Resource)]
63/// # struct SomeOtherResource;
64/// # use bevy_ecs::system::SystemParam;
65/// # #[derive(SystemParam)]
66/// # struct ParamsExample<'w, 's> {
67/// #    query:
68/// Query<'w, 's, Entity>,
69/// #    res:
70/// Res<'w, SomeResource>,
71/// #    res_mut:
72/// ResMut<'w, SomeOtherResource>,
73/// #    local:
74/// Local<'s, u8>,
75/// #    commands:
76/// Commands<'w, 's>,
77/// #    eventreader:
78/// EventReader<'w, 's, SomeEvent>,
79/// #    eventwriter:
80/// EventWriter<'w, SomeEvent>
81/// # }
82/// ```
83/// ## `PhantomData`
84///
85/// [`PhantomData`] is a special type of `SystemParam` that does nothing.
86/// This is useful for constraining generic types or lifetimes.
87///
88/// # Example
89///
90/// ```
91/// # use bevy_ecs::prelude::*;
92/// # #[derive(Resource)]
93/// # struct SomeResource;
94/// use std::marker::PhantomData;
95/// use bevy_ecs::system::SystemParam;
96///
97/// #[derive(SystemParam)]
98/// struct MyParam<'w, Marker: 'static> {
99///     foo: Res<'w, SomeResource>,
100///     marker: PhantomData<Marker>,
101/// }
102///
103/// fn my_system<T: 'static>(param: MyParam<T>) {
104///     // Access the resource through `param.foo`
105/// }
106///
107/// # bevy_ecs::system::assert_is_system(my_system::<()>);
108/// ```
109///
110/// # Generic `SystemParam`s
111///
112/// When using the derive macro, you may see an error in the form of:
113///
114/// ```text
115/// expected ... [ParamType]
116/// found associated type `<[ParamType] as SystemParam>::Item<'_, '_>`
117/// ```
118/// where `[ParamType]` is the type of one of your fields.
119/// To solve this error, you can wrap the field of type `[ParamType]` with [`StaticSystemParam`]
120/// (i.e. `StaticSystemParam<[ParamType]>`).
121///
122/// ## Details
123///
124/// The derive macro requires that the [`SystemParam`] implementation of
125/// each field `F`'s [`Item`](`SystemParam::Item`)'s is itself `F`
126/// (ignoring lifetimes for simplicity).
127/// This assumption is due to type inference reasons, so that the derived [`SystemParam`] can be
128/// used as an argument to a function system.
129/// If the compiler cannot validate this property for `[ParamType]`, it will error in the form shown above.
130///
131/// This will most commonly occur when working with `SystemParam`s generically, as the requirement
132/// has not been proven to the compiler.
133///
134/// ## Custom Validation Messages
135///
136/// When using the derive macro, any [`SystemParamValidationError`]s will be propagated from the sub-parameters.
137/// If you want to override the error message, add a `#[system_param(validation_message = "New message")]` attribute to the parameter.
138///
139/// ```
140/// # use bevy_ecs::prelude::*;
141/// # #[derive(Resource)]
142/// # struct SomeResource;
143/// # use bevy_ecs::system::SystemParam;
144/// #
145/// #[derive(SystemParam)]
146/// struct MyParam<'w> {
147///     #[system_param(validation_message = "Custom Message")]
148///     foo: Res<'w, SomeResource>,
149/// }
150///
151/// let mut world = World::new();
152/// let err = world.run_system_cached(|param: MyParam| {}).unwrap_err();
153/// let expected = "Parameter `MyParam::foo` failed validation: Custom Message";
154/// assert!(err.to_string().ends_with(expected));
155/// ```
156///
157/// ## Builders
158///
159/// If you want to use a [`SystemParamBuilder`](crate::system::SystemParamBuilder) with a derived [`SystemParam`] implementation,
160/// add a `#[system_param(builder)]` attribute to the struct.
161/// This will generate a builder struct whose name is the param struct suffixed with `Builder`.
162/// The builder will not be `pub`, so you may want to expose a method that returns an `impl SystemParamBuilder<T>`.
163///
164/// ```
165/// mod custom_param {
166/// #     use bevy_ecs::{
167/// #         prelude::*,
168/// #         system::{LocalBuilder, QueryParamBuilder, SystemParam},
169/// #     };
170/// #
171///     #[derive(SystemParam)]
172///     #[system_param(builder)]
173///     pub struct CustomParam<'w, 's> {
174///         query: Query<'w, 's, ()>,
175///         local: Local<'s, usize>,
176///     }
177///
178///     impl<'w, 's> CustomParam<'w, 's> {
179///         pub fn builder(
180///             local: usize,
181///             query: impl FnOnce(&mut QueryBuilder<()>),
182///         ) -> impl SystemParamBuilder<Self> {
183///             CustomParamBuilder {
184///                 local: LocalBuilder(local),
185///                 query: QueryParamBuilder::new(query),
186///             }
187///         }
188///     }
189/// }
190///
191/// use custom_param::CustomParam;
192///
193/// # use bevy_ecs::prelude::*;
194/// # #[derive(Component)]
195/// # struct A;
196/// #
197/// # let mut world = World::new();
198/// #
199/// let system = (CustomParam::builder(100, |builder| {
200///     builder.with::<A>();
201/// }),)
202///     .build_state(&mut world)
203///     .build_system(|param: CustomParam| {});
204/// ```
205///
206/// # Safety
207///
208/// The implementor must ensure the following is true.
209/// - [`SystemParam::init_state`] correctly registers all [`World`] accesses used
210///   by [`SystemParam::get_param`] with the provided [`system_meta`](SystemMeta).
211/// - None of the world accesses may conflict with any prior accesses registered
212///   on `system_meta`.
213pub unsafe trait SystemParam: Sized {
214    /// Used to store data which persists across invocations of a system.
215    type State: Send + Sync + 'static;
216
217    /// The item type returned when constructing this system param.
218    /// The value of this associated type should be `Self`, instantiated with new lifetimes.
219    ///
220    /// You could think of [`SystemParam::Item<'w, 's>`] as being an *operation* that changes the lifetimes bound to `Self`.
221    type Item<'world, 'state>: SystemParam<State = Self::State>;
222
223    /// Registers any [`World`] access used by this [`SystemParam`]
224    /// and creates a new instance of this param's [`State`](SystemParam::State).
225    fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State;
226
227    /// For the specified [`Archetype`], registers the components accessed by this [`SystemParam`] (if applicable).a
228    ///
229    /// # Safety
230    /// `archetype` must be from the [`World`] used to initialize `state` in [`SystemParam::init_state`].
231    #[inline]
232    #[expect(
233        unused_variables,
234        reason = "The parameters here are intentionally unused by the default implementation; however, putting underscores here will result in the underscores being copied by rust-analyzer's tab completion."
235    )]
236    unsafe fn new_archetype(
237        state: &mut Self::State,
238        archetype: &Archetype,
239        system_meta: &mut SystemMeta,
240    ) {
241    }
242
243    /// Applies any deferred mutations stored in this [`SystemParam`]'s state.
244    /// This is used to apply [`Commands`] during [`ApplyDeferred`](crate::prelude::ApplyDeferred).
245    ///
246    /// [`Commands`]: crate::prelude::Commands
247    #[inline]
248    #[expect(
249        unused_variables,
250        reason = "The parameters here are intentionally unused by the default implementation; however, putting underscores here will result in the underscores being copied by rust-analyzer's tab completion."
251    )]
252    fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {}
253
254    /// Queues any deferred mutations to be applied at the next [`ApplyDeferred`](crate::prelude::ApplyDeferred).
255    #[inline]
256    #[expect(
257        unused_variables,
258        reason = "The parameters here are intentionally unused by the default implementation; however, putting underscores here will result in the underscores being copied by rust-analyzer's tab completion."
259    )]
260    fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {}
261
262    /// Validates that the param can be acquired by the [`get_param`](SystemParam::get_param).
263    ///
264    /// Built-in executors use this to prevent systems with invalid params from running,
265    /// and any failures here will be bubbled up to the default error handler defined in [`bevy_ecs::error`],
266    /// with a value of type [`SystemParamValidationError`].
267    ///
268    /// For nested [`SystemParam`]s validation will fail if any
269    /// delegated validation fails.
270    ///
271    /// However calling and respecting [`SystemParam::validate_param`]
272    /// is not a strict requirement, [`SystemParam::get_param`] should
273    /// provide it's own safety mechanism to prevent undefined behavior.
274    ///
275    /// The [`world`](UnsafeWorldCell) can only be used to read param's data
276    /// and world metadata. No data can be written.
277    ///
278    /// When using system parameters that require `change_tick` you can use
279    /// [`UnsafeWorldCell::change_tick()`]. Even if this isn't the exact
280    /// same tick used for [`SystemParam::get_param`], the world access
281    /// ensures that the queried data will be the same in both calls.
282    ///
283    /// This method has to be called directly before [`SystemParam::get_param`] with no other (relevant)
284    /// world mutations inbetween. Otherwise, while it won't lead to any undefined behavior,
285    /// the validity of the param may change.
286    ///
287    /// [`System::validate_param`](super::system::System::validate_param),
288    /// calls this method for each supplied system param.
289    ///
290    /// # Safety
291    ///
292    /// - The passed [`UnsafeWorldCell`] must have read-only access to world data
293    ///   registered in [`init_state`](SystemParam::init_state).
294    /// - `world` must be the same [`World`] that was used to initialize [`state`](SystemParam::init_state).
295    /// - All `world`'s archetypes have been processed by [`new_archetype`](SystemParam::new_archetype).
296    #[expect(
297        unused_variables,
298        reason = "The parameters here are intentionally unused by the default implementation; however, putting underscores here will result in the underscores being copied by rust-analyzer's tab completion."
299    )]
300    unsafe fn validate_param(
301        state: &Self::State,
302        system_meta: &SystemMeta,
303        world: UnsafeWorldCell,
304    ) -> Result<(), SystemParamValidationError> {
305        Ok(())
306    }
307
308    /// Creates a parameter to be passed into a [`SystemParamFunction`](super::SystemParamFunction).
309    ///
310    /// # Safety
311    ///
312    /// - The passed [`UnsafeWorldCell`] must have access to any world data registered
313    ///   in [`init_state`](SystemParam::init_state).
314    /// - `world` must be the same [`World`] that was used to initialize [`state`](SystemParam::init_state).
315    /// - All `world`'s archetypes have been processed by [`new_archetype`](SystemParam::new_archetype).
316    unsafe fn get_param<'world, 'state>(
317        state: &'state mut Self::State,
318        system_meta: &SystemMeta,
319        world: UnsafeWorldCell<'world>,
320        change_tick: Tick,
321    ) -> Self::Item<'world, 'state>;
322}
323
324/// A [`SystemParam`] that only reads a given [`World`].
325///
326/// # Safety
327/// This must only be implemented for [`SystemParam`] impls that exclusively read the World passed in to [`SystemParam::get_param`]
328pub unsafe trait ReadOnlySystemParam: SystemParam {}
329
330/// Shorthand way of accessing the associated type [`SystemParam::Item`] for a given [`SystemParam`].
331pub type SystemParamItem<'w, 's, P> = <P as SystemParam>::Item<'w, 's>;
332
333// SAFETY: QueryState is constrained to read-only fetches, so it only reads World.
334unsafe impl<'w, 's, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam
335    for Query<'w, 's, D, F>
336{
337}
338
339// SAFETY: Relevant query ComponentId and ArchetypeComponentId access is applied to SystemMeta. If
340// this Query conflicts with any prior access, a panic will occur.
341unsafe impl<D: QueryData + 'static, F: QueryFilter + 'static> SystemParam for Query<'_, '_, D, F> {
342    type State = QueryState<D, F>;
343    type Item<'w, 's> = Query<'w, 's, D, F>;
344
345    fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
346        let state = QueryState::new_with_access(world, &mut system_meta.archetype_component_access);
347        init_query_param(world, system_meta, &state);
348        state
349    }
350
351    unsafe fn new_archetype(
352        state: &mut Self::State,
353        archetype: &Archetype,
354        system_meta: &mut SystemMeta,
355    ) {
356        state.new_archetype(archetype, &mut system_meta.archetype_component_access);
357    }
358
359    #[inline]
360    unsafe fn get_param<'w, 's>(
361        state: &'s mut Self::State,
362        system_meta: &SystemMeta,
363        world: UnsafeWorldCell<'w>,
364        change_tick: Tick,
365    ) -> Self::Item<'w, 's> {
366        // SAFETY: We have registered all of the query's world accesses,
367        // so the caller ensures that `world` has permission to access any
368        // world data that the query needs.
369        // The caller ensures the world matches the one used in init_state.
370        unsafe { state.query_unchecked_manual_with_ticks(world, system_meta.last_run, change_tick) }
371    }
372}
373
374pub(crate) fn init_query_param<D: QueryData + 'static, F: QueryFilter + 'static>(
375    world: &mut World,
376    system_meta: &mut SystemMeta,
377    state: &QueryState<D, F>,
378) {
379    assert_component_access_compatibility(
380        &system_meta.name,
381        core::any::type_name::<D>(),
382        core::any::type_name::<F>(),
383        &system_meta.component_access_set,
384        &state.component_access,
385        world,
386    );
387    system_meta
388        .component_access_set
389        .add(state.component_access.clone());
390}
391
392fn assert_component_access_compatibility(
393    system_name: &str,
394    query_type: &'static str,
395    filter_type: &'static str,
396    system_access: &FilteredAccessSet<ComponentId>,
397    current: &FilteredAccess<ComponentId>,
398    world: &World,
399) {
400    let conflicts = system_access.get_conflicts_single(current);
401    if conflicts.is_empty() {
402        return;
403    }
404    let mut accesses = conflicts.format_conflict_list(world);
405    // Access list may be empty (if access to all components requested)
406    if !accesses.is_empty() {
407        accesses.push(' ');
408    }
409    panic!("error[B0001]: Query<{}, {}> in system {system_name} accesses component(s) {accesses}in a way that conflicts with a previous system parameter. Consider using `Without<T>` to create disjoint Queries or merging conflicting Queries into a `ParamSet`. See: https://bevyengine.org/learn/errors/b0001", ShortName(query_type), ShortName(filter_type));
410}
411
412// SAFETY: Relevant query ComponentId and ArchetypeComponentId access is applied to SystemMeta. If
413// this Query conflicts with any prior access, a panic will occur.
414unsafe impl<'a, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam for Single<'a, D, F> {
415    type State = QueryState<D, F>;
416    type Item<'w, 's> = Single<'w, D, F>;
417
418    fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
419        Query::init_state(world, system_meta)
420    }
421
422    unsafe fn new_archetype(
423        state: &mut Self::State,
424        archetype: &Archetype,
425        system_meta: &mut SystemMeta,
426    ) {
427        // SAFETY: Delegate to existing `SystemParam` implementations.
428        unsafe { Query::new_archetype(state, archetype, system_meta) };
429    }
430
431    #[inline]
432    unsafe fn get_param<'w, 's>(
433        state: &'s mut Self::State,
434        system_meta: &SystemMeta,
435        world: UnsafeWorldCell<'w>,
436        change_tick: Tick,
437    ) -> Self::Item<'w, 's> {
438        // SAFETY: State ensures that the components it accesses are not accessible somewhere elsewhere.
439        // The caller ensures the world matches the one used in init_state.
440        let query = unsafe {
441            state.query_unchecked_manual_with_ticks(world, system_meta.last_run, change_tick)
442        };
443        let single = query
444            .single_inner()
445            .expect("The query was expected to contain exactly one matching entity.");
446        Single {
447            item: single,
448            _filter: PhantomData,
449        }
450    }
451
452    #[inline]
453    unsafe fn validate_param(
454        state: &Self::State,
455        system_meta: &SystemMeta,
456        world: UnsafeWorldCell,
457    ) -> Result<(), SystemParamValidationError> {
458        // SAFETY: State ensures that the components it accesses are not mutably accessible elsewhere
459        // and the query is read only.
460        // The caller ensures the world matches the one used in init_state.
461        let query = unsafe {
462            state.query_unchecked_manual_with_ticks(
463                world,
464                system_meta.last_run,
465                world.change_tick(),
466            )
467        };
468        match query.single_inner() {
469            Ok(_) => Ok(()),
470            Err(QuerySingleError::NoEntities(_)) => Err(
471                SystemParamValidationError::skipped::<Self>("No matching entities"),
472            ),
473            Err(QuerySingleError::MultipleEntities(_)) => Err(
474                SystemParamValidationError::skipped::<Self>("Multiple matching entities"),
475            ),
476        }
477    }
478}
479
480// SAFETY: Relevant query ComponentId and ArchetypeComponentId access is applied to SystemMeta. If
481// this Query conflicts with any prior access, a panic will occur.
482unsafe impl<'a, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam
483    for Option<Single<'a, D, F>>
484{
485    type State = QueryState<D, F>;
486    type Item<'w, 's> = Option<Single<'w, D, F>>;
487
488    fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
489        Single::init_state(world, system_meta)
490    }
491
492    unsafe fn new_archetype(
493        state: &mut Self::State,
494        archetype: &Archetype,
495        system_meta: &mut SystemMeta,
496    ) {
497        // SAFETY: Delegate to existing `SystemParam` implementations.
498        unsafe { Single::new_archetype(state, archetype, system_meta) };
499    }
500
501    #[inline]
502    unsafe fn get_param<'w, 's>(
503        state: &'s mut Self::State,
504        system_meta: &SystemMeta,
505        world: UnsafeWorldCell<'w>,
506        change_tick: Tick,
507    ) -> Self::Item<'w, 's> {
508        state.validate_world(world.id());
509        // SAFETY: State ensures that the components it accesses are not accessible elsewhere.
510        // The caller ensures the world matches the one used in init_state.
511        let query = unsafe {
512            state.query_unchecked_manual_with_ticks(world, system_meta.last_run, change_tick)
513        };
514        match query.single_inner() {
515            Ok(single) => Some(Single {
516                item: single,
517                _filter: PhantomData,
518            }),
519            Err(QuerySingleError::NoEntities(_)) => None,
520            Err(QuerySingleError::MultipleEntities(e)) => panic!("{}", e),
521        }
522    }
523
524    #[inline]
525    unsafe fn validate_param(
526        state: &Self::State,
527        system_meta: &SystemMeta,
528        world: UnsafeWorldCell,
529    ) -> Result<(), SystemParamValidationError> {
530        // SAFETY: State ensures that the components it accesses are not mutably accessible elsewhere
531        // and the query is read only.
532        // The caller ensures the world matches the one used in init_state.
533        let query = unsafe {
534            state.query_unchecked_manual_with_ticks(
535                world,
536                system_meta.last_run,
537                world.change_tick(),
538            )
539        };
540        match query.single_inner() {
541            Ok(_) | Err(QuerySingleError::NoEntities(_)) => Ok(()),
542            Err(QuerySingleError::MultipleEntities(_)) => Err(
543                SystemParamValidationError::skipped::<Self>("Multiple matching entities"),
544            ),
545        }
546    }
547}
548
549// SAFETY: QueryState is constrained to read-only fetches, so it only reads World.
550unsafe impl<'a, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam
551    for Single<'a, D, F>
552{
553}
554
555// SAFETY: QueryState is constrained to read-only fetches, so it only reads World.
556unsafe impl<'a, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam
557    for Option<Single<'a, D, F>>
558{
559}
560
561// SAFETY: Relevant query ComponentId and ArchetypeComponentId access is applied to SystemMeta. If
562// this Query conflicts with any prior access, a panic will occur.
563unsafe impl<D: QueryData + 'static, F: QueryFilter + 'static> SystemParam
564    for Populated<'_, '_, D, F>
565{
566    type State = QueryState<D, F>;
567    type Item<'w, 's> = Populated<'w, 's, D, F>;
568
569    fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
570        Query::init_state(world, system_meta)
571    }
572
573    unsafe fn new_archetype(
574        state: &mut Self::State,
575        archetype: &Archetype,
576        system_meta: &mut SystemMeta,
577    ) {
578        // SAFETY: Delegate to existing `SystemParam` implementations.
579        unsafe { Query::new_archetype(state, archetype, system_meta) };
580    }
581
582    #[inline]
583    unsafe fn get_param<'w, 's>(
584        state: &'s mut Self::State,
585        system_meta: &SystemMeta,
586        world: UnsafeWorldCell<'w>,
587        change_tick: Tick,
588    ) -> Self::Item<'w, 's> {
589        // SAFETY: Delegate to existing `SystemParam` implementations.
590        let query = unsafe { Query::get_param(state, system_meta, world, change_tick) };
591        Populated(query)
592    }
593
594    #[inline]
595    unsafe fn validate_param(
596        state: &Self::State,
597        system_meta: &SystemMeta,
598        world: UnsafeWorldCell,
599    ) -> Result<(), SystemParamValidationError> {
600        // SAFETY:
601        // - We have read-only access to the components accessed by query.
602        // - The caller ensures the world matches the one used in init_state.
603        let query = unsafe {
604            state.query_unchecked_manual_with_ticks(
605                world,
606                system_meta.last_run,
607                world.change_tick(),
608            )
609        };
610        if query.is_empty() {
611            Err(SystemParamValidationError::skipped::<Self>(
612                "No matching entities",
613            ))
614        } else {
615            Ok(())
616        }
617    }
618}
619
620// SAFETY: QueryState is constrained to read-only fetches, so it only reads World.
621unsafe impl<'w, 's, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam
622    for Populated<'w, 's, D, F>
623{
624}
625
626/// A collection of potentially conflicting [`SystemParam`]s allowed by disjoint access.
627///
628/// Allows systems to safely access and interact with up to 8 mutually exclusive [`SystemParam`]s, such as
629/// two queries that reference the same mutable data or an event reader and writer of the same type.
630///
631/// Each individual [`SystemParam`] can be accessed by using the functions `p0()`, `p1()`, ..., `p7()`,
632/// according to the order they are defined in the `ParamSet`. This ensures that there's either
633/// only one mutable reference to a parameter at a time or any number of immutable references.
634///
635/// # Examples
636///
637/// The following system mutably accesses the same component two times,
638/// which is not allowed due to rust's mutability rules.
639///
640/// ```should_panic
641/// # use bevy_ecs::prelude::*;
642/// #
643/// # #[derive(Component)]
644/// # struct Health;
645/// #
646/// # #[derive(Component)]
647/// # struct Enemy;
648/// #
649/// # #[derive(Component)]
650/// # struct Ally;
651/// #
652/// // This will panic at runtime when the system gets initialized.
653/// fn bad_system(
654///     mut enemies: Query<&mut Health, With<Enemy>>,
655///     mut allies: Query<&mut Health, With<Ally>>,
656/// ) {
657///     // ...
658/// }
659/// #
660/// # let mut bad_system_system = IntoSystem::into_system(bad_system);
661/// # let mut world = World::new();
662/// # bad_system_system.initialize(&mut world);
663/// # bad_system_system.run((), &mut world);
664/// ```
665///
666/// Conflicting `SystemParam`s like these can be placed in a `ParamSet`,
667/// which leverages the borrow checker to ensure that only one of the contained parameters are accessed at a given time.
668///
669/// ```
670/// # use bevy_ecs::prelude::*;
671/// #
672/// # #[derive(Component)]
673/// # struct Health;
674/// #
675/// # #[derive(Component)]
676/// # struct Enemy;
677/// #
678/// # #[derive(Component)]
679/// # struct Ally;
680/// #
681/// // Given the following system
682/// fn fancy_system(
683///     mut set: ParamSet<(
684///         Query<&mut Health, With<Enemy>>,
685///         Query<&mut Health, With<Ally>>,
686///     )>
687/// ) {
688///     // This will access the first `SystemParam`.
689///     for mut health in set.p0().iter_mut() {
690///         // Do your fancy stuff here...
691///     }
692///
693///     // The second `SystemParam`.
694///     // This would fail to compile if the previous parameter was still borrowed.
695///     for mut health in set.p1().iter_mut() {
696///         // Do even fancier stuff here...
697///     }
698/// }
699/// # bevy_ecs::system::assert_is_system(fancy_system);
700/// ```
701///
702/// Of course, `ParamSet`s can be used with any kind of `SystemParam`, not just [queries](Query).
703///
704/// ```
705/// # use bevy_ecs::prelude::*;
706/// #
707/// # #[derive(Event)]
708/// # struct MyEvent;
709/// # impl MyEvent {
710/// #   pub fn new() -> Self { Self }
711/// # }
712/// fn event_system(
713///     mut set: ParamSet<(
714///         // PROBLEM: `EventReader` and `EventWriter` cannot be used together normally,
715///         // because they both need access to the same event queue.
716///         // SOLUTION: `ParamSet` allows these conflicting parameters to be used safely
717///         // by ensuring only one is accessed at a time.
718///         EventReader<MyEvent>,
719///         EventWriter<MyEvent>,
720///         // PROBLEM: `&World` needs read access to everything, which conflicts with
721///         // any mutable access in the same system.
722///         // SOLUTION: `ParamSet` ensures `&World` is only accessed when we're not
723///         // using the other mutable parameters.
724///         &World,
725///     )>,
726/// ) {
727///     for event in set.p0().read() {
728///         // ...
729///         # let _event = event;
730///     }
731///     set.p1().write(MyEvent::new());
732///
733///     let entities = set.p2().entities();
734///     // ...
735///     # let _entities = entities;
736/// }
737/// # bevy_ecs::system::assert_is_system(event_system);
738/// ```
739pub struct ParamSet<'w, 's, T: SystemParam> {
740    param_states: &'s mut T::State,
741    world: UnsafeWorldCell<'w>,
742    system_meta: SystemMeta,
743    change_tick: Tick,
744}
745
746macro_rules! impl_param_set {
747    ($(($index: tt, $param: ident, $system_meta: ident, $fn_name: ident)),*) => {
748        // SAFETY: All parameters are constrained to ReadOnlySystemParam, so World is only read
749        unsafe impl<'w, 's, $($param,)*> ReadOnlySystemParam for ParamSet<'w, 's, ($($param,)*)>
750        where $($param: ReadOnlySystemParam,)*
751        { }
752
753        // SAFETY: Relevant parameter ComponentId and ArchetypeComponentId access is applied to SystemMeta. If any ParamState conflicts
754        // with any prior access, a panic will occur.
755        unsafe impl<'_w, '_s, $($param: SystemParam,)*> SystemParam for ParamSet<'_w, '_s, ($($param,)*)>
756        {
757            type State = ($($param::State,)*);
758            type Item<'w, 's> = ParamSet<'w, 's, ($($param,)*)>;
759
760            #[expect(
761                clippy::allow_attributes,
762                reason = "This is inside a macro meant for tuples; as such, `non_snake_case` won't always lint."
763            )]
764            #[allow(
765                non_snake_case,
766                reason = "Certain variable names are provided by the caller, not by us."
767            )]
768            fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
769                $(
770                    // Pretend to add each param to the system alone, see if it conflicts
771                    let mut $system_meta = system_meta.clone();
772                    $system_meta.component_access_set.clear();
773                    $system_meta.archetype_component_access.clear();
774                    $param::init_state(world, &mut $system_meta);
775                    // The variable is being defined with non_snake_case here
776                    let $param = $param::init_state(world, &mut system_meta.clone());
777                )*
778                // Make the ParamSet non-send if any of its parameters are non-send.
779                if false $(|| !$system_meta.is_send())* {
780                    system_meta.set_non_send();
781                }
782                $(
783                    system_meta
784                        .component_access_set
785                        .extend($system_meta.component_access_set);
786                    system_meta
787                        .archetype_component_access
788                        .extend(&$system_meta.archetype_component_access);
789                )*
790                ($($param,)*)
791            }
792
793            unsafe fn new_archetype(state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta) {
794                // SAFETY: The caller ensures that `archetype` is from the World the state was initialized from in `init_state`.
795                unsafe { <($($param,)*) as SystemParam>::new_archetype(state, archetype, system_meta); }
796            }
797
798            fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
799                <($($param,)*) as SystemParam>::apply(state, system_meta, world);
800            }
801
802            fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
803                <($($param,)*) as SystemParam>::queue(state, system_meta, world.reborrow());
804            }
805
806            #[inline]
807            unsafe fn validate_param<'w, 's>(
808                state: &'s Self::State,
809                system_meta: &SystemMeta,
810                world: UnsafeWorldCell<'w>,
811            ) -> Result<(), SystemParamValidationError> {
812                <($($param,)*) as SystemParam>::validate_param(state, system_meta, world)
813            }
814
815            #[inline]
816            unsafe fn get_param<'w, 's>(
817                state: &'s mut Self::State,
818                system_meta: &SystemMeta,
819                world: UnsafeWorldCell<'w>,
820                change_tick: Tick,
821            ) -> Self::Item<'w, 's> {
822                ParamSet {
823                    param_states: state,
824                    system_meta: system_meta.clone(),
825                    world,
826                    change_tick,
827                }
828            }
829        }
830
831        impl<'w, 's, $($param: SystemParam,)*> ParamSet<'w, 's, ($($param,)*)>
832        {
833            $(
834                /// Gets exclusive access to the parameter at index
835                #[doc = stringify!($index)]
836                /// in this [`ParamSet`].
837                /// No other parameters may be accessed while this one is active.
838                pub fn $fn_name<'a>(&'a mut self) -> SystemParamItem<'a, 'a, $param> {
839                    // SAFETY: systems run without conflicts with other systems.
840                    // Conflicting params in ParamSet are not accessible at the same time
841                    // ParamSets are guaranteed to not conflict with other SystemParams
842                    unsafe {
843                        $param::get_param(&mut self.param_states.$index, &self.system_meta, self.world, self.change_tick)
844                    }
845                }
846            )*
847        }
848    }
849}
850
851all_tuples_enumerated!(impl_param_set, 1, 8, P, m, p);
852
853// SAFETY: Res only reads a single World resource
854unsafe impl<'a, T: Resource> ReadOnlySystemParam for Res<'a, T> {}
855
856// SAFETY: Res ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this Res
857// conflicts with any prior access, a panic will occur.
858unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> {
859    type State = ComponentId;
860    type Item<'w, 's> = Res<'w, T>;
861
862    fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
863        let component_id = world.components_registrator().register_resource::<T>();
864        let archetype_component_id = world.initialize_resource_internal(component_id).id();
865
866        let combined_access = system_meta.component_access_set.combined_access();
867        assert!(
868            !combined_access.has_resource_write(component_id),
869            "error[B0002]: Res<{}> in system {} conflicts with a previous ResMut<{0}> access. Consider removing the duplicate access. See: https://bevyengine.org/learn/errors/b0002",
870            core::any::type_name::<T>(),
871            system_meta.name,
872        );
873        system_meta
874            .component_access_set
875            .add_unfiltered_resource_read(component_id);
876
877        system_meta
878            .archetype_component_access
879            .add_resource_read(archetype_component_id);
880
881        component_id
882    }
883
884    #[inline]
885    unsafe fn validate_param(
886        &component_id: &Self::State,
887        _system_meta: &SystemMeta,
888        world: UnsafeWorldCell,
889    ) -> Result<(), SystemParamValidationError> {
890        // SAFETY: Read-only access to resource metadata.
891        if unsafe { world.storages() }
892            .resources
893            .get(component_id)
894            .is_some_and(ResourceData::is_present)
895        {
896            Ok(())
897        } else {
898            Err(SystemParamValidationError::invalid::<Self>(
899                "Resource does not exist",
900            ))
901        }
902    }
903
904    #[inline]
905    unsafe fn get_param<'w, 's>(
906        &mut component_id: &'s mut Self::State,
907        system_meta: &SystemMeta,
908        world: UnsafeWorldCell<'w>,
909        change_tick: Tick,
910    ) -> Self::Item<'w, 's> {
911        let (ptr, ticks, caller) =
912            world
913                .get_resource_with_ticks(component_id)
914                .unwrap_or_else(|| {
915                    panic!(
916                        "Resource requested by {} does not exist: {}",
917                        system_meta.name,
918                        core::any::type_name::<T>()
919                    )
920                });
921        Res {
922            value: ptr.deref(),
923            ticks: Ticks {
924                added: ticks.added.deref(),
925                changed: ticks.changed.deref(),
926                last_run: system_meta.last_run,
927                this_run: change_tick,
928            },
929            changed_by: caller.map(|caller| caller.deref()),
930        }
931    }
932}
933
934// SAFETY: Only reads a single World resource
935unsafe impl<'a, T: Resource> ReadOnlySystemParam for Option<Res<'a, T>> {}
936
937// SAFETY: this impl defers to `Res`, which initializes and validates the correct world access.
938unsafe impl<'a, T: Resource> SystemParam for Option<Res<'a, T>> {
939    type State = ComponentId;
940    type Item<'w, 's> = Option<Res<'w, T>>;
941
942    fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
943        Res::<T>::init_state(world, system_meta)
944    }
945
946    #[inline]
947    unsafe fn get_param<'w, 's>(
948        &mut component_id: &'s mut Self::State,
949        system_meta: &SystemMeta,
950        world: UnsafeWorldCell<'w>,
951        change_tick: Tick,
952    ) -> Self::Item<'w, 's> {
953        world
954            .get_resource_with_ticks(component_id)
955            .map(|(ptr, ticks, caller)| Res {
956                value: ptr.deref(),
957                ticks: Ticks {
958                    added: ticks.added.deref(),
959                    changed: ticks.changed.deref(),
960                    last_run: system_meta.last_run,
961                    this_run: change_tick,
962                },
963                changed_by: caller.map(|caller| caller.deref()),
964            })
965    }
966}
967
968// SAFETY: Res ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this Res
969// conflicts with any prior access, a panic will occur.
970unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> {
971    type State = ComponentId;
972    type Item<'w, 's> = ResMut<'w, T>;
973
974    fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
975        let component_id = world.components_registrator().register_resource::<T>();
976        let archetype_component_id = world.initialize_resource_internal(component_id).id();
977
978        let combined_access = system_meta.component_access_set.combined_access();
979        if combined_access.has_resource_write(component_id) {
980            panic!(
981                "error[B0002]: ResMut<{}> in system {} conflicts with a previous ResMut<{0}> access. Consider removing the duplicate access. See: https://bevyengine.org/learn/errors/b0002",
982                core::any::type_name::<T>(), system_meta.name);
983        } else if combined_access.has_resource_read(component_id) {
984            panic!(
985                "error[B0002]: ResMut<{}> in system {} conflicts with a previous Res<{0}> access. Consider removing the duplicate access. See: https://bevyengine.org/learn/errors/b0002",
986                core::any::type_name::<T>(), system_meta.name);
987        }
988        system_meta
989            .component_access_set
990            .add_unfiltered_resource_write(component_id);
991
992        system_meta
993            .archetype_component_access
994            .add_resource_write(archetype_component_id);
995
996        component_id
997    }
998
999    #[inline]
1000    unsafe fn validate_param(
1001        &component_id: &Self::State,
1002        _system_meta: &SystemMeta,
1003        world: UnsafeWorldCell,
1004    ) -> Result<(), SystemParamValidationError> {
1005        // SAFETY: Read-only access to resource metadata.
1006        if unsafe { world.storages() }
1007            .resources
1008            .get(component_id)
1009            .is_some_and(ResourceData::is_present)
1010        {
1011            Ok(())
1012        } else {
1013            Err(SystemParamValidationError::invalid::<Self>(
1014                "Resource does not exist",
1015            ))
1016        }
1017    }
1018
1019    #[inline]
1020    unsafe fn get_param<'w, 's>(
1021        &mut component_id: &'s mut Self::State,
1022        system_meta: &SystemMeta,
1023        world: UnsafeWorldCell<'w>,
1024        change_tick: Tick,
1025    ) -> Self::Item<'w, 's> {
1026        let value = world
1027            .get_resource_mut_by_id(component_id)
1028            .unwrap_or_else(|| {
1029                panic!(
1030                    "Resource requested by {} does not exist: {}",
1031                    system_meta.name,
1032                    core::any::type_name::<T>()
1033                )
1034            });
1035        ResMut {
1036            value: value.value.deref_mut::<T>(),
1037            ticks: TicksMut {
1038                added: value.ticks.added,
1039                changed: value.ticks.changed,
1040                last_run: system_meta.last_run,
1041                this_run: change_tick,
1042            },
1043            changed_by: value.changed_by,
1044        }
1045    }
1046}
1047
1048// SAFETY: this impl defers to `ResMut`, which initializes and validates the correct world access.
1049unsafe impl<'a, T: Resource> SystemParam for Option<ResMut<'a, T>> {
1050    type State = ComponentId;
1051    type Item<'w, 's> = Option<ResMut<'w, T>>;
1052
1053    fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
1054        ResMut::<T>::init_state(world, system_meta)
1055    }
1056
1057    #[inline]
1058    unsafe fn get_param<'w, 's>(
1059        &mut component_id: &'s mut Self::State,
1060        system_meta: &SystemMeta,
1061        world: UnsafeWorldCell<'w>,
1062        change_tick: Tick,
1063    ) -> Self::Item<'w, 's> {
1064        world
1065            .get_resource_mut_by_id(component_id)
1066            .map(|value| ResMut {
1067                value: value.value.deref_mut::<T>(),
1068                ticks: TicksMut {
1069                    added: value.ticks.added,
1070                    changed: value.ticks.changed,
1071                    last_run: system_meta.last_run,
1072                    this_run: change_tick,
1073                },
1074                changed_by: value.changed_by,
1075            })
1076    }
1077}
1078
1079/// SAFETY: only reads world
1080unsafe impl<'w> ReadOnlySystemParam for &'w World {}
1081
1082// SAFETY: `read_all` access is set and conflicts result in a panic
1083unsafe impl SystemParam for &'_ World {
1084    type State = ();
1085    type Item<'w, 's> = &'w World;
1086
1087    fn init_state(_world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
1088        let mut access = Access::default();
1089        access.read_all();
1090        if !system_meta
1091            .archetype_component_access
1092            .is_compatible(&access)
1093        {
1094            panic!("&World conflicts with a previous mutable system parameter. Allowing this would break Rust's mutability rules");
1095        }
1096        system_meta.archetype_component_access.extend(&access);
1097
1098        let mut filtered_access = FilteredAccess::default();
1099
1100        filtered_access.read_all();
1101        if !system_meta
1102            .component_access_set
1103            .get_conflicts_single(&filtered_access)
1104            .is_empty()
1105        {
1106            panic!("&World conflicts with a previous mutable system parameter. Allowing this would break Rust's mutability rules");
1107        }
1108        system_meta.component_access_set.add(filtered_access);
1109    }
1110
1111    #[inline]
1112    unsafe fn get_param<'w, 's>(
1113        _state: &'s mut Self::State,
1114        _system_meta: &SystemMeta,
1115        world: UnsafeWorldCell<'w>,
1116        _change_tick: Tick,
1117    ) -> Self::Item<'w, 's> {
1118        // SAFETY: Read-only access to the entire world was registered in `init_state`.
1119        unsafe { world.world() }
1120    }
1121}
1122
1123/// SAFETY: `DeferredWorld` can read all components and resources but cannot be used to gain any other mutable references.
1124unsafe impl<'w> SystemParam for DeferredWorld<'w> {
1125    type State = ();
1126    type Item<'world, 'state> = DeferredWorld<'world>;
1127
1128    fn init_state(_world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
1129        assert!(
1130            !system_meta
1131                .component_access_set
1132                .combined_access()
1133                .has_any_read(),
1134            "DeferredWorld in system {} conflicts with a previous access.",
1135            system_meta.name,
1136        );
1137        system_meta.component_access_set.write_all();
1138        system_meta.archetype_component_access.write_all();
1139    }
1140
1141    unsafe fn get_param<'world, 'state>(
1142        _state: &'state mut Self::State,
1143        _system_meta: &SystemMeta,
1144        world: UnsafeWorldCell<'world>,
1145        _change_tick: Tick,
1146    ) -> Self::Item<'world, 'state> {
1147        world.into_deferred()
1148    }
1149}
1150
1151/// A system local [`SystemParam`].
1152///
1153/// A local may only be accessed by the system itself and is therefore not visible to other systems.
1154/// If two or more systems specify the same local type each will have their own unique local.
1155/// If multiple [`SystemParam`]s within the same system each specify the same local type
1156/// each will get their own distinct data storage.
1157///
1158/// The supplied lifetime parameter is the [`SystemParam`]s `'s` lifetime.
1159///
1160/// # Examples
1161///
1162/// ```
1163/// # use bevy_ecs::prelude::*;
1164/// # let world = &mut World::default();
1165/// fn write_to_local(mut local: Local<usize>) {
1166///     *local = 42;
1167/// }
1168/// fn read_from_local(local: Local<usize>) -> usize {
1169///     *local
1170/// }
1171/// let mut write_system = IntoSystem::into_system(write_to_local);
1172/// let mut read_system = IntoSystem::into_system(read_from_local);
1173/// write_system.initialize(world);
1174/// read_system.initialize(world);
1175///
1176/// assert_eq!(read_system.run((), world), 0);
1177/// write_system.run((), world);
1178/// // Note how the read local is still 0 due to the locals not being shared.
1179/// assert_eq!(read_system.run((), world), 0);
1180/// ```
1181///
1182/// A simple way to set a different default value for a local is by wrapping the value with an Option.
1183///
1184/// ```
1185/// # use bevy_ecs::prelude::*;
1186/// # let world = &mut World::default();
1187/// fn counter_from_10(mut count: Local<Option<usize>>) -> usize {
1188///     let count = count.get_or_insert(10);
1189///     *count += 1;
1190///     *count
1191/// }
1192/// let mut counter_system = IntoSystem::into_system(counter_from_10);
1193/// counter_system.initialize(world);
1194///
1195/// // Counter is initialized at 10, and increases to 11 on first run.
1196/// assert_eq!(counter_system.run((), world), 11);
1197/// // Counter is only increased by 1 on subsequent runs.
1198/// assert_eq!(counter_system.run((), world), 12);
1199/// ```
1200///
1201/// N.B. A [`Local`]s value cannot be read or written to outside of the containing system.
1202/// To add configuration to a system, convert a capturing closure into the system instead:
1203///
1204/// ```
1205/// # use bevy_ecs::prelude::*;
1206/// # use bevy_ecs::system::assert_is_system;
1207/// struct Config(u32);
1208/// #[derive(Resource)]
1209/// struct MyU32Wrapper(u32);
1210/// fn reset_to_system(value: Config) -> impl FnMut(ResMut<MyU32Wrapper>) {
1211///     move |mut val| val.0 = value.0
1212/// }
1213///
1214/// // .add_systems(reset_to_system(my_config))
1215/// # assert_is_system(reset_to_system(Config(10)));
1216/// ```
1217#[derive(Debug)]
1218pub struct Local<'s, T: FromWorld + Send + 'static>(pub(crate) &'s mut T);
1219
1220// SAFETY: Local only accesses internal state
1221unsafe impl<'s, T: FromWorld + Send + 'static> ReadOnlySystemParam for Local<'s, T> {}
1222
1223impl<'s, T: FromWorld + Send + 'static> Deref for Local<'s, T> {
1224    type Target = T;
1225
1226    #[inline]
1227    fn deref(&self) -> &Self::Target {
1228        self.0
1229    }
1230}
1231
1232impl<'s, T: FromWorld + Send + 'static> DerefMut for Local<'s, T> {
1233    #[inline]
1234    fn deref_mut(&mut self) -> &mut Self::Target {
1235        self.0
1236    }
1237}
1238
1239impl<'s, 'a, T: FromWorld + Send + 'static> IntoIterator for &'a Local<'s, T>
1240where
1241    &'a T: IntoIterator,
1242{
1243    type Item = <&'a T as IntoIterator>::Item;
1244    type IntoIter = <&'a T as IntoIterator>::IntoIter;
1245
1246    fn into_iter(self) -> Self::IntoIter {
1247        self.0.into_iter()
1248    }
1249}
1250
1251impl<'s, 'a, T: FromWorld + Send + 'static> IntoIterator for &'a mut Local<'s, T>
1252where
1253    &'a mut T: IntoIterator,
1254{
1255    type Item = <&'a mut T as IntoIterator>::Item;
1256    type IntoIter = <&'a mut T as IntoIterator>::IntoIter;
1257
1258    fn into_iter(self) -> Self::IntoIter {
1259        self.0.into_iter()
1260    }
1261}
1262
1263// SAFETY: only local state is accessed
1264unsafe impl<'a, T: FromWorld + Send + 'static> SystemParam for Local<'a, T> {
1265    type State = SyncCell<T>;
1266    type Item<'w, 's> = Local<'s, T>;
1267
1268    fn init_state(world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {
1269        SyncCell::new(T::from_world(world))
1270    }
1271
1272    #[inline]
1273    unsafe fn get_param<'w, 's>(
1274        state: &'s mut Self::State,
1275        _system_meta: &SystemMeta,
1276        _world: UnsafeWorldCell<'w>,
1277        _change_tick: Tick,
1278    ) -> Self::Item<'w, 's> {
1279        Local(state.get())
1280    }
1281}
1282
1283/// Types that can be used with [`Deferred<T>`] in systems.
1284/// This allows storing system-local data which is used to defer [`World`] mutations.
1285///
1286/// Types that implement `SystemBuffer` should take care to perform as many
1287/// computations up-front as possible. Buffers cannot be applied in parallel,
1288/// so you should try to minimize the time spent in [`SystemBuffer::apply`].
1289pub trait SystemBuffer: FromWorld + Send + 'static {
1290    /// Applies any deferred mutations to the [`World`].
1291    fn apply(&mut self, system_meta: &SystemMeta, world: &mut World);
1292    /// Queues any deferred mutations to be applied at the next [`ApplyDeferred`](crate::prelude::ApplyDeferred).
1293    fn queue(&mut self, _system_meta: &SystemMeta, _world: DeferredWorld) {}
1294}
1295
1296/// A [`SystemParam`] that stores a buffer which gets applied to the [`World`] during
1297/// [`ApplyDeferred`](crate::schedule::ApplyDeferred).
1298/// This is used internally by [`Commands`] to defer `World` mutations.
1299///
1300/// [`Commands`]: crate::system::Commands
1301///
1302/// # Examples
1303///
1304/// By using this type to defer mutations, you can avoid mutable `World` access within
1305/// a system, which allows it to run in parallel with more systems.
1306///
1307/// Note that deferring mutations is *not* free, and should only be used if
1308/// the gains in parallelization outweigh the time it takes to apply deferred mutations.
1309/// In general, [`Deferred`] should only be used for mutations that are infrequent,
1310/// or which otherwise take up a small portion of a system's run-time.
1311///
1312/// ```
1313/// # use bevy_ecs::prelude::*;
1314/// // Tracks whether or not there is a threat the player should be aware of.
1315/// #[derive(Resource, Default)]
1316/// pub struct Alarm(bool);
1317///
1318/// #[derive(Component)]
1319/// pub struct Settlement {
1320///     // ...
1321/// }
1322///
1323/// // A threat from inside the settlement.
1324/// #[derive(Component)]
1325/// pub struct Criminal;
1326///
1327/// // A threat from outside the settlement.
1328/// #[derive(Component)]
1329/// pub struct Monster;
1330///
1331/// # impl Criminal { pub fn is_threat(&self, _: &Settlement) -> bool { true } }
1332///
1333/// use bevy_ecs::system::{Deferred, SystemBuffer, SystemMeta};
1334///
1335/// // Uses deferred mutations to allow signaling the alarm from multiple systems in parallel.
1336/// #[derive(Resource, Default)]
1337/// struct AlarmFlag(bool);
1338///
1339/// impl AlarmFlag {
1340///     /// Sounds the alarm the next time buffers are applied via ApplyDeferred.
1341///     pub fn flag(&mut self) {
1342///         self.0 = true;
1343///     }
1344/// }
1345///
1346/// impl SystemBuffer for AlarmFlag {
1347///     // When `AlarmFlag` is used in a system, this function will get
1348///     // called the next time buffers are applied via ApplyDeferred.
1349///     fn apply(&mut self, system_meta: &SystemMeta, world: &mut World) {
1350///         if self.0 {
1351///             world.resource_mut::<Alarm>().0 = true;
1352///             self.0 = false;
1353///         }
1354///     }
1355/// }
1356///
1357/// // Sound the alarm if there are any criminals who pose a threat.
1358/// fn alert_criminal(
1359///     settlement: Single<&Settlement>,
1360///     criminals: Query<&Criminal>,
1361///     mut alarm: Deferred<AlarmFlag>
1362/// ) {
1363///     for criminal in &criminals {
1364///         // Only sound the alarm if the criminal is a threat.
1365///         // For this example, assume that this check is expensive to run.
1366///         // Since the majority of this system's run-time is dominated
1367///         // by calling `is_threat()`, we defer sounding the alarm to
1368///         // allow this system to run in parallel with other alarm systems.
1369///         if criminal.is_threat(*settlement) {
1370///             alarm.flag();
1371///         }
1372///     }
1373/// }
1374///
1375/// // Sound the alarm if there is a monster.
1376/// fn alert_monster(
1377///     monsters: Query<&Monster>,
1378///     mut alarm: ResMut<Alarm>
1379/// ) {
1380///     if monsters.iter().next().is_some() {
1381///         // Since this system does nothing except for sounding the alarm,
1382///         // it would be pointless to defer it, so we sound the alarm directly.
1383///         alarm.0 = true;
1384///     }
1385/// }
1386///
1387/// let mut world = World::new();
1388/// world.init_resource::<Alarm>();
1389/// world.spawn(Settlement {
1390///     // ...
1391/// });
1392///
1393/// let mut schedule = Schedule::default();
1394/// // These two systems have no conflicts and will run in parallel.
1395/// schedule.add_systems((alert_criminal, alert_monster));
1396///
1397/// // There are no criminals or monsters, so the alarm is not sounded.
1398/// schedule.run(&mut world);
1399/// assert_eq!(world.resource::<Alarm>().0, false);
1400///
1401/// // Spawn a monster, which will cause the alarm to be sounded.
1402/// let m_id = world.spawn(Monster).id();
1403/// schedule.run(&mut world);
1404/// assert_eq!(world.resource::<Alarm>().0, true);
1405///
1406/// // Remove the monster and reset the alarm.
1407/// world.entity_mut(m_id).despawn();
1408/// world.resource_mut::<Alarm>().0 = false;
1409///
1410/// // Spawn a criminal, which will cause the alarm to be sounded.
1411/// world.spawn(Criminal);
1412/// schedule.run(&mut world);
1413/// assert_eq!(world.resource::<Alarm>().0, true);
1414/// ```
1415pub struct Deferred<'a, T: SystemBuffer>(pub(crate) &'a mut T);
1416
1417impl<'a, T: SystemBuffer> Deref for Deferred<'a, T> {
1418    type Target = T;
1419    #[inline]
1420    fn deref(&self) -> &Self::Target {
1421        self.0
1422    }
1423}
1424
1425impl<'a, T: SystemBuffer> DerefMut for Deferred<'a, T> {
1426    #[inline]
1427    fn deref_mut(&mut self) -> &mut Self::Target {
1428        self.0
1429    }
1430}
1431
1432impl<T: SystemBuffer> Deferred<'_, T> {
1433    /// Returns a [`Deferred<T>`] with a smaller lifetime.
1434    /// This is useful if you have `&mut Deferred<T>` but need `Deferred<T>`.
1435    pub fn reborrow(&mut self) -> Deferred<T> {
1436        Deferred(self.0)
1437    }
1438}
1439
1440// SAFETY: Only local state is accessed.
1441unsafe impl<T: SystemBuffer> ReadOnlySystemParam for Deferred<'_, T> {}
1442
1443// SAFETY: Only local state is accessed.
1444unsafe impl<T: SystemBuffer> SystemParam for Deferred<'_, T> {
1445    type State = SyncCell<T>;
1446    type Item<'w, 's> = Deferred<'s, T>;
1447
1448    fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
1449        system_meta.set_has_deferred();
1450        SyncCell::new(T::from_world(world))
1451    }
1452
1453    fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1454        state.get().apply(system_meta, world);
1455    }
1456
1457    fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
1458        state.get().queue(system_meta, world);
1459    }
1460
1461    #[inline]
1462    unsafe fn get_param<'w, 's>(
1463        state: &'s mut Self::State,
1464        _system_meta: &SystemMeta,
1465        _world: UnsafeWorldCell<'w>,
1466        _change_tick: Tick,
1467    ) -> Self::Item<'w, 's> {
1468        Deferred(state.get())
1469    }
1470}
1471
1472/// Shared borrow of a non-[`Send`] resource.
1473///
1474/// Only `Send` resources may be accessed with the [`Res`] [`SystemParam`]. In case that the
1475/// resource does not implement `Send`, this `SystemParam` wrapper can be used. This will instruct
1476/// the scheduler to instead run the system on the main thread so that it doesn't send the resource
1477/// over to another thread.
1478///
1479/// This [`SystemParam`] fails validation if non-send resource doesn't exist.
1480/// This will cause a panic, but can be configured to do nothing or warn once.
1481///
1482/// Use [`Option<NonSend<T>>`] instead if the resource might not always exist.
1483pub struct NonSend<'w, T: 'static> {
1484    pub(crate) value: &'w T,
1485    ticks: ComponentTicks,
1486    last_run: Tick,
1487    this_run: Tick,
1488    changed_by: MaybeLocation<&'w &'static Location<'static>>,
1489}
1490
1491// SAFETY: Only reads a single World non-send resource
1492unsafe impl<'w, T> ReadOnlySystemParam for NonSend<'w, T> {}
1493
1494impl<'w, T> Debug for NonSend<'w, T>
1495where
1496    T: Debug,
1497{
1498    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1499        f.debug_tuple("NonSend").field(&self.value).finish()
1500    }
1501}
1502
1503impl<'w, T: 'static> NonSend<'w, T> {
1504    /// Returns `true` if the resource was added after the system last ran.
1505    pub fn is_added(&self) -> bool {
1506        self.ticks.is_added(self.last_run, self.this_run)
1507    }
1508
1509    /// Returns `true` if the resource was added or mutably dereferenced after the system last ran.
1510    pub fn is_changed(&self) -> bool {
1511        self.ticks.is_changed(self.last_run, self.this_run)
1512    }
1513
1514    /// The location that last caused this to change.
1515    pub fn changed_by(&self) -> MaybeLocation {
1516        self.changed_by.copied()
1517    }
1518}
1519
1520impl<'w, T> Deref for NonSend<'w, T> {
1521    type Target = T;
1522
1523    fn deref(&self) -> &Self::Target {
1524        self.value
1525    }
1526}
1527impl<'a, T> From<NonSendMut<'a, T>> for NonSend<'a, T> {
1528    fn from(nsm: NonSendMut<'a, T>) -> Self {
1529        Self {
1530            value: nsm.value,
1531            ticks: ComponentTicks {
1532                added: nsm.ticks.added.to_owned(),
1533                changed: nsm.ticks.changed.to_owned(),
1534            },
1535            this_run: nsm.ticks.this_run,
1536            last_run: nsm.ticks.last_run,
1537            changed_by: nsm.changed_by.map(|changed_by| &*changed_by),
1538        }
1539    }
1540}
1541
1542// SAFETY: NonSendComponentId and ArchetypeComponentId access is applied to SystemMeta. If this
1543// NonSend conflicts with any prior access, a panic will occur.
1544unsafe impl<'a, T: 'static> SystemParam for NonSend<'a, T> {
1545    type State = ComponentId;
1546    type Item<'w, 's> = NonSend<'w, T>;
1547
1548    fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
1549        system_meta.set_non_send();
1550
1551        let component_id = world.components_registrator().register_non_send::<T>();
1552        let archetype_component_id = world.initialize_non_send_internal(component_id).id();
1553
1554        let combined_access = system_meta.component_access_set.combined_access();
1555        assert!(
1556            !combined_access.has_resource_write(component_id),
1557            "error[B0002]: NonSend<{}> in system {} conflicts with a previous mutable resource access ({0}). Consider removing the duplicate access. See: https://bevyengine.org/learn/errors/b0002",
1558            core::any::type_name::<T>(),
1559            system_meta.name,
1560        );
1561        system_meta
1562            .component_access_set
1563            .add_unfiltered_resource_read(component_id);
1564
1565        system_meta
1566            .archetype_component_access
1567            .add_resource_read(archetype_component_id);
1568
1569        component_id
1570    }
1571
1572    #[inline]
1573    unsafe fn validate_param(
1574        &component_id: &Self::State,
1575        _system_meta: &SystemMeta,
1576        world: UnsafeWorldCell,
1577    ) -> Result<(), SystemParamValidationError> {
1578        // SAFETY: Read-only access to resource metadata.
1579        if unsafe { world.storages() }
1580            .non_send_resources
1581            .get(component_id)
1582            .is_some_and(ResourceData::is_present)
1583        {
1584            Ok(())
1585        } else {
1586            Err(SystemParamValidationError::invalid::<Self>(
1587                "Non-send resource does not exist",
1588            ))
1589        }
1590    }
1591
1592    #[inline]
1593    unsafe fn get_param<'w, 's>(
1594        &mut component_id: &'s mut Self::State,
1595        system_meta: &SystemMeta,
1596        world: UnsafeWorldCell<'w>,
1597        change_tick: Tick,
1598    ) -> Self::Item<'w, 's> {
1599        let (ptr, ticks, caller) =
1600            world
1601                .get_non_send_with_ticks(component_id)
1602                .unwrap_or_else(|| {
1603                    panic!(
1604                        "Non-send resource requested by {} does not exist: {}",
1605                        system_meta.name,
1606                        core::any::type_name::<T>()
1607                    )
1608                });
1609
1610        NonSend {
1611            value: ptr.deref(),
1612            ticks: ticks.read(),
1613            last_run: system_meta.last_run,
1614            this_run: change_tick,
1615            changed_by: caller.map(|caller| caller.deref()),
1616        }
1617    }
1618}
1619
1620// SAFETY: Only reads a single World non-send resource
1621unsafe impl<T: 'static> ReadOnlySystemParam for Option<NonSend<'_, T>> {}
1622
1623// SAFETY: this impl defers to `NonSend`, which initializes and validates the correct world access.
1624unsafe impl<T: 'static> SystemParam for Option<NonSend<'_, T>> {
1625    type State = ComponentId;
1626    type Item<'w, 's> = Option<NonSend<'w, T>>;
1627
1628    fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
1629        NonSend::<T>::init_state(world, system_meta)
1630    }
1631
1632    #[inline]
1633    unsafe fn get_param<'w, 's>(
1634        &mut component_id: &'s mut Self::State,
1635        system_meta: &SystemMeta,
1636        world: UnsafeWorldCell<'w>,
1637        change_tick: Tick,
1638    ) -> Self::Item<'w, 's> {
1639        world
1640            .get_non_send_with_ticks(component_id)
1641            .map(|(ptr, ticks, caller)| NonSend {
1642                value: ptr.deref(),
1643                ticks: ticks.read(),
1644                last_run: system_meta.last_run,
1645                this_run: change_tick,
1646                changed_by: caller.map(|caller| caller.deref()),
1647            })
1648    }
1649}
1650
1651// SAFETY: NonSendMut ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this
1652// NonSendMut conflicts with any prior access, a panic will occur.
1653unsafe impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> {
1654    type State = ComponentId;
1655    type Item<'w, 's> = NonSendMut<'w, T>;
1656
1657    fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
1658        system_meta.set_non_send();
1659
1660        let component_id = world.components_registrator().register_non_send::<T>();
1661        let archetype_component_id = world.initialize_non_send_internal(component_id).id();
1662
1663        let combined_access = system_meta.component_access_set.combined_access();
1664        if combined_access.has_component_write(component_id) {
1665            panic!(
1666                "error[B0002]: NonSendMut<{}> in system {} conflicts with a previous mutable resource access ({0}). Consider removing the duplicate access. See: https://bevyengine.org/learn/errors/b0002",
1667                core::any::type_name::<T>(), system_meta.name);
1668        } else if combined_access.has_component_read(component_id) {
1669            panic!(
1670                "error[B0002]: NonSendMut<{}> in system {} conflicts with a previous immutable resource access ({0}). Consider removing the duplicate access. See: https://bevyengine.org/learn/errors/b0002",
1671                core::any::type_name::<T>(), system_meta.name);
1672        }
1673        system_meta
1674            .component_access_set
1675            .add_unfiltered_resource_write(component_id);
1676
1677        system_meta
1678            .archetype_component_access
1679            .add_resource_write(archetype_component_id);
1680
1681        component_id
1682    }
1683
1684    #[inline]
1685    unsafe fn validate_param(
1686        &component_id: &Self::State,
1687        _system_meta: &SystemMeta,
1688        world: UnsafeWorldCell,
1689    ) -> Result<(), SystemParamValidationError> {
1690        // SAFETY: Read-only access to resource metadata.
1691        if unsafe { world.storages() }
1692            .non_send_resources
1693            .get(component_id)
1694            .is_some_and(ResourceData::is_present)
1695        {
1696            Ok(())
1697        } else {
1698            Err(SystemParamValidationError::invalid::<Self>(
1699                "Non-send resource does not exist",
1700            ))
1701        }
1702    }
1703
1704    #[inline]
1705    unsafe fn get_param<'w, 's>(
1706        &mut component_id: &'s mut Self::State,
1707        system_meta: &SystemMeta,
1708        world: UnsafeWorldCell<'w>,
1709        change_tick: Tick,
1710    ) -> Self::Item<'w, 's> {
1711        let (ptr, ticks, caller) =
1712            world
1713                .get_non_send_with_ticks(component_id)
1714                .unwrap_or_else(|| {
1715                    panic!(
1716                        "Non-send resource requested by {} does not exist: {}",
1717                        system_meta.name,
1718                        core::any::type_name::<T>()
1719                    )
1720                });
1721        NonSendMut {
1722            value: ptr.assert_unique().deref_mut(),
1723            ticks: TicksMut::from_tick_cells(ticks, system_meta.last_run, change_tick),
1724            changed_by: caller.map(|caller| caller.deref_mut()),
1725        }
1726    }
1727}
1728
1729// SAFETY: this impl defers to `NonSendMut`, which initializes and validates the correct world access.
1730unsafe impl<'a, T: 'static> SystemParam for Option<NonSendMut<'a, T>> {
1731    type State = ComponentId;
1732    type Item<'w, 's> = Option<NonSendMut<'w, T>>;
1733
1734    fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
1735        NonSendMut::<T>::init_state(world, system_meta)
1736    }
1737
1738    #[inline]
1739    unsafe fn get_param<'w, 's>(
1740        &mut component_id: &'s mut Self::State,
1741        system_meta: &SystemMeta,
1742        world: UnsafeWorldCell<'w>,
1743        change_tick: Tick,
1744    ) -> Self::Item<'w, 's> {
1745        world
1746            .get_non_send_with_ticks(component_id)
1747            .map(|(ptr, ticks, caller)| NonSendMut {
1748                value: ptr.assert_unique().deref_mut(),
1749                ticks: TicksMut::from_tick_cells(ticks, system_meta.last_run, change_tick),
1750                changed_by: caller.map(|caller| caller.deref_mut()),
1751            })
1752    }
1753}
1754
1755// SAFETY: Only reads World archetypes
1756unsafe impl<'a> ReadOnlySystemParam for &'a Archetypes {}
1757
1758// SAFETY: no component value access
1759unsafe impl<'a> SystemParam for &'a Archetypes {
1760    type State = ();
1761    type Item<'w, 's> = &'w Archetypes;
1762
1763    fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {}
1764
1765    #[inline]
1766    unsafe fn get_param<'w, 's>(
1767        _state: &'s mut Self::State,
1768        _system_meta: &SystemMeta,
1769        world: UnsafeWorldCell<'w>,
1770        _change_tick: Tick,
1771    ) -> Self::Item<'w, 's> {
1772        world.archetypes()
1773    }
1774}
1775
1776// SAFETY: Only reads World components
1777unsafe impl<'a> ReadOnlySystemParam for &'a Components {}
1778
1779// SAFETY: no component value access
1780unsafe impl<'a> SystemParam for &'a Components {
1781    type State = ();
1782    type Item<'w, 's> = &'w Components;
1783
1784    fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {}
1785
1786    #[inline]
1787    unsafe fn get_param<'w, 's>(
1788        _state: &'s mut Self::State,
1789        _system_meta: &SystemMeta,
1790        world: UnsafeWorldCell<'w>,
1791        _change_tick: Tick,
1792    ) -> Self::Item<'w, 's> {
1793        world.components()
1794    }
1795}
1796
1797// SAFETY: Only reads World entities
1798unsafe impl<'a> ReadOnlySystemParam for &'a Entities {}
1799
1800// SAFETY: no component value access
1801unsafe impl<'a> SystemParam for &'a Entities {
1802    type State = ();
1803    type Item<'w, 's> = &'w Entities;
1804
1805    fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {}
1806
1807    #[inline]
1808    unsafe fn get_param<'w, 's>(
1809        _state: &'s mut Self::State,
1810        _system_meta: &SystemMeta,
1811        world: UnsafeWorldCell<'w>,
1812        _change_tick: Tick,
1813    ) -> Self::Item<'w, 's> {
1814        world.entities()
1815    }
1816}
1817
1818// SAFETY: Only reads World bundles
1819unsafe impl<'a> ReadOnlySystemParam for &'a Bundles {}
1820
1821// SAFETY: no component value access
1822unsafe impl<'a> SystemParam for &'a Bundles {
1823    type State = ();
1824    type Item<'w, 's> = &'w Bundles;
1825
1826    fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {}
1827
1828    #[inline]
1829    unsafe fn get_param<'w, 's>(
1830        _state: &'s mut Self::State,
1831        _system_meta: &SystemMeta,
1832        world: UnsafeWorldCell<'w>,
1833        _change_tick: Tick,
1834    ) -> Self::Item<'w, 's> {
1835        world.bundles()
1836    }
1837}
1838
1839/// A [`SystemParam`] that reads the previous and current change ticks of the system.
1840///
1841/// A system's change ticks are updated each time it runs:
1842/// - `last_run` copies the previous value of `change_tick`
1843/// - `this_run` copies the current value of [`World::read_change_tick`]
1844///
1845/// Component change ticks that are more recent than `last_run` will be detected by the system.
1846/// Those can be read by calling [`last_changed`](crate::change_detection::DetectChanges::last_changed)
1847/// on a [`Mut<T>`](crate::change_detection::Mut) or [`ResMut<T>`](ResMut).
1848#[derive(Debug)]
1849pub struct SystemChangeTick {
1850    last_run: Tick,
1851    this_run: Tick,
1852}
1853
1854impl SystemChangeTick {
1855    /// Returns the current [`World`] change tick seen by the system.
1856    #[inline]
1857    pub fn this_run(&self) -> Tick {
1858        self.this_run
1859    }
1860
1861    /// Returns the [`World`] change tick seen by the system the previous time it ran.
1862    #[inline]
1863    pub fn last_run(&self) -> Tick {
1864        self.last_run
1865    }
1866}
1867
1868// SAFETY: Only reads internal system state
1869unsafe impl ReadOnlySystemParam for SystemChangeTick {}
1870
1871// SAFETY: `SystemChangeTick` doesn't require any world access
1872unsafe impl SystemParam for SystemChangeTick {
1873    type State = ();
1874    type Item<'w, 's> = SystemChangeTick;
1875
1876    fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {}
1877
1878    #[inline]
1879    unsafe fn get_param<'w, 's>(
1880        _state: &'s mut Self::State,
1881        system_meta: &SystemMeta,
1882        _world: UnsafeWorldCell<'w>,
1883        change_tick: Tick,
1884    ) -> Self::Item<'w, 's> {
1885        SystemChangeTick {
1886            last_run: system_meta.last_run,
1887            this_run: change_tick,
1888        }
1889    }
1890}
1891
1892// SAFETY: When initialized with `init_state`, `get_param` returns an empty `Vec` and does no access.
1893// Therefore, `init_state` trivially registers all access, and no accesses can conflict.
1894// Note that the safety requirements for non-empty `Vec`s are handled by the `SystemParamBuilder` impl that builds them.
1895unsafe impl<T: SystemParam> SystemParam for Vec<T> {
1896    type State = Vec<T::State>;
1897
1898    type Item<'world, 'state> = Vec<T::Item<'world, 'state>>;
1899
1900    fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {
1901        Vec::new()
1902    }
1903
1904    #[inline]
1905    unsafe fn validate_param(
1906        state: &Self::State,
1907        system_meta: &SystemMeta,
1908        world: UnsafeWorldCell,
1909    ) -> Result<(), SystemParamValidationError> {
1910        for state in state {
1911            T::validate_param(state, system_meta, world)?;
1912        }
1913        Ok(())
1914    }
1915
1916    #[inline]
1917    unsafe fn get_param<'world, 'state>(
1918        state: &'state mut Self::State,
1919        system_meta: &SystemMeta,
1920        world: UnsafeWorldCell<'world>,
1921        change_tick: Tick,
1922    ) -> Self::Item<'world, 'state> {
1923        state
1924            .iter_mut()
1925            // SAFETY:
1926            // - We initialized the state for each parameter in the builder, so the caller ensures we have access to any world data needed by each param.
1927            // - The caller ensures this was the world used to initialize our state, and we used that world to initialize parameter states
1928            .map(|state| unsafe { T::get_param(state, system_meta, world, change_tick) })
1929            .collect()
1930    }
1931
1932    unsafe fn new_archetype(
1933        state: &mut Self::State,
1934        archetype: &Archetype,
1935        system_meta: &mut SystemMeta,
1936    ) {
1937        for state in state {
1938            // SAFETY: The caller ensures that `archetype` is from the World the state was initialized from in `init_state`.
1939            unsafe { T::new_archetype(state, archetype, system_meta) };
1940        }
1941    }
1942
1943    fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1944        for state in state {
1945            T::apply(state, system_meta, world);
1946        }
1947    }
1948
1949    fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
1950        for state in state {
1951            T::queue(state, system_meta, world.reborrow());
1952        }
1953    }
1954}
1955
1956// SAFETY: When initialized with `init_state`, `get_param` returns an empty `Vec` and does no access.
1957// Therefore, `init_state` trivially registers all access, and no accesses can conflict.
1958// Note that the safety requirements for non-empty `Vec`s are handled by the `SystemParamBuilder` impl that builds them.
1959unsafe impl<T: SystemParam> SystemParam for ParamSet<'_, '_, Vec<T>> {
1960    type State = Vec<T::State>;
1961
1962    type Item<'world, 'state> = ParamSet<'world, 'state, Vec<T>>;
1963
1964    fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {
1965        Vec::new()
1966    }
1967
1968    #[inline]
1969    unsafe fn get_param<'world, 'state>(
1970        state: &'state mut Self::State,
1971        system_meta: &SystemMeta,
1972        world: UnsafeWorldCell<'world>,
1973        change_tick: Tick,
1974    ) -> Self::Item<'world, 'state> {
1975        ParamSet {
1976            param_states: state,
1977            system_meta: system_meta.clone(),
1978            world,
1979            change_tick,
1980        }
1981    }
1982
1983    unsafe fn new_archetype(
1984        state: &mut Self::State,
1985        archetype: &Archetype,
1986        system_meta: &mut SystemMeta,
1987    ) {
1988        for state in state {
1989            // SAFETY: The caller ensures that `archetype` is from the World the state was initialized from in `init_state`.
1990            unsafe { T::new_archetype(state, archetype, system_meta) }
1991        }
1992    }
1993
1994    fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1995        for state in state {
1996            T::apply(state, system_meta, world);
1997        }
1998    }
1999
2000    fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
2001        for state in state {
2002            T::queue(state, system_meta, world.reborrow());
2003        }
2004    }
2005}
2006
2007impl<T: SystemParam> ParamSet<'_, '_, Vec<T>> {
2008    /// Accesses the parameter at the given index.
2009    /// No other parameters may be accessed while this one is active.
2010    pub fn get_mut(&mut self, index: usize) -> T::Item<'_, '_> {
2011        // SAFETY:
2012        // - We initialized the state for each parameter in the builder, so the caller ensures we have access to any world data needed by any param.
2013        //   We have mutable access to the ParamSet, so no other params in the set are active.
2014        // - The caller of `get_param` ensured that this was the world used to initialize our state, and we used that world to initialize parameter states
2015        unsafe {
2016            T::get_param(
2017                &mut self.param_states[index],
2018                &self.system_meta,
2019                self.world,
2020                self.change_tick,
2021            )
2022        }
2023    }
2024
2025    /// Calls a closure for each parameter in the set.
2026    pub fn for_each(&mut self, mut f: impl FnMut(T::Item<'_, '_>)) {
2027        self.param_states.iter_mut().for_each(|state| {
2028            f(
2029                // SAFETY:
2030                // - We initialized the state for each parameter in the builder, so the caller ensures we have access to any world data needed by any param.
2031                //   We have mutable access to the ParamSet, so no other params in the set are active.
2032                // - The caller of `get_param` ensured that this was the world used to initialize our state, and we used that world to initialize parameter states
2033                unsafe { T::get_param(state, &self.system_meta, self.world, self.change_tick) },
2034            );
2035        });
2036    }
2037}
2038
2039macro_rules! impl_system_param_tuple {
2040    ($(#[$meta:meta])* $($param: ident),*) => {
2041        $(#[$meta])*
2042        // SAFETY: tuple consists only of ReadOnlySystemParams
2043        unsafe impl<$($param: ReadOnlySystemParam),*> ReadOnlySystemParam for ($($param,)*) {}
2044
2045        #[expect(
2046            clippy::allow_attributes,
2047            reason = "This is in a macro, and as such, the below lints may not always apply."
2048        )]
2049        #[allow(
2050            non_snake_case,
2051            reason = "Certain variable names are provided by the caller, not by us."
2052        )]
2053        #[allow(
2054            unused_variables,
2055            reason = "Zero-length tuples won't use some of the parameters."
2056        )]
2057        $(#[$meta])*
2058        // SAFETY: implementers of each `SystemParam` in the tuple have validated their impls
2059        unsafe impl<$($param: SystemParam),*> SystemParam for ($($param,)*) {
2060            type State = ($($param::State,)*);
2061            type Item<'w, 's> = ($($param::Item::<'w, 's>,)*);
2062
2063            #[inline]
2064            fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
2065                (($($param::init_state(world, system_meta),)*))
2066            }
2067
2068            #[inline]
2069            unsafe fn new_archetype(($($param,)*): &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta) {
2070                #[allow(
2071                    unused_unsafe,
2072                    reason = "Zero-length tuples will not run anything in the unsafe block."
2073                )]
2074                // SAFETY: The caller ensures that `archetype` is from the World the state was initialized from in `init_state`.
2075                unsafe { $($param::new_archetype($param, archetype, system_meta);)* }
2076            }
2077
2078            #[inline]
2079            fn apply(($($param,)*): &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
2080                $($param::apply($param, system_meta, world);)*
2081            }
2082
2083            #[inline]
2084            #[allow(
2085                unused_mut,
2086                reason = "The `world` parameter is unused for zero-length tuples; however, it must be mutable for other lengths of tuples."
2087            )]
2088            fn queue(($($param,)*): &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
2089                $($param::queue($param, system_meta, world.reborrow());)*
2090            }
2091
2092            #[inline]
2093            unsafe fn validate_param(
2094                state: &Self::State,
2095                system_meta: &SystemMeta,
2096                world: UnsafeWorldCell,
2097            ) -> Result<(), SystemParamValidationError> {
2098                let ($($param,)*) = state;
2099                $(
2100                    $param::validate_param($param, system_meta, world)?;
2101                )*
2102                Ok(())
2103            }
2104
2105            #[inline]
2106            unsafe fn get_param<'w, 's>(
2107                state: &'s mut Self::State,
2108                system_meta: &SystemMeta,
2109                world: UnsafeWorldCell<'w>,
2110                change_tick: Tick,
2111            ) -> Self::Item<'w, 's> {
2112                let ($($param,)*) = state;
2113                #[allow(
2114                    clippy::unused_unit,
2115                    reason = "Zero-length tuples won't have any params to get."
2116                )]
2117                ($($param::get_param($param, system_meta, world, change_tick),)*)
2118            }
2119        }
2120    };
2121}
2122
2123all_tuples!(
2124    #[doc(fake_variadic)]
2125    impl_system_param_tuple,
2126    0,
2127    16,
2128    P
2129);
2130
2131/// Contains type aliases for built-in [`SystemParam`]s with `'static` lifetimes.
2132/// This makes it more convenient to refer to these types in contexts where
2133/// explicit lifetime annotations are required.
2134///
2135/// Note that this is entirely safe and tracks lifetimes correctly.
2136/// This purely exists for convenience.
2137///
2138/// You can't instantiate a static `SystemParam`, you'll always end up with
2139/// `Res<'w, T>`, `ResMut<'w, T>` or `&'w T` bound to the lifetime of the provided
2140/// `&'w World`.
2141///
2142/// [`SystemParam`]: super::SystemParam
2143pub mod lifetimeless {
2144    /// A [`Query`](super::Query) with `'static` lifetimes.
2145    pub type SQuery<D, F = ()> = super::Query<'static, 'static, D, F>;
2146    /// A shorthand for writing `&'static T`.
2147    pub type Read<T> = &'static T;
2148    /// A shorthand for writing `&'static mut T`.
2149    pub type Write<T> = &'static mut T;
2150    /// A [`Res`](super::Res) with `'static` lifetimes.
2151    pub type SRes<T> = super::Res<'static, T>;
2152    /// A [`ResMut`](super::ResMut) with `'static` lifetimes.
2153    pub type SResMut<T> = super::ResMut<'static, T>;
2154    /// [`Commands`](crate::system::Commands) with `'static` lifetimes.
2155    pub type SCommands = crate::system::Commands<'static, 'static>;
2156}
2157
2158/// A helper for using system parameters in generic contexts
2159///
2160/// This type is a [`SystemParam`] adapter which always has
2161/// `Self::Item == Self` (ignoring lifetimes for brevity),
2162/// no matter the argument [`SystemParam`] (`P`) (other than
2163/// that `P` must be `'static`)
2164///
2165/// This makes it useful for having arbitrary [`SystemParam`] type arguments
2166/// to function systems, or for generic types using the [`derive@SystemParam`]
2167/// derive:
2168///
2169/// ```
2170/// # use bevy_ecs::prelude::*;
2171/// use bevy_ecs::system::{SystemParam, StaticSystemParam};
2172/// #[derive(SystemParam)]
2173/// struct GenericParam<'w,'s, T: SystemParam + 'static> {
2174///     field: StaticSystemParam<'w, 's, T>,
2175/// }
2176/// fn do_thing_generically<T: SystemParam + 'static>(t: StaticSystemParam<T>) {}
2177///
2178/// fn check_always_is_system<T: SystemParam + 'static>(){
2179///     bevy_ecs::system::assert_is_system(do_thing_generically::<T>);
2180/// }
2181/// ```
2182/// Note that in a real case you'd generally want
2183/// additional bounds on `P`, for your use of the parameter
2184/// to have a reason to be generic.
2185///
2186/// For example, using this would allow a type to be generic over
2187/// whether a resource is accessed mutably or not, with
2188/// impls being bounded on [`P: Deref<Target=MyType>`](Deref), and
2189/// [`P: DerefMut<Target=MyType>`](DerefMut) depending on whether the
2190/// method requires mutable access or not.
2191///
2192/// The method which doesn't use this type will not compile:
2193/// ```compile_fail
2194/// # use bevy_ecs::prelude::*;
2195/// # use bevy_ecs::system::{SystemParam, StaticSystemParam};
2196///
2197/// fn do_thing_generically<T: SystemParam + 'static>(t: T) {}
2198///
2199/// #[derive(SystemParam)]
2200/// struct GenericParam<'w, 's, T: SystemParam> {
2201///     field: T,
2202///     // Use the lifetimes in this type, or they will be unbound.
2203///     phantom: std::marker::PhantomData<&'w &'s ()>
2204/// }
2205/// # fn check_always_is_system<T: SystemParam + 'static>(){
2206/// #    bevy_ecs::system::assert_is_system(do_thing_generically::<T>);
2207/// # }
2208/// ```
2209pub struct StaticSystemParam<'w, 's, P: SystemParam>(SystemParamItem<'w, 's, P>);
2210
2211impl<'w, 's, P: SystemParam> Deref for StaticSystemParam<'w, 's, P> {
2212    type Target = SystemParamItem<'w, 's, P>;
2213
2214    fn deref(&self) -> &Self::Target {
2215        &self.0
2216    }
2217}
2218
2219impl<'w, 's, P: SystemParam> DerefMut for StaticSystemParam<'w, 's, P> {
2220    fn deref_mut(&mut self) -> &mut Self::Target {
2221        &mut self.0
2222    }
2223}
2224
2225impl<'w, 's, P: SystemParam> StaticSystemParam<'w, 's, P> {
2226    /// Get the value of the parameter
2227    pub fn into_inner(self) -> SystemParamItem<'w, 's, P> {
2228        self.0
2229    }
2230}
2231
2232// SAFETY: This doesn't add any more reads, and the delegated fetch confirms it
2233unsafe impl<'w, 's, P: ReadOnlySystemParam + 'static> ReadOnlySystemParam
2234    for StaticSystemParam<'w, 's, P>
2235{
2236}
2237
2238// SAFETY: all methods are just delegated to `P`'s `SystemParam` implementation
2239unsafe impl<P: SystemParam + 'static> SystemParam for StaticSystemParam<'_, '_, P> {
2240    type State = P::State;
2241    type Item<'world, 'state> = StaticSystemParam<'world, 'state, P>;
2242
2243    fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
2244        P::init_state(world, system_meta)
2245    }
2246
2247    unsafe fn new_archetype(
2248        state: &mut Self::State,
2249        archetype: &Archetype,
2250        system_meta: &mut SystemMeta,
2251    ) {
2252        // SAFETY: The caller guarantees that the provided `archetype` matches the World used to initialize `state`.
2253        unsafe { P::new_archetype(state, archetype, system_meta) };
2254    }
2255
2256    fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
2257        P::apply(state, system_meta, world);
2258    }
2259
2260    fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
2261        P::queue(state, system_meta, world);
2262    }
2263
2264    #[inline]
2265    unsafe fn validate_param(
2266        state: &Self::State,
2267        system_meta: &SystemMeta,
2268        world: UnsafeWorldCell,
2269    ) -> Result<(), SystemParamValidationError> {
2270        P::validate_param(state, system_meta, world)
2271    }
2272
2273    #[inline]
2274    unsafe fn get_param<'world, 'state>(
2275        state: &'state mut Self::State,
2276        system_meta: &SystemMeta,
2277        world: UnsafeWorldCell<'world>,
2278        change_tick: Tick,
2279    ) -> Self::Item<'world, 'state> {
2280        // SAFETY: Defer to the safety of P::SystemParam
2281        StaticSystemParam(unsafe { P::get_param(state, system_meta, world, change_tick) })
2282    }
2283}
2284
2285// SAFETY: No world access.
2286unsafe impl<T: ?Sized> SystemParam for PhantomData<T> {
2287    type State = ();
2288    type Item<'world, 'state> = Self;
2289
2290    fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {}
2291
2292    #[inline]
2293    unsafe fn get_param<'world, 'state>(
2294        _state: &'state mut Self::State,
2295        _system_meta: &SystemMeta,
2296        _world: UnsafeWorldCell<'world>,
2297        _change_tick: Tick,
2298    ) -> Self::Item<'world, 'state> {
2299        PhantomData
2300    }
2301}
2302
2303// SAFETY: No world access.
2304unsafe impl<T: ?Sized> ReadOnlySystemParam for PhantomData<T> {}
2305
2306/// A [`SystemParam`] with a type that can be configured at runtime.
2307///
2308/// To be useful, this must be configured using a [`DynParamBuilder`](crate::system::DynParamBuilder) to build the system using a [`SystemParamBuilder`](crate::prelude::SystemParamBuilder).
2309///
2310/// # Examples
2311///
2312/// ```
2313/// # use bevy_ecs::{prelude::*, system::*};
2314/// #
2315/// # #[derive(Default, Resource)]
2316/// # struct A;
2317/// #
2318/// # #[derive(Default, Resource)]
2319/// # struct B;
2320/// #
2321/// # let mut world = World::new();
2322/// # world.init_resource::<A>();
2323/// # world.init_resource::<B>();
2324/// #
2325/// // If the inner parameter doesn't require any special building, use `ParamBuilder`.
2326/// // Either specify the type parameter on `DynParamBuilder::new()` ...
2327/// let system = (DynParamBuilder::new::<Res<A>>(ParamBuilder),)
2328///     .build_state(&mut world)
2329///     .build_system(expects_res_a);
2330/// # world.run_system_once(system);
2331///
2332/// // ... or use a factory method on `ParamBuilder` that returns a specific type.
2333/// let system = (DynParamBuilder::new(ParamBuilder::resource::<A>()),)
2334///     .build_state(&mut world)
2335///     .build_system(expects_res_a);
2336/// # world.run_system_once(system);
2337///
2338/// fn expects_res_a(mut param: DynSystemParam) {
2339///     // Use the `downcast` methods to retrieve the inner parameter.
2340///     // They will return `None` if the type does not match.
2341///     assert!(param.is::<Res<A>>());
2342///     assert!(!param.is::<Res<B>>());
2343///     assert!(param.downcast_mut::<Res<B>>().is_none());
2344///     let res = param.downcast_mut::<Res<A>>().unwrap();
2345///     // The type parameter can be left out if it can be determined from use.
2346///     let res: Res<A> = param.downcast().unwrap();
2347/// }
2348///
2349/// let system = (
2350///     // If the inner parameter also requires building,
2351///     // pass the appropriate `SystemParamBuilder`.
2352///     DynParamBuilder::new(LocalBuilder(10usize)),
2353///     // `DynSystemParam` is just an ordinary `SystemParam`,
2354///     // and can be combined with other parameters as usual!
2355///     ParamBuilder::query(),
2356/// )
2357///     .build_state(&mut world)
2358///     .build_system(|param: DynSystemParam, query: Query<()>| {
2359///         let local: Local<usize> = param.downcast::<Local<usize>>().unwrap();
2360///         assert_eq!(*local, 10);
2361///     });
2362/// # world.run_system_once(system);
2363/// ```
2364pub struct DynSystemParam<'w, 's> {
2365    /// A `ParamState<T>` wrapping the state for the underlying system param.
2366    state: &'s mut dyn Any,
2367    world: UnsafeWorldCell<'w>,
2368    system_meta: SystemMeta,
2369    change_tick: Tick,
2370}
2371
2372impl<'w, 's> DynSystemParam<'w, 's> {
2373    /// # Safety
2374    /// - `state` must be a `ParamState<T>` for some inner `T: SystemParam`.
2375    /// - The passed [`UnsafeWorldCell`] must have access to any world data registered
2376    ///   in [`init_state`](SystemParam::init_state) for the inner system param.
2377    /// - `world` must be the same `World` that was used to initialize
2378    ///   [`state`](SystemParam::init_state) for the inner system param.
2379    unsafe fn new(
2380        state: &'s mut dyn Any,
2381        world: UnsafeWorldCell<'w>,
2382        system_meta: SystemMeta,
2383        change_tick: Tick,
2384    ) -> Self {
2385        Self {
2386            state,
2387            world,
2388            system_meta,
2389            change_tick,
2390        }
2391    }
2392
2393    /// Returns `true` if the inner system param is the same as `T`.
2394    pub fn is<T: SystemParam>(&self) -> bool
2395    // See downcast() function for an explanation of the where clause
2396    where
2397        T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,
2398    {
2399        self.state.is::<ParamState<T::Item<'static, 'static>>>()
2400    }
2401
2402    /// Returns the inner system param if it is the correct type.
2403    /// This consumes the dyn param, so the returned param can have its original world and state lifetimes.
2404    pub fn downcast<T: SystemParam>(self) -> Option<T>
2405    // See downcast() function for an explanation of the where clause
2406    where
2407        T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,
2408    {
2409        // SAFETY:
2410        // - `DynSystemParam::new()` ensures `state` is a `ParamState<T>`, that the world matches,
2411        //   and that it has access required by the inner system param.
2412        // - This consumes the `DynSystemParam`, so it is the only use of `world` with this access and it is available for `'w`.
2413        unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }
2414    }
2415
2416    /// Returns the inner system parameter if it is the correct type.
2417    /// This borrows the dyn param, so the returned param is only valid for the duration of that borrow.
2418    pub fn downcast_mut<'a, T: SystemParam>(&'a mut self) -> Option<T>
2419    // See downcast() function for an explanation of the where clause
2420    where
2421        T::Item<'static, 'static>: SystemParam<Item<'a, 'a> = T> + 'static,
2422    {
2423        // SAFETY:
2424        // - `DynSystemParam::new()` ensures `state` is a `ParamState<T>`, that the world matches,
2425        //   and that it has access required by the inner system param.
2426        // - This exclusively borrows the `DynSystemParam` for `'_`, so it is the only use of `world` with this access for `'_`.
2427        unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }
2428    }
2429
2430    /// Returns the inner system parameter if it is the correct type.
2431    /// This borrows the dyn param, so the returned param is only valid for the duration of that borrow,
2432    /// but since it only performs read access it can keep the original world lifetime.
2433    /// This can be useful with methods like [`Query::iter_inner()`] or [`Res::into_inner()`]
2434    /// to obtain references with the original world lifetime.
2435    pub fn downcast_mut_inner<'a, T: ReadOnlySystemParam>(&'a mut self) -> Option<T>
2436    // See downcast() function for an explanation of the where clause
2437    where
2438        T::Item<'static, 'static>: SystemParam<Item<'w, 'a> = T> + 'static,
2439    {
2440        // SAFETY:
2441        // - `DynSystemParam::new()` ensures `state` is a `ParamState<T>`, that the world matches,
2442        //   and that it has access required by the inner system param.
2443        // - The inner system param only performs read access, so it's safe to copy that access for the full `'w` lifetime.
2444        unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }
2445    }
2446}
2447
2448/// # Safety
2449/// - `state` must be a `ParamState<T>` for some inner `T: SystemParam`.
2450/// - The passed [`UnsafeWorldCell`] must have access to any world data registered
2451///   in [`init_state`](SystemParam::init_state) for the inner system param.
2452/// - `world` must be the same `World` that was used to initialize
2453///   [`state`](SystemParam::init_state) for the inner system param.
2454unsafe fn downcast<'w, 's, T: SystemParam>(
2455    state: &'s mut dyn Any,
2456    system_meta: &SystemMeta,
2457    world: UnsafeWorldCell<'w>,
2458    change_tick: Tick,
2459) -> Option<T>
2460// We need a 'static version of the SystemParam to use with `Any::downcast_mut()`,
2461// and we need a <'w, 's> version to actually return.
2462// The type parameter T must be the one we return in order to get type inference from the return value.
2463// So we use `T::Item<'static, 'static>` as the 'static version, and require that it be 'static.
2464// That means the return value will be T::Item<'static, 'static>::Item<'w, 's>,
2465// so we constrain that to be equal to T.
2466// Every actual `SystemParam` implementation has `T::Item == T` up to lifetimes,
2467// so they should all work with this constraint.
2468where
2469    T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,
2470{
2471    state
2472        .downcast_mut::<ParamState<T::Item<'static, 'static>>>()
2473        .map(|state| {
2474            // SAFETY:
2475            // - The caller ensures the world has access for the underlying system param,
2476            //   and since the downcast succeeded, the underlying system param is T.
2477            // - The caller ensures the `world` matches.
2478            unsafe { T::Item::get_param(&mut state.0, system_meta, world, change_tick) }
2479        })
2480}
2481
2482/// The [`SystemParam::State`] for a [`DynSystemParam`].
2483pub struct DynSystemParamState(Box<dyn DynParamState>);
2484
2485impl DynSystemParamState {
2486    pub(crate) fn new<T: SystemParam + 'static>(state: T::State) -> Self {
2487        Self(Box::new(ParamState::<T>(state)))
2488    }
2489}
2490
2491/// Allows a [`SystemParam::State`] to be used as a trait object for implementing [`DynSystemParam`].
2492trait DynParamState: Sync + Send {
2493    /// Casts the underlying `ParamState<T>` to an `Any` so it can be downcast.
2494    fn as_any_mut(&mut self) -> &mut dyn Any;
2495
2496    /// For the specified [`Archetype`], registers the components accessed by this [`SystemParam`] (if applicable).a
2497    ///
2498    /// # Safety
2499    /// `archetype` must be from the [`World`] used to initialize `state` in [`SystemParam::init_state`].
2500    unsafe fn new_archetype(&mut self, archetype: &Archetype, system_meta: &mut SystemMeta);
2501
2502    /// Applies any deferred mutations stored in this [`SystemParam`]'s state.
2503    /// This is used to apply [`Commands`] during [`ApplyDeferred`](crate::prelude::ApplyDeferred).
2504    ///
2505    /// [`Commands`]: crate::prelude::Commands
2506    fn apply(&mut self, system_meta: &SystemMeta, world: &mut World);
2507
2508    /// Queues any deferred mutations to be applied at the next [`ApplyDeferred`](crate::prelude::ApplyDeferred).
2509    fn queue(&mut self, system_meta: &SystemMeta, world: DeferredWorld);
2510
2511    /// Refer to [`SystemParam::validate_param`].
2512    ///
2513    /// # Safety
2514    /// Refer to [`SystemParam::validate_param`].
2515    unsafe fn validate_param(
2516        &self,
2517        system_meta: &SystemMeta,
2518        world: UnsafeWorldCell,
2519    ) -> Result<(), SystemParamValidationError>;
2520}
2521
2522/// A wrapper around a [`SystemParam::State`] that can be used as a trait object in a [`DynSystemParam`].
2523struct ParamState<T: SystemParam>(T::State);
2524
2525impl<T: SystemParam + 'static> DynParamState for ParamState<T> {
2526    fn as_any_mut(&mut self) -> &mut dyn Any {
2527        self
2528    }
2529
2530    unsafe fn new_archetype(&mut self, archetype: &Archetype, system_meta: &mut SystemMeta) {
2531        // SAFETY: The caller ensures that `archetype` is from the World the state was initialized from in `init_state`.
2532        unsafe { T::new_archetype(&mut self.0, archetype, system_meta) };
2533    }
2534
2535    fn apply(&mut self, system_meta: &SystemMeta, world: &mut World) {
2536        T::apply(&mut self.0, system_meta, world);
2537    }
2538
2539    fn queue(&mut self, system_meta: &SystemMeta, world: DeferredWorld) {
2540        T::queue(&mut self.0, system_meta, world);
2541    }
2542
2543    unsafe fn validate_param(
2544        &self,
2545        system_meta: &SystemMeta,
2546        world: UnsafeWorldCell,
2547    ) -> Result<(), SystemParamValidationError> {
2548        T::validate_param(&self.0, system_meta, world)
2549    }
2550}
2551
2552// SAFETY: `init_state` creates a state of (), which performs no access.  The interesting safety checks are on the `SystemParamBuilder`.
2553unsafe impl SystemParam for DynSystemParam<'_, '_> {
2554    type State = DynSystemParamState;
2555
2556    type Item<'world, 'state> = DynSystemParam<'world, 'state>;
2557
2558    fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {
2559        DynSystemParamState::new::<()>(())
2560    }
2561
2562    #[inline]
2563    unsafe fn validate_param(
2564        state: &Self::State,
2565        system_meta: &SystemMeta,
2566        world: UnsafeWorldCell,
2567    ) -> Result<(), SystemParamValidationError> {
2568        state.0.validate_param(system_meta, world)
2569    }
2570
2571    #[inline]
2572    unsafe fn get_param<'world, 'state>(
2573        state: &'state mut Self::State,
2574        system_meta: &SystemMeta,
2575        world: UnsafeWorldCell<'world>,
2576        change_tick: Tick,
2577    ) -> Self::Item<'world, 'state> {
2578        // SAFETY:
2579        // - `state.0` is a boxed `ParamState<T>`, and its implementation of `as_any_mut` returns `self`.
2580        // - The state was obtained from `SystemParamBuilder::build()`, which registers all [`World`] accesses used
2581        //   by [`SystemParam::get_param`] with the provided [`system_meta`](SystemMeta).
2582        // - The caller ensures that the provided world is the same and has the required access.
2583        unsafe {
2584            DynSystemParam::new(
2585                state.0.as_any_mut(),
2586                world,
2587                system_meta.clone(),
2588                change_tick,
2589            )
2590        }
2591    }
2592
2593    unsafe fn new_archetype(
2594        state: &mut Self::State,
2595        archetype: &Archetype,
2596        system_meta: &mut SystemMeta,
2597    ) {
2598        // SAFETY: The caller ensures that `archetype` is from the World the state was initialized from in `init_state`.
2599        unsafe { state.0.new_archetype(archetype, system_meta) };
2600    }
2601
2602    fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
2603        state.0.apply(system_meta, world);
2604    }
2605
2606    fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
2607        state.0.queue(system_meta, world);
2608    }
2609}
2610
2611// SAFETY: When initialized with `init_state`, `get_param` returns a `FilteredResources` with no access.
2612// Therefore, `init_state` trivially registers all access, and no accesses can conflict.
2613// Note that the safety requirements for non-empty access are handled by the `SystemParamBuilder` impl that builds them.
2614unsafe impl SystemParam for FilteredResources<'_, '_> {
2615    type State = Access<ComponentId>;
2616
2617    type Item<'world, 'state> = FilteredResources<'world, 'state>;
2618
2619    fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {
2620        Access::new()
2621    }
2622
2623    unsafe fn get_param<'world, 'state>(
2624        state: &'state mut Self::State,
2625        system_meta: &SystemMeta,
2626        world: UnsafeWorldCell<'world>,
2627        change_tick: Tick,
2628    ) -> Self::Item<'world, 'state> {
2629        // SAFETY: The caller ensures that `world` has access to anything registered in `init_state` or `build`,
2630        // and the builder registers `access` in `build`.
2631        unsafe { FilteredResources::new(world, state, system_meta.last_run, change_tick) }
2632    }
2633}
2634
2635// SAFETY: FilteredResources only reads resources.
2636unsafe impl ReadOnlySystemParam for FilteredResources<'_, '_> {}
2637
2638// SAFETY: When initialized with `init_state`, `get_param` returns a `FilteredResourcesMut` with no access.
2639// Therefore, `init_state` trivially registers all access, and no accesses can conflict.
2640// Note that the safety requirements for non-empty access are handled by the `SystemParamBuilder` impl that builds them.
2641unsafe impl SystemParam for FilteredResourcesMut<'_, '_> {
2642    type State = Access<ComponentId>;
2643
2644    type Item<'world, 'state> = FilteredResourcesMut<'world, 'state>;
2645
2646    fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {
2647        Access::new()
2648    }
2649
2650    unsafe fn get_param<'world, 'state>(
2651        state: &'state mut Self::State,
2652        system_meta: &SystemMeta,
2653        world: UnsafeWorldCell<'world>,
2654        change_tick: Tick,
2655    ) -> Self::Item<'world, 'state> {
2656        // SAFETY: The caller ensures that `world` has access to anything registered in `init_state` or `build`,
2657        // and the builder registers `access` in `build`.
2658        unsafe { FilteredResourcesMut::new(world, state, system_meta.last_run, change_tick) }
2659    }
2660}
2661
2662/// An error that occurs when a system parameter is not valid,
2663/// used by system executors to determine what to do with a system.
2664///
2665/// Returned as an error from [`SystemParam::validate_param`],
2666/// and handled using the unified error handling mechanisms defined in [`bevy_ecs::error`].
2667#[derive(Debug, PartialEq, Eq, Clone, Error)]
2668pub struct SystemParamValidationError {
2669    /// Whether the system should be skipped.
2670    ///
2671    /// If `false`, the error should be handled.
2672    /// By default, this will result in a panic. See [`crate::error`] for more information.
2673    ///
2674    /// This is the default behavior, and is suitable for system params that should *always* be valid,
2675    /// either because sensible fallback behavior exists (like [`Query`] or because
2676    /// failures in validation should be considered a bug in the user's logic that must be immediately addressed (like [`Res`]).
2677    ///
2678    /// If `true`, the system should be skipped.
2679    /// This is suitable for system params that are intended to only operate in certain application states, such as [`Single`].
2680    pub skipped: bool,
2681
2682    /// A message describing the validation error.
2683    pub message: Cow<'static, str>,
2684
2685    /// A string identifying the invalid parameter.
2686    /// This is usually the type name of the parameter.
2687    pub param: Cow<'static, str>,
2688
2689    /// A string identifying the field within a parameter using `#[derive(SystemParam)]`.
2690    /// This will be an empty string for other parameters.
2691    ///
2692    /// This will be printed after `param` in the `Display` impl, and should include a `::` prefix if non-empty.
2693    pub field: Cow<'static, str>,
2694}
2695
2696impl SystemParamValidationError {
2697    /// Constructs a `SystemParamValidationError` that skips the system.
2698    /// The parameter name is initialized to the type name of `T`, so a `SystemParam` should usually pass `Self`.
2699    pub fn skipped<T>(message: impl Into<Cow<'static, str>>) -> Self {
2700        Self::new::<T>(true, message, Cow::Borrowed(""))
2701    }
2702
2703    /// Constructs a `SystemParamValidationError` for an invalid parameter that should be treated as an error.
2704    /// The parameter name is initialized to the type name of `T`, so a `SystemParam` should usually pass `Self`.
2705    pub fn invalid<T>(message: impl Into<Cow<'static, str>>) -> Self {
2706        Self::new::<T>(false, message, Cow::Borrowed(""))
2707    }
2708
2709    /// Constructs a `SystemParamValidationError` for an invalid parameter.
2710    /// The parameter name is initialized to the type name of `T`, so a `SystemParam` should usually pass `Self`.
2711    pub fn new<T>(
2712        skipped: bool,
2713        message: impl Into<Cow<'static, str>>,
2714        field: impl Into<Cow<'static, str>>,
2715    ) -> Self {
2716        Self {
2717            skipped,
2718            message: message.into(),
2719            param: Cow::Borrowed(core::any::type_name::<T>()),
2720            field: field.into(),
2721        }
2722    }
2723}
2724
2725impl Display for SystemParamValidationError {
2726    fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
2727        write!(
2728            fmt,
2729            "Parameter `{}{}` failed validation: {}",
2730            ShortName(&self.param),
2731            self.field,
2732            self.message
2733        )
2734    }
2735}
2736
2737#[cfg(test)]
2738mod tests {
2739    use super::*;
2740    use crate::system::assert_is_system;
2741    use core::cell::RefCell;
2742
2743    // Compile test for https://github.com/bevyengine/bevy/pull/2838.
2744    #[test]
2745    fn system_param_generic_bounds() {
2746        #[derive(SystemParam)]
2747        pub struct SpecialQuery<
2748            'w,
2749            's,
2750            D: QueryData + Send + Sync + 'static,
2751            F: QueryFilter + Send + Sync + 'static = (),
2752        > {
2753            _query: Query<'w, 's, D, F>,
2754        }
2755
2756        fn my_system(_: SpecialQuery<(), ()>) {}
2757        assert_is_system(my_system);
2758    }
2759
2760    // Compile tests for https://github.com/bevyengine/bevy/pull/6694.
2761    #[test]
2762    fn system_param_flexibility() {
2763        #[derive(SystemParam)]
2764        pub struct SpecialRes<'w, T: Resource> {
2765            _res: Res<'w, T>,
2766        }
2767
2768        #[derive(SystemParam)]
2769        pub struct SpecialLocal<'s, T: FromWorld + Send + 'static> {
2770            _local: Local<'s, T>,
2771        }
2772
2773        #[derive(Resource)]
2774        struct R;
2775
2776        fn my_system(_: SpecialRes<R>, _: SpecialLocal<u32>) {}
2777        assert_is_system(my_system);
2778    }
2779
2780    #[derive(Resource)]
2781    pub struct R<const I: usize>;
2782
2783    // Compile test for https://github.com/bevyengine/bevy/pull/7001.
2784    #[test]
2785    fn system_param_const_generics() {
2786        #[expect(
2787            dead_code,
2788            reason = "This struct is used to ensure that const generics are supported as a SystemParam; thus, the inner value never needs to be read."
2789        )]
2790        #[derive(SystemParam)]
2791        pub struct ConstGenericParam<'w, const I: usize>(Res<'w, R<I>>);
2792
2793        fn my_system(_: ConstGenericParam<0>, _: ConstGenericParam<1000>) {}
2794        assert_is_system(my_system);
2795    }
2796
2797    // Compile test for https://github.com/bevyengine/bevy/pull/6867.
2798    #[test]
2799    fn system_param_field_limit() {
2800        #[derive(SystemParam)]
2801        pub struct LongParam<'w> {
2802            // Each field should be a distinct type so there will
2803            // be an error if the derive messes up the field order.
2804            _r0: Res<'w, R<0>>,
2805            _r1: Res<'w, R<1>>,
2806            _r2: Res<'w, R<2>>,
2807            _r3: Res<'w, R<3>>,
2808            _r4: Res<'w, R<4>>,
2809            _r5: Res<'w, R<5>>,
2810            _r6: Res<'w, R<6>>,
2811            _r7: Res<'w, R<7>>,
2812            _r8: Res<'w, R<8>>,
2813            _r9: Res<'w, R<9>>,
2814            _r10: Res<'w, R<10>>,
2815            _r11: Res<'w, R<11>>,
2816            _r12: Res<'w, R<12>>,
2817            _r13: Res<'w, R<13>>,
2818            _r14: Res<'w, R<14>>,
2819            _r15: Res<'w, R<15>>,
2820            _r16: Res<'w, R<16>>,
2821        }
2822
2823        fn long_system(_: LongParam) {}
2824        assert_is_system(long_system);
2825    }
2826
2827    // Compile test for https://github.com/bevyengine/bevy/pull/6919.
2828    // Regression test for https://github.com/bevyengine/bevy/issues/7447.
2829    #[test]
2830    fn system_param_phantom_data() {
2831        #[derive(SystemParam)]
2832        struct PhantomParam<'w, T: Resource, Marker: 'static> {
2833            _foo: Res<'w, T>,
2834            marker: PhantomData<&'w Marker>,
2835        }
2836
2837        fn my_system(_: PhantomParam<R<0>, ()>) {}
2838        assert_is_system(my_system);
2839    }
2840
2841    // Compile tests for https://github.com/bevyengine/bevy/pull/6957.
2842    #[test]
2843    fn system_param_struct_variants() {
2844        #[derive(SystemParam)]
2845        pub struct UnitParam;
2846
2847        #[expect(
2848            dead_code,
2849            reason = "This struct is used to ensure that tuple structs are supported as a SystemParam; thus, the inner values never need to be read."
2850        )]
2851        #[derive(SystemParam)]
2852        pub struct TupleParam<'w, 's, R: Resource, L: FromWorld + Send + 'static>(
2853            Res<'w, R>,
2854            Local<'s, L>,
2855        );
2856
2857        fn my_system(_: UnitParam, _: TupleParam<R<0>, u32>) {}
2858        assert_is_system(my_system);
2859    }
2860
2861    // Regression test for https://github.com/bevyengine/bevy/issues/4200.
2862    #[test]
2863    fn system_param_private_fields() {
2864        #[derive(Resource)]
2865        struct PrivateResource;
2866
2867        #[expect(
2868            dead_code,
2869            reason = "This struct is used to ensure that SystemParam's derive can't leak private fields; thus, the inner values never need to be read."
2870        )]
2871        #[derive(SystemParam)]
2872        pub struct EncapsulatedParam<'w>(Res<'w, PrivateResource>);
2873
2874        fn my_system(_: EncapsulatedParam) {}
2875        assert_is_system(my_system);
2876    }
2877
2878    // Regression test for https://github.com/bevyengine/bevy/issues/7103.
2879    #[test]
2880    fn system_param_where_clause() {
2881        #[derive(SystemParam)]
2882        pub struct WhereParam<'w, 's, D>
2883        where
2884            D: 'static + QueryData,
2885        {
2886            _q: Query<'w, 's, D, ()>,
2887        }
2888
2889        fn my_system(_: WhereParam<()>) {}
2890        assert_is_system(my_system);
2891    }
2892
2893    // Regression test for https://github.com/bevyengine/bevy/issues/1727.
2894    #[test]
2895    fn system_param_name_collision() {
2896        #[derive(Resource)]
2897        pub struct FetchState;
2898
2899        #[derive(SystemParam)]
2900        pub struct Collide<'w> {
2901            _x: Res<'w, FetchState>,
2902        }
2903
2904        fn my_system(_: Collide) {}
2905        assert_is_system(my_system);
2906    }
2907
2908    // Regression test for https://github.com/bevyengine/bevy/issues/8192.
2909    #[test]
2910    fn system_param_invariant_lifetime() {
2911        #[derive(SystemParam)]
2912        pub struct InvariantParam<'w, 's> {
2913            _set: ParamSet<'w, 's, (Query<'w, 's, ()>,)>,
2914        }
2915
2916        fn my_system(_: InvariantParam) {}
2917        assert_is_system(my_system);
2918    }
2919
2920    // Compile test for https://github.com/bevyengine/bevy/pull/9589.
2921    #[test]
2922    fn non_sync_local() {
2923        fn non_sync_system(cell: Local<RefCell<u8>>) {
2924            assert_eq!(*cell.borrow(), 0);
2925        }
2926
2927        let mut world = World::new();
2928        let mut schedule = crate::schedule::Schedule::default();
2929        schedule.add_systems(non_sync_system);
2930        schedule.run(&mut world);
2931    }
2932
2933    // Regression test for https://github.com/bevyengine/bevy/issues/10207.
2934    #[test]
2935    fn param_set_non_send_first() {
2936        fn non_send_param_set(mut p: ParamSet<(NonSend<*mut u8>, ())>) {
2937            let _ = p.p0();
2938            p.p1();
2939        }
2940
2941        let mut world = World::new();
2942        world.insert_non_send_resource(core::ptr::null_mut::<u8>());
2943        let mut schedule = crate::schedule::Schedule::default();
2944        schedule.add_systems((non_send_param_set, non_send_param_set, non_send_param_set));
2945        schedule.run(&mut world);
2946    }
2947
2948    // Regression test for https://github.com/bevyengine/bevy/issues/10207.
2949    #[test]
2950    fn param_set_non_send_second() {
2951        fn non_send_param_set(mut p: ParamSet<((), NonSendMut<*mut u8>)>) {
2952            p.p0();
2953            let _ = p.p1();
2954        }
2955
2956        let mut world = World::new();
2957        world.insert_non_send_resource(core::ptr::null_mut::<u8>());
2958        let mut schedule = crate::schedule::Schedule::default();
2959        schedule.add_systems((non_send_param_set, non_send_param_set, non_send_param_set));
2960        schedule.run(&mut world);
2961    }
2962
2963    fn _dyn_system_param_type_inference(mut p: DynSystemParam) {
2964        // Make sure the downcast() methods are able to infer their type parameters from the use of the return type.
2965        // This is just a compilation test, so there is nothing to run.
2966        let _query: Query<()> = p.downcast_mut().unwrap();
2967        let _query: Query<()> = p.downcast_mut_inner().unwrap();
2968        let _query: Query<()> = p.downcast().unwrap();
2969    }
2970
2971    #[test]
2972    #[should_panic = "Encountered an error in system `bevy_ecs::system::system_param::tests::missing_resource_error::res_system`: Parameter `Res<MissingResource>` failed validation: Resource does not exist"]
2973    fn missing_resource_error() {
2974        #[derive(Resource)]
2975        pub struct MissingResource;
2976
2977        let mut schedule = crate::schedule::Schedule::default();
2978        schedule.add_systems(res_system);
2979        let mut world = World::new();
2980        schedule.run(&mut world);
2981
2982        fn res_system(_: Res<MissingResource>) {}
2983    }
2984
2985    #[test]
2986    #[should_panic = "Encountered an error in system `bevy_ecs::system::system_param::tests::missing_event_error::event_system`: Parameter `EventReader<MissingEvent>::events` failed validation: Event not initialized"]
2987    fn missing_event_error() {
2988        use crate::prelude::{Event, EventReader};
2989
2990        #[derive(Event)]
2991        pub struct MissingEvent;
2992
2993        let mut schedule = crate::schedule::Schedule::default();
2994        schedule.add_systems(event_system);
2995        let mut world = World::new();
2996        schedule.run(&mut world);
2997
2998        fn event_system(_: EventReader<MissingEvent>) {}
2999    }
3000}