pub use crate::change_detection::{NonSendMut, Res, ResMut}; use crate::{ archetype::{Archetype, Archetypes}, bundle::Bundles, change_detection::{MaybeLocation, Ticks, TicksMut}, component::{ComponentId, ComponentTicks, Components, Tick}, entity::Entities, query::{ Access, FilteredAccess, FilteredAccessSet, QueryData, QueryFilter, QuerySingleError, QueryState, ReadOnlyQueryData, }, resource::Resource, storage::ResourceData, system::{Query, Single, SystemMeta}, world::{ unsafe_world_cell::UnsafeWorldCell, DeferredWorld, FilteredResources, FilteredResourcesMut, FromWorld, World, }, }; use alloc::{borrow::ToOwned, boxed::Box, vec::Vec}; pub use bevy_ecs_macros::SystemParam; use bevy_ptr::UnsafeCellDeref; use bevy_utils::synccell::SyncCell; use core::{ any::Any, fmt::Debug, marker::PhantomData, ops::{Deref, DerefMut}, panic::Location, }; use derive_more::derive::Display; use disqualified::ShortName; use thiserror::Error; use super::Populated; use variadics_please::{all_tuples, all_tuples_enumerated}; /// A parameter that can be used in a [`System`](super::System). /// /// # Derive /// /// This trait can be derived with the [`derive@super::SystemParam`] macro. /// This macro only works if each field on the derived struct implements [`SystemParam`]. /// Note: There are additional requirements on the field types. /// See the *Generic `SystemParam`s* section for details and workarounds of the probable /// cause if this derive causes an error to be emitted. /// /// Derived `SystemParam` structs may have two lifetimes: `'w` for data stored in the [`World`], /// and `'s` for data stored in the parameter's state. /// /// The following list shows the most common [`SystemParam`]s and which lifetime they require /// /// ``` /// # use bevy_ecs::prelude::*; /// # #[derive(Resource)] /// # struct SomeResource; /// # #[derive(Event)] /// # struct SomeEvent; /// # #[derive(Resource)] /// # struct SomeOtherResource; /// # use bevy_ecs::system::SystemParam; /// # #[derive(SystemParam)] /// # struct ParamsExample<'w, 's> { /// # query: /// Query<'w, 's, Entity>, /// # res: /// Res<'w, SomeResource>, /// # res_mut: /// ResMut<'w, SomeOtherResource>, /// # local: /// Local<'s, u8>, /// # commands: /// Commands<'w, 's>, /// # eventreader: /// EventReader<'w, 's, SomeEvent>, /// # eventwriter: /// EventWriter<'w, SomeEvent> /// # } /// ``` /// ## `PhantomData` /// /// [`PhantomData`] is a special type of `SystemParam` that does nothing. /// This is useful for constraining generic types or lifetimes. /// /// # Example /// /// ``` /// # use bevy_ecs::prelude::*; /// # #[derive(Resource)] /// # struct SomeResource; /// use std::marker::PhantomData; /// use bevy_ecs::system::SystemParam; /// /// #[derive(SystemParam)] /// struct MyParam<'w, Marker: 'static> { /// foo: Res<'w, SomeResource>, /// marker: PhantomData, /// } /// /// fn my_system(param: MyParam) { /// // Access the resource through `param.foo` /// } /// /// # bevy_ecs::system::assert_is_system(my_system::<()>); /// ``` /// /// # Generic `SystemParam`s /// /// When using the derive macro, you may see an error in the form of: /// /// ```text /// expected ... [ParamType] /// found associated type `<[ParamType] as SystemParam>::Item<'_, '_>` /// ``` /// where `[ParamType]` is the type of one of your fields. /// To solve this error, you can wrap the field of type `[ParamType]` with [`StaticSystemParam`] /// (i.e. `StaticSystemParam<[ParamType]>`). /// /// ## Details /// /// The derive macro requires that the [`SystemParam`] implementation of /// each field `F`'s [`Item`](`SystemParam::Item`)'s is itself `F` /// (ignoring lifetimes for simplicity). /// This assumption is due to type inference reasons, so that the derived [`SystemParam`] can be /// used as an argument to a function system. /// If the compiler cannot validate this property for `[ParamType]`, it will error in the form shown above. /// /// This will most commonly occur when working with `SystemParam`s generically, as the requirement /// has not been proven to the compiler. /// /// ## Builders /// /// If you want to use a [`SystemParamBuilder`](crate::system::SystemParamBuilder) with a derived [`SystemParam`] implementation, /// add a `#[system_param(builder)]` attribute to the struct. /// This will generate a builder struct whose name is the param struct suffixed with `Builder`. /// The builder will not be `pub`, so you may want to expose a method that returns an `impl SystemParamBuilder`. /// /// ``` /// mod custom_param { /// # use bevy_ecs::{ /// # prelude::*, /// # system::{LocalBuilder, QueryParamBuilder, SystemParam}, /// # }; /// # /// #[derive(SystemParam)] /// #[system_param(builder)] /// pub struct CustomParam<'w, 's> { /// query: Query<'w, 's, ()>, /// local: Local<'s, usize>, /// } /// /// impl<'w, 's> CustomParam<'w, 's> { /// pub fn builder( /// local: usize, /// query: impl FnOnce(&mut QueryBuilder<()>), /// ) -> impl SystemParamBuilder { /// CustomParamBuilder { /// local: LocalBuilder(local), /// query: QueryParamBuilder::new(query), /// } /// } /// } /// } /// /// use custom_param::CustomParam; /// /// # use bevy_ecs::prelude::*; /// # #[derive(Component)] /// # struct A; /// # /// # let mut world = World::new(); /// # /// let system = (CustomParam::builder(100, |builder| { /// builder.with::(); /// }),) /// .build_state(&mut world) /// .build_system(|param: CustomParam| {}); /// ``` /// /// # Safety /// /// The implementor must ensure the following is true. /// - [`SystemParam::init_state`] correctly registers all [`World`] accesses used /// by [`SystemParam::get_param`] with the provided [`system_meta`](SystemMeta). /// - None of the world accesses may conflict with any prior accesses registered /// on `system_meta`. pub unsafe trait SystemParam: Sized { /// Used to store data which persists across invocations of a system. type State: Send + Sync + 'static; /// The item type returned when constructing this system param. /// The value of this associated type should be `Self`, instantiated with new lifetimes. /// /// You could think of [`SystemParam::Item<'w, 's>`] as being an *operation* that changes the lifetimes bound to `Self`. type Item<'world, 'state>: SystemParam; /// Registers any [`World`] access used by this [`SystemParam`] /// and creates a new instance of this param's [`State`](SystemParam::State). fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State; /// For the specified [`Archetype`], registers the components accessed by this [`SystemParam`] (if applicable).a /// /// # Safety /// `archetype` must be from the [`World`] used to initialize `state` in [`SystemParam::init_state`]. #[inline] #[expect( unused_variables, 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." )] unsafe fn new_archetype( state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta, ) { } /// Applies any deferred mutations stored in this [`SystemParam`]'s state. /// This is used to apply [`Commands`] during [`ApplyDeferred`](crate::prelude::ApplyDeferred). /// /// [`Commands`]: crate::prelude::Commands #[inline] #[expect( unused_variables, 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." )] fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {} /// Queues any deferred mutations to be applied at the next [`ApplyDeferred`](crate::prelude::ApplyDeferred). #[inline] #[expect( unused_variables, 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." )] fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {} /// Validates that the param can be acquired by the [`get_param`](SystemParam::get_param). /// /// Built-in executors use this to prevent systems with invalid params from running, /// and any failures here will be bubbled up to the default error handler defined in [`bevy_ecs::error`], /// with a value of type [`SystemParamValidationError`]. /// /// For nested [`SystemParam`]s validation will fail if any /// delegated validation fails. /// /// However calling and respecting [`SystemParam::validate_param`] /// is not a strict requirement, [`SystemParam::get_param`] should /// provide it's own safety mechanism to prevent undefined behavior. /// /// The [`world`](UnsafeWorldCell) can only be used to read param's data /// and world metadata. No data can be written. /// /// When using system parameters that require `change_tick` you can use /// [`UnsafeWorldCell::change_tick()`]. Even if this isn't the exact /// same tick used for [`SystemParam::get_param`], the world access /// ensures that the queried data will be the same in both calls. /// /// This method has to be called directly before [`SystemParam::get_param`] with no other (relevant) /// world mutations inbetween. Otherwise, while it won't lead to any undefined behavior, /// the validity of the param may change. /// /// [`System::validate_param`](super::system::System::validate_param), /// calls this method for each supplied system param. /// /// # Safety /// /// - The passed [`UnsafeWorldCell`] must have read-only access to world data /// registered in [`init_state`](SystemParam::init_state). /// - `world` must be the same [`World`] that was used to initialize [`state`](SystemParam::init_state). /// - All `world`'s archetypes have been processed by [`new_archetype`](SystemParam::new_archetype). #[expect( unused_variables, 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." )] unsafe fn validate_param( state: &Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell, ) -> Result<(), SystemParamValidationError> { Ok(()) } /// Creates a parameter to be passed into a [`SystemParamFunction`](super::SystemParamFunction). /// /// # Safety /// /// - The passed [`UnsafeWorldCell`] must have access to any world data registered /// in [`init_state`](SystemParam::init_state). /// - `world` must be the same [`World`] that was used to initialize [`state`](SystemParam::init_state). /// - All `world`'s archetypes have been processed by [`new_archetype`](SystemParam::new_archetype). unsafe fn get_param<'world, 'state>( state: &'state mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'world>, change_tick: Tick, ) -> Self::Item<'world, 'state>; } /// A [`SystemParam`] that only reads a given [`World`]. /// /// # Safety /// This must only be implemented for [`SystemParam`] impls that exclusively read the World passed in to [`SystemParam::get_param`] pub unsafe trait ReadOnlySystemParam: SystemParam {} /// Shorthand way of accessing the associated type [`SystemParam::Item`] for a given [`SystemParam`]. pub type SystemParamItem<'w, 's, P> =

::Item<'w, 's>; // SAFETY: QueryState is constrained to read-only fetches, so it only reads World. unsafe impl<'w, 's, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam for Query<'w, 's, D, F> { } // SAFETY: Relevant query ComponentId and ArchetypeComponentId access is applied to SystemMeta. If // this Query conflicts with any prior access, a panic will occur. unsafe impl SystemParam for Query<'_, '_, D, F> { type State = QueryState; type Item<'w, 's> = Query<'w, 's, D, F>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { let state = QueryState::new_with_access(world, &mut system_meta.archetype_component_access); init_query_param(world, system_meta, &state); state } unsafe fn new_archetype( state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta, ) { state.new_archetype(archetype, &mut system_meta.archetype_component_access); } #[inline] unsafe fn get_param<'w, 's>( state: &'s mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> Self::Item<'w, 's> { // SAFETY: We have registered all of the query's world accesses, // so the caller ensures that `world` has permission to access any // world data that the query needs. // The caller ensures the world matches the one used in init_state. unsafe { state.query_unchecked_manual_with_ticks(world, system_meta.last_run, change_tick) } } } pub(crate) fn init_query_param( world: &mut World, system_meta: &mut SystemMeta, state: &QueryState, ) { assert_component_access_compatibility( &system_meta.name, core::any::type_name::(), core::any::type_name::(), &system_meta.component_access_set, &state.component_access, world, ); system_meta .component_access_set .add(state.component_access.clone()); } fn assert_component_access_compatibility( system_name: &str, query_type: &'static str, filter_type: &'static str, system_access: &FilteredAccessSet, current: &FilteredAccess, world: &World, ) { let conflicts = system_access.get_conflicts_single(current); if conflicts.is_empty() { return; } let mut accesses = conflicts.format_conflict_list(world); // Access list may be empty (if access to all components requested) if !accesses.is_empty() { accesses.push(' '); } 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` to create disjoint Queries or merging conflicting Queries into a `ParamSet`. See: https://bevyengine.org/learn/errors/b0001", ShortName(query_type), ShortName(filter_type)); } // SAFETY: Relevant query ComponentId and ArchetypeComponentId access is applied to SystemMeta. If // this Query conflicts with any prior access, a panic will occur. unsafe impl<'a, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam for Single<'a, D, F> { type State = QueryState; type Item<'w, 's> = Single<'w, D, F>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { Query::init_state(world, system_meta) } unsafe fn new_archetype( state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta, ) { // SAFETY: Delegate to existing `SystemParam` implementations. unsafe { Query::new_archetype(state, archetype, system_meta) }; } #[inline] unsafe fn get_param<'w, 's>( state: &'s mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> Self::Item<'w, 's> { // SAFETY: State ensures that the components it accesses are not accessible somewhere elsewhere. // The caller ensures the world matches the one used in init_state. let query = unsafe { state.query_unchecked_manual_with_ticks(world, system_meta.last_run, change_tick) }; let single = query .single_inner() .expect("The query was expected to contain exactly one matching entity."); Single { item: single, _filter: PhantomData, } } #[inline] unsafe fn validate_param( state: &Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell, ) -> Result<(), SystemParamValidationError> { // SAFETY: State ensures that the components it accesses are not mutably accessible elsewhere // and the query is read only. // The caller ensures the world matches the one used in init_state. let query = unsafe { state.query_unchecked_manual_with_ticks( world, system_meta.last_run, world.change_tick(), ) }; match query.single_inner() { Ok(_) => Ok(()), Err(_) => Err(SystemParamValidationError::skipped()), } } } // SAFETY: Relevant query ComponentId and ArchetypeComponentId access is applied to SystemMeta. If // this Query conflicts with any prior access, a panic will occur. unsafe impl<'a, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam for Option> { type State = QueryState; type Item<'w, 's> = Option>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { Single::init_state(world, system_meta) } unsafe fn new_archetype( state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta, ) { // SAFETY: Delegate to existing `SystemParam` implementations. unsafe { Single::new_archetype(state, archetype, system_meta) }; } #[inline] unsafe fn get_param<'w, 's>( state: &'s mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> Self::Item<'w, 's> { state.validate_world(world.id()); // SAFETY: State ensures that the components it accesses are not accessible elsewhere. // The caller ensures the world matches the one used in init_state. let query = unsafe { state.query_unchecked_manual_with_ticks(world, system_meta.last_run, change_tick) }; match query.single_inner() { Ok(single) => Some(Single { item: single, _filter: PhantomData, }), Err(QuerySingleError::NoEntities(_)) => None, Err(QuerySingleError::MultipleEntities(e)) => panic!("{}", e), } } #[inline] unsafe fn validate_param( state: &Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell, ) -> Result<(), SystemParamValidationError> { // SAFETY: State ensures that the components it accesses are not mutably accessible elsewhere // and the query is read only. // The caller ensures the world matches the one used in init_state. let query = unsafe { state.query_unchecked_manual_with_ticks( world, system_meta.last_run, world.change_tick(), ) }; match query.single_inner() { Ok(_) | Err(QuerySingleError::NoEntities(_)) => Ok(()), Err(QuerySingleError::MultipleEntities(_)) => { Err(SystemParamValidationError::skipped()) } } } } // SAFETY: QueryState is constrained to read-only fetches, so it only reads World. unsafe impl<'a, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam for Single<'a, D, F> { } // SAFETY: QueryState is constrained to read-only fetches, so it only reads World. unsafe impl<'a, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam for Option> { } // SAFETY: Relevant query ComponentId and ArchetypeComponentId access is applied to SystemMeta. If // this Query conflicts with any prior access, a panic will occur. unsafe impl SystemParam for Populated<'_, '_, D, F> { type State = QueryState; type Item<'w, 's> = Populated<'w, 's, D, F>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { Query::init_state(world, system_meta) } unsafe fn new_archetype( state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta, ) { // SAFETY: Delegate to existing `SystemParam` implementations. unsafe { Query::new_archetype(state, archetype, system_meta) }; } #[inline] unsafe fn get_param<'w, 's>( state: &'s mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> Self::Item<'w, 's> { // SAFETY: Delegate to existing `SystemParam` implementations. let query = unsafe { Query::get_param(state, system_meta, world, change_tick) }; Populated(query) } #[inline] unsafe fn validate_param( state: &Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell, ) -> Result<(), SystemParamValidationError> { // SAFETY: // - We have read-only access to the components accessed by query. // - The caller ensures the world matches the one used in init_state. let query = unsafe { state.query_unchecked_manual_with_ticks( world, system_meta.last_run, world.change_tick(), ) }; if query.is_empty() { Err(SystemParamValidationError::skipped()) } else { Ok(()) } } } // SAFETY: QueryState is constrained to read-only fetches, so it only reads World. unsafe impl<'w, 's, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam for Populated<'w, 's, D, F> { } /// A collection of potentially conflicting [`SystemParam`]s allowed by disjoint access. /// /// Allows systems to safely access and interact with up to 8 mutually exclusive [`SystemParam`]s, such as /// two queries that reference the same mutable data or an event reader and writer of the same type. /// /// Each individual [`SystemParam`] can be accessed by using the functions `p0()`, `p1()`, ..., `p7()`, /// according to the order they are defined in the `ParamSet`. This ensures that there's either /// only one mutable reference to a parameter at a time or any number of immutable references. /// /// # Examples /// /// The following system mutably accesses the same component two times, /// which is not allowed due to rust's mutability rules. /// /// ```should_panic /// # use bevy_ecs::prelude::*; /// # /// # #[derive(Component)] /// # struct Health; /// # /// # #[derive(Component)] /// # struct Enemy; /// # /// # #[derive(Component)] /// # struct Ally; /// # /// // This will panic at runtime when the system gets initialized. /// fn bad_system( /// mut enemies: Query<&mut Health, With>, /// mut allies: Query<&mut Health, With>, /// ) { /// // ... /// } /// # /// # let mut bad_system_system = IntoSystem::into_system(bad_system); /// # let mut world = World::new(); /// # bad_system_system.initialize(&mut world); /// # bad_system_system.run((), &mut world); /// ``` /// /// Conflicting `SystemParam`s like these can be placed in a `ParamSet`, /// which leverages the borrow checker to ensure that only one of the contained parameters are accessed at a given time. /// /// ``` /// # use bevy_ecs::prelude::*; /// # /// # #[derive(Component)] /// # struct Health; /// # /// # #[derive(Component)] /// # struct Enemy; /// # /// # #[derive(Component)] /// # struct Ally; /// # /// // Given the following system /// fn fancy_system( /// mut set: ParamSet<( /// Query<&mut Health, With>, /// Query<&mut Health, With>, /// )> /// ) { /// // This will access the first `SystemParam`. /// for mut health in set.p0().iter_mut() { /// // Do your fancy stuff here... /// } /// /// // The second `SystemParam`. /// // This would fail to compile if the previous parameter was still borrowed. /// for mut health in set.p1().iter_mut() { /// // Do even fancier stuff here... /// } /// } /// # bevy_ecs::system::assert_is_system(fancy_system); /// ``` /// /// Of course, `ParamSet`s can be used with any kind of `SystemParam`, not just [queries](Query). /// /// ``` /// # use bevy_ecs::prelude::*; /// # /// # #[derive(Event)] /// # struct MyEvent; /// # impl MyEvent { /// # pub fn new() -> Self { Self } /// # } /// fn event_system( /// mut set: ParamSet<( /// // PROBLEM: `EventReader` and `EventWriter` cannot be used together normally, /// // because they both need access to the same event queue. /// // SOLUTION: `ParamSet` allows these conflicting parameters to be used safely /// // by ensuring only one is accessed at a time. /// EventReader, /// EventWriter, /// // PROBLEM: `&World` needs read access to everything, which conflicts with /// // any mutable access in the same system. /// // SOLUTION: `ParamSet` ensures `&World` is only accessed when we're not /// // using the other mutable parameters. /// &World, /// )>, /// ) { /// for event in set.p0().read() { /// // ... /// # let _event = event; /// } /// set.p1().write(MyEvent::new()); /// /// let entities = set.p2().entities(); /// // ... /// # let _entities = entities; /// } /// # bevy_ecs::system::assert_is_system(event_system); /// ``` pub struct ParamSet<'w, 's, T: SystemParam> { param_states: &'s mut T::State, world: UnsafeWorldCell<'w>, system_meta: SystemMeta, change_tick: Tick, } macro_rules! impl_param_set { ($(($index: tt, $param: ident, $system_meta: ident, $fn_name: ident)),*) => { // SAFETY: All parameters are constrained to ReadOnlySystemParam, so World is only read unsafe impl<'w, 's, $($param,)*> ReadOnlySystemParam for ParamSet<'w, 's, ($($param,)*)> where $($param: ReadOnlySystemParam,)* { } // SAFETY: Relevant parameter ComponentId and ArchetypeComponentId access is applied to SystemMeta. If any ParamState conflicts // with any prior access, a panic will occur. unsafe impl<'_w, '_s, $($param: SystemParam,)*> SystemParam for ParamSet<'_w, '_s, ($($param,)*)> { type State = ($($param::State,)*); type Item<'w, 's> = ParamSet<'w, 's, ($($param,)*)>; #[expect( clippy::allow_attributes, reason = "This is inside a macro meant for tuples; as such, `non_snake_case` won't always lint." )] #[allow( non_snake_case, reason = "Certain variable names are provided by the caller, not by us." )] fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { $( // Pretend to add each param to the system alone, see if it conflicts let mut $system_meta = system_meta.clone(); $system_meta.component_access_set.clear(); $system_meta.archetype_component_access.clear(); $param::init_state(world, &mut $system_meta); // The variable is being defined with non_snake_case here let $param = $param::init_state(world, &mut system_meta.clone()); )* // Make the ParamSet non-send if any of its parameters are non-send. if false $(|| !$system_meta.is_send())* { system_meta.set_non_send(); } $( system_meta .component_access_set .extend($system_meta.component_access_set); system_meta .archetype_component_access .extend(&$system_meta.archetype_component_access); )* ($($param,)*) } unsafe fn new_archetype(state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta) { // SAFETY: The caller ensures that `archetype` is from the World the state was initialized from in `init_state`. unsafe { <($($param,)*) as SystemParam>::new_archetype(state, archetype, system_meta); } } fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) { <($($param,)*) as SystemParam>::apply(state, system_meta, world); } fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) { <($($param,)*) as SystemParam>::queue(state, system_meta, world.reborrow()); } #[inline] unsafe fn validate_param<'w, 's>( state: &'s Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, ) -> Result<(), SystemParamValidationError> { <($($param,)*) as SystemParam>::validate_param(state, system_meta, world) } #[inline] unsafe fn get_param<'w, 's>( state: &'s mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> Self::Item<'w, 's> { ParamSet { param_states: state, system_meta: system_meta.clone(), world, change_tick, } } } impl<'w, 's, $($param: SystemParam,)*> ParamSet<'w, 's, ($($param,)*)> { $( /// Gets exclusive access to the parameter at index #[doc = stringify!($index)] /// in this [`ParamSet`]. /// No other parameters may be accessed while this one is active. pub fn $fn_name<'a>(&'a mut self) -> SystemParamItem<'a, 'a, $param> { // SAFETY: systems run without conflicts with other systems. // Conflicting params in ParamSet are not accessible at the same time // ParamSets are guaranteed to not conflict with other SystemParams unsafe { $param::get_param(&mut self.param_states.$index, &self.system_meta, self.world, self.change_tick) } } )* } } } all_tuples_enumerated!(impl_param_set, 1, 8, P, m, p); // SAFETY: Res only reads a single World resource unsafe impl<'a, T: Resource> ReadOnlySystemParam for Res<'a, T> {} // SAFETY: Res ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this Res // conflicts with any prior access, a panic will occur. unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> { type State = ComponentId; type Item<'w, 's> = Res<'w, T>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { let component_id = world.components_registrator().register_resource::(); let archetype_component_id = world.initialize_resource_internal(component_id).id(); let combined_access = system_meta.component_access_set.combined_access(); assert!( !combined_access.has_resource_write(component_id), "error[B0002]: Res<{}> in system {} conflicts with a previous ResMut<{0}> access. Consider removing the duplicate access. See: https://bevyengine.org/learn/errors/b0002", core::any::type_name::(), system_meta.name, ); system_meta .component_access_set .add_unfiltered_resource_read(component_id); system_meta .archetype_component_access .add_resource_read(archetype_component_id); component_id } #[inline] unsafe fn validate_param( &component_id: &Self::State, _system_meta: &SystemMeta, world: UnsafeWorldCell, ) -> Result<(), SystemParamValidationError> { // SAFETY: Read-only access to resource metadata. if unsafe { world.storages() } .resources .get(component_id) .is_some_and(ResourceData::is_present) { Ok(()) } else { Err(SystemParamValidationError::invalid()) } } #[inline] unsafe fn get_param<'w, 's>( &mut component_id: &'s mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> Self::Item<'w, 's> { let (ptr, ticks, caller) = world .get_resource_with_ticks(component_id) .unwrap_or_else(|| { panic!( "Resource requested by {} does not exist: {}", system_meta.name, core::any::type_name::() ) }); Res { value: ptr.deref(), ticks: Ticks { added: ticks.added.deref(), changed: ticks.changed.deref(), last_run: system_meta.last_run, this_run: change_tick, }, changed_by: caller.map(|caller| caller.deref()), } } } // SAFETY: Only reads a single World resource unsafe impl<'a, T: Resource> ReadOnlySystemParam for Option> {} // SAFETY: this impl defers to `Res`, which initializes and validates the correct world access. unsafe impl<'a, T: Resource> SystemParam for Option> { type State = ComponentId; type Item<'w, 's> = Option>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { Res::::init_state(world, system_meta) } #[inline] unsafe fn get_param<'w, 's>( &mut component_id: &'s mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> Self::Item<'w, 's> { world .get_resource_with_ticks(component_id) .map(|(ptr, ticks, caller)| Res { value: ptr.deref(), ticks: Ticks { added: ticks.added.deref(), changed: ticks.changed.deref(), last_run: system_meta.last_run, this_run: change_tick, }, changed_by: caller.map(|caller| caller.deref()), }) } } // SAFETY: Res ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this Res // conflicts with any prior access, a panic will occur. unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> { type State = ComponentId; type Item<'w, 's> = ResMut<'w, T>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { let component_id = world.components_registrator().register_resource::(); let archetype_component_id = world.initialize_resource_internal(component_id).id(); let combined_access = system_meta.component_access_set.combined_access(); if combined_access.has_resource_write(component_id) { panic!( "error[B0002]: ResMut<{}> in system {} conflicts with a previous ResMut<{0}> access. Consider removing the duplicate access. See: https://bevyengine.org/learn/errors/b0002", core::any::type_name::(), system_meta.name); } else if combined_access.has_resource_read(component_id) { panic!( "error[B0002]: ResMut<{}> in system {} conflicts with a previous Res<{0}> access. Consider removing the duplicate access. See: https://bevyengine.org/learn/errors/b0002", core::any::type_name::(), system_meta.name); } system_meta .component_access_set .add_unfiltered_resource_write(component_id); system_meta .archetype_component_access .add_resource_write(archetype_component_id); component_id } #[inline] unsafe fn validate_param( &component_id: &Self::State, _system_meta: &SystemMeta, world: UnsafeWorldCell, ) -> Result<(), SystemParamValidationError> { // SAFETY: Read-only access to resource metadata. if unsafe { world.storages() } .resources .get(component_id) .is_some_and(ResourceData::is_present) { Ok(()) } else { Err(SystemParamValidationError::invalid()) } } #[inline] unsafe fn get_param<'w, 's>( &mut component_id: &'s mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> Self::Item<'w, 's> { let value = world .get_resource_mut_by_id(component_id) .unwrap_or_else(|| { panic!( "Resource requested by {} does not exist: {}", system_meta.name, core::any::type_name::() ) }); ResMut { value: value.value.deref_mut::(), ticks: TicksMut { added: value.ticks.added, changed: value.ticks.changed, last_run: system_meta.last_run, this_run: change_tick, }, changed_by: value.changed_by, } } } // SAFETY: this impl defers to `ResMut`, which initializes and validates the correct world access. unsafe impl<'a, T: Resource> SystemParam for Option> { type State = ComponentId; type Item<'w, 's> = Option>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { ResMut::::init_state(world, system_meta) } #[inline] unsafe fn get_param<'w, 's>( &mut component_id: &'s mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> Self::Item<'w, 's> { world .get_resource_mut_by_id(component_id) .map(|value| ResMut { value: value.value.deref_mut::(), ticks: TicksMut { added: value.ticks.added, changed: value.ticks.changed, last_run: system_meta.last_run, this_run: change_tick, }, changed_by: value.changed_by, }) } } /// SAFETY: only reads world unsafe impl<'w> ReadOnlySystemParam for &'w World {} // SAFETY: `read_all` access is set and conflicts result in a panic unsafe impl SystemParam for &'_ World { type State = (); type Item<'w, 's> = &'w World; fn init_state(_world: &mut World, system_meta: &mut SystemMeta) -> Self::State { let mut access = Access::default(); access.read_all(); if !system_meta .archetype_component_access .is_compatible(&access) { panic!("&World conflicts with a previous mutable system parameter. Allowing this would break Rust's mutability rules"); } system_meta.archetype_component_access.extend(&access); let mut filtered_access = FilteredAccess::default(); filtered_access.read_all(); if !system_meta .component_access_set .get_conflicts_single(&filtered_access) .is_empty() { panic!("&World conflicts with a previous mutable system parameter. Allowing this would break Rust's mutability rules"); } system_meta.component_access_set.add(filtered_access); } #[inline] unsafe fn get_param<'w, 's>( _state: &'s mut Self::State, _system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, _change_tick: Tick, ) -> Self::Item<'w, 's> { // SAFETY: Read-only access to the entire world was registered in `init_state`. unsafe { world.world() } } } /// SAFETY: `DeferredWorld` can read all components and resources but cannot be used to gain any other mutable references. unsafe impl<'w> SystemParam for DeferredWorld<'w> { type State = (); type Item<'world, 'state> = DeferredWorld<'world>; fn init_state(_world: &mut World, system_meta: &mut SystemMeta) -> Self::State { assert!( !system_meta .component_access_set .combined_access() .has_any_read(), "DeferredWorld in system {} conflicts with a previous access.", system_meta.name, ); system_meta.component_access_set.write_all(); system_meta.archetype_component_access.write_all(); } unsafe fn get_param<'world, 'state>( _state: &'state mut Self::State, _system_meta: &SystemMeta, world: UnsafeWorldCell<'world>, _change_tick: Tick, ) -> Self::Item<'world, 'state> { world.into_deferred() } } /// A system local [`SystemParam`]. /// /// A local may only be accessed by the system itself and is therefore not visible to other systems. /// If two or more systems specify the same local type each will have their own unique local. /// If multiple [`SystemParam`]s within the same system each specify the same local type /// each will get their own distinct data storage. /// /// The supplied lifetime parameter is the [`SystemParam`]s `'s` lifetime. /// /// # Examples /// /// ``` /// # use bevy_ecs::prelude::*; /// # let world = &mut World::default(); /// fn write_to_local(mut local: Local) { /// *local = 42; /// } /// fn read_from_local(local: Local) -> usize { /// *local /// } /// let mut write_system = IntoSystem::into_system(write_to_local); /// let mut read_system = IntoSystem::into_system(read_from_local); /// write_system.initialize(world); /// read_system.initialize(world); /// /// assert_eq!(read_system.run((), world), 0); /// write_system.run((), world); /// // Note how the read local is still 0 due to the locals not being shared. /// assert_eq!(read_system.run((), world), 0); /// ``` /// /// A simple way to set a different default value for a local is by wrapping the value with an Option. /// /// ``` /// # use bevy_ecs::prelude::*; /// # let world = &mut World::default(); /// fn counter_from_10(mut count: Local>) -> usize { /// let count = count.get_or_insert(10); /// *count += 1; /// *count /// } /// let mut counter_system = IntoSystem::into_system(counter_from_10); /// counter_system.initialize(world); /// /// // Counter is initialized at 10, and increases to 11 on first run. /// assert_eq!(counter_system.run((), world), 11); /// // Counter is only increased by 1 on subsequent runs. /// assert_eq!(counter_system.run((), world), 12); /// ``` /// /// N.B. A [`Local`]s value cannot be read or written to outside of the containing system. /// To add configuration to a system, convert a capturing closure into the system instead: /// /// ``` /// # use bevy_ecs::prelude::*; /// # use bevy_ecs::system::assert_is_system; /// struct Config(u32); /// #[derive(Resource)] /// struct MyU32Wrapper(u32); /// fn reset_to_system(value: Config) -> impl FnMut(ResMut) { /// move |mut val| val.0 = value.0 /// } /// /// // .add_systems(reset_to_system(my_config)) /// # assert_is_system(reset_to_system(Config(10))); /// ``` #[derive(Debug)] pub struct Local<'s, T: FromWorld + Send + 'static>(pub(crate) &'s mut T); // SAFETY: Local only accesses internal state unsafe impl<'s, T: FromWorld + Send + 'static> ReadOnlySystemParam for Local<'s, T> {} impl<'s, T: FromWorld + Send + 'static> Deref for Local<'s, T> { type Target = T; #[inline] fn deref(&self) -> &Self::Target { self.0 } } impl<'s, T: FromWorld + Send + 'static> DerefMut for Local<'s, T> { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { self.0 } } impl<'s, 'a, T: FromWorld + Send + 'static> IntoIterator for &'a Local<'s, T> where &'a T: IntoIterator, { type Item = <&'a T as IntoIterator>::Item; type IntoIter = <&'a T as IntoIterator>::IntoIter; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } } impl<'s, 'a, T: FromWorld + Send + 'static> IntoIterator for &'a mut Local<'s, T> where &'a mut T: IntoIterator, { type Item = <&'a mut T as IntoIterator>::Item; type IntoIter = <&'a mut T as IntoIterator>::IntoIter; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } } // SAFETY: only local state is accessed unsafe impl<'a, T: FromWorld + Send + 'static> SystemParam for Local<'a, T> { type State = SyncCell; type Item<'w, 's> = Local<'s, T>; fn init_state(world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { SyncCell::new(T::from_world(world)) } #[inline] unsafe fn get_param<'w, 's>( state: &'s mut Self::State, _system_meta: &SystemMeta, _world: UnsafeWorldCell<'w>, _change_tick: Tick, ) -> Self::Item<'w, 's> { Local(state.get()) } } /// Types that can be used with [`Deferred`] in systems. /// This allows storing system-local data which is used to defer [`World`] mutations. /// /// Types that implement `SystemBuffer` should take care to perform as many /// computations up-front as possible. Buffers cannot be applied in parallel, /// so you should try to minimize the time spent in [`SystemBuffer::apply`]. pub trait SystemBuffer: FromWorld + Send + 'static { /// Applies any deferred mutations to the [`World`]. fn apply(&mut self, system_meta: &SystemMeta, world: &mut World); /// Queues any deferred mutations to be applied at the next [`ApplyDeferred`](crate::prelude::ApplyDeferred). fn queue(&mut self, _system_meta: &SystemMeta, _world: DeferredWorld) {} } /// A [`SystemParam`] that stores a buffer which gets applied to the [`World`] during /// [`ApplyDeferred`](crate::schedule::ApplyDeferred). /// This is used internally by [`Commands`] to defer `World` mutations. /// /// [`Commands`]: crate::system::Commands /// /// # Examples /// /// By using this type to defer mutations, you can avoid mutable `World` access within /// a system, which allows it to run in parallel with more systems. /// /// Note that deferring mutations is *not* free, and should only be used if /// the gains in parallelization outweigh the time it takes to apply deferred mutations. /// In general, [`Deferred`] should only be used for mutations that are infrequent, /// or which otherwise take up a small portion of a system's run-time. /// /// ``` /// # use bevy_ecs::prelude::*; /// // Tracks whether or not there is a threat the player should be aware of. /// #[derive(Resource, Default)] /// pub struct Alarm(bool); /// /// #[derive(Component)] /// pub struct Settlement { /// // ... /// } /// /// // A threat from inside the settlement. /// #[derive(Component)] /// pub struct Criminal; /// /// // A threat from outside the settlement. /// #[derive(Component)] /// pub struct Monster; /// /// # impl Criminal { pub fn is_threat(&self, _: &Settlement) -> bool { true } } /// /// use bevy_ecs::system::{Deferred, SystemBuffer, SystemMeta}; /// /// // Uses deferred mutations to allow signaling the alarm from multiple systems in parallel. /// #[derive(Resource, Default)] /// struct AlarmFlag(bool); /// /// impl AlarmFlag { /// /// Sounds the alarm the next time buffers are applied via ApplyDeferred. /// pub fn flag(&mut self) { /// self.0 = true; /// } /// } /// /// impl SystemBuffer for AlarmFlag { /// // When `AlarmFlag` is used in a system, this function will get /// // called the next time buffers are applied via ApplyDeferred. /// fn apply(&mut self, system_meta: &SystemMeta, world: &mut World) { /// if self.0 { /// world.resource_mut::().0 = true; /// self.0 = false; /// } /// } /// } /// /// // Sound the alarm if there are any criminals who pose a threat. /// fn alert_criminal( /// settlement: Single<&Settlement>, /// criminals: Query<&Criminal>, /// mut alarm: Deferred /// ) { /// for criminal in &criminals { /// // Only sound the alarm if the criminal is a threat. /// // For this example, assume that this check is expensive to run. /// // Since the majority of this system's run-time is dominated /// // by calling `is_threat()`, we defer sounding the alarm to /// // allow this system to run in parallel with other alarm systems. /// if criminal.is_threat(*settlement) { /// alarm.flag(); /// } /// } /// } /// /// // Sound the alarm if there is a monster. /// fn alert_monster( /// monsters: Query<&Monster>, /// mut alarm: ResMut /// ) { /// if monsters.iter().next().is_some() { /// // Since this system does nothing except for sounding the alarm, /// // it would be pointless to defer it, so we sound the alarm directly. /// alarm.0 = true; /// } /// } /// /// let mut world = World::new(); /// world.init_resource::(); /// world.spawn(Settlement { /// // ... /// }); /// /// let mut schedule = Schedule::default(); /// // These two systems have no conflicts and will run in parallel. /// schedule.add_systems((alert_criminal, alert_monster)); /// /// // There are no criminals or monsters, so the alarm is not sounded. /// schedule.run(&mut world); /// assert_eq!(world.resource::().0, false); /// /// // Spawn a monster, which will cause the alarm to be sounded. /// let m_id = world.spawn(Monster).id(); /// schedule.run(&mut world); /// assert_eq!(world.resource::().0, true); /// /// // Remove the monster and reset the alarm. /// world.entity_mut(m_id).despawn(); /// world.resource_mut::().0 = false; /// /// // Spawn a criminal, which will cause the alarm to be sounded. /// world.spawn(Criminal); /// schedule.run(&mut world); /// assert_eq!(world.resource::().0, true); /// ``` pub struct Deferred<'a, T: SystemBuffer>(pub(crate) &'a mut T); impl<'a, T: SystemBuffer> Deref for Deferred<'a, T> { type Target = T; #[inline] fn deref(&self) -> &Self::Target { self.0 } } impl<'a, T: SystemBuffer> DerefMut for Deferred<'a, T> { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { self.0 } } impl Deferred<'_, T> { /// Returns a [`Deferred`] with a smaller lifetime. /// This is useful if you have `&mut Deferred` but need `Deferred`. pub fn reborrow(&mut self) -> Deferred { Deferred(self.0) } } // SAFETY: Only local state is accessed. unsafe impl ReadOnlySystemParam for Deferred<'_, T> {} // SAFETY: Only local state is accessed. unsafe impl SystemParam for Deferred<'_, T> { type State = SyncCell; type Item<'w, 's> = Deferred<'s, T>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { system_meta.set_has_deferred(); SyncCell::new(T::from_world(world)) } fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) { state.get().apply(system_meta, world); } fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) { state.get().queue(system_meta, world); } #[inline] unsafe fn get_param<'w, 's>( state: &'s mut Self::State, _system_meta: &SystemMeta, _world: UnsafeWorldCell<'w>, _change_tick: Tick, ) -> Self::Item<'w, 's> { Deferred(state.get()) } } /// A dummy type that is [`!Send`](Send), to force systems to run on the main thread. pub struct NonSendMarker; // SAFETY: No world access. unsafe impl SystemParam for NonSendMarker { type State = (); type Item<'w, 's> = Self; #[inline] fn init_state(_world: &mut World, system_meta: &mut SystemMeta) -> Self::State { system_meta.set_non_send(); } #[inline] unsafe fn get_param<'world, 'state>( _state: &'state mut Self::State, _system_meta: &SystemMeta, _world: UnsafeWorldCell<'world>, _change_tick: Tick, ) -> Self::Item<'world, 'state> { Self } } // SAFETY: Does not read any world state unsafe impl ReadOnlySystemParam for NonSendMarker {} /// Shared borrow of a non-[`Send`] resource. /// /// Only `Send` resources may be accessed with the [`Res`] [`SystemParam`]. In case that the /// resource does not implement `Send`, this `SystemParam` wrapper can be used. This will instruct /// the scheduler to instead run the system on the main thread so that it doesn't send the resource /// over to another thread. /// /// This [`SystemParam`] fails validation if non-send resource doesn't exist. /// This will cause a panic, but can be configured to do nothing or warn once. /// /// Use [`Option>`] instead if the resource might not always exist. pub struct NonSend<'w, T: 'static> { pub(crate) value: &'w T, ticks: ComponentTicks, last_run: Tick, this_run: Tick, changed_by: MaybeLocation<&'w &'static Location<'static>>, } // SAFETY: Only reads a single World non-send resource unsafe impl<'w, T> ReadOnlySystemParam for NonSend<'w, T> {} impl<'w, T> Debug for NonSend<'w, T> where T: Debug, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_tuple("NonSend").field(&self.value).finish() } } impl<'w, T: 'static> NonSend<'w, T> { /// Returns `true` if the resource was added after the system last ran. pub fn is_added(&self) -> bool { self.ticks.is_added(self.last_run, self.this_run) } /// Returns `true` if the resource was added or mutably dereferenced after the system last ran. pub fn is_changed(&self) -> bool { self.ticks.is_changed(self.last_run, self.this_run) } /// The location that last caused this to change. pub fn changed_by(&self) -> MaybeLocation { self.changed_by.copied() } } impl<'w, T> Deref for NonSend<'w, T> { type Target = T; fn deref(&self) -> &Self::Target { self.value } } impl<'a, T> From> for NonSend<'a, T> { fn from(nsm: NonSendMut<'a, T>) -> Self { Self { value: nsm.value, ticks: ComponentTicks { added: nsm.ticks.added.to_owned(), changed: nsm.ticks.changed.to_owned(), }, this_run: nsm.ticks.this_run, last_run: nsm.ticks.last_run, changed_by: nsm.changed_by.map(|changed_by| &*changed_by), } } } // SAFETY: NonSendComponentId and ArchetypeComponentId access is applied to SystemMeta. If this // NonSend conflicts with any prior access, a panic will occur. unsafe impl<'a, T: 'static> SystemParam for NonSend<'a, T> { type State = ComponentId; type Item<'w, 's> = NonSend<'w, T>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { system_meta.set_non_send(); let component_id = world.components_registrator().register_non_send::(); let archetype_component_id = world.initialize_non_send_internal(component_id).id(); let combined_access = system_meta.component_access_set.combined_access(); assert!( !combined_access.has_resource_write(component_id), "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", core::any::type_name::(), system_meta.name, ); system_meta .component_access_set .add_unfiltered_resource_read(component_id); system_meta .archetype_component_access .add_resource_read(archetype_component_id); component_id } #[inline] unsafe fn validate_param( &component_id: &Self::State, _system_meta: &SystemMeta, world: UnsafeWorldCell, ) -> Result<(), SystemParamValidationError> { // SAFETY: Read-only access to resource metadata. if unsafe { world.storages() } .non_send_resources .get(component_id) .is_some_and(ResourceData::is_present) { Ok(()) } else { Err(SystemParamValidationError::invalid()) } } #[inline] unsafe fn get_param<'w, 's>( &mut component_id: &'s mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> Self::Item<'w, 's> { let (ptr, ticks, caller) = world .get_non_send_with_ticks(component_id) .unwrap_or_else(|| { panic!( "Non-send resource requested by {} does not exist: {}", system_meta.name, core::any::type_name::() ) }); NonSend { value: ptr.deref(), ticks: ticks.read(), last_run: system_meta.last_run, this_run: change_tick, changed_by: caller.map(|caller| caller.deref()), } } } // SAFETY: Only reads a single World non-send resource unsafe impl ReadOnlySystemParam for Option> {} // SAFETY: this impl defers to `NonSend`, which initializes and validates the correct world access. unsafe impl SystemParam for Option> { type State = ComponentId; type Item<'w, 's> = Option>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { NonSend::::init_state(world, system_meta) } #[inline] unsafe fn get_param<'w, 's>( &mut component_id: &'s mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> Self::Item<'w, 's> { world .get_non_send_with_ticks(component_id) .map(|(ptr, ticks, caller)| NonSend { value: ptr.deref(), ticks: ticks.read(), last_run: system_meta.last_run, this_run: change_tick, changed_by: caller.map(|caller| caller.deref()), }) } } // SAFETY: NonSendMut ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this // NonSendMut conflicts with any prior access, a panic will occur. unsafe impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> { type State = ComponentId; type Item<'w, 's> = NonSendMut<'w, T>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { system_meta.set_non_send(); let component_id = world.components_registrator().register_non_send::(); let archetype_component_id = world.initialize_non_send_internal(component_id).id(); let combined_access = system_meta.component_access_set.combined_access(); if combined_access.has_component_write(component_id) { panic!( "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", core::any::type_name::(), system_meta.name); } else if combined_access.has_component_read(component_id) { panic!( "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", core::any::type_name::(), system_meta.name); } system_meta .component_access_set .add_unfiltered_resource_write(component_id); system_meta .archetype_component_access .add_resource_write(archetype_component_id); component_id } #[inline] unsafe fn validate_param( &component_id: &Self::State, _system_meta: &SystemMeta, world: UnsafeWorldCell, ) -> Result<(), SystemParamValidationError> { // SAFETY: Read-only access to resource metadata. if unsafe { world.storages() } .non_send_resources .get(component_id) .is_some_and(ResourceData::is_present) { Ok(()) } else { Err(SystemParamValidationError::invalid()) } } #[inline] unsafe fn get_param<'w, 's>( &mut component_id: &'s mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> Self::Item<'w, 's> { let (ptr, ticks, caller) = world .get_non_send_with_ticks(component_id) .unwrap_or_else(|| { panic!( "Non-send resource requested by {} does not exist: {}", system_meta.name, core::any::type_name::() ) }); NonSendMut { value: ptr.assert_unique().deref_mut(), ticks: TicksMut::from_tick_cells(ticks, system_meta.last_run, change_tick), changed_by: caller.map(|caller| caller.deref_mut()), } } } // SAFETY: this impl defers to `NonSendMut`, which initializes and validates the correct world access. unsafe impl<'a, T: 'static> SystemParam for Option> { type State = ComponentId; type Item<'w, 's> = Option>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { NonSendMut::::init_state(world, system_meta) } #[inline] unsafe fn get_param<'w, 's>( &mut component_id: &'s mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> Self::Item<'w, 's> { world .get_non_send_with_ticks(component_id) .map(|(ptr, ticks, caller)| NonSendMut { value: ptr.assert_unique().deref_mut(), ticks: TicksMut::from_tick_cells(ticks, system_meta.last_run, change_tick), changed_by: caller.map(|caller| caller.deref_mut()), }) } } // SAFETY: Only reads World archetypes unsafe impl<'a> ReadOnlySystemParam for &'a Archetypes {} // SAFETY: no component value access unsafe impl<'a> SystemParam for &'a Archetypes { type State = (); type Item<'w, 's> = &'w Archetypes; fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} #[inline] unsafe fn get_param<'w, 's>( _state: &'s mut Self::State, _system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, _change_tick: Tick, ) -> Self::Item<'w, 's> { world.archetypes() } } // SAFETY: Only reads World components unsafe impl<'a> ReadOnlySystemParam for &'a Components {} // SAFETY: no component value access unsafe impl<'a> SystemParam for &'a Components { type State = (); type Item<'w, 's> = &'w Components; fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} #[inline] unsafe fn get_param<'w, 's>( _state: &'s mut Self::State, _system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, _change_tick: Tick, ) -> Self::Item<'w, 's> { world.components() } } // SAFETY: Only reads World entities unsafe impl<'a> ReadOnlySystemParam for &'a Entities {} // SAFETY: no component value access unsafe impl<'a> SystemParam for &'a Entities { type State = (); type Item<'w, 's> = &'w Entities; fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} #[inline] unsafe fn get_param<'w, 's>( _state: &'s mut Self::State, _system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, _change_tick: Tick, ) -> Self::Item<'w, 's> { world.entities() } } // SAFETY: Only reads World bundles unsafe impl<'a> ReadOnlySystemParam for &'a Bundles {} // SAFETY: no component value access unsafe impl<'a> SystemParam for &'a Bundles { type State = (); type Item<'w, 's> = &'w Bundles; fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} #[inline] unsafe fn get_param<'w, 's>( _state: &'s mut Self::State, _system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, _change_tick: Tick, ) -> Self::Item<'w, 's> { world.bundles() } } /// A [`SystemParam`] that reads the previous and current change ticks of the system. /// /// A system's change ticks are updated each time it runs: /// - `last_run` copies the previous value of `change_tick` /// - `this_run` copies the current value of [`World::read_change_tick`] /// /// Component change ticks that are more recent than `last_run` will be detected by the system. /// Those can be read by calling [`last_changed`](crate::change_detection::DetectChanges::last_changed) /// on a [`Mut`](crate::change_detection::Mut) or [`ResMut`](ResMut). #[derive(Debug)] pub struct SystemChangeTick { last_run: Tick, this_run: Tick, } impl SystemChangeTick { /// Returns the current [`World`] change tick seen by the system. #[inline] pub fn this_run(&self) -> Tick { self.this_run } /// Returns the [`World`] change tick seen by the system the previous time it ran. #[inline] pub fn last_run(&self) -> Tick { self.last_run } } // SAFETY: Only reads internal system state unsafe impl ReadOnlySystemParam for SystemChangeTick {} // SAFETY: `SystemChangeTick` doesn't require any world access unsafe impl SystemParam for SystemChangeTick { type State = (); type Item<'w, 's> = SystemChangeTick; fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} #[inline] unsafe fn get_param<'w, 's>( _state: &'s mut Self::State, system_meta: &SystemMeta, _world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> Self::Item<'w, 's> { SystemChangeTick { last_run: system_meta.last_run, this_run: change_tick, } } } // SAFETY: When initialized with `init_state`, `get_param` returns an empty `Vec` and does no access. // Therefore, `init_state` trivially registers all access, and no accesses can conflict. // Note that the safety requirements for non-empty `Vec`s are handled by the `SystemParamBuilder` impl that builds them. unsafe impl SystemParam for Vec { type State = Vec; type Item<'world, 'state> = Vec>; fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { Vec::new() } #[inline] unsafe fn validate_param( state: &Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell, ) -> Result<(), SystemParamValidationError> { for state in state { T::validate_param(state, system_meta, world)?; } Ok(()) } #[inline] unsafe fn get_param<'world, 'state>( state: &'state mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'world>, change_tick: Tick, ) -> Self::Item<'world, 'state> { state .iter_mut() // SAFETY: // - 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. // - The caller ensures this was the world used to initialize our state, and we used that world to initialize parameter states .map(|state| unsafe { T::get_param(state, system_meta, world, change_tick) }) .collect() } unsafe fn new_archetype( state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta, ) { for state in state { // SAFETY: The caller ensures that `archetype` is from the World the state was initialized from in `init_state`. unsafe { T::new_archetype(state, archetype, system_meta) }; } } fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) { for state in state { T::apply(state, system_meta, world); } } fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) { for state in state { T::queue(state, system_meta, world.reborrow()); } } } // SAFETY: When initialized with `init_state`, `get_param` returns an empty `Vec` and does no access. // Therefore, `init_state` trivially registers all access, and no accesses can conflict. // Note that the safety requirements for non-empty `Vec`s are handled by the `SystemParamBuilder` impl that builds them. unsafe impl SystemParam for ParamSet<'_, '_, Vec> { type State = Vec; type Item<'world, 'state> = ParamSet<'world, 'state, Vec>; fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { Vec::new() } #[inline] unsafe fn get_param<'world, 'state>( state: &'state mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'world>, change_tick: Tick, ) -> Self::Item<'world, 'state> { ParamSet { param_states: state, system_meta: system_meta.clone(), world, change_tick, } } unsafe fn new_archetype( state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta, ) { for state in state { // SAFETY: The caller ensures that `archetype` is from the World the state was initialized from in `init_state`. unsafe { T::new_archetype(state, archetype, system_meta) } } } fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) { for state in state { T::apply(state, system_meta, world); } } fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) { for state in state { T::queue(state, system_meta, world.reborrow()); } } } impl ParamSet<'_, '_, Vec> { /// Accesses the parameter at the given index. /// No other parameters may be accessed while this one is active. pub fn get_mut(&mut self, index: usize) -> T::Item<'_, '_> { // SAFETY: // - 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. // We have mutable access to the ParamSet, so no other params in the set are active. // - 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 unsafe { T::get_param( &mut self.param_states[index], &self.system_meta, self.world, self.change_tick, ) } } /// Calls a closure for each parameter in the set. pub fn for_each(&mut self, mut f: impl FnMut(T::Item<'_, '_>)) { self.param_states.iter_mut().for_each(|state| { f( // SAFETY: // - 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. // We have mutable access to the ParamSet, so no other params in the set are active. // - 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 unsafe { T::get_param(state, &self.system_meta, self.world, self.change_tick) }, ); }); } } macro_rules! impl_system_param_tuple { ($(#[$meta:meta])* $($param: ident),*) => { $(#[$meta])* // SAFETY: tuple consists only of ReadOnlySystemParams unsafe impl<$($param: ReadOnlySystemParam),*> ReadOnlySystemParam for ($($param,)*) {} #[expect( clippy::allow_attributes, reason = "This is in a macro, and as such, the below lints may not always apply." )] #[allow( non_snake_case, reason = "Certain variable names are provided by the caller, not by us." )] #[allow( unused_variables, reason = "Zero-length tuples won't use some of the parameters." )] $(#[$meta])* // SAFETY: implementers of each `SystemParam` in the tuple have validated their impls unsafe impl<$($param: SystemParam),*> SystemParam for ($($param,)*) { type State = ($($param::State,)*); type Item<'w, 's> = ($($param::Item::<'w, 's>,)*); #[inline] fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { (($($param::init_state(world, system_meta),)*)) } #[inline] unsafe fn new_archetype(($($param,)*): &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta) { #[allow( unused_unsafe, reason = "Zero-length tuples will not run anything in the unsafe block." )] // SAFETY: The caller ensures that `archetype` is from the World the state was initialized from in `init_state`. unsafe { $($param::new_archetype($param, archetype, system_meta);)* } } #[inline] fn apply(($($param,)*): &mut Self::State, system_meta: &SystemMeta, world: &mut World) { $($param::apply($param, system_meta, world);)* } #[inline] #[allow( unused_mut, reason = "The `world` parameter is unused for zero-length tuples; however, it must be mutable for other lengths of tuples." )] fn queue(($($param,)*): &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) { $($param::queue($param, system_meta, world.reborrow());)* } #[inline] unsafe fn validate_param( state: &Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell, ) -> Result<(), SystemParamValidationError> { let ($($param,)*) = state; $( $param::validate_param($param, system_meta, world)?; )* Ok(()) } #[inline] unsafe fn get_param<'w, 's>( state: &'s mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> Self::Item<'w, 's> { let ($($param,)*) = state; #[allow( clippy::unused_unit, reason = "Zero-length tuples won't have any params to get." )] ($($param::get_param($param, system_meta, world, change_tick),)*) } } }; } all_tuples!( #[doc(fake_variadic)] impl_system_param_tuple, 0, 16, P ); /// Contains type aliases for built-in [`SystemParam`]s with `'static` lifetimes. /// This makes it more convenient to refer to these types in contexts where /// explicit lifetime annotations are required. /// /// Note that this is entirely safe and tracks lifetimes correctly. /// This purely exists for convenience. /// /// You can't instantiate a static `SystemParam`, you'll always end up with /// `Res<'w, T>`, `ResMut<'w, T>` or `&'w T` bound to the lifetime of the provided /// `&'w World`. /// /// [`SystemParam`]: super::SystemParam pub mod lifetimeless { /// A [`Query`](super::Query) with `'static` lifetimes. pub type SQuery = super::Query<'static, 'static, D, F>; /// A shorthand for writing `&'static T`. pub type Read = &'static T; /// A shorthand for writing `&'static mut T`. pub type Write = &'static mut T; /// A [`Res`](super::Res) with `'static` lifetimes. pub type SRes = super::Res<'static, T>; /// A [`ResMut`](super::ResMut) with `'static` lifetimes. pub type SResMut = super::ResMut<'static, T>; /// [`Commands`](crate::system::Commands) with `'static` lifetimes. pub type SCommands = crate::system::Commands<'static, 'static>; } /// A helper for using system parameters in generic contexts /// /// This type is a [`SystemParam`] adapter which always has /// `Self::Item == Self` (ignoring lifetimes for brevity), /// no matter the argument [`SystemParam`] (`P`) (other than /// that `P` must be `'static`) /// /// This makes it useful for having arbitrary [`SystemParam`] type arguments /// to function systems, or for generic types using the [`derive@SystemParam`] /// derive: /// /// ``` /// # use bevy_ecs::prelude::*; /// use bevy_ecs::system::{SystemParam, StaticSystemParam}; /// #[derive(SystemParam)] /// struct GenericParam<'w,'s, T: SystemParam + 'static> { /// field: StaticSystemParam<'w, 's, T>, /// } /// fn do_thing_generically(t: StaticSystemParam) {} /// /// fn check_always_is_system(){ /// bevy_ecs::system::assert_is_system(do_thing_generically::); /// } /// ``` /// Note that in a real case you'd generally want /// additional bounds on `P`, for your use of the parameter /// to have a reason to be generic. /// /// For example, using this would allow a type to be generic over /// whether a resource is accessed mutably or not, with /// impls being bounded on [`P: Deref`](Deref), and /// [`P: DerefMut`](DerefMut) depending on whether the /// method requires mutable access or not. /// /// The method which doesn't use this type will not compile: /// ```compile_fail /// # use bevy_ecs::prelude::*; /// # use bevy_ecs::system::{SystemParam, StaticSystemParam}; /// /// fn do_thing_generically(t: T) {} /// /// #[derive(SystemParam)] /// struct GenericParam<'w, 's, T: SystemParam> { /// field: T, /// // Use the lifetimes in this type, or they will be unbound. /// phantom: std::marker::PhantomData<&'w &'s ()> /// } /// # fn check_always_is_system(){ /// # bevy_ecs::system::assert_is_system(do_thing_generically::); /// # } /// ``` pub struct StaticSystemParam<'w, 's, P: SystemParam>(SystemParamItem<'w, 's, P>); impl<'w, 's, P: SystemParam> Deref for StaticSystemParam<'w, 's, P> { type Target = SystemParamItem<'w, 's, P>; fn deref(&self) -> &Self::Target { &self.0 } } impl<'w, 's, P: SystemParam> DerefMut for StaticSystemParam<'w, 's, P> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl<'w, 's, P: SystemParam> StaticSystemParam<'w, 's, P> { /// Get the value of the parameter pub fn into_inner(self) -> SystemParamItem<'w, 's, P> { self.0 } } // SAFETY: This doesn't add any more reads, and the delegated fetch confirms it unsafe impl<'w, 's, P: ReadOnlySystemParam + 'static> ReadOnlySystemParam for StaticSystemParam<'w, 's, P> { } // SAFETY: all methods are just delegated to `P`'s `SystemParam` implementation unsafe impl SystemParam for StaticSystemParam<'_, '_, P> { type State = P::State; type Item<'world, 'state> = StaticSystemParam<'world, 'state, P>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { P::init_state(world, system_meta) } unsafe fn new_archetype( state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta, ) { // SAFETY: The caller guarantees that the provided `archetype` matches the World used to initialize `state`. unsafe { P::new_archetype(state, archetype, system_meta) }; } fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) { P::apply(state, system_meta, world); } fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) { P::queue(state, system_meta, world); } #[inline] unsafe fn validate_param( state: &Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell, ) -> Result<(), SystemParamValidationError> { P::validate_param(state, system_meta, world) } #[inline] unsafe fn get_param<'world, 'state>( state: &'state mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'world>, change_tick: Tick, ) -> Self::Item<'world, 'state> { // SAFETY: Defer to the safety of P::SystemParam StaticSystemParam(unsafe { P::get_param(state, system_meta, world, change_tick) }) } } // SAFETY: No world access. unsafe impl SystemParam for PhantomData { type State = (); type Item<'world, 'state> = Self; fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} #[inline] unsafe fn get_param<'world, 'state>( _state: &'state mut Self::State, _system_meta: &SystemMeta, _world: UnsafeWorldCell<'world>, _change_tick: Tick, ) -> Self::Item<'world, 'state> { PhantomData } } // SAFETY: No world access. unsafe impl ReadOnlySystemParam for PhantomData {} /// A [`SystemParam`] with a type that can be configured at runtime. /// /// To be useful, this must be configured using a [`DynParamBuilder`](crate::system::DynParamBuilder) to build the system using a [`SystemParamBuilder`](crate::prelude::SystemParamBuilder). /// /// # Examples /// /// ``` /// # use bevy_ecs::{prelude::*, system::*}; /// # /// # #[derive(Default, Resource)] /// # struct A; /// # /// # #[derive(Default, Resource)] /// # struct B; /// # /// # let mut world = World::new(); /// # world.init_resource::(); /// # world.init_resource::(); /// # /// // If the inner parameter doesn't require any special building, use `ParamBuilder`. /// // Either specify the type parameter on `DynParamBuilder::new()` ... /// let system = (DynParamBuilder::new::>(ParamBuilder),) /// .build_state(&mut world) /// .build_system(expects_res_a); /// # world.run_system_once(system); /// /// // ... or use a factory method on `ParamBuilder` that returns a specific type. /// let system = (DynParamBuilder::new(ParamBuilder::resource::()),) /// .build_state(&mut world) /// .build_system(expects_res_a); /// # world.run_system_once(system); /// /// fn expects_res_a(mut param: DynSystemParam) { /// // Use the `downcast` methods to retrieve the inner parameter. /// // They will return `None` if the type does not match. /// assert!(param.is::>()); /// assert!(!param.is::>()); /// assert!(param.downcast_mut::>().is_none()); /// let res = param.downcast_mut::>().unwrap(); /// // The type parameter can be left out if it can be determined from use. /// let res: Res = param.downcast().unwrap(); /// } /// /// let system = ( /// // If the inner parameter also requires building, /// // pass the appropriate `SystemParamBuilder`. /// DynParamBuilder::new(LocalBuilder(10usize)), /// // `DynSystemParam` is just an ordinary `SystemParam`, /// // and can be combined with other parameters as usual! /// ParamBuilder::query(), /// ) /// .build_state(&mut world) /// .build_system(|param: DynSystemParam, query: Query<()>| { /// let local: Local = param.downcast::>().unwrap(); /// assert_eq!(*local, 10); /// }); /// # world.run_system_once(system); /// ``` pub struct DynSystemParam<'w, 's> { /// A `ParamState` wrapping the state for the underlying system param. state: &'s mut dyn Any, world: UnsafeWorldCell<'w>, system_meta: SystemMeta, change_tick: Tick, } impl<'w, 's> DynSystemParam<'w, 's> { /// # Safety /// - `state` must be a `ParamState` for some inner `T: SystemParam`. /// - The passed [`UnsafeWorldCell`] must have access to any world data registered /// in [`init_state`](SystemParam::init_state) for the inner system param. /// - `world` must be the same `World` that was used to initialize /// [`state`](SystemParam::init_state) for the inner system param. unsafe fn new( state: &'s mut dyn Any, world: UnsafeWorldCell<'w>, system_meta: SystemMeta, change_tick: Tick, ) -> Self { Self { state, world, system_meta, change_tick, } } /// Returns `true` if the inner system param is the same as `T`. pub fn is(&self) -> bool // See downcast() function for an explanation of the where clause where T::Item<'static, 'static>: SystemParam = T> + 'static, { self.state.is::>>() } /// Returns the inner system param if it is the correct type. /// This consumes the dyn param, so the returned param can have its original world and state lifetimes. pub fn downcast(self) -> Option // See downcast() function for an explanation of the where clause where T::Item<'static, 'static>: SystemParam = T> + 'static, { // SAFETY: // - `DynSystemParam::new()` ensures `state` is a `ParamState`, that the world matches, // and that it has access required by the inner system param. // - This consumes the `DynSystemParam`, so it is the only use of `world` with this access and it is available for `'w`. unsafe { downcast::(self.state, &self.system_meta, self.world, self.change_tick) } } /// Returns the inner system parameter if it is the correct type. /// This borrows the dyn param, so the returned param is only valid for the duration of that borrow. pub fn downcast_mut<'a, T: SystemParam>(&'a mut self) -> Option // See downcast() function for an explanation of the where clause where T::Item<'static, 'static>: SystemParam = T> + 'static, { // SAFETY: // - `DynSystemParam::new()` ensures `state` is a `ParamState`, that the world matches, // and that it has access required by the inner system param. // - This exclusively borrows the `DynSystemParam` for `'_`, so it is the only use of `world` with this access for `'_`. unsafe { downcast::(self.state, &self.system_meta, self.world, self.change_tick) } } /// Returns the inner system parameter if it is the correct type. /// This borrows the dyn param, so the returned param is only valid for the duration of that borrow, /// but since it only performs read access it can keep the original world lifetime. /// This can be useful with methods like [`Query::iter_inner()`] or [`Res::into_inner()`] /// to obtain references with the original world lifetime. pub fn downcast_mut_inner<'a, T: ReadOnlySystemParam>(&'a mut self) -> Option // See downcast() function for an explanation of the where clause where T::Item<'static, 'static>: SystemParam = T> + 'static, { // SAFETY: // - `DynSystemParam::new()` ensures `state` is a `ParamState`, that the world matches, // and that it has access required by the inner system param. // - The inner system param only performs read access, so it's safe to copy that access for the full `'w` lifetime. unsafe { downcast::(self.state, &self.system_meta, self.world, self.change_tick) } } } /// # Safety /// - `state` must be a `ParamState` for some inner `T: SystemParam`. /// - The passed [`UnsafeWorldCell`] must have access to any world data registered /// in [`init_state`](SystemParam::init_state) for the inner system param. /// - `world` must be the same `World` that was used to initialize /// [`state`](SystemParam::init_state) for the inner system param. unsafe fn downcast<'w, 's, T: SystemParam>( state: &'s mut dyn Any, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick, ) -> Option // We need a 'static version of the SystemParam to use with `Any::downcast_mut()`, // and we need a <'w, 's> version to actually return. // The type parameter T must be the one we return in order to get type inference from the return value. // So we use `T::Item<'static, 'static>` as the 'static version, and require that it be 'static. // That means the return value will be T::Item<'static, 'static>::Item<'w, 's>, // so we constrain that to be equal to T. // Every actual `SystemParam` implementation has `T::Item == T` up to lifetimes, // so they should all work with this constraint. where T::Item<'static, 'static>: SystemParam = T> + 'static, { state .downcast_mut::>>() .map(|state| { // SAFETY: // - The caller ensures the world has access for the underlying system param, // and since the downcast succeeded, the underlying system param is T. // - The caller ensures the `world` matches. unsafe { T::Item::get_param(&mut state.0, system_meta, world, change_tick) } }) } /// The [`SystemParam::State`] for a [`DynSystemParam`]. pub struct DynSystemParamState(Box); impl DynSystemParamState { pub(crate) fn new(state: T::State) -> Self { Self(Box::new(ParamState::(state))) } } /// Allows a [`SystemParam::State`] to be used as a trait object for implementing [`DynSystemParam`]. trait DynParamState: Sync + Send { /// Casts the underlying `ParamState` to an `Any` so it can be downcast. fn as_any_mut(&mut self) -> &mut dyn Any; /// For the specified [`Archetype`], registers the components accessed by this [`SystemParam`] (if applicable).a /// /// # Safety /// `archetype` must be from the [`World`] used to initialize `state` in [`SystemParam::init_state`]. unsafe fn new_archetype(&mut self, archetype: &Archetype, system_meta: &mut SystemMeta); /// Applies any deferred mutations stored in this [`SystemParam`]'s state. /// This is used to apply [`Commands`] during [`ApplyDeferred`](crate::prelude::ApplyDeferred). /// /// [`Commands`]: crate::prelude::Commands fn apply(&mut self, system_meta: &SystemMeta, world: &mut World); /// Queues any deferred mutations to be applied at the next [`ApplyDeferred`](crate::prelude::ApplyDeferred). fn queue(&mut self, system_meta: &SystemMeta, world: DeferredWorld); /// Refer to [`SystemParam::validate_param`]. /// /// # Safety /// Refer to [`SystemParam::validate_param`]. unsafe fn validate_param( &self, system_meta: &SystemMeta, world: UnsafeWorldCell, ) -> Result<(), SystemParamValidationError>; } /// A wrapper around a [`SystemParam::State`] that can be used as a trait object in a [`DynSystemParam`]. struct ParamState(T::State); impl DynParamState for ParamState { fn as_any_mut(&mut self) -> &mut dyn Any { self } unsafe fn new_archetype(&mut self, archetype: &Archetype, system_meta: &mut SystemMeta) { // SAFETY: The caller ensures that `archetype` is from the World the state was initialized from in `init_state`. unsafe { T::new_archetype(&mut self.0, archetype, system_meta) }; } fn apply(&mut self, system_meta: &SystemMeta, world: &mut World) { T::apply(&mut self.0, system_meta, world); } fn queue(&mut self, system_meta: &SystemMeta, world: DeferredWorld) { T::queue(&mut self.0, system_meta, world); } unsafe fn validate_param( &self, system_meta: &SystemMeta, world: UnsafeWorldCell, ) -> Result<(), SystemParamValidationError> { T::validate_param(&self.0, system_meta, world) } } // SAFETY: `init_state` creates a state of (), which performs no access. The interesting safety checks are on the `SystemParamBuilder`. unsafe impl SystemParam for DynSystemParam<'_, '_> { type State = DynSystemParamState; type Item<'world, 'state> = DynSystemParam<'world, 'state>; fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { DynSystemParamState::new::<()>(()) } #[inline] unsafe fn validate_param( state: &Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell, ) -> Result<(), SystemParamValidationError> { state.0.validate_param(system_meta, world) } #[inline] unsafe fn get_param<'world, 'state>( state: &'state mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'world>, change_tick: Tick, ) -> Self::Item<'world, 'state> { // SAFETY: // - `state.0` is a boxed `ParamState`, and its implementation of `as_any_mut` returns `self`. // - The state was obtained from `SystemParamBuilder::build()`, which registers all [`World`] accesses used // by [`SystemParam::get_param`] with the provided [`system_meta`](SystemMeta). // - The caller ensures that the provided world is the same and has the required access. unsafe { DynSystemParam::new( state.0.as_any_mut(), world, system_meta.clone(), change_tick, ) } } unsafe fn new_archetype( state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta, ) { // SAFETY: The caller ensures that `archetype` is from the World the state was initialized from in `init_state`. unsafe { state.0.new_archetype(archetype, system_meta) }; } fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) { state.0.apply(system_meta, world); } fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) { state.0.queue(system_meta, world); } } // SAFETY: When initialized with `init_state`, `get_param` returns a `FilteredResources` with no access. // Therefore, `init_state` trivially registers all access, and no accesses can conflict. // Note that the safety requirements for non-empty access are handled by the `SystemParamBuilder` impl that builds them. unsafe impl SystemParam for FilteredResources<'_, '_> { type State = Access; type Item<'world, 'state> = FilteredResources<'world, 'state>; fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { Access::new() } unsafe fn get_param<'world, 'state>( state: &'state mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'world>, change_tick: Tick, ) -> Self::Item<'world, 'state> { // SAFETY: The caller ensures that `world` has access to anything registered in `init_state` or `build`, // and the builder registers `access` in `build`. unsafe { FilteredResources::new(world, state, system_meta.last_run, change_tick) } } } // SAFETY: FilteredResources only reads resources. unsafe impl ReadOnlySystemParam for FilteredResources<'_, '_> {} // SAFETY: When initialized with `init_state`, `get_param` returns a `FilteredResourcesMut` with no access. // Therefore, `init_state` trivially registers all access, and no accesses can conflict. // Note that the safety requirements for non-empty access are handled by the `SystemParamBuilder` impl that builds them. unsafe impl SystemParam for FilteredResourcesMut<'_, '_> { type State = Access; type Item<'world, 'state> = FilteredResourcesMut<'world, 'state>; fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { Access::new() } unsafe fn get_param<'world, 'state>( state: &'state mut Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'world>, change_tick: Tick, ) -> Self::Item<'world, 'state> { // SAFETY: The caller ensures that `world` has access to anything registered in `init_state` or `build`, // and the builder registers `access` in `build`. unsafe { FilteredResourcesMut::new(world, state, system_meta.last_run, change_tick) } } } /// An error that occurs when a system parameter is not valid, /// used by system executors to determine what to do with a system. /// /// Returned as an error from [`SystemParam::validate_param`], /// and handled using the unified error handling mechanisms defined in [`bevy_ecs::error`]. #[derive(Debug, PartialEq, Eq, Clone, Display, Error)] pub struct SystemParamValidationError { /// Whether the system should be skipped. /// /// If `false`, the error should be handled. /// By default, this will result in a panic. See [`crate::error`] for more information. /// /// This is the default behavior, and is suitable for system params that should *always* be valid, /// either because sensible fallback behavior exists (like [`Query`] or because /// failures in validation should be considered a bug in the user's logic that must be immediately addressed (like [`Res`]). /// /// If `true`, the system should be skipped. /// This is suitable for system params that are intended to only operate in certain application states, such as [`Single`]. pub skipped: bool, } impl SystemParamValidationError { /// Constructs a `SystemParamValidationError` that skips the system. pub const fn skipped() -> Self { Self { skipped: true } } /// Constructs a `SystemParamValidationError` for an invalid parameter that should be treated as an error. pub const fn invalid() -> Self { Self { skipped: false } } } #[cfg(test)] mod tests { use super::*; use crate::system::assert_is_system; use core::cell::RefCell; // Compile test for https://github.com/bevyengine/bevy/pull/2838. #[test] fn system_param_generic_bounds() { #[derive(SystemParam)] pub struct SpecialQuery< 'w, 's, D: QueryData + Send + Sync + 'static, F: QueryFilter + Send + Sync + 'static = (), > { _query: Query<'w, 's, D, F>, } fn my_system(_: SpecialQuery<(), ()>) {} assert_is_system(my_system); } // Compile tests for https://github.com/bevyengine/bevy/pull/6694. #[test] fn system_param_flexibility() { #[derive(SystemParam)] pub struct SpecialRes<'w, T: Resource> { _res: Res<'w, T>, } #[derive(SystemParam)] pub struct SpecialLocal<'s, T: FromWorld + Send + 'static> { _local: Local<'s, T>, } #[derive(Resource)] struct R; fn my_system(_: SpecialRes, _: SpecialLocal) {} assert_is_system(my_system); } #[derive(Resource)] pub struct R; // Compile test for https://github.com/bevyengine/bevy/pull/7001. #[test] fn system_param_const_generics() { #[expect( dead_code, reason = "This struct is used to ensure that const generics are supported as a SystemParam; thus, the inner value never needs to be read." )] #[derive(SystemParam)] pub struct ConstGenericParam<'w, const I: usize>(Res<'w, R>); fn my_system(_: ConstGenericParam<0>, _: ConstGenericParam<1000>) {} assert_is_system(my_system); } // Compile test for https://github.com/bevyengine/bevy/pull/6867. #[test] fn system_param_field_limit() { #[derive(SystemParam)] pub struct LongParam<'w> { // Each field should be a distinct type so there will // be an error if the derive messes up the field order. _r0: Res<'w, R<0>>, _r1: Res<'w, R<1>>, _r2: Res<'w, R<2>>, _r3: Res<'w, R<3>>, _r4: Res<'w, R<4>>, _r5: Res<'w, R<5>>, _r6: Res<'w, R<6>>, _r7: Res<'w, R<7>>, _r8: Res<'w, R<8>>, _r9: Res<'w, R<9>>, _r10: Res<'w, R<10>>, _r11: Res<'w, R<11>>, _r12: Res<'w, R<12>>, _r13: Res<'w, R<13>>, _r14: Res<'w, R<14>>, _r15: Res<'w, R<15>>, _r16: Res<'w, R<16>>, } fn long_system(_: LongParam) {} assert_is_system(long_system); } // Compile test for https://github.com/bevyengine/bevy/pull/6919. // Regression test for https://github.com/bevyengine/bevy/issues/7447. #[test] fn system_param_phantom_data() { #[derive(SystemParam)] struct PhantomParam<'w, T: Resource, Marker: 'static> { _foo: Res<'w, T>, marker: PhantomData<&'w Marker>, } fn my_system(_: PhantomParam, ()>) {} assert_is_system(my_system); } // Compile tests for https://github.com/bevyengine/bevy/pull/6957. #[test] fn system_param_struct_variants() { #[derive(SystemParam)] pub struct UnitParam; #[expect( dead_code, reason = "This struct is used to ensure that tuple structs are supported as a SystemParam; thus, the inner values never need to be read." )] #[derive(SystemParam)] pub struct TupleParam<'w, 's, R: Resource, L: FromWorld + Send + 'static>( Res<'w, R>, Local<'s, L>, ); fn my_system(_: UnitParam, _: TupleParam, u32>) {} assert_is_system(my_system); } // Regression test for https://github.com/bevyengine/bevy/issues/4200. #[test] fn system_param_private_fields() { #[derive(Resource)] struct PrivateResource; #[expect( dead_code, 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." )] #[derive(SystemParam)] pub struct EncapsulatedParam<'w>(Res<'w, PrivateResource>); fn my_system(_: EncapsulatedParam) {} assert_is_system(my_system); } // Regression test for https://github.com/bevyengine/bevy/issues/7103. #[test] fn system_param_where_clause() { #[derive(SystemParam)] pub struct WhereParam<'w, 's, D> where D: 'static + QueryData, { _q: Query<'w, 's, D, ()>, } fn my_system(_: WhereParam<()>) {} assert_is_system(my_system); } // Regression test for https://github.com/bevyengine/bevy/issues/1727. #[test] fn system_param_name_collision() { #[derive(Resource)] pub struct FetchState; #[derive(SystemParam)] pub struct Collide<'w> { _x: Res<'w, FetchState>, } fn my_system(_: Collide) {} assert_is_system(my_system); } // Regression test for https://github.com/bevyengine/bevy/issues/8192. #[test] fn system_param_invariant_lifetime() { #[derive(SystemParam)] pub struct InvariantParam<'w, 's> { _set: ParamSet<'w, 's, (Query<'w, 's, ()>,)>, } fn my_system(_: InvariantParam) {} assert_is_system(my_system); } // Compile test for https://github.com/bevyengine/bevy/pull/9589. #[test] fn non_sync_local() { fn non_sync_system(cell: Local>) { assert_eq!(*cell.borrow(), 0); } let mut world = World::new(); let mut schedule = crate::schedule::Schedule::default(); schedule.add_systems(non_sync_system); schedule.run(&mut world); } // Regression test for https://github.com/bevyengine/bevy/issues/10207. #[test] fn param_set_non_send_first() { fn non_send_param_set(mut p: ParamSet<(NonSend<*mut u8>, ())>) { let _ = p.p0(); p.p1(); } let mut world = World::new(); world.insert_non_send_resource(core::ptr::null_mut::()); let mut schedule = crate::schedule::Schedule::default(); schedule.add_systems((non_send_param_set, non_send_param_set, non_send_param_set)); schedule.run(&mut world); } // Regression test for https://github.com/bevyengine/bevy/issues/10207. #[test] fn param_set_non_send_second() { fn non_send_param_set(mut p: ParamSet<((), NonSendMut<*mut u8>)>) { p.p0(); let _ = p.p1(); } let mut world = World::new(); world.insert_non_send_resource(core::ptr::null_mut::()); let mut schedule = crate::schedule::Schedule::default(); schedule.add_systems((non_send_param_set, non_send_param_set, non_send_param_set)); schedule.run(&mut world); } fn _dyn_system_param_type_inference(mut p: DynSystemParam) { // Make sure the downcast() methods are able to infer their type parameters from the use of the return type. // This is just a compilation test, so there is nothing to run. let _query: Query<()> = p.downcast_mut().unwrap(); let _query: Query<()> = p.downcast_mut_inner().unwrap(); let _query: Query<()> = p.downcast().unwrap(); } }