Path: blob/main/crates/bevy_ecs/src/system/system_param.rs
6604 views
pub use crate::change_detection::{NonSendMut, Res, ResMut};1use crate::{2archetype::Archetypes,3bundle::Bundles,4change_detection::{MaybeLocation, Ticks, TicksMut},5component::{ComponentId, ComponentTicks, Components, Tick},6entity::Entities,7query::{8Access, FilteredAccess, FilteredAccessSet, QueryData, QueryFilter, QuerySingleError,9QueryState, ReadOnlyQueryData,10},11resource::Resource,12storage::ResourceData,13system::{Query, Single, SystemMeta},14world::{15unsafe_world_cell::UnsafeWorldCell, DeferredWorld, FilteredResources, FilteredResourcesMut,16FromWorld, World,17},18};19use alloc::{20borrow::{Cow, ToOwned},21boxed::Box,22vec::Vec,23};24pub use bevy_ecs_macros::SystemParam;25use bevy_platform::cell::SyncCell;26use bevy_ptr::UnsafeCellDeref;27use bevy_utils::prelude::DebugName;28use core::{29any::Any,30fmt::{Debug, Display},31marker::PhantomData,32ops::{Deref, DerefMut},33panic::Location,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(BufferedEvent)]62/// # struct SomeEvent;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/// # eventreader:81/// EventReader<'w, 's, SomeEvent>,82/// # eventwriter:83/// EventWriter<'w, SomeEvent>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(BufferedEvent)]608/// # struct MyEvent;609/// # impl MyEvent {610/// # pub fn new() -> Self { Self }611/// # }612/// fn event_system(613/// mut set: ParamSet<(614/// // PROBLEM: `EventReader` and `EventWriter` cannot be used together normally,615/// // because they both need access to the same event queue.616/// // SOLUTION: `ParamSet` allows these conflicting parameters to be used safely617/// // by ensuring only one is accessed at a time.618/// EventReader<MyEvent>,619/// EventWriter<MyEvent>,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 event in set.p0().read() {628/// // ...629/// # let _event = event;630/// }631/// set.p1().write(MyEvent::new());632///633/// let entities = set.p2().entities();634/// // ...635/// # let _entities = entities;636/// }637/// # bevy_ecs::system::assert_is_system(event_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<($($param,)*) as SystemParam>::validate_param(state, system_meta, world)711}712713#[inline]714unsafe fn get_param<'w, 's>(715state: &'s mut Self::State,716system_meta: &SystemMeta,717world: UnsafeWorldCell<'w>,718change_tick: Tick,719) -> Self::Item<'w, 's> {720ParamSet {721param_states: state,722system_meta: system_meta.clone(),723world,724change_tick,725}726}727}728729impl<'w, 's, $($param: SystemParam,)*> ParamSet<'w, 's, ($($param,)*)>730{731$(732/// Gets exclusive access to the parameter at index733#[doc = stringify!($index)]734/// in this [`ParamSet`].735/// No other parameters may be accessed while this one is active.736pub fn $fn_name<'a>(&'a mut self) -> SystemParamItem<'a, 'a, $param> {737// SAFETY: systems run without conflicts with other systems.738// Conflicting params in ParamSet are not accessible at the same time739// ParamSets are guaranteed to not conflict with other SystemParams740unsafe {741$param::get_param(&mut self.param_states.$index, &self.system_meta, self.world, self.change_tick)742}743}744)*745}746}747}748749all_tuples_enumerated!(impl_param_set, 1, 8, P, p);750751// SAFETY: Res only reads a single World resource752unsafe impl<'a, T: Resource> ReadOnlySystemParam for Res<'a, T> {}753754// SAFETY: Res ComponentId access is applied to SystemMeta. If this Res755// conflicts with any prior access, a panic will occur.756unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> {757type State = ComponentId;758type Item<'w, 's> = Res<'w, T>;759760fn init_state(world: &mut World) -> Self::State {761world.components_registrator().register_resource::<T>()762}763764fn init_access(765&component_id: &Self::State,766system_meta: &mut SystemMeta,767component_access_set: &mut FilteredAccessSet,768_world: &mut World,769) {770let combined_access = component_access_set.combined_access();771assert!(772!combined_access.has_resource_write(component_id),773"error[B0002]: Res<{}> in system {} conflicts with a previous ResMut<{0}> access. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",774DebugName::type_name::<T>(),775system_meta.name,776);777778component_access_set.add_unfiltered_resource_read(component_id);779}780781#[inline]782unsafe fn validate_param(783&mut component_id: &mut Self::State,784_system_meta: &SystemMeta,785world: UnsafeWorldCell,786) -> Result<(), SystemParamValidationError> {787// SAFETY: Read-only access to resource metadata.788if unsafe { world.storages() }789.resources790.get(component_id)791.is_some_and(ResourceData::is_present)792{793Ok(())794} else {795Err(SystemParamValidationError::invalid::<Self>(796"Resource does not exist",797))798}799}800801#[inline]802unsafe fn get_param<'w, 's>(803&mut component_id: &'s mut Self::State,804system_meta: &SystemMeta,805world: UnsafeWorldCell<'w>,806change_tick: Tick,807) -> Self::Item<'w, 's> {808let (ptr, ticks, caller) =809world810.get_resource_with_ticks(component_id)811.unwrap_or_else(|| {812panic!(813"Resource requested by {} does not exist: {}",814system_meta.name,815DebugName::type_name::<T>()816);817});818Res {819value: ptr.deref(),820ticks: Ticks {821added: ticks.added.deref(),822changed: ticks.changed.deref(),823last_run: system_meta.last_run,824this_run: change_tick,825},826changed_by: caller.map(|caller| caller.deref()),827}828}829}830831// SAFETY: Res ComponentId access is applied to SystemMeta. If this Res832// conflicts with any prior access, a panic will occur.833unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> {834type State = ComponentId;835type Item<'w, 's> = ResMut<'w, T>;836837fn init_state(world: &mut World) -> Self::State {838world.components_registrator().register_resource::<T>()839}840841fn init_access(842&component_id: &Self::State,843system_meta: &mut SystemMeta,844component_access_set: &mut FilteredAccessSet,845_world: &mut World,846) {847let combined_access = component_access_set.combined_access();848if combined_access.has_resource_write(component_id) {849panic!(850"error[B0002]: ResMut<{}> in system {} conflicts with a previous ResMut<{0}> access. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",851DebugName::type_name::<T>(), system_meta.name);852} else if combined_access.has_resource_read(component_id) {853panic!(854"error[B0002]: ResMut<{}> in system {} conflicts with a previous Res<{0}> access. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",855DebugName::type_name::<T>(), system_meta.name);856}857component_access_set.add_unfiltered_resource_write(component_id);858}859860#[inline]861unsafe fn validate_param(862&mut component_id: &mut Self::State,863_system_meta: &SystemMeta,864world: UnsafeWorldCell,865) -> Result<(), SystemParamValidationError> {866// SAFETY: Read-only access to resource metadata.867if unsafe { world.storages() }868.resources869.get(component_id)870.is_some_and(ResourceData::is_present)871{872Ok(())873} else {874Err(SystemParamValidationError::invalid::<Self>(875"Resource does not exist",876))877}878}879880#[inline]881unsafe fn get_param<'w, 's>(882&mut component_id: &'s mut Self::State,883system_meta: &SystemMeta,884world: UnsafeWorldCell<'w>,885change_tick: Tick,886) -> Self::Item<'w, 's> {887let value = world888.get_resource_mut_by_id(component_id)889.unwrap_or_else(|| {890panic!(891"Resource requested by {} does not exist: {}",892system_meta.name,893DebugName::type_name::<T>()894);895});896ResMut {897value: value.value.deref_mut::<T>(),898ticks: TicksMut {899added: value.ticks.added,900changed: value.ticks.changed,901last_run: system_meta.last_run,902this_run: change_tick,903},904changed_by: value.changed_by,905}906}907}908909/// SAFETY: only reads world910unsafe impl<'w> ReadOnlySystemParam for &'w World {}911912// SAFETY: `read_all` access is set and conflicts result in a panic913unsafe impl SystemParam for &'_ World {914type State = ();915type Item<'w, 's> = &'w World;916917fn init_state(_world: &mut World) -> Self::State {}918919fn init_access(920_state: &Self::State,921_system_meta: &mut SystemMeta,922component_access_set: &mut FilteredAccessSet,923_world: &mut World,924) {925let mut filtered_access = FilteredAccess::default();926927filtered_access.read_all();928if !component_access_set929.get_conflicts_single(&filtered_access)930.is_empty()931{932panic!("&World conflicts with a previous mutable system parameter. Allowing this would break Rust's mutability rules");933}934component_access_set.add(filtered_access);935}936937#[inline]938unsafe fn get_param<'w, 's>(939_state: &'s mut Self::State,940_system_meta: &SystemMeta,941world: UnsafeWorldCell<'w>,942_change_tick: Tick,943) -> Self::Item<'w, 's> {944// SAFETY: Read-only access to the entire world was registered in `init_state`.945unsafe { world.world() }946}947}948949/// SAFETY: `DeferredWorld` can read all components and resources but cannot be used to gain any other mutable references.950unsafe impl<'w> SystemParam for DeferredWorld<'w> {951type State = ();952type Item<'world, 'state> = DeferredWorld<'world>;953954fn init_state(_world: &mut World) -> Self::State {}955956fn init_access(957_state: &Self::State,958system_meta: &mut SystemMeta,959component_access_set: &mut FilteredAccessSet,960_world: &mut World,961) {962assert!(963!component_access_set.combined_access().has_any_read(),964"DeferredWorld in system {} conflicts with a previous access.",965system_meta.name,966);967component_access_set.write_all();968}969970unsafe fn get_param<'world, 'state>(971_state: &'state mut Self::State,972_system_meta: &SystemMeta,973world: UnsafeWorldCell<'world>,974_change_tick: Tick,975) -> Self::Item<'world, 'state> {976world.into_deferred()977}978}979980/// A system local [`SystemParam`].981///982/// A local may only be accessed by the system itself and is therefore not visible to other systems.983/// If two or more systems specify the same local type each will have their own unique local.984/// If multiple [`SystemParam`]s within the same system each specify the same local type985/// each will get their own distinct data storage.986///987/// The supplied lifetime parameter is the [`SystemParam`]s `'s` lifetime.988///989/// # Examples990///991/// ```992/// # use bevy_ecs::prelude::*;993/// # let world = &mut World::default();994/// fn write_to_local(mut local: Local<usize>) {995/// *local = 42;996/// }997/// fn read_from_local(local: Local<usize>) -> usize {998/// *local999/// }1000/// let mut write_system = IntoSystem::into_system(write_to_local);1001/// let mut read_system = IntoSystem::into_system(read_from_local);1002/// write_system.initialize(world);1003/// read_system.initialize(world);1004///1005/// assert_eq!(read_system.run((), world).unwrap(), 0);1006/// write_system.run((), world);1007/// // Note how the read local is still 0 due to the locals not being shared.1008/// assert_eq!(read_system.run((), world).unwrap(), 0);1009/// ```1010///1011/// A simple way to set a different default value for a local is by wrapping the value with an Option.1012///1013/// ```1014/// # use bevy_ecs::prelude::*;1015/// # let world = &mut World::default();1016/// fn counter_from_10(mut count: Local<Option<usize>>) -> usize {1017/// let count = count.get_or_insert(10);1018/// *count += 1;1019/// *count1020/// }1021/// let mut counter_system = IntoSystem::into_system(counter_from_10);1022/// counter_system.initialize(world);1023///1024/// // Counter is initialized at 10, and increases to 11 on first run.1025/// assert_eq!(counter_system.run((), world).unwrap(), 11);1026/// // Counter is only increased by 1 on subsequent runs.1027/// assert_eq!(counter_system.run((), world).unwrap(), 12);1028/// ```1029///1030/// N.B. A [`Local`]s value cannot be read or written to outside of the containing system.1031/// To add configuration to a system, convert a capturing closure into the system instead:1032///1033/// ```1034/// # use bevy_ecs::prelude::*;1035/// # use bevy_ecs::system::assert_is_system;1036/// struct Config(u32);1037/// #[derive(Resource)]1038/// struct MyU32Wrapper(u32);1039/// fn reset_to_system(value: Config) -> impl FnMut(ResMut<MyU32Wrapper>) {1040/// move |mut val| val.0 = value.01041/// }1042///1043/// // .add_systems(reset_to_system(my_config))1044/// # assert_is_system(reset_to_system(Config(10)));1045/// ```1046#[derive(Debug)]1047pub struct Local<'s, T: FromWorld + Send + 'static>(pub(crate) &'s mut T);10481049// SAFETY: Local only accesses internal state1050unsafe impl<'s, T: FromWorld + Send + 'static> ReadOnlySystemParam for Local<'s, T> {}10511052impl<'s, T: FromWorld + Send + 'static> Deref for Local<'s, T> {1053type Target = T;10541055#[inline]1056fn deref(&self) -> &Self::Target {1057self.01058}1059}10601061impl<'s, T: FromWorld + Send + 'static> DerefMut for Local<'s, T> {1062#[inline]1063fn deref_mut(&mut self) -> &mut Self::Target {1064self.01065}1066}10671068impl<'s, 'a, T: FromWorld + Send + 'static> IntoIterator for &'a Local<'s, T>1069where1070&'a T: IntoIterator,1071{1072type Item = <&'a T as IntoIterator>::Item;1073type IntoIter = <&'a T as IntoIterator>::IntoIter;10741075fn into_iter(self) -> Self::IntoIter {1076self.0.into_iter()1077}1078}10791080impl<'s, 'a, T: FromWorld + Send + 'static> IntoIterator for &'a mut Local<'s, T>1081where1082&'a mut T: IntoIterator,1083{1084type Item = <&'a mut T as IntoIterator>::Item;1085type IntoIter = <&'a mut T as IntoIterator>::IntoIter;10861087fn into_iter(self) -> Self::IntoIter {1088self.0.into_iter()1089}1090}10911092// SAFETY: only local state is accessed1093unsafe impl<'a, T: FromWorld + Send + 'static> SystemParam for Local<'a, T> {1094type State = SyncCell<T>;1095type Item<'w, 's> = Local<'s, T>;10961097fn init_state(world: &mut World) -> Self::State {1098SyncCell::new(T::from_world(world))1099}11001101fn init_access(1102_state: &Self::State,1103_system_meta: &mut SystemMeta,1104_component_access_set: &mut FilteredAccessSet,1105_world: &mut World,1106) {1107}11081109#[inline]1110unsafe fn get_param<'w, 's>(1111state: &'s mut Self::State,1112_system_meta: &SystemMeta,1113_world: UnsafeWorldCell<'w>,1114_change_tick: Tick,1115) -> Self::Item<'w, 's> {1116Local(state.get())1117}1118}11191120/// Types that can be used with [`Deferred<T>`] in systems.1121/// This allows storing system-local data which is used to defer [`World`] mutations.1122///1123/// Types that implement `SystemBuffer` should take care to perform as many1124/// computations up-front as possible. Buffers cannot be applied in parallel,1125/// so you should try to minimize the time spent in [`SystemBuffer::apply`].1126pub trait SystemBuffer: FromWorld + Send + 'static {1127/// Applies any deferred mutations to the [`World`].1128fn apply(&mut self, system_meta: &SystemMeta, world: &mut World);1129/// Queues any deferred mutations to be applied at the next [`ApplyDeferred`](crate::prelude::ApplyDeferred).1130fn queue(&mut self, _system_meta: &SystemMeta, _world: DeferredWorld) {}1131}11321133/// A [`SystemParam`] that stores a buffer which gets applied to the [`World`] during1134/// [`ApplyDeferred`](crate::schedule::ApplyDeferred).1135/// This is used internally by [`Commands`] to defer `World` mutations.1136///1137/// [`Commands`]: crate::system::Commands1138///1139/// # Examples1140///1141/// By using this type to defer mutations, you can avoid mutable `World` access within1142/// a system, which allows it to run in parallel with more systems.1143///1144/// Note that deferring mutations is *not* free, and should only be used if1145/// the gains in parallelization outweigh the time it takes to apply deferred mutations.1146/// In general, [`Deferred`] should only be used for mutations that are infrequent,1147/// or which otherwise take up a small portion of a system's run-time.1148///1149/// ```1150/// # use bevy_ecs::prelude::*;1151/// // Tracks whether or not there is a threat the player should be aware of.1152/// #[derive(Resource, Default)]1153/// pub struct Alarm(bool);1154///1155/// #[derive(Component)]1156/// pub struct Settlement {1157/// // ...1158/// }1159///1160/// // A threat from inside the settlement.1161/// #[derive(Component)]1162/// pub struct Criminal;1163///1164/// // A threat from outside the settlement.1165/// #[derive(Component)]1166/// pub struct Monster;1167///1168/// # impl Criminal { pub fn is_threat(&self, _: &Settlement) -> bool { true } }1169///1170/// use bevy_ecs::system::{Deferred, SystemBuffer, SystemMeta};1171///1172/// // Uses deferred mutations to allow signaling the alarm from multiple systems in parallel.1173/// #[derive(Resource, Default)]1174/// struct AlarmFlag(bool);1175///1176/// impl AlarmFlag {1177/// /// Sounds the alarm the next time buffers are applied via ApplyDeferred.1178/// pub fn flag(&mut self) {1179/// self.0 = true;1180/// }1181/// }1182///1183/// impl SystemBuffer for AlarmFlag {1184/// // When `AlarmFlag` is used in a system, this function will get1185/// // called the next time buffers are applied via ApplyDeferred.1186/// fn apply(&mut self, system_meta: &SystemMeta, world: &mut World) {1187/// if self.0 {1188/// world.resource_mut::<Alarm>().0 = true;1189/// self.0 = false;1190/// }1191/// }1192/// }1193///1194/// // Sound the alarm if there are any criminals who pose a threat.1195/// fn alert_criminal(1196/// settlement: Single<&Settlement>,1197/// criminals: Query<&Criminal>,1198/// mut alarm: Deferred<AlarmFlag>1199/// ) {1200/// for criminal in &criminals {1201/// // Only sound the alarm if the criminal is a threat.1202/// // For this example, assume that this check is expensive to run.1203/// // Since the majority of this system's run-time is dominated1204/// // by calling `is_threat()`, we defer sounding the alarm to1205/// // allow this system to run in parallel with other alarm systems.1206/// if criminal.is_threat(*settlement) {1207/// alarm.flag();1208/// }1209/// }1210/// }1211///1212/// // Sound the alarm if there is a monster.1213/// fn alert_monster(1214/// monsters: Query<&Monster>,1215/// mut alarm: ResMut<Alarm>1216/// ) {1217/// if monsters.iter().next().is_some() {1218/// // Since this system does nothing except for sounding the alarm,1219/// // it would be pointless to defer it, so we sound the alarm directly.1220/// alarm.0 = true;1221/// }1222/// }1223///1224/// let mut world = World::new();1225/// world.init_resource::<Alarm>();1226/// world.spawn(Settlement {1227/// // ...1228/// });1229///1230/// let mut schedule = Schedule::default();1231/// // These two systems have no conflicts and will run in parallel.1232/// schedule.add_systems((alert_criminal, alert_monster));1233///1234/// // There are no criminals or monsters, so the alarm is not sounded.1235/// schedule.run(&mut world);1236/// assert_eq!(world.resource::<Alarm>().0, false);1237///1238/// // Spawn a monster, which will cause the alarm to be sounded.1239/// let m_id = world.spawn(Monster).id();1240/// schedule.run(&mut world);1241/// assert_eq!(world.resource::<Alarm>().0, true);1242///1243/// // Remove the monster and reset the alarm.1244/// world.entity_mut(m_id).despawn();1245/// world.resource_mut::<Alarm>().0 = false;1246///1247/// // Spawn a criminal, which will cause the alarm to be sounded.1248/// world.spawn(Criminal);1249/// schedule.run(&mut world);1250/// assert_eq!(world.resource::<Alarm>().0, true);1251/// ```1252pub struct Deferred<'a, T: SystemBuffer>(pub(crate) &'a mut T);12531254impl<'a, T: SystemBuffer> Deref for Deferred<'a, T> {1255type Target = T;1256#[inline]1257fn deref(&self) -> &Self::Target {1258self.01259}1260}12611262impl<'a, T: SystemBuffer> DerefMut for Deferred<'a, T> {1263#[inline]1264fn deref_mut(&mut self) -> &mut Self::Target {1265self.01266}1267}12681269impl<T: SystemBuffer> Deferred<'_, T> {1270/// Returns a [`Deferred<T>`] with a smaller lifetime.1271/// This is useful if you have `&mut Deferred<T>` but need `Deferred<T>`.1272pub fn reborrow(&mut self) -> Deferred<'_, T> {1273Deferred(self.0)1274}1275}12761277// SAFETY: Only local state is accessed.1278unsafe impl<T: SystemBuffer> ReadOnlySystemParam for Deferred<'_, T> {}12791280// SAFETY: Only local state is accessed.1281unsafe impl<T: SystemBuffer> SystemParam for Deferred<'_, T> {1282type State = SyncCell<T>;1283type Item<'w, 's> = Deferred<'s, T>;12841285fn init_state(world: &mut World) -> Self::State {1286SyncCell::new(T::from_world(world))1287}12881289fn init_access(1290_state: &Self::State,1291system_meta: &mut SystemMeta,1292_component_access_set: &mut FilteredAccessSet,1293_world: &mut World,1294) {1295system_meta.set_has_deferred();1296}12971298fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {1299state.get().apply(system_meta, world);1300}13011302fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {1303state.get().queue(system_meta, world);1304}13051306#[inline]1307unsafe fn get_param<'w, 's>(1308state: &'s mut Self::State,1309_system_meta: &SystemMeta,1310_world: UnsafeWorldCell<'w>,1311_change_tick: Tick,1312) -> Self::Item<'w, 's> {1313Deferred(state.get())1314}1315}13161317/// A dummy type that is [`!Send`](Send), to force systems to run on the main thread.1318pub struct NonSendMarker(PhantomData<*mut ()>);13191320// SAFETY: No world access.1321unsafe impl SystemParam for NonSendMarker {1322type State = ();1323type Item<'w, 's> = Self;13241325#[inline]1326fn init_state(_world: &mut World) -> Self::State {}13271328fn init_access(1329_state: &Self::State,1330system_meta: &mut SystemMeta,1331_component_access_set: &mut FilteredAccessSet,1332_world: &mut World,1333) {1334system_meta.set_non_send();1335}13361337#[inline]1338unsafe fn get_param<'world, 'state>(1339_state: &'state mut Self::State,1340_system_meta: &SystemMeta,1341_world: UnsafeWorldCell<'world>,1342_change_tick: Tick,1343) -> Self::Item<'world, 'state> {1344Self(PhantomData)1345}1346}13471348// SAFETY: Does not read any world state1349unsafe impl ReadOnlySystemParam for NonSendMarker {}13501351/// Shared borrow of a non-[`Send`] resource.1352///1353/// Only `Send` resources may be accessed with the [`Res`] [`SystemParam`]. In case that the1354/// resource does not implement `Send`, this `SystemParam` wrapper can be used. This will instruct1355/// the scheduler to instead run the system on the main thread so that it doesn't send the resource1356/// over to another thread.1357///1358/// This [`SystemParam`] fails validation if non-send resource doesn't exist.1359/// This will cause a panic, but can be configured to do nothing or warn once.1360///1361/// Use [`Option<NonSend<T>>`] instead if the resource might not always exist.1362pub struct NonSend<'w, T: 'static> {1363pub(crate) value: &'w T,1364ticks: ComponentTicks,1365last_run: Tick,1366this_run: Tick,1367changed_by: MaybeLocation<&'w &'static Location<'static>>,1368}13691370// SAFETY: Only reads a single World non-send resource1371unsafe impl<'w, T> ReadOnlySystemParam for NonSend<'w, T> {}13721373impl<'w, T> Debug for NonSend<'w, T>1374where1375T: Debug,1376{1377fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {1378f.debug_tuple("NonSend").field(&self.value).finish()1379}1380}13811382impl<'w, T: 'static> NonSend<'w, T> {1383/// Returns `true` if the resource was added after the system last ran.1384pub fn is_added(&self) -> bool {1385self.ticks.is_added(self.last_run, self.this_run)1386}13871388/// Returns `true` if the resource was added or mutably dereferenced after the system last ran.1389pub fn is_changed(&self) -> bool {1390self.ticks.is_changed(self.last_run, self.this_run)1391}13921393/// The location that last caused this to change.1394pub fn changed_by(&self) -> MaybeLocation {1395self.changed_by.copied()1396}1397}13981399impl<'w, T> Deref for NonSend<'w, T> {1400type Target = T;14011402fn deref(&self) -> &Self::Target {1403self.value1404}1405}14061407impl<'a, T> From<NonSendMut<'a, T>> for NonSend<'a, T> {1408fn from(nsm: NonSendMut<'a, T>) -> Self {1409Self {1410value: nsm.value,1411ticks: ComponentTicks {1412added: nsm.ticks.added.to_owned(),1413changed: nsm.ticks.changed.to_owned(),1414},1415this_run: nsm.ticks.this_run,1416last_run: nsm.ticks.last_run,1417changed_by: nsm.changed_by.map(|changed_by| &*changed_by),1418}1419}1420}14211422// SAFETY: NonSendComponentId access is applied to SystemMeta. If this1423// NonSend conflicts with any prior access, a panic will occur.1424unsafe impl<'a, T: 'static> SystemParam for NonSend<'a, T> {1425type State = ComponentId;1426type Item<'w, 's> = NonSend<'w, T>;14271428fn init_state(world: &mut World) -> Self::State {1429world.components_registrator().register_non_send::<T>()1430}14311432fn init_access(1433&component_id: &Self::State,1434system_meta: &mut SystemMeta,1435component_access_set: &mut FilteredAccessSet,1436_world: &mut World,1437) {1438system_meta.set_non_send();14391440let combined_access = component_access_set.combined_access();1441assert!(1442!combined_access.has_resource_write(component_id),1443"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",1444DebugName::type_name::<T>(),1445system_meta.name,1446);1447component_access_set.add_unfiltered_resource_read(component_id);1448}14491450#[inline]1451unsafe fn validate_param(1452&mut component_id: &mut Self::State,1453_system_meta: &SystemMeta,1454world: UnsafeWorldCell,1455) -> Result<(), SystemParamValidationError> {1456// SAFETY: Read-only access to resource metadata.1457if unsafe { world.storages() }1458.non_send_resources1459.get(component_id)1460.is_some_and(ResourceData::is_present)1461{1462Ok(())1463} else {1464Err(SystemParamValidationError::invalid::<Self>(1465"Non-send resource does not exist",1466))1467}1468}14691470#[inline]1471unsafe fn get_param<'w, 's>(1472&mut component_id: &'s mut Self::State,1473system_meta: &SystemMeta,1474world: UnsafeWorldCell<'w>,1475change_tick: Tick,1476) -> Self::Item<'w, 's> {1477let (ptr, ticks, caller) =1478world1479.get_non_send_with_ticks(component_id)1480.unwrap_or_else(|| {1481panic!(1482"Non-send resource requested by {} does not exist: {}",1483system_meta.name,1484DebugName::type_name::<T>()1485)1486});14871488NonSend {1489value: ptr.deref(),1490ticks: ticks.read(),1491last_run: system_meta.last_run,1492this_run: change_tick,1493changed_by: caller.map(|caller| caller.deref()),1494}1495}1496}14971498// SAFETY: NonSendMut ComponentId access is applied to SystemMeta. If this1499// NonSendMut conflicts with any prior access, a panic will occur.1500unsafe impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> {1501type State = ComponentId;1502type Item<'w, 's> = NonSendMut<'w, T>;15031504fn init_state(world: &mut World) -> Self::State {1505world.components_registrator().register_non_send::<T>()1506}15071508fn init_access(1509&component_id: &Self::State,1510system_meta: &mut SystemMeta,1511component_access_set: &mut FilteredAccessSet,1512_world: &mut World,1513) {1514system_meta.set_non_send();15151516let combined_access = component_access_set.combined_access();1517if combined_access.has_component_write(component_id) {1518panic!(1519"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",1520DebugName::type_name::<T>(), system_meta.name);1521} else if combined_access.has_component_read(component_id) {1522panic!(1523"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",1524DebugName::type_name::<T>(), system_meta.name);1525}1526component_access_set.add_unfiltered_resource_write(component_id);1527}15281529#[inline]1530unsafe fn validate_param(1531&mut component_id: &mut Self::State,1532_system_meta: &SystemMeta,1533world: UnsafeWorldCell,1534) -> Result<(), SystemParamValidationError> {1535// SAFETY: Read-only access to resource metadata.1536if unsafe { world.storages() }1537.non_send_resources1538.get(component_id)1539.is_some_and(ResourceData::is_present)1540{1541Ok(())1542} else {1543Err(SystemParamValidationError::invalid::<Self>(1544"Non-send resource does not exist",1545))1546}1547}15481549#[inline]1550unsafe fn get_param<'w, 's>(1551&mut component_id: &'s mut Self::State,1552system_meta: &SystemMeta,1553world: UnsafeWorldCell<'w>,1554change_tick: Tick,1555) -> Self::Item<'w, 's> {1556let (ptr, ticks, caller) =1557world1558.get_non_send_with_ticks(component_id)1559.unwrap_or_else(|| {1560panic!(1561"Non-send resource requested by {} does not exist: {}",1562system_meta.name,1563DebugName::type_name::<T>()1564);1565});1566NonSendMut {1567value: ptr.assert_unique().deref_mut(),1568ticks: TicksMut::from_tick_cells(ticks, system_meta.last_run, change_tick),1569changed_by: caller.map(|caller| caller.deref_mut()),1570}1571}1572}15731574// SAFETY: Only reads World archetypes1575unsafe impl<'a> ReadOnlySystemParam for &'a Archetypes {}15761577// SAFETY: no component value access1578unsafe impl<'a> SystemParam for &'a Archetypes {1579type State = ();1580type Item<'w, 's> = &'w Archetypes;15811582fn init_state(_world: &mut World) -> Self::State {}15831584fn init_access(1585_state: &Self::State,1586_system_meta: &mut SystemMeta,1587_component_access_set: &mut FilteredAccessSet,1588_world: &mut World,1589) {1590}15911592#[inline]1593unsafe fn get_param<'w, 's>(1594_state: &'s mut Self::State,1595_system_meta: &SystemMeta,1596world: UnsafeWorldCell<'w>,1597_change_tick: Tick,1598) -> Self::Item<'w, 's> {1599world.archetypes()1600}1601}16021603// SAFETY: Only reads World components1604unsafe impl<'a> ReadOnlySystemParam for &'a Components {}16051606// SAFETY: no component value access1607unsafe impl<'a> SystemParam for &'a Components {1608type State = ();1609type Item<'w, 's> = &'w Components;16101611fn init_state(_world: &mut World) -> Self::State {}16121613fn init_access(1614_state: &Self::State,1615_system_meta: &mut SystemMeta,1616_component_access_set: &mut FilteredAccessSet,1617_world: &mut World,1618) {1619}16201621#[inline]1622unsafe fn get_param<'w, 's>(1623_state: &'s mut Self::State,1624_system_meta: &SystemMeta,1625world: UnsafeWorldCell<'w>,1626_change_tick: Tick,1627) -> Self::Item<'w, 's> {1628world.components()1629}1630}16311632// SAFETY: Only reads World entities1633unsafe impl<'a> ReadOnlySystemParam for &'a Entities {}16341635// SAFETY: no component value access1636unsafe impl<'a> SystemParam for &'a Entities {1637type State = ();1638type Item<'w, 's> = &'w Entities;16391640fn init_state(_world: &mut World) -> Self::State {}16411642fn init_access(1643_state: &Self::State,1644_system_meta: &mut SystemMeta,1645_component_access_set: &mut FilteredAccessSet,1646_world: &mut World,1647) {1648}16491650#[inline]1651unsafe fn get_param<'w, 's>(1652_state: &'s mut Self::State,1653_system_meta: &SystemMeta,1654world: UnsafeWorldCell<'w>,1655_change_tick: Tick,1656) -> Self::Item<'w, 's> {1657world.entities()1658}1659}16601661// SAFETY: Only reads World bundles1662unsafe impl<'a> ReadOnlySystemParam for &'a Bundles {}16631664// SAFETY: no component value access1665unsafe impl<'a> SystemParam for &'a Bundles {1666type State = ();1667type Item<'w, 's> = &'w Bundles;16681669fn init_state(_world: &mut World) -> Self::State {}16701671fn init_access(1672_state: &Self::State,1673_system_meta: &mut SystemMeta,1674_component_access_set: &mut FilteredAccessSet,1675_world: &mut World,1676) {1677}16781679#[inline]1680unsafe fn get_param<'w, 's>(1681_state: &'s mut Self::State,1682_system_meta: &SystemMeta,1683world: UnsafeWorldCell<'w>,1684_change_tick: Tick,1685) -> Self::Item<'w, 's> {1686world.bundles()1687}1688}16891690/// A [`SystemParam`] that reads the previous and current change ticks of the system.1691///1692/// A system's change ticks are updated each time it runs:1693/// - `last_run` copies the previous value of `change_tick`1694/// - `this_run` copies the current value of [`World::read_change_tick`]1695///1696/// Component change ticks that are more recent than `last_run` will be detected by the system.1697/// Those can be read by calling [`last_changed`](crate::change_detection::DetectChanges::last_changed)1698/// on a [`Mut<T>`](crate::change_detection::Mut) or [`ResMut<T>`](ResMut).1699#[derive(Debug, Clone, Copy)]1700pub struct SystemChangeTick {1701last_run: Tick,1702this_run: Tick,1703}17041705impl SystemChangeTick {1706/// Returns the current [`World`] change tick seen by the system.1707#[inline]1708pub fn this_run(&self) -> Tick {1709self.this_run1710}17111712/// Returns the [`World`] change tick seen by the system the previous time it ran.1713#[inline]1714pub fn last_run(&self) -> Tick {1715self.last_run1716}1717}17181719// SAFETY: Only reads internal system state1720unsafe impl ReadOnlySystemParam for SystemChangeTick {}17211722// SAFETY: `SystemChangeTick` doesn't require any world access1723unsafe impl SystemParam for SystemChangeTick {1724type State = ();1725type Item<'w, 's> = SystemChangeTick;17261727fn init_state(_world: &mut World) -> Self::State {}17281729fn init_access(1730_state: &Self::State,1731_system_meta: &mut SystemMeta,1732_component_access_set: &mut FilteredAccessSet,1733_world: &mut World,1734) {1735}17361737#[inline]1738unsafe fn get_param<'w, 's>(1739_state: &'s mut Self::State,1740system_meta: &SystemMeta,1741_world: UnsafeWorldCell<'w>,1742change_tick: Tick,1743) -> Self::Item<'w, 's> {1744SystemChangeTick {1745last_run: system_meta.last_run,1746this_run: change_tick,1747}1748}1749}17501751// SAFETY: Delegates to `T`, which ensures the safety requirements are met1752unsafe impl<T: SystemParam> SystemParam for Option<T> {1753type State = T::State;17541755type Item<'world, 'state> = Option<T::Item<'world, 'state>>;17561757fn init_state(world: &mut World) -> Self::State {1758T::init_state(world)1759}17601761fn init_access(1762state: &Self::State,1763system_meta: &mut SystemMeta,1764component_access_set: &mut FilteredAccessSet,1765world: &mut World,1766) {1767T::init_access(state, system_meta, component_access_set, world);1768}17691770#[inline]1771unsafe fn get_param<'world, 'state>(1772state: &'state mut Self::State,1773system_meta: &SystemMeta,1774world: UnsafeWorldCell<'world>,1775change_tick: Tick,1776) -> Self::Item<'world, 'state> {1777T::validate_param(state, system_meta, world)1778.ok()1779.map(|()| T::get_param(state, system_meta, world, change_tick))1780}17811782fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {1783T::apply(state, system_meta, world);1784}17851786fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {1787T::queue(state, system_meta, world);1788}1789}17901791// SAFETY: Delegates to `T`, which ensures the safety requirements are met1792unsafe impl<T: ReadOnlySystemParam> ReadOnlySystemParam for Option<T> {}17931794// SAFETY: Delegates to `T`, which ensures the safety requirements are met1795unsafe impl<T: SystemParam> SystemParam for Result<T, SystemParamValidationError> {1796type State = T::State;17971798type Item<'world, 'state> = Result<T::Item<'world, 'state>, SystemParamValidationError>;17991800fn init_state(world: &mut World) -> Self::State {1801T::init_state(world)1802}18031804fn init_access(1805state: &Self::State,1806system_meta: &mut SystemMeta,1807component_access_set: &mut FilteredAccessSet,1808world: &mut World,1809) {1810T::init_access(state, system_meta, component_access_set, world);1811}18121813#[inline]1814unsafe fn get_param<'world, 'state>(1815state: &'state mut Self::State,1816system_meta: &SystemMeta,1817world: UnsafeWorldCell<'world>,1818change_tick: Tick,1819) -> Self::Item<'world, 'state> {1820T::validate_param(state, system_meta, world)1821.map(|()| T::get_param(state, system_meta, world, change_tick))1822}18231824fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {1825T::apply(state, system_meta, world);1826}18271828fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {1829T::queue(state, system_meta, world);1830}1831}18321833// SAFETY: Delegates to `T`, which ensures the safety requirements are met1834unsafe impl<T: ReadOnlySystemParam> ReadOnlySystemParam for Result<T, SystemParamValidationError> {}18351836/// A [`SystemParam`] that wraps another parameter and causes its system to skip instead of failing when the parameter is invalid.1837///1838/// # Example1839///1840/// ```1841/// # use bevy_ecs::prelude::*;1842/// # #[derive(Resource)]1843/// # struct SomeResource;1844/// // This system will fail if `SomeResource` is not present.1845/// fn fails_on_missing_resource(res: Res<SomeResource>) {}1846///1847/// // This system will skip without error if `SomeResource` is not present.1848/// fn skips_on_missing_resource(res: If<Res<SomeResource>>) {1849/// // The inner parameter is available using `Deref`1850/// let some_resource: &SomeResource = &res;1851/// }1852/// # bevy_ecs::system::assert_is_system(skips_on_missing_resource);1853/// ```1854#[derive(Debug)]1855pub struct If<T>(pub T);18561857impl<T> If<T> {1858/// Returns the inner `T`.1859///1860/// The inner value is `pub`, so you can also obtain it by destructuring the parameter:1861///1862/// ```1863/// # use bevy_ecs::prelude::*;1864/// # #[derive(Resource)]1865/// # struct SomeResource;1866/// fn skips_on_missing_resource(If(res): If<Res<SomeResource>>) {1867/// let some_resource: Res<SomeResource> = res;1868/// }1869/// # bevy_ecs::system::assert_is_system(skips_on_missing_resource);1870/// ```1871pub fn into_inner(self) -> T {1872self.01873}1874}18751876impl<T> Deref for If<T> {1877type Target = T;1878fn deref(&self) -> &Self::Target {1879&self.01880}1881}18821883impl<T> DerefMut for If<T> {1884fn deref_mut(&mut self) -> &mut Self::Target {1885&mut self.01886}1887}18881889// SAFETY: Delegates to `T`, which ensures the safety requirements are met1890unsafe impl<T: SystemParam> SystemParam for If<T> {1891type State = T::State;18921893type Item<'world, 'state> = If<T::Item<'world, 'state>>;18941895fn init_state(world: &mut World) -> Self::State {1896T::init_state(world)1897}18981899fn init_access(1900state: &Self::State,1901system_meta: &mut SystemMeta,1902component_access_set: &mut FilteredAccessSet,1903world: &mut World,1904) {1905T::init_access(state, system_meta, component_access_set, world);1906}19071908#[inline]1909unsafe fn validate_param(1910state: &mut Self::State,1911system_meta: &SystemMeta,1912world: UnsafeWorldCell,1913) -> Result<(), SystemParamValidationError> {1914T::validate_param(state, system_meta, world).map_err(|mut e| {1915e.skipped = true;1916e1917})1918}19191920#[inline]1921unsafe fn get_param<'world, 'state>(1922state: &'state mut Self::State,1923system_meta: &SystemMeta,1924world: UnsafeWorldCell<'world>,1925change_tick: Tick,1926) -> Self::Item<'world, 'state> {1927If(T::get_param(state, system_meta, world, change_tick))1928}19291930fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {1931T::apply(state, system_meta, world);1932}19331934fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {1935T::queue(state, system_meta, world);1936}1937}19381939// SAFETY: Delegates to `T`, which ensures the safety requirements are met1940unsafe impl<T: ReadOnlySystemParam> ReadOnlySystemParam for If<T> {}19411942// SAFETY: Registers access for each element of `state`.1943// If any one conflicts, it will panic.1944unsafe impl<T: SystemParam> SystemParam for Vec<T> {1945type State = Vec<T::State>;19461947type Item<'world, 'state> = Vec<T::Item<'world, 'state>>;19481949fn init_state(_world: &mut World) -> Self::State {1950Vec::new()1951}19521953fn init_access(1954state: &Self::State,1955system_meta: &mut SystemMeta,1956component_access_set: &mut FilteredAccessSet,1957world: &mut World,1958) {1959for state in state {1960T::init_access(state, system_meta, component_access_set, world);1961}1962}19631964#[inline]1965unsafe fn validate_param(1966state: &mut Self::State,1967system_meta: &SystemMeta,1968world: UnsafeWorldCell,1969) -> Result<(), SystemParamValidationError> {1970for state in state {1971T::validate_param(state, system_meta, world)?;1972}1973Ok(())1974}19751976#[inline]1977unsafe fn get_param<'world, 'state>(1978state: &'state mut Self::State,1979system_meta: &SystemMeta,1980world: UnsafeWorldCell<'world>,1981change_tick: Tick,1982) -> Self::Item<'world, 'state> {1983state1984.iter_mut()1985// SAFETY:1986// - 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.1987// - The caller ensures this was the world used to initialize our state, and we used that world to initialize parameter states1988.map(|state| unsafe { T::get_param(state, system_meta, world, change_tick) })1989.collect()1990}19911992fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {1993for state in state {1994T::apply(state, system_meta, world);1995}1996}19971998fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {1999for state in state {2000T::queue(state, system_meta, world.reborrow());2001}2002}2003}20042005// SAFETY: Registers access for each element of `state`.2006// If any one conflicts with a previous parameter,2007// the call passing a copy of the current access will panic.2008unsafe impl<T: SystemParam> SystemParam for ParamSet<'_, '_, Vec<T>> {2009type State = Vec<T::State>;20102011type Item<'world, 'state> = ParamSet<'world, 'state, Vec<T>>;20122013fn init_state(_world: &mut World) -> Self::State {2014Vec::new()2015}20162017fn init_access(2018state: &Self::State,2019system_meta: &mut SystemMeta,2020component_access_set: &mut FilteredAccessSet,2021world: &mut World,2022) {2023for state in state {2024// Call `init_access` on a clone of the original access set to check for conflicts2025let component_access_set_clone = &mut component_access_set.clone();2026T::init_access(state, system_meta, component_access_set_clone, world);2027}2028for state in state {2029// Pretend to add the param to the system alone to gather the new access,2030// then merge its access into the system.2031let mut access_set = FilteredAccessSet::new();2032T::init_access(state, system_meta, &mut access_set, world);2033component_access_set.extend(access_set);2034}2035}20362037#[inline]2038unsafe fn get_param<'world, 'state>(2039state: &'state mut Self::State,2040system_meta: &SystemMeta,2041world: UnsafeWorldCell<'world>,2042change_tick: Tick,2043) -> Self::Item<'world, 'state> {2044ParamSet {2045param_states: state,2046system_meta: system_meta.clone(),2047world,2048change_tick,2049}2050}20512052fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {2053for state in state {2054T::apply(state, system_meta, world);2055}2056}20572058fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {2059for state in state {2060T::queue(state, system_meta, world.reborrow());2061}2062}2063}20642065impl<T: SystemParam> ParamSet<'_, '_, Vec<T>> {2066/// Accesses the parameter at the given index.2067/// No other parameters may be accessed while this one is active.2068pub fn get_mut(&mut self, index: usize) -> T::Item<'_, '_> {2069// SAFETY:2070// - We initialized the access for each parameter, so the caller ensures we have access to any world data needed by any param.2071// We have mutable access to the ParamSet, so no other params in the set are active.2072// - The caller of `get_param` ensured that this was the world used to initialize our state, and we used that world to initialize parameter states2073unsafe {2074T::get_param(2075&mut self.param_states[index],2076&self.system_meta,2077self.world,2078self.change_tick,2079)2080}2081}20822083/// Calls a closure for each parameter in the set.2084pub fn for_each(&mut self, mut f: impl FnMut(T::Item<'_, '_>)) {2085self.param_states.iter_mut().for_each(|state| {2086f(2087// SAFETY:2088// - We initialized the access for each parameter, so the caller ensures we have access to any world data needed by any param.2089// We have mutable access to the ParamSet, so no other params in the set are active.2090// - The caller of `get_param` ensured that this was the world used to initialize our state, and we used that world to initialize parameter states2091unsafe { T::get_param(state, &self.system_meta, self.world, self.change_tick) },2092);2093});2094}2095}20962097macro_rules! impl_system_param_tuple {2098($(#[$meta:meta])* $($param: ident),*) => {2099$(#[$meta])*2100// SAFETY: tuple consists only of ReadOnlySystemParams2101unsafe impl<$($param: ReadOnlySystemParam),*> ReadOnlySystemParam for ($($param,)*) {}21022103#[expect(2104clippy::allow_attributes,2105reason = "This is in a macro, and as such, the below lints may not always apply."2106)]2107#[allow(2108non_snake_case,2109reason = "Certain variable names are provided by the caller, not by us."2110)]2111#[allow(2112unused_variables,2113reason = "Zero-length tuples won't use some of the parameters."2114)]2115$(#[$meta])*2116// SAFETY: implementers of each `SystemParam` in the tuple have validated their impls2117unsafe impl<$($param: SystemParam),*> SystemParam for ($($param,)*) {2118type State = ($($param::State,)*);2119type Item<'w, 's> = ($($param::Item::<'w, 's>,)*);21202121#[inline]2122fn init_state(world: &mut World) -> Self::State {2123(($($param::init_state(world),)*))2124}21252126fn init_access(state: &Self::State, _system_meta: &mut SystemMeta, _component_access_set: &mut FilteredAccessSet, _world: &mut World) {2127let ($($param,)*) = state;2128$($param::init_access($param, _system_meta, _component_access_set, _world);)*2129}21302131#[inline]2132fn apply(($($param,)*): &mut Self::State, system_meta: &SystemMeta, world: &mut World) {2133$($param::apply($param, system_meta, world);)*2134}21352136#[inline]2137#[allow(2138unused_mut,2139reason = "The `world` parameter is unused for zero-length tuples; however, it must be mutable for other lengths of tuples."2140)]2141fn queue(($($param,)*): &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {2142$($param::queue($param, system_meta, world.reborrow());)*2143}21442145#[inline]2146unsafe fn validate_param(2147state: &mut Self::State,2148system_meta: &SystemMeta,2149world: UnsafeWorldCell,2150) -> Result<(), SystemParamValidationError> {2151let ($($param,)*) = state;2152$(2153$param::validate_param($param, system_meta, world)?;2154)*2155Ok(())2156}21572158#[inline]2159unsafe fn get_param<'w, 's>(2160state: &'s mut Self::State,2161system_meta: &SystemMeta,2162world: UnsafeWorldCell<'w>,2163change_tick: Tick,2164) -> Self::Item<'w, 's> {2165let ($($param,)*) = state;2166#[allow(2167clippy::unused_unit,2168reason = "Zero-length tuples won't have any params to get."2169)]2170($($param::get_param($param, system_meta, world, change_tick),)*)2171}2172}2173};2174}21752176all_tuples!(2177#[doc(fake_variadic)]2178impl_system_param_tuple,21790,218016,2181P2182);21832184/// Contains type aliases for built-in [`SystemParam`]s with `'static` lifetimes.2185/// This makes it more convenient to refer to these types in contexts where2186/// explicit lifetime annotations are required.2187///2188/// Note that this is entirely safe and tracks lifetimes correctly.2189/// This purely exists for convenience.2190///2191/// You can't instantiate a static `SystemParam`, you'll always end up with2192/// `Res<'w, T>`, `ResMut<'w, T>` or `&'w T` bound to the lifetime of the provided2193/// `&'w World`.2194///2195/// [`SystemParam`]: super::SystemParam2196pub mod lifetimeless {2197/// A [`Query`](super::Query) with `'static` lifetimes.2198pub type SQuery<D, F = ()> = super::Query<'static, 'static, D, F>;2199/// A shorthand for writing `&'static T`.2200pub type Read<T> = &'static T;2201/// A shorthand for writing `&'static mut T`.2202pub type Write<T> = &'static mut T;2203/// A [`Res`](super::Res) with `'static` lifetimes.2204pub type SRes<T> = super::Res<'static, T>;2205/// A [`ResMut`](super::ResMut) with `'static` lifetimes.2206pub type SResMut<T> = super::ResMut<'static, T>;2207/// [`Commands`](crate::system::Commands) with `'static` lifetimes.2208pub type SCommands = crate::system::Commands<'static, 'static>;2209}22102211/// A helper for using system parameters in generic contexts2212///2213/// This type is a [`SystemParam`] adapter which always has2214/// `Self::Item == Self` (ignoring lifetimes for brevity),2215/// no matter the argument [`SystemParam`] (`P`) (other than2216/// that `P` must be `'static`)2217///2218/// This makes it useful for having arbitrary [`SystemParam`] type arguments2219/// to function systems, or for generic types using the [`derive@SystemParam`]2220/// derive:2221///2222/// ```2223/// # use bevy_ecs::prelude::*;2224/// use bevy_ecs::system::{SystemParam, StaticSystemParam};2225/// #[derive(SystemParam)]2226/// struct GenericParam<'w,'s, T: SystemParam + 'static> {2227/// field: StaticSystemParam<'w, 's, T>,2228/// }2229/// fn do_thing_generically<T: SystemParam + 'static>(t: StaticSystemParam<T>) {}2230///2231/// fn check_always_is_system<T: SystemParam + 'static>(){2232/// bevy_ecs::system::assert_is_system(do_thing_generically::<T>);2233/// }2234/// ```2235/// Note that in a real case you'd generally want2236/// additional bounds on `P`, for your use of the parameter2237/// to have a reason to be generic.2238///2239/// For example, using this would allow a type to be generic over2240/// whether a resource is accessed mutably or not, with2241/// impls being bounded on [`P: Deref<Target=MyType>`](Deref), and2242/// [`P: DerefMut<Target=MyType>`](DerefMut) depending on whether the2243/// method requires mutable access or not.2244///2245/// The method which doesn't use this type will not compile:2246/// ```compile_fail2247/// # use bevy_ecs::prelude::*;2248/// # use bevy_ecs::system::{SystemParam, StaticSystemParam};2249///2250/// fn do_thing_generically<T: SystemParam + 'static>(t: T) {}2251///2252/// #[derive(SystemParam)]2253/// struct GenericParam<'w, 's, T: SystemParam> {2254/// field: T,2255/// // Use the lifetimes in this type, or they will be unbound.2256/// phantom: std::marker::PhantomData<&'w &'s ()>2257/// }2258/// # fn check_always_is_system<T: SystemParam + 'static>(){2259/// # bevy_ecs::system::assert_is_system(do_thing_generically::<T>);2260/// # }2261/// ```2262pub struct StaticSystemParam<'w, 's, P: SystemParam>(SystemParamItem<'w, 's, P>);22632264impl<'w, 's, P: SystemParam> Deref for StaticSystemParam<'w, 's, P> {2265type Target = SystemParamItem<'w, 's, P>;22662267fn deref(&self) -> &Self::Target {2268&self.02269}2270}22712272impl<'w, 's, P: SystemParam> DerefMut for StaticSystemParam<'w, 's, P> {2273fn deref_mut(&mut self) -> &mut Self::Target {2274&mut self.02275}2276}22772278impl<'w, 's, P: SystemParam> StaticSystemParam<'w, 's, P> {2279/// Get the value of the parameter2280pub fn into_inner(self) -> SystemParamItem<'w, 's, P> {2281self.02282}2283}22842285// SAFETY: This doesn't add any more reads, and the delegated fetch confirms it2286unsafe impl<'w, 's, P: ReadOnlySystemParam + 'static> ReadOnlySystemParam2287for StaticSystemParam<'w, 's, P>2288{2289}22902291// SAFETY: all methods are just delegated to `P`'s `SystemParam` implementation2292unsafe impl<P: SystemParam + 'static> SystemParam for StaticSystemParam<'_, '_, P> {2293type State = P::State;2294type Item<'world, 'state> = StaticSystemParam<'world, 'state, P>;22952296fn init_state(world: &mut World) -> Self::State {2297P::init_state(world)2298}22992300fn init_access(2301state: &Self::State,2302system_meta: &mut SystemMeta,2303component_access_set: &mut FilteredAccessSet,2304world: &mut World,2305) {2306P::init_access(state, system_meta, component_access_set, world);2307}23082309fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {2310P::apply(state, system_meta, world);2311}23122313fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {2314P::queue(state, system_meta, world);2315}23162317#[inline]2318unsafe fn validate_param(2319state: &mut Self::State,2320system_meta: &SystemMeta,2321world: UnsafeWorldCell,2322) -> Result<(), SystemParamValidationError> {2323P::validate_param(state, system_meta, world)2324}23252326#[inline]2327unsafe fn get_param<'world, 'state>(2328state: &'state mut Self::State,2329system_meta: &SystemMeta,2330world: UnsafeWorldCell<'world>,2331change_tick: Tick,2332) -> Self::Item<'world, 'state> {2333// SAFETY: Defer to the safety of P::SystemParam2334StaticSystemParam(unsafe { P::get_param(state, system_meta, world, change_tick) })2335}2336}23372338// SAFETY: No world access.2339unsafe impl<T: ?Sized> SystemParam for PhantomData<T> {2340type State = ();2341type Item<'world, 'state> = Self;23422343fn init_state(_world: &mut World) -> Self::State {}23442345fn init_access(2346_state: &Self::State,2347_system_meta: &mut SystemMeta,2348_component_access_set: &mut FilteredAccessSet,2349_world: &mut World,2350) {2351}23522353#[inline]2354unsafe fn get_param<'world, 'state>(2355_state: &'state mut Self::State,2356_system_meta: &SystemMeta,2357_world: UnsafeWorldCell<'world>,2358_change_tick: Tick,2359) -> Self::Item<'world, 'state> {2360PhantomData2361}2362}23632364// SAFETY: No world access.2365unsafe impl<T: ?Sized> ReadOnlySystemParam for PhantomData<T> {}23662367/// A [`SystemParam`] with a type that can be configured at runtime.2368///2369/// To be useful, this must be configured using a [`DynParamBuilder`](crate::system::DynParamBuilder) to build the system using a [`SystemParamBuilder`](crate::prelude::SystemParamBuilder).2370///2371/// # Examples2372///2373/// ```2374/// # use bevy_ecs::{prelude::*, system::*};2375/// #2376/// # #[derive(Default, Resource)]2377/// # struct A;2378/// #2379/// # #[derive(Default, Resource)]2380/// # struct B;2381/// #2382/// # let mut world = World::new();2383/// # world.init_resource::<A>();2384/// # world.init_resource::<B>();2385/// #2386/// // If the inner parameter doesn't require any special building, use `ParamBuilder`.2387/// // Either specify the type parameter on `DynParamBuilder::new()` ...2388/// let system = (DynParamBuilder::new::<Res<A>>(ParamBuilder),)2389/// .build_state(&mut world)2390/// .build_system(expects_res_a);2391/// # world.run_system_once(system);2392///2393/// // ... or use a factory method on `ParamBuilder` that returns a specific type.2394/// let system = (DynParamBuilder::new(ParamBuilder::resource::<A>()),)2395/// .build_state(&mut world)2396/// .build_system(expects_res_a);2397/// # world.run_system_once(system);2398///2399/// fn expects_res_a(mut param: DynSystemParam) {2400/// // Use the `downcast` methods to retrieve the inner parameter.2401/// // They will return `None` if the type does not match.2402/// assert!(param.is::<Res<A>>());2403/// assert!(!param.is::<Res<B>>());2404/// assert!(param.downcast_mut::<Res<B>>().is_none());2405/// let res = param.downcast_mut::<Res<A>>().unwrap();2406/// // The type parameter can be left out if it can be determined from use.2407/// let res: Res<A> = param.downcast().unwrap();2408/// }2409///2410/// let system = (2411/// // If the inner parameter also requires building,2412/// // pass the appropriate `SystemParamBuilder`.2413/// DynParamBuilder::new(LocalBuilder(10usize)),2414/// // `DynSystemParam` is just an ordinary `SystemParam`,2415/// // and can be combined with other parameters as usual!2416/// ParamBuilder::query(),2417/// )2418/// .build_state(&mut world)2419/// .build_system(|param: DynSystemParam, query: Query<()>| {2420/// let local: Local<usize> = param.downcast::<Local<usize>>().unwrap();2421/// assert_eq!(*local, 10);2422/// });2423/// # world.run_system_once(system);2424/// ```2425pub struct DynSystemParam<'w, 's> {2426/// A `ParamState<T>` wrapping the state for the underlying system param.2427state: &'s mut dyn Any,2428world: UnsafeWorldCell<'w>,2429system_meta: SystemMeta,2430change_tick: Tick,2431}24322433impl<'w, 's> DynSystemParam<'w, 's> {2434/// # Safety2435/// - `state` must be a `ParamState<T>` for some inner `T: SystemParam`.2436/// - The passed [`UnsafeWorldCell`] must have access to any world data registered2437/// in [`init_state`](SystemParam::init_state) for the inner system param.2438/// - `world` must be the same `World` that was used to initialize2439/// [`state`](SystemParam::init_state) for the inner system param.2440unsafe fn new(2441state: &'s mut dyn Any,2442world: UnsafeWorldCell<'w>,2443system_meta: SystemMeta,2444change_tick: Tick,2445) -> Self {2446Self {2447state,2448world,2449system_meta,2450change_tick,2451}2452}24532454/// Returns `true` if the inner system param is the same as `T`.2455pub fn is<T: SystemParam>(&self) -> bool2456// See downcast() function for an explanation of the where clause2457where2458T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,2459{2460self.state.is::<ParamState<T::Item<'static, 'static>>>()2461}24622463/// Returns the inner system param if it is the correct type.2464/// This consumes the dyn param, so the returned param can have its original world and state lifetimes.2465pub fn downcast<T: SystemParam>(self) -> Option<T>2466// See downcast() function for an explanation of the where clause2467where2468T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,2469{2470// SAFETY:2471// - `DynSystemParam::new()` ensures `state` is a `ParamState<T>`, that the world matches,2472// and that it has access required by the inner system param.2473// - This consumes the `DynSystemParam`, so it is the only use of `world` with this access and it is available for `'w`.2474unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }2475}24762477/// Returns the inner system parameter if it is the correct type.2478/// This borrows the dyn param, so the returned param is only valid for the duration of that borrow.2479pub fn downcast_mut<'a, T: SystemParam>(&'a mut self) -> Option<T>2480// See downcast() function for an explanation of the where clause2481where2482T::Item<'static, 'static>: SystemParam<Item<'a, 'a> = T> + 'static,2483{2484// SAFETY:2485// - `DynSystemParam::new()` ensures `state` is a `ParamState<T>`, that the world matches,2486// and that it has access required by the inner system param.2487// - This exclusively borrows the `DynSystemParam` for `'_`, so it is the only use of `world` with this access for `'_`.2488unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }2489}24902491/// Returns the inner system parameter if it is the correct type.2492/// This borrows the dyn param, so the returned param is only valid for the duration of that borrow,2493/// but since it only performs read access it can keep the original world lifetime.2494/// This can be useful with methods like [`Query::iter_inner()`] or [`Res::into_inner()`]2495/// to obtain references with the original world lifetime.2496pub fn downcast_mut_inner<'a, T: ReadOnlySystemParam>(&'a mut self) -> Option<T>2497// See downcast() function for an explanation of the where clause2498where2499T::Item<'static, 'static>: SystemParam<Item<'w, 'a> = T> + 'static,2500{2501// SAFETY:2502// - `DynSystemParam::new()` ensures `state` is a `ParamState<T>`, that the world matches,2503// and that it has access required by the inner system param.2504// - The inner system param only performs read access, so it's safe to copy that access for the full `'w` lifetime.2505unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }2506}2507}25082509/// # Safety2510/// - `state` must be a `ParamState<T>` for some inner `T: SystemParam`.2511/// - The passed [`UnsafeWorldCell`] must have access to any world data registered2512/// in [`init_state`](SystemParam::init_state) for the inner system param.2513/// - `world` must be the same `World` that was used to initialize2514/// [`state`](SystemParam::init_state) for the inner system param.2515unsafe fn downcast<'w, 's, T: SystemParam>(2516state: &'s mut dyn Any,2517system_meta: &SystemMeta,2518world: UnsafeWorldCell<'w>,2519change_tick: Tick,2520) -> Option<T>2521// We need a 'static version of the SystemParam to use with `Any::downcast_mut()`,2522// and we need a <'w, 's> version to actually return.2523// The type parameter T must be the one we return in order to get type inference from the return value.2524// So we use `T::Item<'static, 'static>` as the 'static version, and require that it be 'static.2525// That means the return value will be T::Item<'static, 'static>::Item<'w, 's>,2526// so we constrain that to be equal to T.2527// Every actual `SystemParam` implementation has `T::Item == T` up to lifetimes,2528// so they should all work with this constraint.2529where2530T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,2531{2532state2533.downcast_mut::<ParamState<T::Item<'static, 'static>>>()2534.map(|state| {2535// SAFETY:2536// - The caller ensures the world has access for the underlying system param,2537// and since the downcast succeeded, the underlying system param is T.2538// - The caller ensures the `world` matches.2539unsafe { T::Item::get_param(&mut state.0, system_meta, world, change_tick) }2540})2541}25422543/// The [`SystemParam::State`] for a [`DynSystemParam`].2544pub struct DynSystemParamState(Box<dyn DynParamState>);25452546impl DynSystemParamState {2547pub(crate) fn new<T: SystemParam + 'static>(state: T::State) -> Self {2548Self(Box::new(ParamState::<T>(state)))2549}2550}25512552/// Allows a [`SystemParam::State`] to be used as a trait object for implementing [`DynSystemParam`].2553trait DynParamState: Sync + Send + Any {2554/// Applies any deferred mutations stored in this [`SystemParam`]'s state.2555/// This is used to apply [`Commands`] during [`ApplyDeferred`](crate::prelude::ApplyDeferred).2556///2557/// [`Commands`]: crate::prelude::Commands2558fn apply(&mut self, system_meta: &SystemMeta, world: &mut World);25592560/// Queues any deferred mutations to be applied at the next [`ApplyDeferred`](crate::prelude::ApplyDeferred).2561fn queue(&mut self, system_meta: &SystemMeta, world: DeferredWorld);25622563/// Registers any [`World`] access used by this [`SystemParam`]2564fn init_access(2565&self,2566system_meta: &mut SystemMeta,2567component_access_set: &mut FilteredAccessSet,2568world: &mut World,2569);25702571/// Refer to [`SystemParam::validate_param`].2572///2573/// # Safety2574/// Refer to [`SystemParam::validate_param`].2575unsafe fn validate_param(2576&mut self,2577system_meta: &SystemMeta,2578world: UnsafeWorldCell,2579) -> Result<(), SystemParamValidationError>;2580}25812582/// A wrapper around a [`SystemParam::State`] that can be used as a trait object in a [`DynSystemParam`].2583struct ParamState<T: SystemParam>(T::State);25842585impl<T: SystemParam + 'static> DynParamState for ParamState<T> {2586fn apply(&mut self, system_meta: &SystemMeta, world: &mut World) {2587T::apply(&mut self.0, system_meta, world);2588}25892590fn queue(&mut self, system_meta: &SystemMeta, world: DeferredWorld) {2591T::queue(&mut self.0, system_meta, world);2592}25932594fn init_access(2595&self,2596system_meta: &mut SystemMeta,2597component_access_set: &mut FilteredAccessSet,2598world: &mut World,2599) {2600T::init_access(&self.0, system_meta, component_access_set, world);2601}26022603unsafe fn validate_param(2604&mut self,2605system_meta: &SystemMeta,2606world: UnsafeWorldCell,2607) -> Result<(), SystemParamValidationError> {2608T::validate_param(&mut self.0, system_meta, world)2609}2610}26112612// SAFETY: Delegates to the wrapped parameter, which ensures the safety requirements are met2613unsafe impl SystemParam for DynSystemParam<'_, '_> {2614type State = DynSystemParamState;26152616type Item<'world, 'state> = DynSystemParam<'world, 'state>;26172618fn init_state(_world: &mut World) -> Self::State {2619DynSystemParamState::new::<()>(())2620}26212622fn init_access(2623state: &Self::State,2624system_meta: &mut SystemMeta,2625component_access_set: &mut FilteredAccessSet,2626world: &mut World,2627) {2628state2629.02630.init_access(system_meta, component_access_set, world);2631}26322633#[inline]2634unsafe fn validate_param(2635state: &mut Self::State,2636system_meta: &SystemMeta,2637world: UnsafeWorldCell,2638) -> Result<(), SystemParamValidationError> {2639state.0.validate_param(system_meta, world)2640}26412642#[inline]2643unsafe fn get_param<'world, 'state>(2644state: &'state mut Self::State,2645system_meta: &SystemMeta,2646world: UnsafeWorldCell<'world>,2647change_tick: Tick,2648) -> Self::Item<'world, 'state> {2649// SAFETY:2650// - `state.0` is a boxed `ParamState<T>`.2651// - `init_access` calls `DynParamState::init_access`, which calls `init_access` on the inner parameter,2652// so the caller ensures the world has the necessary access.2653// - The caller ensures that the provided world is the same and has the required access.2654unsafe { DynSystemParam::new(state.0.as_mut(), world, system_meta.clone(), change_tick) }2655}26562657fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {2658state.0.apply(system_meta, world);2659}26602661fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {2662state.0.queue(system_meta, world);2663}2664}26652666// SAFETY: Resource ComponentId access is applied to the access. If this FilteredResources2667// conflicts with any prior access, a panic will occur.2668unsafe impl SystemParam for FilteredResources<'_, '_> {2669type State = Access;26702671type Item<'world, 'state> = FilteredResources<'world, 'state>;26722673fn init_state(_world: &mut World) -> Self::State {2674Access::new()2675}26762677fn init_access(2678access: &Self::State,2679system_meta: &mut SystemMeta,2680component_access_set: &mut FilteredAccessSet,2681world: &mut World,2682) {2683let combined_access = component_access_set.combined_access();2684let conflicts = combined_access.get_conflicts(access);2685if !conflicts.is_empty() {2686let accesses = conflicts.format_conflict_list(world);2687let system_name = &system_meta.name;2688panic!("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");2689}26902691if access.has_read_all_resources() {2692component_access_set.add_unfiltered_read_all_resources();2693} else {2694for component_id in access.resource_reads_and_writes() {2695component_access_set.add_unfiltered_resource_read(component_id);2696}2697}2698}26992700unsafe fn get_param<'world, 'state>(2701state: &'state mut Self::State,2702system_meta: &SystemMeta,2703world: UnsafeWorldCell<'world>,2704change_tick: Tick,2705) -> Self::Item<'world, 'state> {2706// SAFETY: The caller ensures that `world` has access to anything registered in `init_access`,2707// and we registered all resource access in `state``.2708unsafe { FilteredResources::new(world, state, system_meta.last_run, change_tick) }2709}2710}27112712// SAFETY: FilteredResources only reads resources.2713unsafe impl ReadOnlySystemParam for FilteredResources<'_, '_> {}27142715// SAFETY: Resource ComponentId access is applied to the access. If this FilteredResourcesMut2716// conflicts with any prior access, a panic will occur.2717unsafe impl SystemParam for FilteredResourcesMut<'_, '_> {2718type State = Access;27192720type Item<'world, 'state> = FilteredResourcesMut<'world, 'state>;27212722fn init_state(_world: &mut World) -> Self::State {2723Access::new()2724}27252726fn init_access(2727access: &Self::State,2728system_meta: &mut SystemMeta,2729component_access_set: &mut FilteredAccessSet,2730world: &mut World,2731) {2732let combined_access = component_access_set.combined_access();2733let conflicts = combined_access.get_conflicts(access);2734if !conflicts.is_empty() {2735let accesses = conflicts.format_conflict_list(world);2736let system_name = &system_meta.name;2737panic!("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");2738}27392740if access.has_read_all_resources() {2741component_access_set.add_unfiltered_read_all_resources();2742} else {2743for component_id in access.resource_reads() {2744component_access_set.add_unfiltered_resource_read(component_id);2745}2746}27472748if access.has_write_all_resources() {2749component_access_set.add_unfiltered_write_all_resources();2750} else {2751for component_id in access.resource_writes() {2752component_access_set.add_unfiltered_resource_write(component_id);2753}2754}2755}27562757unsafe fn get_param<'world, 'state>(2758state: &'state mut Self::State,2759system_meta: &SystemMeta,2760world: UnsafeWorldCell<'world>,2761change_tick: Tick,2762) -> Self::Item<'world, 'state> {2763// SAFETY: The caller ensures that `world` has access to anything registered in `init_access`,2764// and we registered all resource access in `state``.2765unsafe { FilteredResourcesMut::new(world, state, system_meta.last_run, change_tick) }2766}2767}27682769/// An error that occurs when a system parameter is not valid,2770/// used by system executors to determine what to do with a system.2771///2772/// Returned as an error from [`SystemParam::validate_param`],2773/// and handled using the unified error handling mechanisms defined in [`bevy_ecs::error`].2774#[derive(Debug, PartialEq, Eq, Clone, Error)]2775pub struct SystemParamValidationError {2776/// Whether the system should be skipped.2777///2778/// If `false`, the error should be handled.2779/// By default, this will result in a panic. See [`crate::error`] for more information.2780///2781/// This is the default behavior, and is suitable for system params that should *always* be valid,2782/// either because sensible fallback behavior exists (like [`Query`]) or because2783/// failures in validation should be considered a bug in the user's logic that must be immediately addressed (like [`Res`]).2784///2785/// If `true`, the system should be skipped.2786/// This is set by wrapping the system param in [`If`],2787/// and indicates that the system is intended to only operate in certain application states.2788pub skipped: bool,27892790/// A message describing the validation error.2791pub message: Cow<'static, str>,27922793/// A string identifying the invalid parameter.2794/// This is usually the type name of the parameter.2795pub param: DebugName,27962797/// A string identifying the field within a parameter using `#[derive(SystemParam)]`.2798/// This will be an empty string for other parameters.2799///2800/// This will be printed after `param` in the `Display` impl, and should include a `::` prefix if non-empty.2801pub field: Cow<'static, str>,2802}28032804impl SystemParamValidationError {2805/// Constructs a `SystemParamValidationError` that skips the system.2806/// The parameter name is initialized to the type name of `T`, so a `SystemParam` should usually pass `Self`.2807pub fn skipped<T>(message: impl Into<Cow<'static, str>>) -> Self {2808Self::new::<T>(true, message, Cow::Borrowed(""))2809}28102811/// Constructs a `SystemParamValidationError` for an invalid parameter that should be treated as an error.2812/// The parameter name is initialized to the type name of `T`, so a `SystemParam` should usually pass `Self`.2813pub fn invalid<T>(message: impl Into<Cow<'static, str>>) -> Self {2814Self::new::<T>(false, message, Cow::Borrowed(""))2815}28162817/// Constructs a `SystemParamValidationError` for an invalid parameter.2818/// The parameter name is initialized to the type name of `T`, so a `SystemParam` should usually pass `Self`.2819pub fn new<T>(2820skipped: bool,2821message: impl Into<Cow<'static, str>>,2822field: impl Into<Cow<'static, str>>,2823) -> Self {2824Self {2825skipped,2826message: message.into(),2827param: DebugName::type_name::<T>(),2828field: field.into(),2829}2830}28312832pub(crate) const EMPTY: Self = Self {2833skipped: false,2834message: Cow::Borrowed(""),2835param: DebugName::borrowed(""),2836field: Cow::Borrowed(""),2837};2838}28392840impl Display for SystemParamValidationError {2841fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {2842write!(2843fmt,2844"Parameter `{}{}` failed validation: {}",2845self.param.shortname(),2846self.field,2847self.message2848)?;2849if !self.skipped {2850write!(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.")?;2851}2852Ok(())2853}2854}28552856#[cfg(test)]2857mod tests {2858use super::*;2859use crate::system::assert_is_system;2860use core::cell::RefCell;28612862// Compile test for https://github.com/bevyengine/bevy/pull/2838.2863#[test]2864fn system_param_generic_bounds() {2865#[derive(SystemParam)]2866pub struct SpecialQuery<2867'w,2868's,2869D: QueryData + Send + Sync + 'static,2870F: QueryFilter + Send + Sync + 'static = (),2871> {2872_query: Query<'w, 's, D, F>,2873}28742875fn my_system(_: SpecialQuery<(), ()>) {}2876assert_is_system(my_system);2877}28782879// Compile tests for https://github.com/bevyengine/bevy/pull/6694.2880#[test]2881fn system_param_flexibility() {2882#[derive(SystemParam)]2883pub struct SpecialRes<'w, T: Resource> {2884_res: Res<'w, T>,2885}28862887#[derive(SystemParam)]2888pub struct SpecialLocal<'s, T: FromWorld + Send + 'static> {2889_local: Local<'s, T>,2890}28912892#[derive(Resource)]2893struct R;28942895fn my_system(_: SpecialRes<R>, _: SpecialLocal<u32>) {}2896assert_is_system(my_system);2897}28982899#[derive(Resource)]2900pub struct R<const I: usize>;29012902// Compile test for https://github.com/bevyengine/bevy/pull/7001.2903#[test]2904fn system_param_const_generics() {2905#[expect(2906dead_code,2907reason = "This struct is used to ensure that const generics are supported as a SystemParam; thus, the inner value never needs to be read."2908)]2909#[derive(SystemParam)]2910pub struct ConstGenericParam<'w, const I: usize>(Res<'w, R<I>>);29112912fn my_system(_: ConstGenericParam<0>, _: ConstGenericParam<1000>) {}2913assert_is_system(my_system);2914}29152916// Compile test for https://github.com/bevyengine/bevy/pull/6867.2917#[test]2918fn system_param_field_limit() {2919#[derive(SystemParam)]2920pub struct LongParam<'w> {2921// Each field should be a distinct type so there will2922// be an error if the derive messes up the field order.2923_r0: Res<'w, R<0>>,2924_r1: Res<'w, R<1>>,2925_r2: Res<'w, R<2>>,2926_r3: Res<'w, R<3>>,2927_r4: Res<'w, R<4>>,2928_r5: Res<'w, R<5>>,2929_r6: Res<'w, R<6>>,2930_r7: Res<'w, R<7>>,2931_r8: Res<'w, R<8>>,2932_r9: Res<'w, R<9>>,2933_r10: Res<'w, R<10>>,2934_r11: Res<'w, R<11>>,2935_r12: Res<'w, R<12>>,2936_r13: Res<'w, R<13>>,2937_r14: Res<'w, R<14>>,2938_r15: Res<'w, R<15>>,2939_r16: Res<'w, R<16>>,2940}29412942fn long_system(_: LongParam) {}2943assert_is_system(long_system);2944}29452946// Compile test for https://github.com/bevyengine/bevy/pull/6919.2947// Regression test for https://github.com/bevyengine/bevy/issues/7447.2948#[test]2949fn system_param_phantom_data() {2950#[derive(SystemParam)]2951struct PhantomParam<'w, T: Resource, Marker: 'static> {2952_foo: Res<'w, T>,2953marker: PhantomData<&'w Marker>,2954}29552956fn my_system(_: PhantomParam<R<0>, ()>) {}2957assert_is_system(my_system);2958}29592960// Compile tests for https://github.com/bevyengine/bevy/pull/6957.2961#[test]2962fn system_param_struct_variants() {2963#[derive(SystemParam)]2964pub struct UnitParam;29652966#[expect(2967dead_code,2968reason = "This struct is used to ensure that tuple structs are supported as a SystemParam; thus, the inner values never need to be read."2969)]2970#[derive(SystemParam)]2971pub struct TupleParam<'w, 's, R: Resource, L: FromWorld + Send + 'static>(2972Res<'w, R>,2973Local<'s, L>,2974);29752976fn my_system(_: UnitParam, _: TupleParam<R<0>, u32>) {}2977assert_is_system(my_system);2978}29792980// Regression test for https://github.com/bevyengine/bevy/issues/4200.2981#[test]2982fn system_param_private_fields() {2983#[derive(Resource)]2984struct PrivateResource;29852986#[expect(2987dead_code,2988reason = "This struct is used to ensure that SystemParam's derive can't leak private fields; thus, the inner values never need to be read."2989)]2990#[derive(SystemParam)]2991pub struct EncapsulatedParam<'w>(Res<'w, PrivateResource>);29922993fn my_system(_: EncapsulatedParam) {}2994assert_is_system(my_system);2995}29962997// Regression test for https://github.com/bevyengine/bevy/issues/7103.2998#[test]2999fn system_param_where_clause() {3000#[derive(SystemParam)]3001pub struct WhereParam<'w, 's, D>3002where3003D: 'static + QueryData,3004{3005_q: Query<'w, 's, D, ()>,3006}30073008fn my_system(_: WhereParam<()>) {}3009assert_is_system(my_system);3010}30113012// Regression test for https://github.com/bevyengine/bevy/issues/1727.3013#[test]3014fn system_param_name_collision() {3015#[derive(Resource)]3016pub struct FetchState;30173018#[derive(SystemParam)]3019pub struct Collide<'w> {3020_x: Res<'w, FetchState>,3021}30223023fn my_system(_: Collide) {}3024assert_is_system(my_system);3025}30263027// Regression test for https://github.com/bevyengine/bevy/issues/8192.3028#[test]3029fn system_param_invariant_lifetime() {3030#[derive(SystemParam)]3031pub struct InvariantParam<'w, 's> {3032_set: ParamSet<'w, 's, (Query<'w, 's, ()>,)>,3033}30343035fn my_system(_: InvariantParam) {}3036assert_is_system(my_system);3037}30383039// Compile test for https://github.com/bevyengine/bevy/pull/9589.3040#[test]3041fn non_sync_local() {3042fn non_sync_system(cell: Local<RefCell<u8>>) {3043assert_eq!(*cell.borrow(), 0);3044}30453046let mut world = World::new();3047let mut schedule = crate::schedule::Schedule::default();3048schedule.add_systems(non_sync_system);3049schedule.run(&mut world);3050}30513052// Regression test for https://github.com/bevyengine/bevy/issues/10207.3053#[test]3054fn param_set_non_send_first() {3055fn non_send_param_set(mut p: ParamSet<(NonSend<*mut u8>, ())>) {3056let _ = p.p0();3057p.p1();3058}30593060let mut world = World::new();3061world.insert_non_send_resource(core::ptr::null_mut::<u8>());3062let mut schedule = crate::schedule::Schedule::default();3063schedule.add_systems((non_send_param_set, non_send_param_set, non_send_param_set));3064schedule.run(&mut world);3065}30663067// Regression test for https://github.com/bevyengine/bevy/issues/10207.3068#[test]3069fn param_set_non_send_second() {3070fn non_send_param_set(mut p: ParamSet<((), NonSendMut<*mut u8>)>) {3071p.p0();3072let _ = p.p1();3073}30743075let mut world = World::new();3076world.insert_non_send_resource(core::ptr::null_mut::<u8>());3077let mut schedule = crate::schedule::Schedule::default();3078schedule.add_systems((non_send_param_set, non_send_param_set, non_send_param_set));3079schedule.run(&mut world);3080}30813082fn _dyn_system_param_type_inference(mut p: DynSystemParam) {3083// Make sure the downcast() methods are able to infer their type parameters from the use of the return type.3084// This is just a compilation test, so there is nothing to run.3085let _query: Query<()> = p.downcast_mut().unwrap();3086let _query: Query<()> = p.downcast_mut_inner().unwrap();3087let _query: Query<()> = p.downcast().unwrap();3088}30893090#[test]3091#[should_panic]3092fn missing_resource_error() {3093#[derive(Resource)]3094pub struct MissingResource;30953096let mut schedule = crate::schedule::Schedule::default();3097schedule.add_systems(res_system);3098let mut world = World::new();3099schedule.run(&mut world);31003101fn res_system(_: Res<MissingResource>) {}3102}31033104#[test]3105#[should_panic]3106fn missing_event_error() {3107use crate::prelude::{BufferedEvent, EventReader};31083109#[derive(BufferedEvent)]3110pub struct MissingEvent;31113112let mut schedule = crate::schedule::Schedule::default();3113schedule.add_systems(event_system);3114let mut world = World::new();3115schedule.run(&mut world);31163117fn event_system(_: EventReader<MissingEvent>) {}3118}3119}312031213122