Path: blob/main/crates/bevy_ecs/src/system/system_param.rs
9550 views
#![expect(1unsafe_op_in_unsafe_fn,2reason = "See #11590. To be removed once all applicable unsafe code has an unsafe block with a safety comment."3)]45pub use crate::change_detection::{NonSend, NonSendMut, Res, ResMut};6use crate::{7archetype::Archetypes,8bundle::Bundles,9change_detection::{ComponentTicksMut, ComponentTicksRef, Tick},10component::{ComponentId, Components},11entity::{Entities, EntityAllocator},12query::{13Access, FilteredAccess, FilteredAccessSet, QueryData, QueryFilter, QuerySingleError,14QueryState, ReadOnlyQueryData,15},16resource::{Resource, IS_RESOURCE},17storage::NonSendData,18system::{Query, Single, SystemMeta},19world::{20unsafe_world_cell::UnsafeWorldCell, DeferredWorld, FilteredResources, FilteredResourcesMut,21FromWorld, World,22},23};24use alloc::{borrow::Cow, boxed::Box, vec::Vec};25pub use bevy_ecs_macros::SystemParam;26use bevy_platform::cell::SyncCell;27use bevy_ptr::UnsafeCellDeref;28use bevy_utils::prelude::DebugName;29use core::{30any::Any,31fmt::{Debug, Display},32marker::PhantomData,33ops::{Deref, DerefMut},34};35use thiserror::Error;3637use super::Populated;38use variadics_please::{all_tuples, all_tuples_enumerated};3940/// A parameter that can be used in a [`System`](super::System).41///42/// # Derive43///44/// This trait can be derived with the [`derive@super::SystemParam`] macro.45/// This macro only works if each field on the derived struct implements [`SystemParam`].46/// Note: There are additional requirements on the field types.47/// See the *Generic `SystemParam`s* section for details and workarounds of the probable48/// cause if this derive causes an error to be emitted.49///50/// Derived `SystemParam` structs may have two lifetimes: `'w` for data stored in the [`World`],51/// and `'s` for data stored in the parameter's state.52///53/// The following list shows the most common [`SystemParam`]s and which lifetime they require54///55/// ```56/// # use bevy_ecs::prelude::*;57/// # #[derive(Component)]58/// # struct SomeComponent;59/// # #[derive(Resource)]60/// # struct SomeResource;61/// # #[derive(Message)]62/// # struct SomeMessage;63/// # #[derive(Resource)]64/// # struct SomeOtherResource;65/// # use bevy_ecs::system::SystemParam;66/// # #[derive(SystemParam)]67/// # struct ParamsExample<'w, 's> {68/// # query:69/// Query<'w, 's, Entity>,70/// # query2:71/// Query<'w, 's, &'static SomeComponent>,72/// # res:73/// Res<'w, SomeResource>,74/// # res_mut:75/// ResMut<'w, SomeOtherResource>,76/// # local:77/// Local<'s, u8>,78/// # commands:79/// Commands<'w, 's>,80/// # message_reader:81/// MessageReader<'w, 's, SomeMessage>,82/// # message_writer:83/// MessageWriter<'w, SomeMessage>84/// # }85/// ```86/// ## `PhantomData`87///88/// [`PhantomData`] is a special type of `SystemParam` that does nothing.89/// This is useful for constraining generic types or lifetimes.90///91/// # Example92///93/// ```94/// # use bevy_ecs::prelude::*;95/// # #[derive(Resource)]96/// # struct SomeResource;97/// use std::marker::PhantomData;98/// use bevy_ecs::system::SystemParam;99///100/// #[derive(SystemParam)]101/// struct MyParam<'w, Marker: 'static> {102/// foo: Res<'w, SomeResource>,103/// marker: PhantomData<Marker>,104/// }105///106/// fn my_system<T: 'static>(param: MyParam<T>) {107/// // Access the resource through `param.foo`108/// }109///110/// # bevy_ecs::system::assert_is_system(my_system::<()>);111/// ```112///113/// # Generic `SystemParam`s114///115/// When using the derive macro, you may see an error in the form of:116///117/// ```text118/// expected ... [ParamType]119/// found associated type `<[ParamType] as SystemParam>::Item<'_, '_>`120/// ```121/// where `[ParamType]` is the type of one of your fields.122/// To solve this error, you can wrap the field of type `[ParamType]` with [`StaticSystemParam`]123/// (i.e. `StaticSystemParam<[ParamType]>`).124///125/// ## Details126///127/// The derive macro requires that the [`SystemParam`] implementation of128/// each field `F`'s [`Item`](`SystemParam::Item`)'s is itself `F`129/// (ignoring lifetimes for simplicity).130/// This assumption is due to type inference reasons, so that the derived [`SystemParam`] can be131/// used as an argument to a function system.132/// If the compiler cannot validate this property for `[ParamType]`, it will error in the form shown above.133///134/// This will most commonly occur when working with `SystemParam`s generically, as the requirement135/// has not been proven to the compiler.136///137/// ## Custom Validation Messages138///139/// When using the derive macro, any [`SystemParamValidationError`]s will be propagated from the sub-parameters.140/// If you want to override the error message, add a `#[system_param(validation_message = "New message")]` attribute to the parameter.141///142/// ```143/// # use bevy_ecs::prelude::*;144/// # #[derive(Resource)]145/// # struct SomeResource;146/// # use bevy_ecs::system::SystemParam;147/// #148/// #[derive(SystemParam)]149/// struct MyParam<'w> {150/// #[system_param(validation_message = "Custom Message")]151/// foo: Res<'w, SomeResource>,152/// }153///154/// let mut world = World::new();155/// let err = world.run_system_cached(|param: MyParam| {}).unwrap_err();156/// let expected = "Parameter `MyParam::foo` failed validation: Custom Message";157/// # #[cfg(feature="Trace")] // Without debug_utils/debug enabled MyParam::foo is stripped and breaks the assert158/// assert!(err.to_string().contains(expected));159/// ```160///161/// ## Builders162///163/// If you want to use a [`SystemParamBuilder`](crate::system::SystemParamBuilder) with a derived [`SystemParam`] implementation,164/// add a `#[system_param(builder)]` attribute to the struct.165/// This will generate a builder struct whose name is the param struct suffixed with `Builder`.166/// The builder will not be `pub`, so you may want to expose a method that returns an `impl SystemParamBuilder<T>`.167///168/// ```169/// mod custom_param {170/// # use bevy_ecs::{171/// # prelude::*,172/// # system::{LocalBuilder, QueryParamBuilder, SystemParam},173/// # };174/// #175/// #[derive(SystemParam)]176/// #[system_param(builder)]177/// pub struct CustomParam<'w, 's> {178/// query: Query<'w, 's, ()>,179/// local: Local<'s, usize>,180/// }181///182/// impl<'w, 's> CustomParam<'w, 's> {183/// pub fn builder(184/// local: usize,185/// query: impl FnOnce(&mut QueryBuilder<()>),186/// ) -> impl SystemParamBuilder<Self> {187/// CustomParamBuilder {188/// local: LocalBuilder(local),189/// query: QueryParamBuilder::new(query),190/// }191/// }192/// }193/// }194///195/// use custom_param::CustomParam;196///197/// # use bevy_ecs::prelude::*;198/// # #[derive(Component)]199/// # struct A;200/// #201/// # let mut world = World::new();202/// #203/// let system = (CustomParam::builder(100, |builder| {204/// builder.with::<A>();205/// }),)206/// .build_state(&mut world)207/// .build_system(|param: CustomParam| {});208/// ```209///210/// # Safety211///212/// The implementor must ensure the following is true.213/// - [`SystemParam::init_access`] correctly registers all [`World`] accesses used214/// by [`SystemParam::get_param`] with the provided [`system_meta`](SystemMeta).215/// - None of the world accesses may conflict with any prior accesses registered216/// on `system_meta`.217pub unsafe trait SystemParam: Sized {218/// Used to store data which persists across invocations of a system.219type State: Send + Sync + 'static;220221/// The item type returned when constructing this system param.222/// The value of this associated type should be `Self`, instantiated with new lifetimes.223///224/// You could think of [`SystemParam::Item<'w, 's>`] as being an *operation* that changes the lifetimes bound to `Self`.225type Item<'world, 'state>: SystemParam<State = Self::State>;226227/// Creates a new instance of this param's [`State`](SystemParam::State).228fn init_state(world: &mut World) -> Self::State;229230/// Registers any [`World`] access used by this [`SystemParam`]231fn init_access(232state: &Self::State,233system_meta: &mut SystemMeta,234component_access_set: &mut FilteredAccessSet,235world: &mut World,236);237238/// Applies any deferred mutations stored in this [`SystemParam`]'s state.239/// This is used to apply [`Commands`] during [`ApplyDeferred`](crate::prelude::ApplyDeferred).240///241/// [`Commands`]: crate::prelude::Commands242#[inline]243#[expect(244unused_variables,245reason = "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."246)]247fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {}248249/// Queues any deferred mutations to be applied at the next [`ApplyDeferred`](crate::prelude::ApplyDeferred).250#[inline]251#[expect(252unused_variables,253reason = "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."254)]255fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {}256257/// Validates that the param can be acquired by the [`get_param`](SystemParam::get_param).258///259/// Built-in executors use this to prevent systems with invalid params from running,260/// and any failures here will be bubbled up to the default error handler defined in [`bevy_ecs::error`],261/// with a value of type [`SystemParamValidationError`].262///263/// For nested [`SystemParam`]s validation will fail if any264/// delegated validation fails.265///266/// However calling and respecting [`SystemParam::validate_param`]267/// is not a strict requirement, [`SystemParam::get_param`] should268/// provide it's own safety mechanism to prevent undefined behavior.269///270/// The [`world`](UnsafeWorldCell) can only be used to read param's data271/// and world metadata. No data can be written.272///273/// When using system parameters that require `change_tick` you can use274/// [`UnsafeWorldCell::change_tick()`]. Even if this isn't the exact275/// same tick used for [`SystemParam::get_param`], the world access276/// ensures that the queried data will be the same in both calls.277///278/// This method has to be called directly before [`SystemParam::get_param`] with no other (relevant)279/// world mutations inbetween. Otherwise, while it won't lead to any undefined behavior,280/// the validity of the param may change.281///282/// [`System::validate_param`](super::system::System::validate_param),283/// calls this method for each supplied system param.284///285/// # Safety286///287/// - The passed [`UnsafeWorldCell`] must have read-only access to world data288/// registered in [`init_access`](SystemParam::init_access).289/// - `world` must be the same [`World`] that was used to initialize [`state`](SystemParam::init_state).290#[expect(291unused_variables,292reason = "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."293)]294unsafe fn validate_param(295state: &mut Self::State,296system_meta: &SystemMeta,297world: UnsafeWorldCell,298) -> Result<(), SystemParamValidationError> {299Ok(())300}301302/// Creates a parameter to be passed into a [`SystemParamFunction`](super::SystemParamFunction).303///304/// # Safety305///306/// - The passed [`UnsafeWorldCell`] must have access to any world data registered307/// in [`init_access`](SystemParam::init_access).308/// - `world` must be the same [`World`] that was used to initialize [`state`](SystemParam::init_state).309unsafe fn get_param<'world, 'state>(310state: &'state mut Self::State,311system_meta: &SystemMeta,312world: UnsafeWorldCell<'world>,313change_tick: Tick,314) -> Self::Item<'world, 'state>;315}316317/// A [`SystemParam`] that only reads a given [`World`].318///319/// # Safety320/// This must only be implemented for [`SystemParam`] impls that exclusively read the World passed in to [`SystemParam::get_param`]321pub unsafe trait ReadOnlySystemParam: SystemParam {}322323/// Shorthand way of accessing the associated type [`SystemParam::Item`] for a given [`SystemParam`].324pub type SystemParamItem<'w, 's, P> = <P as SystemParam>::Item<'w, 's>;325326// SAFETY: QueryState is constrained to read-only fetches, so it only reads World.327unsafe impl<'w, 's, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam328for Query<'w, 's, D, F>329{330}331332// SAFETY: Relevant query ComponentId access is applied to SystemMeta. If333// this Query conflicts with any prior access, a panic will occur.334unsafe impl<D: QueryData + 'static, F: QueryFilter + 'static> SystemParam for Query<'_, '_, D, F> {335type State = QueryState<D, F>;336type Item<'w, 's> = Query<'w, 's, D, F>;337338fn init_state(world: &mut World) -> Self::State {339QueryState::new(world)340}341342fn init_access(343state: &Self::State,344system_meta: &mut SystemMeta,345component_access_set: &mut FilteredAccessSet,346world: &mut World,347) {348assert_component_access_compatibility(349&system_meta.name,350DebugName::type_name::<D>(),351DebugName::type_name::<F>(),352component_access_set,353&state.component_access,354world,355);356component_access_set.add(state.component_access.clone());357}358359#[inline]360unsafe fn get_param<'w, 's>(361state: &'s mut Self::State,362system_meta: &SystemMeta,363world: UnsafeWorldCell<'w>,364change_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 any368// world data that the query needs.369// The caller ensures the world matches the one used in init_state.370unsafe { state.query_unchecked_with_ticks(world, system_meta.last_run, change_tick) }371}372}373374fn assert_component_access_compatibility(375system_name: &DebugName,376query_type: DebugName,377filter_type: DebugName,378system_access: &FilteredAccessSet,379current: &FilteredAccess,380world: &World,381) {382let conflicts = system_access.get_conflicts_single(current);383if conflicts.is_empty() {384return;385}386let mut accesses = conflicts.format_conflict_list(world);387// Access list may be empty (if access to all components requested)388if !accesses.is_empty() {389accesses.push(' ');390}391panic!("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://bevy.org/learn/errors/b0001", query_type.shortname(), filter_type.shortname());392}393394// SAFETY: Relevant query ComponentId access is applied to SystemMeta. If395// this Query conflicts with any prior access, a panic will occur.396unsafe impl<'a, 'b, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam397for Single<'a, 'b, D, F>398{399type State = QueryState<D, F>;400type Item<'w, 's> = Single<'w, 's, D, F>;401402fn init_state(world: &mut World) -> Self::State {403Query::init_state(world)404}405406fn init_access(407state: &Self::State,408system_meta: &mut SystemMeta,409component_access_set: &mut FilteredAccessSet,410world: &mut World,411) {412Query::init_access(state, system_meta, component_access_set, world);413}414415#[inline]416unsafe fn get_param<'w, 's>(417state: &'s mut Self::State,418system_meta: &SystemMeta,419world: UnsafeWorldCell<'w>,420change_tick: Tick,421) -> Self::Item<'w, 's> {422// SAFETY: State ensures that the components it accesses are not accessible somewhere elsewhere.423// The caller ensures the world matches the one used in init_state.424let query =425unsafe { state.query_unchecked_with_ticks(world, system_meta.last_run, change_tick) };426let single = query427.single_inner()428.expect("The query was expected to contain exactly one matching entity.");429Single {430item: single,431_filter: PhantomData,432}433}434435#[inline]436unsafe fn validate_param(437state: &mut Self::State,438system_meta: &SystemMeta,439world: UnsafeWorldCell,440) -> Result<(), SystemParamValidationError> {441// SAFETY: State ensures that the components it accesses are not mutably accessible elsewhere442// and the query is read only.443// The caller ensures the world matches the one used in init_state.444let query = unsafe {445state.query_unchecked_with_ticks(world, system_meta.last_run, world.change_tick())446};447match query.single_inner() {448Ok(_) => Ok(()),449Err(QuerySingleError::NoEntities(_)) => Err(450SystemParamValidationError::skipped::<Self>("No matching entities"),451),452Err(QuerySingleError::MultipleEntities(_)) => Err(453SystemParamValidationError::skipped::<Self>("Multiple matching entities"),454),455}456}457}458459// SAFETY: QueryState is constrained to read-only fetches, so it only reads World.460unsafe impl<'a, 'b, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam461for Single<'a, 'b, D, F>462{463}464465// SAFETY: Relevant query ComponentId access is applied to SystemMeta. If466// this Query conflicts with any prior access, a panic will occur.467unsafe impl<D: QueryData + 'static, F: QueryFilter + 'static> SystemParam468for Populated<'_, '_, D, F>469{470type State = QueryState<D, F>;471type Item<'w, 's> = Populated<'w, 's, D, F>;472473fn init_state(world: &mut World) -> Self::State {474Query::init_state(world)475}476477fn init_access(478state: &Self::State,479system_meta: &mut SystemMeta,480component_access_set: &mut FilteredAccessSet,481world: &mut World,482) {483Query::init_access(state, system_meta, component_access_set, world);484}485486#[inline]487unsafe fn get_param<'w, 's>(488state: &'s mut Self::State,489system_meta: &SystemMeta,490world: UnsafeWorldCell<'w>,491change_tick: Tick,492) -> Self::Item<'w, 's> {493// SAFETY: Delegate to existing `SystemParam` implementations.494let query = unsafe { Query::get_param(state, system_meta, world, change_tick) };495Populated(query)496}497498#[inline]499unsafe fn validate_param(500state: &mut Self::State,501system_meta: &SystemMeta,502world: UnsafeWorldCell,503) -> Result<(), SystemParamValidationError> {504// SAFETY:505// - We have read-only access to the components accessed by query.506// - The caller ensures the world matches the one used in init_state.507let query = unsafe {508state.query_unchecked_with_ticks(world, system_meta.last_run, world.change_tick())509};510if query.is_empty() {511Err(SystemParamValidationError::skipped::<Self>(512"No matching entities",513))514} else {515Ok(())516}517}518}519520// SAFETY: QueryState is constrained to read-only fetches, so it only reads World.521unsafe impl<'w, 's, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam522for Populated<'w, 's, D, F>523{524}525526/// A collection of potentially conflicting [`SystemParam`]s allowed by disjoint access.527///528/// Allows systems to safely access and interact with up to 8 mutually exclusive [`SystemParam`]s, such as529/// two queries that reference the same mutable data or an event reader and writer of the same type.530///531/// Each individual [`SystemParam`] can be accessed by using the functions `p0()`, `p1()`, ..., `p7()`,532/// according to the order they are defined in the `ParamSet`. This ensures that there's either533/// only one mutable reference to a parameter at a time or any number of immutable references.534///535/// # Examples536///537/// The following system mutably accesses the same component two times,538/// which is not allowed due to rust's mutability rules.539///540/// ```should_panic541/// # use bevy_ecs::prelude::*;542/// #543/// # #[derive(Component)]544/// # struct Health;545/// #546/// # #[derive(Component)]547/// # struct Enemy;548/// #549/// # #[derive(Component)]550/// # struct Ally;551/// #552/// // This will panic at runtime when the system gets initialized.553/// fn bad_system(554/// mut enemies: Query<&mut Health, With<Enemy>>,555/// mut allies: Query<&mut Health, With<Ally>>,556/// ) {557/// // ...558/// }559/// #560/// # let mut bad_system_system = IntoSystem::into_system(bad_system);561/// # let mut world = World::new();562/// # bad_system_system.initialize(&mut world);563/// # bad_system_system.run((), &mut world);564/// ```565///566/// Conflicting `SystemParam`s like these can be placed in a `ParamSet`,567/// which leverages the borrow checker to ensure that only one of the contained parameters are accessed at a given time.568///569/// ```570/// # use bevy_ecs::prelude::*;571/// #572/// # #[derive(Component)]573/// # struct Health;574/// #575/// # #[derive(Component)]576/// # struct Enemy;577/// #578/// # #[derive(Component)]579/// # struct Ally;580/// #581/// // Given the following system582/// fn fancy_system(583/// mut set: ParamSet<(584/// Query<&mut Health, With<Enemy>>,585/// Query<&mut Health, With<Ally>>,586/// )>587/// ) {588/// // This will access the first `SystemParam`.589/// for mut health in set.p0().iter_mut() {590/// // Do your fancy stuff here...591/// }592///593/// // The second `SystemParam`.594/// // This would fail to compile if the previous parameter was still borrowed.595/// for mut health in set.p1().iter_mut() {596/// // Do even fancier stuff here...597/// }598/// }599/// # bevy_ecs::system::assert_is_system(fancy_system);600/// ```601///602/// Of course, `ParamSet`s can be used with any kind of `SystemParam`, not just [queries](Query).603///604/// ```605/// # use bevy_ecs::prelude::*;606/// #607/// # #[derive(Message)]608/// # struct MyMessage;609/// # impl MyMessage {610/// # pub fn new() -> Self { Self }611/// # }612/// fn message_system(613/// mut set: ParamSet<(614/// // PROBLEM: `MessageReader` and `MessageWriter` cannot be used together normally,615/// // because they both need access to the same message queue.616/// // SOLUTION: `ParamSet` allows these conflicting parameters to be used safely617/// // by ensuring only one is accessed at a time.618/// MessageReader<MyMessage>,619/// MessageWriter<MyMessage>,620/// // PROBLEM: `&World` needs read access to everything, which conflicts with621/// // any mutable access in the same system.622/// // SOLUTION: `ParamSet` ensures `&World` is only accessed when we're not623/// // using the other mutable parameters.624/// &World,625/// )>,626/// ) {627/// for message in set.p0().read() {628/// // ...629/// # let _message = message;630/// }631/// set.p1().write(MyMessage::new());632///633/// let entities = set.p2().entities();634/// // ...635/// # let _entities = entities;636/// }637/// # bevy_ecs::system::assert_is_system(message_system);638/// ```639pub struct ParamSet<'w, 's, T: SystemParam> {640param_states: &'s mut T::State,641world: UnsafeWorldCell<'w>,642system_meta: SystemMeta,643change_tick: Tick,644}645646macro_rules! impl_param_set {647($(($index: tt, $param: ident, $fn_name: ident)),*) => {648// SAFETY: All parameters are constrained to ReadOnlySystemParam, so World is only read649unsafe impl<'w, 's, $($param,)*> ReadOnlySystemParam for ParamSet<'w, 's, ($($param,)*)>650where $($param: ReadOnlySystemParam,)*651{ }652653// SAFETY: Relevant parameter ComponentId access is applied to SystemMeta. If any ParamState conflicts654// with any prior access, a panic will occur.655unsafe impl<'_w, '_s, $($param: SystemParam,)*> SystemParam for ParamSet<'_w, '_s, ($($param,)*)>656{657type State = ($($param::State,)*);658type Item<'w, 's> = ParamSet<'w, 's, ($($param,)*)>;659660#[expect(661clippy::allow_attributes,662reason = "This is inside a macro meant for tuples; as such, `non_snake_case` won't always lint."663)]664#[allow(665non_snake_case,666reason = "Certain variable names are provided by the caller, not by us."667)]668fn init_state(world: &mut World) -> Self::State {669($($param::init_state(world),)*)670}671672#[expect(673clippy::allow_attributes,674reason = "This is inside a macro meant for tuples; as such, `non_snake_case` won't always lint."675)]676#[allow(677non_snake_case,678reason = "Certain variable names are provided by the caller, not by us."679)]680fn init_access(state: &Self::State, system_meta: &mut SystemMeta, component_access_set: &mut FilteredAccessSet, world: &mut World) {681let ($($param,)*) = state;682$(683// Call `init_access` on a clone of the original access set to check for conflicts684let component_access_set_clone = &mut component_access_set.clone();685$param::init_access($param, system_meta, component_access_set_clone, world);686)*687$(688// Pretend to add the param to the system alone to gather the new access,689// then merge its access into the system.690let mut access_set = FilteredAccessSet::new();691$param::init_access($param, system_meta, &mut access_set, world);692component_access_set.extend(access_set);693)*694}695696fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {697<($($param,)*) as SystemParam>::apply(state, system_meta, world);698}699700fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {701<($($param,)*) as SystemParam>::queue(state, system_meta, world.reborrow());702}703704#[inline]705unsafe fn validate_param<'w, 's>(706state: &'s mut Self::State,707system_meta: &SystemMeta,708world: UnsafeWorldCell<'w>,709) -> Result<(), SystemParamValidationError> {710// SAFETY: Upheld by caller711unsafe {712<($($param,)*) as SystemParam>::validate_param(state, system_meta, world)713}714}715716#[inline]717unsafe fn get_param<'w, 's>(718state: &'s mut Self::State,719system_meta: &SystemMeta,720world: UnsafeWorldCell<'w>,721change_tick: Tick,722) -> Self::Item<'w, 's> {723ParamSet {724param_states: state,725system_meta: system_meta.clone(),726world,727change_tick,728}729}730}731732impl<'w, 's, $($param: SystemParam,)*> ParamSet<'w, 's, ($($param,)*)>733{734$(735/// Gets exclusive access to the parameter at index736#[doc = stringify!($index)]737/// in this [`ParamSet`].738/// No other parameters may be accessed while this one is active.739pub fn $fn_name<'a>(&'a mut self) -> SystemParamItem<'a, 'a, $param> {740// SAFETY: systems run without conflicts with other systems.741// Conflicting params in ParamSet are not accessible at the same time742// ParamSets are guaranteed to not conflict with other SystemParams743unsafe {744$param::get_param(&mut self.param_states.$index, &self.system_meta, self.world, self.change_tick)745}746}747)*748}749}750}751752all_tuples_enumerated!(impl_param_set, 1, 8, P, p);753754// SAFETY: Res only reads a single World resource755unsafe impl<'a, T: Resource> ReadOnlySystemParam for Res<'a, T> {}756757// SAFETY: Res ComponentId access is applied to SystemMeta. If this Res758// conflicts with any prior access, a panic will occur.759unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> {760type State = ComponentId;761type Item<'w, 's> = Res<'w, T>;762763fn init_state(world: &mut World) -> Self::State {764world.components_registrator().register_component::<T>()765}766767fn init_access(768&component_id: &Self::State,769system_meta: &mut SystemMeta,770component_access_set: &mut FilteredAccessSet,771_world: &mut World,772) {773let combined_access = component_access_set.combined_access();774assert!(775!combined_access.has_resource_write(component_id),776"error[B0002]: Res<{}> in system {} conflicts with a previous ResMut<{0}> access. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",777DebugName::type_name::<T>(),778system_meta.name,779);780781let mut filter = FilteredAccess::default();782filter.add_component_read(component_id);783filter.add_resource_read(component_id);784filter.and_with(IS_RESOURCE);785786assert!(component_access_set787.get_conflicts_single(&filter)788.is_empty(),789"error[B0002]: Res<{}> in system {} conflicts with a previous query. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",790DebugName::type_name::<T>(),791system_meta.name792);793794component_access_set.add(filter);795}796797#[inline]798unsafe fn validate_param(799&mut component_id: &mut Self::State,800_system_meta: &SystemMeta,801world: UnsafeWorldCell,802) -> Result<(), SystemParamValidationError> {803// SAFETY: Read-only access to the resource804if let Some(entity) = unsafe { world.resource_entities() }.get(component_id)805&& let Ok(entity_ref) = world.get_entity(*entity)806&& entity_ref.contains_id(component_id)807{808Ok(())809} else {810Err(SystemParamValidationError::invalid::<Self>(811"Resource does not exist",812))813}814}815816#[inline]817unsafe fn get_param<'w, 's>(818&mut component_id: &'s mut Self::State,819system_meta: &SystemMeta,820world: UnsafeWorldCell<'w>,821change_tick: Tick,822) -> Self::Item<'w, 's> {823let (ptr, ticks) = world824.get_resource_with_ticks(component_id)825.unwrap_or_else(|| {826panic!(827"Resource requested by {} does not exist: {}",828system_meta.name,829DebugName::type_name::<T>()830);831});832Res {833value: ptr.deref(),834ticks: ComponentTicksRef {835added: ticks.added.deref(),836changed: ticks.changed.deref(),837changed_by: ticks.changed_by.map(|changed_by| changed_by.deref()),838last_run: system_meta.last_run,839this_run: change_tick,840},841}842}843}844845// SAFETY: Res ComponentId access is applied to SystemMeta. If this Res846// conflicts with any prior access, a panic will occur.847unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> {848type State = ComponentId;849type Item<'w, 's> = ResMut<'w, T>;850851fn init_state(world: &mut World) -> Self::State {852world.components_registrator().register_component::<T>()853}854855fn init_access(856&component_id: &Self::State,857system_meta: &mut SystemMeta,858component_access_set: &mut FilteredAccessSet,859_world: &mut World,860) {861let combined_access = component_access_set.combined_access();862if combined_access.has_resource_write(component_id) {863panic!(864"error[B0002]: ResMut<{}> in system {} conflicts with a previous ResMut<{0}> access. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",865DebugName::type_name::<T>(), system_meta.name);866} else if combined_access.has_resource_read(component_id) {867panic!(868"error[B0002]: ResMut<{}> in system {} conflicts with a previous Res<{0}> access. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",869DebugName::type_name::<T>(), system_meta.name);870}871872let mut filter = FilteredAccess::default();873filter.add_component_write(component_id);874filter.add_resource_write(component_id);875filter.and_with(IS_RESOURCE);876877assert!(component_access_set878.get_conflicts_single(&filter)879.is_empty(),880"error[B0002]: ResMut<{}> in system {} conflicts with a previous query. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",881DebugName::type_name::<T>(),882system_meta.name883);884885component_access_set.add(filter);886}887888#[inline]889unsafe fn validate_param(890&mut component_id: &mut Self::State,891_system_meta: &SystemMeta,892world: UnsafeWorldCell,893) -> Result<(), SystemParamValidationError> {894// SAFETY: Read-only access to the resource.895if let Some(entity) = unsafe { world.resource_entities() }.get(component_id)896&& let Ok(entity_ref) = world.get_entity(*entity)897&& entity_ref.contains_id(component_id)898{899Ok(())900} else {901Err(SystemParamValidationError::invalid::<Self>(902"Resource does not exist",903))904}905}906907#[inline]908unsafe fn get_param<'w, 's>(909&mut component_id: &'s mut Self::State,910system_meta: &SystemMeta,911world: UnsafeWorldCell<'w>,912change_tick: Tick,913) -> Self::Item<'w, 's> {914let value = world915.get_resource_mut_by_id(component_id)916.unwrap_or_else(|| {917panic!(918"Resource requested by {} does not exist: {}",919system_meta.name,920DebugName::type_name::<T>()921);922});923ResMut {924value: value.value.deref_mut::<T>(),925ticks: ComponentTicksMut {926added: value.ticks.added,927changed: value.ticks.changed,928changed_by: value.ticks.changed_by,929last_run: system_meta.last_run,930this_run: change_tick,931},932}933}934}935936// SAFETY: only reads world937unsafe impl<'w> ReadOnlySystemParam for &'w World {}938939// SAFETY: `read_all` access is set and conflicts result in a panic940unsafe impl SystemParam for &'_ World {941type State = ();942type Item<'w, 's> = &'w World;943944fn init_state(_world: &mut World) -> Self::State {}945946fn init_access(947_state: &Self::State,948_system_meta: &mut SystemMeta,949component_access_set: &mut FilteredAccessSet,950_world: &mut World,951) {952let mut filtered_access = FilteredAccess::default();953954filtered_access.read_all();955if !component_access_set956.get_conflicts_single(&filtered_access)957.is_empty()958{959panic!("&World conflicts with a previous mutable system parameter. Allowing this would break Rust's mutability rules");960}961component_access_set.add(filtered_access);962}963964#[inline]965unsafe fn get_param<'w, 's>(966_state: &'s mut Self::State,967_system_meta: &SystemMeta,968world: UnsafeWorldCell<'w>,969_change_tick: Tick,970) -> Self::Item<'w, 's> {971// SAFETY: Read-only access to the entire world was registered in `init_state`.972unsafe { world.world() }973}974}975976// SAFETY: `DeferredWorld` can read all components and resources but cannot be used to gain any other mutable references.977unsafe impl<'w> SystemParam for DeferredWorld<'w> {978type State = ();979type Item<'world, 'state> = DeferredWorld<'world>;980981fn init_state(_world: &mut World) -> Self::State {}982983fn init_access(984_state: &Self::State,985system_meta: &mut SystemMeta,986component_access_set: &mut FilteredAccessSet,987_world: &mut World,988) {989assert!(990!component_access_set.combined_access().has_any_read(),991"DeferredWorld in system {} conflicts with a previous access.",992system_meta.name,993);994component_access_set.write_all();995}996997unsafe fn get_param<'world, 'state>(998_state: &'state mut Self::State,999_system_meta: &SystemMeta,1000world: UnsafeWorldCell<'world>,1001_change_tick: Tick,1002) -> Self::Item<'world, 'state> {1003// SAFETY: Upheld by caller1004unsafe { world.into_deferred() }1005}1006}10071008/// A [`SystemParam`] that provides a system-private value of `T` that persists across system calls.1009///1010/// The initial value is created by calling `T`'s [`FromWorld::from_world`] (or [`Default::default`] if `T: Default`).1011///1012/// A local may only be accessed by the system itself and is therefore not visible to other systems.1013/// If two or more systems specify the same local type each will have their own unique local.1014/// If multiple [`SystemParam`]s within the same system each specify the same local type1015/// each will get their own distinct data storage.1016///1017/// The supplied lifetime parameter is the [`SystemParam`]s `'s` lifetime.1018///1019/// # Examples1020///1021/// ```1022/// # use bevy_ecs::prelude::*;1023/// # let world = &mut World::default();1024/// fn counter(mut count: Local<u32>) -> u32 {1025/// *count += 1;1026/// *count1027/// }1028/// let mut counter_system = IntoSystem::into_system(counter);1029/// counter_system.initialize(world);1030///1031/// // Counter is initialized to u32's default value of 0, and increases to 1 on first run.1032/// assert_eq!(counter_system.run((), world).unwrap(), 1);1033/// // Counter gets the same value and increases to 2 on its second call.1034/// assert_eq!(counter_system.run((), world).unwrap(), 2);1035/// ```1036///1037/// A simple way to set a different default value for a local is by wrapping the value with an Option.1038///1039/// ```1040/// # use bevy_ecs::prelude::*;1041/// # let world = &mut World::default();1042/// fn counter_from_10(mut count: Local<Option<u32>>) -> u32 {1043/// let count = count.get_or_insert(10);1044/// *count += 1;1045/// *count1046/// }1047/// let mut counter_system = IntoSystem::into_system(counter_from_10);1048/// counter_system.initialize(world);1049///1050/// // Counter is initialized at 10, and increases to 11 on first run.1051/// assert_eq!(counter_system.run((), world).unwrap(), 11);1052/// // Counter is only increased by 1 on subsequent runs.1053/// assert_eq!(counter_system.run((), world).unwrap(), 12);1054/// ```1055///1056/// A system can have multiple `Local` values with the same type, each with distinct values.1057///1058/// ```1059/// # use bevy_ecs::prelude::*;1060/// # let world = &mut World::default();1061/// fn double_counter(mut count: Local<u32>, mut double_count: Local<u32>) -> (u32, u32) {1062/// *count += 1;1063/// *double_count += 2;1064/// (*count, *double_count)1065/// }1066/// let mut counter_system = IntoSystem::into_system(double_counter);1067/// counter_system.initialize(world);1068///1069/// assert_eq!(counter_system.run((), world).unwrap(), (1, 2));1070/// assert_eq!(counter_system.run((), world).unwrap(), (2, 4));1071/// ```1072///1073/// This example shows that two systems using the same type for their own `Local` get distinct locals.1074///1075/// ```1076/// # use bevy_ecs::prelude::*;1077/// # let world = &mut World::default();1078/// fn write_to_local(mut local: Local<usize>) {1079/// *local = 42;1080/// }1081/// fn read_from_local(local: Local<usize>) -> usize {1082/// *local1083/// }1084/// let mut write_system = IntoSystem::into_system(write_to_local);1085/// let mut read_system = IntoSystem::into_system(read_from_local);1086/// write_system.initialize(world);1087/// read_system.initialize(world);1088///1089/// assert_eq!(read_system.run((), world).unwrap(), 0);1090/// write_system.run((), world);1091/// // The read local is still 0 due to the locals not being shared.1092/// assert_eq!(read_system.run((), world).unwrap(), 0);1093/// ```1094///1095/// You can use a `Local` to avoid reallocating memory every system call.1096///1097/// ```1098/// # use bevy_ecs::prelude::*;1099/// fn some_system(mut vec: Local<Vec<u32>>) {1100/// // Do your regular system logic, using the vec, as normal.1101///1102/// // At end of function, clear the vec's contents so its empty for next system call.1103/// // If it's possible the capacity could get too large, you may want to check and resize that as well.1104/// vec.clear();1105/// }1106/// ```1107///1108/// N.B. A [`Local`]s value cannot be read or written to outside of the containing system.1109/// To add configuration to a system, convert a capturing closure into the system instead:1110///1111/// ```1112/// # use bevy_ecs::prelude::*;1113/// # use bevy_ecs::system::assert_is_system;1114/// struct Config(u32);1115/// #[derive(Resource)]1116/// struct MyU32Wrapper(u32);1117/// fn reset_to_system(value: Config) -> impl FnMut(ResMut<MyU32Wrapper>) {1118/// move |mut val| val.0 = value.01119/// }1120///1121/// // .add_systems(reset_to_system(my_config))1122/// # assert_is_system(reset_to_system(Config(10)));1123/// ```1124#[derive(Debug)]1125pub struct Local<'s, T: FromWorld + Send + 'static>(pub(crate) &'s mut T);11261127// SAFETY: Local only accesses internal state1128unsafe impl<'s, T: FromWorld + Send + 'static> ReadOnlySystemParam for Local<'s, T> {}11291130impl<'s, T: FromWorld + Send + 'static> Deref for Local<'s, T> {1131type Target = T;11321133#[inline]1134fn deref(&self) -> &Self::Target {1135self.01136}1137}11381139impl<'s, T: FromWorld + Send + 'static> DerefMut for Local<'s, T> {1140#[inline]1141fn deref_mut(&mut self) -> &mut Self::Target {1142self.01143}1144}11451146impl<'s, 'a, T: FromWorld + Send + 'static> IntoIterator for &'a Local<'s, T>1147where1148&'a T: IntoIterator,1149{1150type Item = <&'a T as IntoIterator>::Item;1151type IntoIter = <&'a T as IntoIterator>::IntoIter;11521153fn into_iter(self) -> Self::IntoIter {1154self.0.into_iter()1155}1156}11571158impl<'s, 'a, T: FromWorld + Send + 'static> IntoIterator for &'a mut Local<'s, T>1159where1160&'a mut T: IntoIterator,1161{1162type Item = <&'a mut T as IntoIterator>::Item;1163type IntoIter = <&'a mut T as IntoIterator>::IntoIter;11641165fn into_iter(self) -> Self::IntoIter {1166self.0.into_iter()1167}1168}11691170// SAFETY: only local state is accessed1171unsafe impl<'a, T: FromWorld + Send + 'static> SystemParam for Local<'a, T> {1172type State = SyncCell<T>;1173type Item<'w, 's> = Local<'s, T>;11741175fn init_state(world: &mut World) -> Self::State {1176SyncCell::new(T::from_world(world))1177}11781179fn init_access(1180_state: &Self::State,1181_system_meta: &mut SystemMeta,1182_component_access_set: &mut FilteredAccessSet,1183_world: &mut World,1184) {1185}11861187#[inline]1188unsafe fn get_param<'w, 's>(1189state: &'s mut Self::State,1190_system_meta: &SystemMeta,1191_world: UnsafeWorldCell<'w>,1192_change_tick: Tick,1193) -> Self::Item<'w, 's> {1194Local(state.get())1195}1196}11971198/// Types that can be used with [`Deferred<T>`] in systems.1199/// This allows storing system-local data which is used to defer [`World`] mutations.1200///1201/// Types that implement `SystemBuffer` should take care to perform as many1202/// computations up-front as possible. Buffers cannot be applied in parallel,1203/// so you should try to minimize the time spent in [`SystemBuffer::apply`].1204pub trait SystemBuffer: FromWorld + Send + 'static {1205/// Applies any deferred mutations to the [`World`].1206fn apply(&mut self, system_meta: &SystemMeta, world: &mut World) {1207self.queue(system_meta, world.into());1208}1209/// Queues any deferred mutations to be applied at the next [`ApplyDeferred`](crate::prelude::ApplyDeferred).1210///1211/// To queue structural changes to [`DeferredWorld`], a command queue of the [`DeferredWorld`]1212/// should be used via [`commands`](crate::world::DeferredWorld::commands).1213fn queue(&mut self, _system_meta: &SystemMeta, _world: DeferredWorld);1214}12151216/// A [`SystemParam`] that stores a buffer which gets applied to the [`World`] during1217/// [`ApplyDeferred`](crate::schedule::ApplyDeferred).1218/// This is used internally by [`Commands`] to defer `World` mutations.1219///1220/// [`Commands`]: crate::system::Commands1221///1222/// # Examples1223///1224/// By using this type to defer mutations, you can avoid mutable `World` access within1225/// a system, which allows it to run in parallel with more systems.1226///1227/// Note that deferring mutations is *not* free, and should only be used if1228/// the gains in parallelization outweigh the time it takes to apply deferred mutations.1229/// In general, [`Deferred`] should only be used for mutations that are infrequent,1230/// or which otherwise take up a small portion of a system's run-time.1231///1232/// ```1233/// # use bevy_ecs::prelude::*;1234/// # use bevy_ecs::world::DeferredWorld;1235/// // Tracks whether or not there is a threat the player should be aware of.1236/// #[derive(Resource, Default)]1237/// pub struct Alarm(bool);1238///1239/// #[derive(Component)]1240/// pub struct Settlement {1241/// // ...1242/// }1243///1244/// // A threat from inside the settlement.1245/// #[derive(Component)]1246/// pub struct Criminal;1247///1248/// // A threat from outside the settlement.1249/// #[derive(Component)]1250/// pub struct Monster;1251///1252/// # impl Criminal { pub fn is_threat(&self, _: &Settlement) -> bool { true } }1253///1254/// use bevy_ecs::system::{Deferred, SystemBuffer, SystemMeta};1255///1256/// // Uses deferred mutations to allow signaling the alarm from multiple systems in parallel.1257/// #[derive(Resource, Default)]1258/// struct AlarmFlag(bool);1259///1260/// impl AlarmFlag {1261/// /// Sounds the alarm the next time buffers are applied via ApplyDeferred.1262/// pub fn flag(&mut self) {1263/// self.0 = true;1264/// }1265/// }1266///1267/// impl SystemBuffer for AlarmFlag {1268/// // When `AlarmFlag` is used in a system, this function will get1269/// // called the next time buffers are applied via ApplyDeferred.1270/// fn queue(&mut self, system_meta: &SystemMeta, mut world: DeferredWorld) {1271/// if self.0 {1272/// world.resource_mut::<Alarm>().0 = true;1273/// self.0 = false;1274/// }1275/// }1276/// }1277///1278/// // Sound the alarm if there are any criminals who pose a threat.1279/// fn alert_criminal(1280/// settlement: Single<&Settlement>,1281/// criminals: Query<&Criminal>,1282/// mut alarm: Deferred<AlarmFlag>1283/// ) {1284/// for criminal in &criminals {1285/// // Only sound the alarm if the criminal is a threat.1286/// // For this example, assume that this check is expensive to run.1287/// // Since the majority of this system's run-time is dominated1288/// // by calling `is_threat()`, we defer sounding the alarm to1289/// // allow this system to run in parallel with other alarm systems.1290/// if criminal.is_threat(*settlement) {1291/// alarm.flag();1292/// }1293/// }1294/// }1295///1296/// // Sound the alarm if there is a monster.1297/// fn alert_monster(1298/// monsters: Query<&Monster>,1299/// mut alarm: ResMut<Alarm>1300/// ) {1301/// if monsters.iter().next().is_some() {1302/// // Since this system does nothing except for sounding the alarm,1303/// // it would be pointless to defer it, so we sound the alarm directly.1304/// alarm.0 = true;1305/// }1306/// }1307///1308/// let mut world = World::new();1309/// world.init_resource::<Alarm>();1310/// world.spawn(Settlement {1311/// // ...1312/// });1313///1314/// let mut schedule = Schedule::default();1315/// // These two systems have no conflicts and will run in parallel.1316/// schedule.add_systems((alert_criminal, alert_monster));1317///1318/// // There are no criminals or monsters, so the alarm is not sounded.1319/// schedule.run(&mut world);1320/// assert_eq!(world.resource::<Alarm>().0, false);1321///1322/// // Spawn a monster, which will cause the alarm to be sounded.1323/// let m_id = world.spawn(Monster).id();1324/// schedule.run(&mut world);1325/// assert_eq!(world.resource::<Alarm>().0, true);1326///1327/// // Remove the monster and reset the alarm.1328/// world.entity_mut(m_id).despawn();1329/// world.resource_mut::<Alarm>().0 = false;1330///1331/// // Spawn a criminal, which will cause the alarm to be sounded.1332/// world.spawn(Criminal);1333/// schedule.run(&mut world);1334/// assert_eq!(world.resource::<Alarm>().0, true);1335/// ```1336pub struct Deferred<'a, T: SystemBuffer>(pub(crate) &'a mut T);13371338impl<'a, T: SystemBuffer> Deref for Deferred<'a, T> {1339type Target = T;1340#[inline]1341fn deref(&self) -> &Self::Target {1342self.01343}1344}13451346impl<'a, T: SystemBuffer> DerefMut for Deferred<'a, T> {1347#[inline]1348fn deref_mut(&mut self) -> &mut Self::Target {1349self.01350}1351}13521353impl<T: SystemBuffer> Deferred<'_, T> {1354/// Returns a [`Deferred<T>`] with a smaller lifetime.1355/// This is useful if you have `&mut Deferred<T>` but need `Deferred<T>`.1356pub fn reborrow(&mut self) -> Deferred<'_, T> {1357Deferred(self.0)1358}1359}13601361// SAFETY: Only local state is accessed.1362unsafe impl<T: SystemBuffer> ReadOnlySystemParam for Deferred<'_, T> {}13631364// SAFETY: Only local state is accessed.1365unsafe impl<T: SystemBuffer> SystemParam for Deferred<'_, T> {1366type State = SyncCell<T>;1367type Item<'w, 's> = Deferred<'s, T>;13681369#[track_caller]1370fn init_state(world: &mut World) -> Self::State {1371SyncCell::new(T::from_world(world))1372}13731374fn init_access(1375_state: &Self::State,1376system_meta: &mut SystemMeta,1377_component_access_set: &mut FilteredAccessSet,1378_world: &mut World,1379) {1380system_meta.set_has_deferred();1381}13821383fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {1384state.get().apply(system_meta, world);1385}13861387fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {1388state.get().queue(system_meta, world);1389}13901391#[inline]1392unsafe fn get_param<'w, 's>(1393state: &'s mut Self::State,1394_system_meta: &SystemMeta,1395_world: UnsafeWorldCell<'w>,1396_change_tick: Tick,1397) -> Self::Item<'w, 's> {1398Deferred(state.get())1399}1400}14011402/// A dummy type to tell the executor to run the system exclusively.1403pub struct ExclusiveMarker(PhantomData<()>);14041405// SAFETY: No world access.1406unsafe impl SystemParam for ExclusiveMarker {1407type State = ();1408type Item<'w, 's> = Self;14091410#[inline]1411fn init_state(_world: &mut World) -> Self::State {}14121413fn init_access(1414_state: &Self::State,1415system_meta: &mut SystemMeta,1416_component_access_set: &mut FilteredAccessSet,1417_world: &mut World,1418) {1419system_meta.set_exclusive();1420}14211422#[inline]1423unsafe fn get_param<'world, 'state>(1424_state: &'state mut Self::State,1425_system_meta: &SystemMeta,1426_world: UnsafeWorldCell<'world>,1427_change_tick: Tick,1428) -> Self::Item<'world, 'state> {1429Self(PhantomData)1430}1431}14321433// SAFETY: Does not read any world state1434unsafe impl ReadOnlySystemParam for ExclusiveMarker {}14351436/// A dummy type that is [`!Send`](Send), to force systems to run on the main thread.1437pub struct NonSendMarker(PhantomData<*mut ()>);14381439// SAFETY: No world access.1440unsafe impl SystemParam for NonSendMarker {1441type State = ();1442type Item<'w, 's> = Self;14431444#[inline]1445fn init_state(_world: &mut World) -> Self::State {}14461447fn init_access(1448_state: &Self::State,1449system_meta: &mut SystemMeta,1450_component_access_set: &mut FilteredAccessSet,1451_world: &mut World,1452) {1453system_meta.set_non_send();1454}14551456#[inline]1457unsafe fn get_param<'world, 'state>(1458_state: &'state mut Self::State,1459_system_meta: &SystemMeta,1460_world: UnsafeWorldCell<'world>,1461_change_tick: Tick,1462) -> Self::Item<'world, 'state> {1463Self(PhantomData)1464}1465}14661467// SAFETY: Does not read any world state1468unsafe impl ReadOnlySystemParam for NonSendMarker {}14691470// SAFETY: Only reads a single World non-send resource1471unsafe impl<'w, T> ReadOnlySystemParam for NonSend<'w, T> {}14721473// SAFETY: NonSendComponentId access is applied to SystemMeta. If this1474// NonSend conflicts with any prior access, a panic will occur.1475unsafe impl<'a, T: 'static> SystemParam for NonSend<'a, T> {1476type State = ComponentId;1477type Item<'w, 's> = NonSend<'w, T>;14781479fn init_state(world: &mut World) -> Self::State {1480world.components_registrator().register_non_send::<T>()1481}14821483fn init_access(1484&component_id: &Self::State,1485system_meta: &mut SystemMeta,1486component_access_set: &mut FilteredAccessSet,1487_world: &mut World,1488) {1489system_meta.set_non_send();14901491let combined_access = component_access_set.combined_access();1492assert!(1493!combined_access.has_resource_write(component_id),1494"error[B0002]: NonSend<{}> in system {} conflicts with a previous mutable resource access ({0}). Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",1495DebugName::type_name::<T>(),1496system_meta.name,1497);1498component_access_set.add_unfiltered_resource_read(component_id);1499}15001501#[inline]1502unsafe fn validate_param(1503&mut component_id: &mut Self::State,1504_system_meta: &SystemMeta,1505world: UnsafeWorldCell,1506) -> Result<(), SystemParamValidationError> {1507// SAFETY: Read-only access to non-send metadata.1508if unsafe { world.storages() }1509.non_sends1510.get(component_id)1511.is_some_and(NonSendData::is_present)1512{1513Ok(())1514} else {1515Err(SystemParamValidationError::invalid::<Self>(1516"Non-send resource does not exist",1517))1518}1519}15201521#[inline]1522unsafe fn get_param<'w, 's>(1523&mut component_id: &'s mut Self::State,1524system_meta: &SystemMeta,1525world: UnsafeWorldCell<'w>,1526change_tick: Tick,1527) -> Self::Item<'w, 's> {1528let (ptr, ticks) = world1529.get_non_send_with_ticks(component_id)1530.unwrap_or_else(|| {1531panic!(1532"Non-send resource requested by {} does not exist: {}",1533system_meta.name,1534DebugName::type_name::<T>()1535);1536});1537NonSend {1538value: ptr.deref(),1539ticks: ComponentTicksRef::from_tick_cells(ticks, system_meta.last_run, change_tick),1540}1541}1542}15431544// SAFETY: NonSendMut ComponentId access is applied to SystemMeta. If this1545// NonSendMut conflicts with any prior access, a panic will occur.1546unsafe impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> {1547type State = ComponentId;1548type Item<'w, 's> = NonSendMut<'w, T>;15491550fn init_state(world: &mut World) -> Self::State {1551world.components_registrator().register_non_send::<T>()1552}15531554fn init_access(1555&component_id: &Self::State,1556system_meta: &mut SystemMeta,1557component_access_set: &mut FilteredAccessSet,1558_world: &mut World,1559) {1560system_meta.set_non_send();15611562let combined_access = component_access_set.combined_access();1563if combined_access.has_resource_write(component_id) {1564panic!(1565"error[B0002]: NonSendMut<{}> in system {} conflicts with a previous mutable resource access ({0}). Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",1566DebugName::type_name::<T>(), system_meta.name);1567} else if combined_access.has_resource_read(component_id) {1568panic!(1569"error[B0002]: NonSendMut<{}> in system {} conflicts with a previous immutable resource access ({0}). Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",1570DebugName::type_name::<T>(), system_meta.name);1571}1572component_access_set.add_unfiltered_resource_write(component_id);1573}15741575#[inline]1576unsafe fn validate_param(1577&mut component_id: &mut Self::State,1578_system_meta: &SystemMeta,1579world: UnsafeWorldCell,1580) -> Result<(), SystemParamValidationError> {1581// SAFETY: Read-only access to non-send metadata.1582if unsafe { world.storages() }1583.non_sends1584.get(component_id)1585.is_some_and(NonSendData::is_present)1586{1587Ok(())1588} else {1589Err(SystemParamValidationError::invalid::<Self>(1590"Non-send resource does not exist",1591))1592}1593}15941595#[inline]1596unsafe fn get_param<'w, 's>(1597&mut component_id: &'s mut Self::State,1598system_meta: &SystemMeta,1599world: UnsafeWorldCell<'w>,1600change_tick: Tick,1601) -> Self::Item<'w, 's> {1602let (ptr, ticks) = world1603.get_non_send_with_ticks(component_id)1604.unwrap_or_else(|| {1605panic!(1606"Non-send resource requested by {} does not exist: {}",1607system_meta.name,1608DebugName::type_name::<T>()1609);1610});1611NonSendMut {1612value: ptr.assert_unique().deref_mut(),1613ticks: ComponentTicksMut::from_tick_cells(ticks, system_meta.last_run, change_tick),1614}1615}1616}16171618// SAFETY: Only reads World archetypes1619unsafe impl<'a> ReadOnlySystemParam for &'a Archetypes {}16201621// SAFETY: no component value access1622unsafe impl<'a> SystemParam for &'a Archetypes {1623type State = ();1624type Item<'w, 's> = &'w Archetypes;16251626fn init_state(_world: &mut World) -> Self::State {}16271628fn init_access(1629_state: &Self::State,1630_system_meta: &mut SystemMeta,1631_component_access_set: &mut FilteredAccessSet,1632_world: &mut World,1633) {1634}16351636#[inline]1637unsafe fn get_param<'w, 's>(1638_state: &'s mut Self::State,1639_system_meta: &SystemMeta,1640world: UnsafeWorldCell<'w>,1641_change_tick: Tick,1642) -> Self::Item<'w, 's> {1643world.archetypes()1644}1645}16461647// SAFETY: Only reads World components1648unsafe impl<'a> ReadOnlySystemParam for &'a Components {}16491650// SAFETY: no component value access1651unsafe impl<'a> SystemParam for &'a Components {1652type State = ();1653type Item<'w, 's> = &'w Components;16541655fn init_state(_world: &mut World) -> Self::State {}16561657fn init_access(1658_state: &Self::State,1659_system_meta: &mut SystemMeta,1660_component_access_set: &mut FilteredAccessSet,1661_world: &mut World,1662) {1663}16641665#[inline]1666unsafe fn get_param<'w, 's>(1667_state: &'s mut Self::State,1668_system_meta: &SystemMeta,1669world: UnsafeWorldCell<'w>,1670_change_tick: Tick,1671) -> Self::Item<'w, 's> {1672world.components()1673}1674}16751676// SAFETY: Only reads World entities1677unsafe impl<'a> ReadOnlySystemParam for &'a Entities {}16781679// SAFETY: no component value access1680unsafe impl<'a> SystemParam for &'a Entities {1681type State = ();1682type Item<'w, 's> = &'w Entities;16831684fn init_state(_world: &mut World) -> Self::State {}16851686fn init_access(1687_state: &Self::State,1688_system_meta: &mut SystemMeta,1689_component_access_set: &mut FilteredAccessSet,1690_world: &mut World,1691) {1692}16931694#[inline]1695unsafe fn get_param<'w, 's>(1696_state: &'s mut Self::State,1697_system_meta: &SystemMeta,1698world: UnsafeWorldCell<'w>,1699_change_tick: Tick,1700) -> Self::Item<'w, 's> {1701world.entities()1702}1703}17041705// SAFETY: Only reads World entities1706unsafe impl<'a> ReadOnlySystemParam for &'a EntityAllocator {}17071708// SAFETY: no component value access1709unsafe impl<'a> SystemParam for &'a EntityAllocator {1710type State = ();1711type Item<'w, 's> = &'w EntityAllocator;17121713fn init_state(_world: &mut World) -> Self::State {}17141715fn init_access(1716_state: &Self::State,1717_system_meta: &mut SystemMeta,1718_component_access_set: &mut FilteredAccessSet,1719_world: &mut World,1720) {1721}17221723#[inline]1724unsafe fn get_param<'w, 's>(1725_state: &'s mut Self::State,1726_system_meta: &SystemMeta,1727world: UnsafeWorldCell<'w>,1728_change_tick: Tick,1729) -> Self::Item<'w, 's> {1730world.entity_allocator()1731}1732}17331734// SAFETY: Only reads World bundles1735unsafe impl<'a> ReadOnlySystemParam for &'a Bundles {}17361737// SAFETY: no component value access1738unsafe impl<'a> SystemParam for &'a Bundles {1739type State = ();1740type Item<'w, 's> = &'w Bundles;17411742fn init_state(_world: &mut World) -> Self::State {}17431744fn init_access(1745_state: &Self::State,1746_system_meta: &mut SystemMeta,1747_component_access_set: &mut FilteredAccessSet,1748_world: &mut World,1749) {1750}17511752#[inline]1753unsafe fn get_param<'w, 's>(1754_state: &'s mut Self::State,1755_system_meta: &SystemMeta,1756world: UnsafeWorldCell<'w>,1757_change_tick: Tick,1758) -> Self::Item<'w, 's> {1759world.bundles()1760}1761}17621763/// A [`SystemParam`] that reads the previous and current change ticks of the system.1764///1765/// A system's change ticks are updated each time it runs:1766/// - `last_run` copies the previous value of `change_tick`1767/// - `this_run` copies the current value of [`World::read_change_tick`]1768///1769/// Component change ticks that are more recent than `last_run` will be detected by the system.1770/// Those can be read by calling [`last_changed`](crate::change_detection::DetectChanges::last_changed)1771/// on a [`Mut<T>`](crate::change_detection::Mut) or [`ResMut<T>`](ResMut).1772#[derive(Debug, Clone, Copy)]1773pub struct SystemChangeTick {1774last_run: Tick,1775this_run: Tick,1776}17771778impl SystemChangeTick {1779/// Returns the current [`World`] change tick seen by the system.1780#[inline]1781pub fn this_run(&self) -> Tick {1782self.this_run1783}17841785/// Returns the [`World`] change tick seen by the system the previous time it ran.1786#[inline]1787pub fn last_run(&self) -> Tick {1788self.last_run1789}1790}17911792// SAFETY: Only reads internal system state1793unsafe impl ReadOnlySystemParam for SystemChangeTick {}17941795// SAFETY: `SystemChangeTick` doesn't require any world access1796unsafe impl SystemParam for SystemChangeTick {1797type State = ();1798type Item<'w, 's> = SystemChangeTick;17991800fn init_state(_world: &mut World) -> Self::State {}18011802fn init_access(1803_state: &Self::State,1804_system_meta: &mut SystemMeta,1805_component_access_set: &mut FilteredAccessSet,1806_world: &mut World,1807) {1808}18091810#[inline]1811unsafe fn get_param<'w, 's>(1812_state: &'s mut Self::State,1813system_meta: &SystemMeta,1814_world: UnsafeWorldCell<'w>,1815change_tick: Tick,1816) -> Self::Item<'w, 's> {1817SystemChangeTick {1818last_run: system_meta.last_run,1819this_run: change_tick,1820}1821}1822}18231824// SAFETY: Delegates to `T`, which ensures the safety requirements are met1825unsafe impl<T: SystemParam> SystemParam for Option<T> {1826type State = T::State;18271828type Item<'world, 'state> = Option<T::Item<'world, 'state>>;18291830fn init_state(world: &mut World) -> Self::State {1831T::init_state(world)1832}18331834fn init_access(1835state: &Self::State,1836system_meta: &mut SystemMeta,1837component_access_set: &mut FilteredAccessSet,1838world: &mut World,1839) {1840T::init_access(state, system_meta, component_access_set, world);1841}18421843#[inline]1844unsafe fn get_param<'world, 'state>(1845state: &'state mut Self::State,1846system_meta: &SystemMeta,1847world: UnsafeWorldCell<'world>,1848change_tick: Tick,1849) -> Self::Item<'world, 'state> {1850// SAFETY: Upheld by caller1851unsafe {1852T::validate_param(state, system_meta, world)1853.ok()1854.map(|()| T::get_param(state, system_meta, world, change_tick))1855}1856}18571858fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {1859T::apply(state, system_meta, world);1860}18611862fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {1863T::queue(state, system_meta, world);1864}1865}18661867// SAFETY: Delegates to `T`, which ensures the safety requirements are met1868unsafe impl<T: ReadOnlySystemParam> ReadOnlySystemParam for Option<T> {}18691870// SAFETY: Delegates to `T`, which ensures the safety requirements are met1871unsafe impl<T: SystemParam> SystemParam for Result<T, SystemParamValidationError> {1872type State = T::State;18731874type Item<'world, 'state> = Result<T::Item<'world, 'state>, SystemParamValidationError>;18751876fn init_state(world: &mut World) -> Self::State {1877T::init_state(world)1878}18791880fn init_access(1881state: &Self::State,1882system_meta: &mut SystemMeta,1883component_access_set: &mut FilteredAccessSet,1884world: &mut World,1885) {1886T::init_access(state, system_meta, component_access_set, world);1887}18881889#[inline]1890unsafe fn get_param<'world, 'state>(1891state: &'state mut Self::State,1892system_meta: &SystemMeta,1893world: UnsafeWorldCell<'world>,1894change_tick: Tick,1895) -> Self::Item<'world, 'state> {1896// SAFETY: Upheld by caller1897unsafe {1898T::validate_param(state, system_meta, world)1899.map(|()| T::get_param(state, system_meta, world, change_tick))1900}1901}19021903fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {1904T::apply(state, system_meta, world);1905}19061907fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {1908T::queue(state, system_meta, world);1909}1910}19111912// SAFETY: Delegates to `T`, which ensures the safety requirements are met1913unsafe impl<T: ReadOnlySystemParam> ReadOnlySystemParam for Result<T, SystemParamValidationError> {}19141915/// A [`SystemParam`] that wraps another parameter and causes its system to skip instead of failing when the parameter is invalid.1916///1917/// # Example1918///1919/// ```1920/// # use bevy_ecs::prelude::*;1921/// # #[derive(Resource)]1922/// # struct SomeResource;1923/// // This system will fail if `SomeResource` is not present.1924/// fn fails_on_missing_resource(res: Res<SomeResource>) {}1925///1926/// // This system will skip without error if `SomeResource` is not present.1927/// fn skips_on_missing_resource(res: If<Res<SomeResource>>) {1928/// // The inner parameter is available using `Deref`1929/// let some_resource: &SomeResource = &res;1930/// }1931/// # bevy_ecs::system::assert_is_system(skips_on_missing_resource);1932/// ```1933#[derive(Debug)]1934pub struct If<T>(pub T);19351936impl<T> If<T> {1937/// Returns the inner `T`.1938///1939/// The inner value is `pub`, so you can also obtain it by destructuring the parameter:1940///1941/// ```1942/// # use bevy_ecs::prelude::*;1943/// # #[derive(Resource)]1944/// # struct SomeResource;1945/// fn skips_on_missing_resource(If(res): If<Res<SomeResource>>) {1946/// let some_resource: Res<SomeResource> = res;1947/// }1948/// # bevy_ecs::system::assert_is_system(skips_on_missing_resource);1949/// ```1950pub fn into_inner(self) -> T {1951self.01952}1953}19541955impl<T> Deref for If<T> {1956type Target = T;1957fn deref(&self) -> &Self::Target {1958&self.01959}1960}19611962impl<T> DerefMut for If<T> {1963fn deref_mut(&mut self) -> &mut Self::Target {1964&mut self.01965}1966}19671968// SAFETY: Delegates to `T`, which ensures the safety requirements are met1969unsafe impl<T: SystemParam> SystemParam for If<T> {1970type State = T::State;19711972type Item<'world, 'state> = If<T::Item<'world, 'state>>;19731974fn init_state(world: &mut World) -> Self::State {1975T::init_state(world)1976}19771978fn init_access(1979state: &Self::State,1980system_meta: &mut SystemMeta,1981component_access_set: &mut FilteredAccessSet,1982world: &mut World,1983) {1984T::init_access(state, system_meta, component_access_set, world);1985}19861987#[inline]1988unsafe fn validate_param(1989state: &mut Self::State,1990system_meta: &SystemMeta,1991world: UnsafeWorldCell,1992) -> Result<(), SystemParamValidationError> {1993// SAFETY: Upheld by caller1994unsafe { T::validate_param(state, system_meta, world) }.map_err(|mut e| {1995e.skipped = true;1996e1997})1998}19992000#[inline]2001unsafe fn get_param<'world, 'state>(2002state: &'state mut Self::State,2003system_meta: &SystemMeta,2004world: UnsafeWorldCell<'world>,2005change_tick: Tick,2006) -> Self::Item<'world, 'state> {2007// SAFETY: Upheld by caller.2008If(unsafe { T::get_param(state, system_meta, world, change_tick) })2009}20102011fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {2012T::apply(state, system_meta, world);2013}20142015fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {2016T::queue(state, system_meta, world);2017}2018}20192020// SAFETY: Delegates to `T`, which ensures the safety requirements are met2021unsafe impl<T: ReadOnlySystemParam> ReadOnlySystemParam for If<T> {}20222023// SAFETY: Registers access for each element of `state`.2024// If any one conflicts, it will panic.2025unsafe impl<T: SystemParam> SystemParam for Vec<T> {2026type State = Vec<T::State>;20272028type Item<'world, 'state> = Vec<T::Item<'world, 'state>>;20292030fn init_state(_world: &mut World) -> Self::State {2031Vec::new()2032}20332034fn init_access(2035state: &Self::State,2036system_meta: &mut SystemMeta,2037component_access_set: &mut FilteredAccessSet,2038world: &mut World,2039) {2040for state in state {2041T::init_access(state, system_meta, component_access_set, world);2042}2043}20442045#[inline]2046unsafe fn validate_param(2047state: &mut Self::State,2048system_meta: &SystemMeta,2049world: UnsafeWorldCell,2050) -> Result<(), SystemParamValidationError> {2051for state in state {2052// SAFETY: Upheld by caller2053unsafe { T::validate_param(state, system_meta, world)? };2054}2055Ok(())2056}20572058#[inline]2059unsafe fn get_param<'world, 'state>(2060state: &'state mut Self::State,2061system_meta: &SystemMeta,2062world: UnsafeWorldCell<'world>,2063change_tick: Tick,2064) -> Self::Item<'world, 'state> {2065state2066.iter_mut()2067// SAFETY:2068// - We initialized the access for each parameter in `init_access`, so the caller ensures we have access to any world data needed by each param.2069// - The caller ensures this was the world used to initialize our state, and we used that world to initialize parameter states2070.map(|state| unsafe { T::get_param(state, system_meta, world, change_tick) })2071.collect()2072}20732074fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {2075for state in state {2076T::apply(state, system_meta, world);2077}2078}20792080fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {2081for state in state {2082T::queue(state, system_meta, world.reborrow());2083}2084}2085}20862087// SAFETY: Registers access for each element of `state`.2088// If any one conflicts with a previous parameter,2089// the call passing a copy of the current access will panic.2090unsafe impl<T: SystemParam> SystemParam for ParamSet<'_, '_, Vec<T>> {2091type State = Vec<T::State>;20922093type Item<'world, 'state> = ParamSet<'world, 'state, Vec<T>>;20942095fn init_state(_world: &mut World) -> Self::State {2096Vec::new()2097}20982099fn init_access(2100state: &Self::State,2101system_meta: &mut SystemMeta,2102component_access_set: &mut FilteredAccessSet,2103world: &mut World,2104) {2105for state in state {2106// Call `init_access` on a clone of the original access set to check for conflicts2107let component_access_set_clone = &mut component_access_set.clone();2108T::init_access(state, system_meta, component_access_set_clone, world);2109}2110for state in state {2111// Pretend to add the param to the system alone to gather the new access,2112// then merge its access into the system.2113let mut access_set = FilteredAccessSet::new();2114T::init_access(state, system_meta, &mut access_set, world);2115component_access_set.extend(access_set);2116}2117}21182119#[inline]2120unsafe fn get_param<'world, 'state>(2121state: &'state mut Self::State,2122system_meta: &SystemMeta,2123world: UnsafeWorldCell<'world>,2124change_tick: Tick,2125) -> Self::Item<'world, 'state> {2126ParamSet {2127param_states: state,2128system_meta: system_meta.clone(),2129world,2130change_tick,2131}2132}21332134fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {2135for state in state {2136T::apply(state, system_meta, world);2137}2138}21392140fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {2141for state in state {2142T::queue(state, system_meta, world.reborrow());2143}2144}2145}21462147impl<T: SystemParam> ParamSet<'_, '_, Vec<T>> {2148/// Accesses the parameter at the given index.2149/// No other parameters may be accessed while this one is active.2150pub fn get_mut(&mut self, index: usize) -> T::Item<'_, '_> {2151// SAFETY:2152// - We initialized the access for each parameter, so the caller ensures we have access to any world data needed by any param.2153// We have mutable access to the ParamSet, so no other params in the set are active.2154// - The caller of `get_param` ensured that this was the world used to initialize our state, and we used that world to initialize parameter states2155unsafe {2156T::get_param(2157&mut self.param_states[index],2158&self.system_meta,2159self.world,2160self.change_tick,2161)2162}2163}21642165/// Calls a closure for each parameter in the set.2166pub fn for_each(&mut self, mut f: impl FnMut(T::Item<'_, '_>)) {2167self.param_states.iter_mut().for_each(|state| {2168f(2169// SAFETY:2170// - We initialized the access for each parameter, so the caller ensures we have access to any world data needed by any param.2171// We have mutable access to the ParamSet, so no other params in the set are active.2172// - The caller of `get_param` ensured that this was the world used to initialize our state, and we used that world to initialize parameter states2173unsafe { T::get_param(state, &self.system_meta, self.world, self.change_tick) },2174);2175});2176}2177}21782179macro_rules! impl_system_param_tuple {2180($(#[$meta:meta])* $($param: ident),*) => {2181$(#[$meta])*2182// SAFETY: tuple consists only of ReadOnlySystemParams2183unsafe impl<$($param: ReadOnlySystemParam),*> ReadOnlySystemParam for ($($param,)*) {}21842185#[expect(2186clippy::allow_attributes,2187reason = "This is in a macro, and as such, the below lints may not always apply."2188)]2189#[allow(2190non_snake_case,2191reason = "Certain variable names are provided by the caller, not by us."2192)]2193#[allow(2194unused_variables,2195reason = "Zero-length tuples won't use some of the parameters."2196)]2197#[allow(clippy::unused_unit, reason = "Zero length tuple is unit.")]2198$(#[$meta])*2199// SAFETY: implementers of each `SystemParam` in the tuple have validated their impls2200unsafe impl<$($param: SystemParam),*> SystemParam for ($($param,)*) {2201type State = ($($param::State,)*);2202type Item<'w, 's> = ($($param::Item::<'w, 's>,)*);22032204#[inline]2205#[track_caller]2206fn init_state(world: &mut World) -> Self::State {2207($($param::init_state(world),)*)2208}22092210fn init_access(state: &Self::State, _system_meta: &mut SystemMeta, _component_access_set: &mut FilteredAccessSet, _world: &mut World) {2211let ($($param,)*) = state;2212$($param::init_access($param, _system_meta, _component_access_set, _world);)*2213}22142215#[inline]2216fn apply(($($param,)*): &mut Self::State, system_meta: &SystemMeta, world: &mut World) {2217$($param::apply($param, system_meta, world);)*2218}22192220#[inline]2221#[allow(2222unused_mut,2223reason = "The `world` parameter is unused for zero-length tuples; however, it must be mutable for other lengths of tuples."2224)]2225fn queue(($($param,)*): &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {2226$($param::queue($param, system_meta, world.reborrow());)*2227}22282229#[inline]2230unsafe fn validate_param(2231state: &mut Self::State,2232system_meta: &SystemMeta,2233world: UnsafeWorldCell,2234) -> Result<(), SystemParamValidationError> {2235let ($($param,)*) = state;22362237#[allow(2238unused_unsafe,2239reason = "Zero-length tuples won't have any params to validate."2240)]2241// SAFETY: Upheld by caller2242unsafe {2243$(2244$param::validate_param($param, system_meta, world)?;2245)*2246}2247Ok(())2248}22492250#[inline]2251#[track_caller]2252unsafe fn get_param<'w, 's>(2253state: &'s mut Self::State,2254system_meta: &SystemMeta,2255world: UnsafeWorldCell<'w>,2256change_tick: Tick,2257) -> Self::Item<'w, 's> {2258let ($($param,)*) = state;22592260#[allow(2261unused_unsafe,2262reason = "Zero-length tuples won't have any params to validate."2263)]2264// SAFETY: Upheld by caller2265unsafe {2266#[allow(2267clippy::unused_unit,2268reason = "Zero-length tuples won't have any params to get."2269)]2270($($param::get_param($param, system_meta, world, change_tick),)*)2271}2272}2273}2274};2275}22762277all_tuples!(2278#[doc(fake_variadic)]2279impl_system_param_tuple,22800,228116,2282P2283);22842285/// Contains type aliases for built-in [`SystemParam`]s with `'static` lifetimes.2286/// This makes it more convenient to refer to these types in contexts where2287/// explicit lifetime annotations are required.2288///2289/// Note that this is entirely safe and tracks lifetimes correctly.2290/// This purely exists for convenience.2291///2292/// You can't instantiate a static `SystemParam`, you'll always end up with2293/// `Res<'w, T>`, `ResMut<'w, T>` or `&'w T` bound to the lifetime of the provided2294/// `&'w World`.2295///2296/// [`SystemParam`]: super::SystemParam2297pub mod lifetimeless {2298/// A [`Query`](super::Query) with `'static` lifetimes.2299pub type SQuery<D, F = ()> = super::Query<'static, 'static, D, F>;2300/// A shorthand for writing `&'static T`.2301pub type Read<T> = &'static T;2302/// A shorthand for writing `&'static mut T`.2303pub type Write<T> = &'static mut T;2304/// A [`Res`](super::Res) with `'static` lifetimes.2305pub type SRes<T> = super::Res<'static, T>;2306/// A [`ResMut`](super::ResMut) with `'static` lifetimes.2307pub type SResMut<T> = super::ResMut<'static, T>;2308/// [`Commands`](crate::system::Commands) with `'static` lifetimes.2309pub type SCommands = crate::system::Commands<'static, 'static>;2310}23112312/// A helper for using system parameters in generic contexts2313///2314/// This type is a [`SystemParam`] adapter which always has2315/// `Self::Item == Self` (ignoring lifetimes for brevity),2316/// no matter the argument [`SystemParam`] (`P`) (other than2317/// that `P` must be `'static`)2318///2319/// This makes it useful for having arbitrary [`SystemParam`] type arguments2320/// to function systems, or for generic types using the [`derive@SystemParam`]2321/// derive:2322///2323/// ```2324/// # use bevy_ecs::prelude::*;2325/// use bevy_ecs::system::{SystemParam, StaticSystemParam};2326/// #[derive(SystemParam)]2327/// struct GenericParam<'w,'s, T: SystemParam + 'static> {2328/// field: StaticSystemParam<'w, 's, T>,2329/// }2330/// fn do_thing_generically<T: SystemParam + 'static>(t: StaticSystemParam<T>) {}2331///2332/// fn check_always_is_system<T: SystemParam + 'static>(){2333/// bevy_ecs::system::assert_is_system(do_thing_generically::<T>);2334/// }2335/// ```2336/// Note that in a real case you'd generally want2337/// additional bounds on `P`, for your use of the parameter2338/// to have a reason to be generic.2339///2340/// For example, using this would allow a type to be generic over2341/// whether a resource is accessed mutably or not, with2342/// impls being bounded on [`P: Deref<Target=MyType>`](Deref), and2343/// [`P: DerefMut<Target=MyType>`](DerefMut) depending on whether the2344/// method requires mutable access or not.2345///2346/// The method which doesn't use this type will not compile:2347/// ```compile_fail2348/// # use bevy_ecs::prelude::*;2349/// # use bevy_ecs::system::{SystemParam, StaticSystemParam};2350///2351/// fn do_thing_generically<T: SystemParam + 'static>(t: T) {}2352///2353/// #[derive(SystemParam)]2354/// struct GenericParam<'w, 's, T: SystemParam> {2355/// field: T,2356/// // Use the lifetimes in this type, or they will be unbound.2357/// phantom: std::marker::PhantomData<&'w &'s ()>2358/// }2359/// # fn check_always_is_system<T: SystemParam + 'static>(){2360/// # bevy_ecs::system::assert_is_system(do_thing_generically::<T>);2361/// # }2362/// ```2363pub struct StaticSystemParam<'w, 's, P: SystemParam>(SystemParamItem<'w, 's, P>);23642365impl<'w, 's, P: SystemParam> Deref for StaticSystemParam<'w, 's, P> {2366type Target = SystemParamItem<'w, 's, P>;23672368fn deref(&self) -> &Self::Target {2369&self.02370}2371}23722373impl<'w, 's, P: SystemParam> DerefMut for StaticSystemParam<'w, 's, P> {2374fn deref_mut(&mut self) -> &mut Self::Target {2375&mut self.02376}2377}23782379impl<'w, 's, P: SystemParam> StaticSystemParam<'w, 's, P> {2380/// Get the value of the parameter2381pub fn into_inner(self) -> SystemParamItem<'w, 's, P> {2382self.02383}2384}23852386// SAFETY: This doesn't add any more reads, and the delegated fetch confirms it2387unsafe impl<'w, 's, P: ReadOnlySystemParam + 'static> ReadOnlySystemParam2388for StaticSystemParam<'w, 's, P>2389{2390}23912392// SAFETY: all methods are just delegated to `P`'s `SystemParam` implementation2393unsafe impl<P: SystemParam + 'static> SystemParam for StaticSystemParam<'_, '_, P> {2394type State = P::State;2395type Item<'world, 'state> = StaticSystemParam<'world, 'state, P>;23962397fn init_state(world: &mut World) -> Self::State {2398P::init_state(world)2399}24002401fn init_access(2402state: &Self::State,2403system_meta: &mut SystemMeta,2404component_access_set: &mut FilteredAccessSet,2405world: &mut World,2406) {2407P::init_access(state, system_meta, component_access_set, world);2408}24092410fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {2411P::apply(state, system_meta, world);2412}24132414fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {2415P::queue(state, system_meta, world);2416}24172418#[inline]2419unsafe fn validate_param(2420state: &mut Self::State,2421system_meta: &SystemMeta,2422world: UnsafeWorldCell,2423) -> Result<(), SystemParamValidationError> {2424// SAFETY: Upheld by caller2425unsafe { P::validate_param(state, system_meta, world) }2426}24272428#[inline]2429unsafe fn get_param<'world, 'state>(2430state: &'state mut Self::State,2431system_meta: &SystemMeta,2432world: UnsafeWorldCell<'world>,2433change_tick: Tick,2434) -> Self::Item<'world, 'state> {2435// SAFETY: Defer to the safety of P::SystemParam2436StaticSystemParam(unsafe { P::get_param(state, system_meta, world, change_tick) })2437}2438}24392440// SAFETY: No world access.2441unsafe impl<T: ?Sized> SystemParam for PhantomData<T> {2442type State = ();2443type Item<'world, 'state> = Self;24442445fn init_state(_world: &mut World) -> Self::State {}24462447fn init_access(2448_state: &Self::State,2449_system_meta: &mut SystemMeta,2450_component_access_set: &mut FilteredAccessSet,2451_world: &mut World,2452) {2453}24542455#[inline]2456unsafe fn get_param<'world, 'state>(2457_state: &'state mut Self::State,2458_system_meta: &SystemMeta,2459_world: UnsafeWorldCell<'world>,2460_change_tick: Tick,2461) -> Self::Item<'world, 'state> {2462PhantomData2463}2464}24652466// SAFETY: No world access.2467unsafe impl<T: ?Sized> ReadOnlySystemParam for PhantomData<T> {}24682469/// A [`SystemParam`] with a type that can be configured at runtime.2470///2471/// To be useful, this must be configured using a [`DynParamBuilder`](crate::system::DynParamBuilder) to build the system using a [`SystemParamBuilder`](crate::prelude::SystemParamBuilder).2472///2473/// # Examples2474///2475/// ```2476/// # use bevy_ecs::{prelude::*, system::*};2477/// #2478/// # #[derive(Default, Resource)]2479/// # struct A;2480/// #2481/// # #[derive(Default, Resource)]2482/// # struct B;2483/// #2484/// # let mut world = World::new();2485/// # world.init_resource::<A>();2486/// # world.init_resource::<B>();2487/// #2488/// // If the inner parameter doesn't require any special building, use `ParamBuilder`.2489/// // Either specify the type parameter on `DynParamBuilder::new()` ...2490/// let system = (DynParamBuilder::new::<Res<A>>(ParamBuilder),)2491/// .build_state(&mut world)2492/// .build_system(expects_res_a);2493/// # world.run_system_once(system);2494///2495/// // ... or use a factory method on `ParamBuilder` that returns a specific type.2496/// let system = (DynParamBuilder::new(ParamBuilder::resource::<A>()),)2497/// .build_state(&mut world)2498/// .build_system(expects_res_a);2499/// # world.run_system_once(system);2500///2501/// fn expects_res_a(mut param: DynSystemParam) {2502/// // Use the `downcast` methods to retrieve the inner parameter.2503/// // They will return `None` if the type does not match.2504/// assert!(param.is::<Res<A>>());2505/// assert!(!param.is::<Res<B>>());2506/// assert!(param.downcast_mut::<Res<B>>().is_none());2507/// let res = param.downcast_mut::<Res<A>>().unwrap();2508/// // The type parameter can be left out if it can be determined from use.2509/// let res: Res<A> = param.downcast().unwrap();2510/// }2511///2512/// let system = (2513/// // If the inner parameter also requires building,2514/// // pass the appropriate `SystemParamBuilder`.2515/// DynParamBuilder::new(LocalBuilder(10usize)),2516/// // `DynSystemParam` is just an ordinary `SystemParam`,2517/// // and can be combined with other parameters as usual!2518/// ParamBuilder::query(),2519/// )2520/// .build_state(&mut world)2521/// .build_system(|param: DynSystemParam, query: Query<()>| {2522/// let local: Local<usize> = param.downcast::<Local<usize>>().unwrap();2523/// assert_eq!(*local, 10);2524/// });2525/// # world.run_system_once(system);2526/// ```2527pub struct DynSystemParam<'w, 's> {2528/// A `ParamState<T>` wrapping the state for the underlying system param.2529state: &'s mut dyn Any,2530world: UnsafeWorldCell<'w>,2531system_meta: SystemMeta,2532change_tick: Tick,2533}25342535impl<'w, 's> DynSystemParam<'w, 's> {2536/// # Safety2537/// - `state` must be a `ParamState<T>` for some inner `T: SystemParam`.2538/// - The passed [`UnsafeWorldCell`] must have access to any world data registered2539/// in [`init_state`](SystemParam::init_state) for the inner system param.2540/// - `world` must be the same `World` that was used to initialize2541/// [`state`](SystemParam::init_state) for the inner system param.2542unsafe fn new(2543state: &'s mut dyn Any,2544world: UnsafeWorldCell<'w>,2545system_meta: SystemMeta,2546change_tick: Tick,2547) -> Self {2548Self {2549state,2550world,2551system_meta,2552change_tick,2553}2554}25552556/// Returns `true` if the inner system param is the same as `T`.2557pub fn is<T: SystemParam>(&self) -> bool2558// See downcast() function for an explanation of the where clause2559where2560T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,2561{2562self.state.is::<ParamState<T::Item<'static, 'static>>>()2563}25642565/// Returns the inner system param if it is the correct type.2566/// This consumes the dyn param, so the returned param can have its original world and state lifetimes.2567pub fn downcast<T: SystemParam>(self) -> Option<T>2568// See downcast() function for an explanation of the where clause2569where2570T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,2571{2572// SAFETY:2573// - `DynSystemParam::new()` ensures `state` is a `ParamState<T>`, that the world matches,2574// and that it has access required by the inner system param.2575// - This consumes the `DynSystemParam`, so it is the only use of `world` with this access and it is available for `'w`.2576unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }2577}25782579/// Returns the inner system parameter if it is the correct type.2580/// This borrows the dyn param, so the returned param is only valid for the duration of that borrow.2581pub fn downcast_mut<'a, T: SystemParam>(&'a mut self) -> Option<T>2582// See downcast() function for an explanation of the where clause2583where2584T::Item<'static, 'static>: SystemParam<Item<'a, 'a> = T> + 'static,2585{2586// SAFETY:2587// - `DynSystemParam::new()` ensures `state` is a `ParamState<T>`, that the world matches,2588// and that it has access required by the inner system param.2589// - This exclusively borrows the `DynSystemParam` for `'_`, so it is the only use of `world` with this access for `'_`.2590unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }2591}25922593/// Returns the inner system parameter if it is the correct type.2594/// This borrows the dyn param, so the returned param is only valid for the duration of that borrow,2595/// but since it only performs read access it can keep the original world lifetime.2596/// This can be useful with methods like [`Query::iter_inner()`] or [`Res::into_inner()`]2597/// to obtain references with the original world lifetime.2598pub fn downcast_mut_inner<'a, T: ReadOnlySystemParam>(&'a mut self) -> Option<T>2599// See downcast() function for an explanation of the where clause2600where2601T::Item<'static, 'static>: SystemParam<Item<'w, 'a> = T> + 'static,2602{2603// SAFETY:2604// - `DynSystemParam::new()` ensures `state` is a `ParamState<T>`, that the world matches,2605// and that it has access required by the inner system param.2606// - The inner system param only performs read access, so it's safe to copy that access for the full `'w` lifetime.2607unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }2608}2609}26102611/// # Safety2612/// - `state` must be a `ParamState<T>` for some inner `T: SystemParam`.2613/// - The passed [`UnsafeWorldCell`] must have access to any world data registered2614/// in [`init_state`](SystemParam::init_state) for the inner system param.2615/// - `world` must be the same `World` that was used to initialize2616/// [`state`](SystemParam::init_state) for the inner system param.2617unsafe fn downcast<'w, 's, T: SystemParam>(2618state: &'s mut dyn Any,2619system_meta: &SystemMeta,2620world: UnsafeWorldCell<'w>,2621change_tick: Tick,2622) -> Option<T>2623// We need a 'static version of the SystemParam to use with `Any::downcast_mut()`,2624// and we need a <'w, 's> version to actually return.2625// The type parameter T must be the one we return in order to get type inference from the return value.2626// So we use `T::Item<'static, 'static>` as the 'static version, and require that it be 'static.2627// That means the return value will be T::Item<'static, 'static>::Item<'w, 's>,2628// so we constrain that to be equal to T.2629// Every actual `SystemParam` implementation has `T::Item == T` up to lifetimes,2630// so they should all work with this constraint.2631where2632T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,2633{2634state2635.downcast_mut::<ParamState<T::Item<'static, 'static>>>()2636.map(|state| {2637// SAFETY:2638// - The caller ensures the world has access for the underlying system param,2639// and since the downcast succeeded, the underlying system param is T.2640// - The caller ensures the `world` matches.2641unsafe { T::Item::get_param(&mut state.0, system_meta, world, change_tick) }2642})2643}26442645/// The [`SystemParam::State`] for a [`DynSystemParam`].2646pub struct DynSystemParamState(Box<dyn DynParamState>);26472648impl DynSystemParamState {2649pub(crate) fn new<T: SystemParam + 'static>(state: T::State) -> Self {2650Self(Box::new(ParamState::<T>(state)))2651}2652}26532654/// Allows a [`SystemParam::State`] to be used as a trait object for implementing [`DynSystemParam`].2655trait DynParamState: Sync + Send + Any {2656/// Applies any deferred mutations stored in this [`SystemParam`]'s state.2657/// This is used to apply [`Commands`] during [`ApplyDeferred`](crate::prelude::ApplyDeferred).2658///2659/// [`Commands`]: crate::prelude::Commands2660fn apply(&mut self, system_meta: &SystemMeta, world: &mut World);26612662/// Queues any deferred mutations to be applied at the next [`ApplyDeferred`](crate::prelude::ApplyDeferred).2663fn queue(&mut self, system_meta: &SystemMeta, world: DeferredWorld);26642665/// Registers any [`World`] access used by this [`SystemParam`]2666fn init_access(2667&self,2668system_meta: &mut SystemMeta,2669component_access_set: &mut FilteredAccessSet,2670world: &mut World,2671);26722673/// Refer to [`SystemParam::validate_param`].2674///2675/// # Safety2676/// Refer to [`SystemParam::validate_param`].2677unsafe fn validate_param(2678&mut self,2679system_meta: &SystemMeta,2680world: UnsafeWorldCell,2681) -> Result<(), SystemParamValidationError>;2682}26832684/// A wrapper around a [`SystemParam::State`] that can be used as a trait object in a [`DynSystemParam`].2685struct ParamState<T: SystemParam>(T::State);26862687impl<T: SystemParam + 'static> DynParamState for ParamState<T> {2688fn apply(&mut self, system_meta: &SystemMeta, world: &mut World) {2689T::apply(&mut self.0, system_meta, world);2690}26912692fn queue(&mut self, system_meta: &SystemMeta, world: DeferredWorld) {2693T::queue(&mut self.0, system_meta, world);2694}26952696fn init_access(2697&self,2698system_meta: &mut SystemMeta,2699component_access_set: &mut FilteredAccessSet,2700world: &mut World,2701) {2702T::init_access(&self.0, system_meta, component_access_set, world);2703}27042705unsafe fn validate_param(2706&mut self,2707system_meta: &SystemMeta,2708world: UnsafeWorldCell,2709) -> Result<(), SystemParamValidationError> {2710// SAFETY: Upheld by caller2711unsafe { T::validate_param(&mut self.0, system_meta, world) }2712}2713}27142715// SAFETY: Delegates to the wrapped parameter, which ensures the safety requirements are met2716unsafe impl SystemParam for DynSystemParam<'_, '_> {2717type State = DynSystemParamState;27182719type Item<'world, 'state> = DynSystemParam<'world, 'state>;27202721fn init_state(_world: &mut World) -> Self::State {2722DynSystemParamState::new::<()>(())2723}27242725fn init_access(2726state: &Self::State,2727system_meta: &mut SystemMeta,2728component_access_set: &mut FilteredAccessSet,2729world: &mut World,2730) {2731state2732.02733.init_access(system_meta, component_access_set, world);2734}27352736#[inline]2737unsafe fn validate_param(2738state: &mut Self::State,2739system_meta: &SystemMeta,2740world: UnsafeWorldCell,2741) -> Result<(), SystemParamValidationError> {2742// SAFETY: Upheld by caller.2743unsafe { state.0.validate_param(system_meta, world) }2744}27452746#[inline]2747unsafe fn get_param<'world, 'state>(2748state: &'state mut Self::State,2749system_meta: &SystemMeta,2750world: UnsafeWorldCell<'world>,2751change_tick: Tick,2752) -> Self::Item<'world, 'state> {2753// SAFETY:2754// - `state.0` is a boxed `ParamState<T>`.2755// - `init_access` calls `DynParamState::init_access`, which calls `init_access` on the inner parameter,2756// so the caller ensures the world has the necessary access.2757// - The caller ensures that the provided world is the same and has the required access.2758unsafe { DynSystemParam::new(state.0.as_mut(), world, system_meta.clone(), change_tick) }2759}27602761fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {2762state.0.apply(system_meta, world);2763}27642765fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {2766state.0.queue(system_meta, world);2767}2768}27692770// SAFETY: Resource ComponentId access is applied to the access. If this FilteredResources2771// conflicts with any prior access, a panic will occur.2772unsafe impl SystemParam for FilteredResources<'_, '_> {2773type State = Access;27742775type Item<'world, 'state> = FilteredResources<'world, 'state>;27762777fn init_state(_world: &mut World) -> Self::State {2778Access::new()2779}27802781fn init_access(2782access: &Self::State,2783system_meta: &mut SystemMeta,2784component_access_set: &mut FilteredAccessSet,2785world: &mut World,2786) {2787let combined_access = component_access_set.combined_access();2788let conflicts = combined_access.get_conflicts(access);2789if !conflicts.is_empty() {2790let accesses = conflicts.format_conflict_list(world);2791let system_name = &system_meta.name;2792panic!("error[B0002]: FilteredResources in system {system_name} accesses resources(s){accesses} in a way that conflicts with a previous system parameter. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002");2793}27942795if access.has_read_all_resources() {2796component_access_set.add_unfiltered_read_all_resources();2797} else {2798for component_id in access.resource_reads_and_writes() {2799component_access_set.add_unfiltered_resource_read(component_id);2800}2801}2802}28032804unsafe fn get_param<'world, 'state>(2805state: &'state mut Self::State,2806system_meta: &SystemMeta,2807world: UnsafeWorldCell<'world>,2808change_tick: Tick,2809) -> Self::Item<'world, 'state> {2810// SAFETY: The caller ensures that `world` has access to anything registered in `init_access`,2811// and we registered all resource access in `state``.2812unsafe { FilteredResources::new(world, state, system_meta.last_run, change_tick) }2813}2814}28152816// SAFETY: FilteredResources only reads resources.2817unsafe impl ReadOnlySystemParam for FilteredResources<'_, '_> {}28182819// SAFETY: Resource ComponentId access is applied to the access. If this FilteredResourcesMut2820// conflicts with any prior access, a panic will occur.2821unsafe impl SystemParam for FilteredResourcesMut<'_, '_> {2822type State = Access;28232824type Item<'world, 'state> = FilteredResourcesMut<'world, 'state>;28252826fn init_state(_world: &mut World) -> Self::State {2827Access::new()2828}28292830fn init_access(2831access: &Self::State,2832system_meta: &mut SystemMeta,2833component_access_set: &mut FilteredAccessSet,2834world: &mut World,2835) {2836let combined_access = component_access_set.combined_access();2837let conflicts = combined_access.get_conflicts(access);2838if !conflicts.is_empty() {2839let accesses = conflicts.format_conflict_list(world);2840let system_name = &system_meta.name;2841panic!("error[B0002]: FilteredResourcesMut in system {system_name} accesses resources(s){accesses} in a way that conflicts with a previous system parameter. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002");2842}28432844if access.has_read_all_resources() {2845component_access_set.add_unfiltered_read_all_resources();2846} else {2847for component_id in access.resource_reads() {2848component_access_set.add_unfiltered_resource_read(component_id);2849}2850}28512852if access.has_write_all_resources() {2853component_access_set.add_unfiltered_write_all_resources();2854} else {2855for component_id in access.resource_writes() {2856component_access_set.add_unfiltered_resource_write(component_id);2857}2858}2859}28602861unsafe fn get_param<'world, 'state>(2862state: &'state mut Self::State,2863system_meta: &SystemMeta,2864world: UnsafeWorldCell<'world>,2865change_tick: Tick,2866) -> Self::Item<'world, 'state> {2867// SAFETY: The caller ensures that `world` has access to anything registered in `init_access`,2868// and we registered all resource access in `state``.2869unsafe { FilteredResourcesMut::new(world, state, system_meta.last_run, change_tick) }2870}2871}28722873/// An error that occurs when a system parameter is not valid,2874/// used by system executors to determine what to do with a system.2875///2876/// Returned as an error from [`SystemParam::validate_param`],2877/// and handled using the unified error handling mechanisms defined in [`bevy_ecs::error`].2878#[derive(Debug, PartialEq, Eq, Clone, Error)]2879pub struct SystemParamValidationError {2880/// Whether the system should be skipped.2881///2882/// If `false`, the error should be handled.2883/// By default, this will result in a panic. See [`error`](`crate::error`) for more information.2884///2885/// This is the default behavior, and is suitable for system params that should *always* be valid,2886/// either because sensible fallback behavior exists (like [`Query`]) or because2887/// failures in validation should be considered a bug in the user's logic that must be immediately addressed (like [`Res`]).2888///2889/// If `true`, the system should be skipped.2890/// This is set by wrapping the system param in [`If`],2891/// and indicates that the system is intended to only operate in certain application states.2892pub skipped: bool,28932894/// A message describing the validation error.2895pub message: Cow<'static, str>,28962897/// A string identifying the invalid parameter.2898/// This is usually the type name of the parameter.2899pub param: DebugName,29002901/// A string identifying the field within a parameter using `#[derive(SystemParam)]`.2902/// This will be an empty string for other parameters.2903///2904/// This will be printed after `param` in the `Display` impl, and should include a `::` prefix if non-empty.2905pub field: Cow<'static, str>,2906}29072908impl SystemParamValidationError {2909/// Constructs a `SystemParamValidationError` that skips the system.2910/// The parameter name is initialized to the type name of `T`, so a `SystemParam` should usually pass `Self`.2911pub fn skipped<T>(message: impl Into<Cow<'static, str>>) -> Self {2912Self::new::<T>(true, message, Cow::Borrowed(""))2913}29142915/// Constructs a `SystemParamValidationError` for an invalid parameter that should be treated as an error.2916/// The parameter name is initialized to the type name of `T`, so a `SystemParam` should usually pass `Self`.2917pub fn invalid<T>(message: impl Into<Cow<'static, str>>) -> Self {2918Self::new::<T>(false, message, Cow::Borrowed(""))2919}29202921/// Constructs a `SystemParamValidationError` for an invalid parameter.2922/// The parameter name is initialized to the type name of `T`, so a `SystemParam` should usually pass `Self`.2923pub fn new<T>(2924skipped: bool,2925message: impl Into<Cow<'static, str>>,2926field: impl Into<Cow<'static, str>>,2927) -> Self {2928Self {2929skipped,2930message: message.into(),2931param: DebugName::type_name::<T>(),2932field: field.into(),2933}2934}29352936pub(crate) const EMPTY: Self = Self {2937skipped: false,2938message: Cow::Borrowed(""),2939param: DebugName::borrowed(""),2940field: Cow::Borrowed(""),2941};2942}29432944impl Display for SystemParamValidationError {2945fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {2946write!(2947fmt,2948"Parameter `{}{}` failed validation: {}",2949self.param.shortname(),2950self.field,2951self.message2952)?;2953if !self.skipped {2954write!(fmt, "\nIf this is an expected state, wrap the parameter in `Option<T>` and handle `None` when it happens, or wrap the parameter in `If<T>` to skip the system when it happens.")?;2955}2956Ok(())2957}2958}29592960#[cfg(test)]2961mod tests {2962use super::*;2963use crate::system::assert_is_system;2964use core::cell::RefCell;29652966#[test]2967#[should_panic]2968fn non_send_alias() {2969#[derive(Resource)]2970struct A(usize);2971fn my_system(mut res0: NonSendMut<A>, mut res1: NonSendMut<A>) {2972res0.0 += 1;2973res1.0 += 1;2974}2975let mut world = World::new();2976world.insert_non_send(A(42));2977let mut schedule = crate::schedule::Schedule::default();2978schedule.add_systems(my_system);2979schedule.run(&mut world);2980}29812982// Compile test for https://github.com/bevyengine/bevy/pull/2838.2983#[test]2984fn system_param_generic_bounds() {2985#[derive(SystemParam)]2986pub struct SpecialQuery<2987'w,2988's,2989D: QueryData + Send + Sync + 'static,2990F: QueryFilter + Send + Sync + 'static = (),2991> {2992_query: Query<'w, 's, D, F>,2993}29942995fn my_system(_: SpecialQuery<(), ()>) {}2996assert_is_system(my_system);2997}29982999// Compile tests for https://github.com/bevyengine/bevy/pull/6694.3000#[test]3001fn system_param_flexibility() {3002#[derive(SystemParam)]3003pub struct SpecialRes<'w, T: Resource> {3004_res: Res<'w, T>,3005}30063007#[derive(SystemParam)]3008pub struct SpecialLocal<'s, T: FromWorld + Send + 'static> {3009_local: Local<'s, T>,3010}30113012#[derive(Resource)]3013struct R;30143015fn my_system(_: SpecialRes<R>, _: SpecialLocal<u32>) {}3016assert_is_system(my_system);3017}30183019#[derive(Resource)]3020pub struct R<const I: usize>;30213022// Compile test for https://github.com/bevyengine/bevy/pull/7001.3023#[test]3024fn system_param_const_generics() {3025#[expect(3026dead_code,3027reason = "This struct is used to ensure that const generics are supported as a SystemParam; thus, the inner value never needs to be read."3028)]3029#[derive(SystemParam)]3030pub struct ConstGenericParam<'w, const I: usize>(Res<'w, R<I>>);30313032fn my_system(_: ConstGenericParam<0>, _: ConstGenericParam<1000>) {}3033assert_is_system(my_system);3034}30353036// Compile test for https://github.com/bevyengine/bevy/pull/6867.3037#[test]3038fn system_param_field_limit() {3039#[derive(SystemParam)]3040pub struct LongParam<'w> {3041// Each field should be a distinct type so there will3042// be an error if the derive messes up the field order.3043_r0: Res<'w, R<0>>,3044_r1: Res<'w, R<1>>,3045_r2: Res<'w, R<2>>,3046_r3: Res<'w, R<3>>,3047_r4: Res<'w, R<4>>,3048_r5: Res<'w, R<5>>,3049_r6: Res<'w, R<6>>,3050_r7: Res<'w, R<7>>,3051_r8: Res<'w, R<8>>,3052_r9: Res<'w, R<9>>,3053_r10: Res<'w, R<10>>,3054_r11: Res<'w, R<11>>,3055_r12: Res<'w, R<12>>,3056_r13: Res<'w, R<13>>,3057_r14: Res<'w, R<14>>,3058_r15: Res<'w, R<15>>,3059_r16: Res<'w, R<16>>,3060}30613062fn long_system(_: LongParam) {}3063assert_is_system(long_system);3064}30653066// Compile test for https://github.com/bevyengine/bevy/pull/6919.3067// Regression test for https://github.com/bevyengine/bevy/issues/7447.3068#[test]3069fn system_param_phantom_data() {3070#[derive(SystemParam)]3071struct PhantomParam<'w, T: Resource, Marker: 'static> {3072_foo: Res<'w, T>,3073marker: PhantomData<&'w Marker>,3074}30753076fn my_system(_: PhantomParam<R<0>, ()>) {}3077assert_is_system(my_system);3078}30793080// Compile tests for https://github.com/bevyengine/bevy/pull/6957.3081#[test]3082fn system_param_struct_variants() {3083#[derive(SystemParam)]3084pub struct UnitParam;30853086#[expect(3087dead_code,3088reason = "This struct is used to ensure that tuple structs are supported as a SystemParam; thus, the inner values never need to be read."3089)]3090#[derive(SystemParam)]3091pub struct TupleParam<'w, 's, R: Resource, L: FromWorld + Send + 'static>(3092Res<'w, R>,3093Local<'s, L>,3094);30953096fn my_system(_: UnitParam, _: TupleParam<R<0>, u32>) {}3097assert_is_system(my_system);3098}30993100// Regression test for https://github.com/bevyengine/bevy/issues/4200.3101#[test]3102fn system_param_private_fields() {3103#[derive(Resource)]3104struct PrivateResource;31053106#[expect(3107dead_code,3108reason = "This struct is used to ensure that SystemParam's derive can't leak private fields; thus, the inner values never need to be read."3109)]3110#[derive(SystemParam)]3111pub struct EncapsulatedParam<'w>(Res<'w, PrivateResource>);31123113fn my_system(_: EncapsulatedParam) {}3114assert_is_system(my_system);3115}31163117// Regression test for https://github.com/bevyengine/bevy/issues/7103.3118#[test]3119fn system_param_where_clause() {3120#[derive(SystemParam)]3121pub struct WhereParam<'w, 's, D>3122where3123D: 'static + QueryData,3124{3125_q: Query<'w, 's, D, ()>,3126}31273128fn my_system(_: WhereParam<()>) {}3129assert_is_system(my_system);3130}31313132// Regression test for https://github.com/bevyengine/bevy/issues/1727.3133#[test]3134fn system_param_name_collision() {3135#[derive(Resource)]3136pub struct FetchState;31373138#[derive(SystemParam)]3139pub struct Collide<'w> {3140_x: Res<'w, FetchState>,3141}31423143fn my_system(_: Collide) {}3144assert_is_system(my_system);3145}31463147// Regression test for https://github.com/bevyengine/bevy/issues/8192.3148#[test]3149fn system_param_invariant_lifetime() {3150#[derive(SystemParam)]3151pub struct InvariantParam<'w, 's> {3152_set: ParamSet<'w, 's, (Query<'w, 's, ()>,)>,3153}31543155fn my_system(_: InvariantParam) {}3156assert_is_system(my_system);3157}31583159// Compile test for https://github.com/bevyengine/bevy/pull/9589.3160#[test]3161fn non_sync_local() {3162fn non_sync_system(cell: Local<RefCell<u8>>) {3163assert_eq!(*cell.borrow(), 0);3164}31653166let mut world = World::new();3167let mut schedule = crate::schedule::Schedule::default();3168schedule.add_systems(non_sync_system);3169schedule.run(&mut world);3170}31713172// Regression test for https://github.com/bevyengine/bevy/issues/10207.3173#[test]3174fn param_set_non_send_first() {3175fn non_send_param_set(mut p: ParamSet<(NonSend<*mut u8>, ())>) {3176let _ = p.p0();3177p.p1();3178}31793180let mut world = World::new();3181world.insert_non_send(core::ptr::null_mut::<u8>());3182let mut schedule = crate::schedule::Schedule::default();3183schedule.add_systems((non_send_param_set, non_send_param_set, non_send_param_set));3184schedule.run(&mut world);3185}31863187// Regression test for https://github.com/bevyengine/bevy/issues/10207.3188#[test]3189fn param_set_non_send_second() {3190fn non_send_param_set(mut p: ParamSet<((), NonSendMut<*mut u8>)>) {3191p.p0();3192let _ = p.p1();3193}31943195let mut world = World::new();3196world.insert_non_send(core::ptr::null_mut::<u8>());3197let mut schedule = crate::schedule::Schedule::default();3198schedule.add_systems((non_send_param_set, non_send_param_set, non_send_param_set));3199schedule.run(&mut world);3200}32013202fn _dyn_system_param_type_inference(mut p: DynSystemParam) {3203// Make sure the downcast() methods are able to infer their type parameters from the use of the return type.3204// This is just a compilation test, so there is nothing to run.3205let _query: Query<()> = p.downcast_mut().unwrap();3206let _query: Query<()> = p.downcast_mut_inner().unwrap();3207let _query: Query<()> = p.downcast().unwrap();3208}32093210#[test]3211#[should_panic]3212fn missing_resource_error() {3213#[derive(Resource)]3214pub struct MissingResource;32153216let mut schedule = crate::schedule::Schedule::default();3217schedule.add_systems(res_system);3218let mut world = World::new();3219schedule.run(&mut world);32203221fn res_system(_: Res<MissingResource>) {}3222}32233224#[test]3225#[should_panic]3226fn missing_message_error() {3227use crate::prelude::{Message, MessageReader};32283229#[derive(Message)]3230pub struct MissingEvent;32313232let mut schedule = crate::schedule::Schedule::default();3233schedule.add_systems(message_system);3234let mut world = World::new();3235schedule.run(&mut world);32363237fn message_system(_: MessageReader<MissingEvent>) {}3238}3239}324032413242