1#![expect(
2 unsafe_op_in_unsafe_fn,
3 reason = "See #11590. To be removed once all applicable unsafe code has an unsafe block with a safety comment."
4)]
56pub use crate::change_detection::{NonSend, NonSendMut, Res, ResMut};
7use crate::{
8archetype::Archetypes,
9bundle::Bundles,
10 change_detection::{ComponentTicksMut, ComponentTicksRef, Tick},
11 component::{ComponentId, Components, Mutable},
12 entity::{Entities, EntityAllocator},
13 query::{
14Access, FilteredAccess, FilteredAccessSet, IterQueryData, QueryData, QueryFilter,
15QuerySingleError, QueryState, ReadOnlyQueryData,
16 },
17 resource::{Resource, IS_RESOURCE},
18 system::{Query, Single, SystemMeta},
19 world::{
20unsafe_world_cell::UnsafeWorldCell, DeferredWorld, FilteredResources, FilteredResourcesMut,
21FromWorld, World,
22 },
23};
24use alloc::{borrow::Cow, boxed::Box, vec::Vec};
25pub use bevy_ecs_macros::SystemParam;
26use bevy_platform::cell::SyncCell;
27use bevy_ptr::UnsafeCellDeref;
28use bevy_utils::prelude::DebugName;
29use core::{
30any::Any,
31 fmt::{Debug, Display},
32marker::PhantomData,
33 ops::{Deref, DerefMut},
34};
35use thiserror::Error;
3637use super::Populated;
38use variadics_please::{all_tuples, all_tuples_enumerated};
3940/// A parameter that can be used in a [`System`](super::System).
41///
42/// # Derive
43///
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 probable
48/// 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 require
54///
55/// ```
56/// # use bevy_ecs::prelude::*;
57/// # #[derive(Component)]
58/// # struct SomeComponent;
59/// # #[derive(Resource)]
60/// # struct SomeResource;
61/// # #[derive(Message)]
62/// # struct SomeMessage;
63/// # #[derive(Resource)]
64/// # struct SomeOtherResource;
65/// # use bevy_ecs::system::SystemParam;
66/// # #[derive(SystemParam)]
67/// # struct ParamsExample<'w, 's> {
68/// # query:
69/// Query<'w, 's, Entity>,
70/// # query2:
71/// Query<'w, 's, &'static SomeComponent>,
72/// # res:
73/// Res<'w, SomeResource>,
74/// # res_mut:
75/// ResMut<'w, SomeOtherResource>,
76/// # local:
77/// Local<'s, u8>,
78/// # commands:
79/// Commands<'w, 's>,
80/// # message_reader:
81/// MessageReader<'w, 's, SomeMessage>,
82/// # message_writer:
83/// MessageWriter<'w, SomeMessage>
84/// # }
85/// ```
86/// ## `PhantomData`
87///
88/// [`PhantomData`] is a special type of `SystemParam` that does nothing.
89/// This is useful for constraining generic types or lifetimes.
90///
91/// # Example
92///
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`s
114///
115/// When using the derive macro, you may see an error in the form of:
116///
117/// ```text
118/// 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/// ## Details
126///
127/// The derive macro requires that the [`SystemParam`] implementation of
128/// 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 be
131/// 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 requirement
135/// has not been proven to the compiler.
136///
137/// ## Custom Validation Messages
138///
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 assert
158/// assert!(err.to_string().contains(expected));
159/// ```
160///
161/// ## Builders
162///
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/// # Safety
211///
212/// The implementor must ensure the following is true.
213/// - [`SystemParam::init_access`] correctly registers all [`World`] accesses used
214/// by [`SystemParam::get_param`] with the provided [`system_meta`](SystemMeta).
215/// - None of the world accesses may conflict with any prior accesses registered
216/// 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`].
231 ///
232 /// This method must panic if the access would conflict with any existing access in the [`FilteredAccessSet`].
233fn init_access(
234 state: &Self::State,
235 system_meta: &mut SystemMeta,
236 component_access_set: &mut FilteredAccessSet,
237 world: &mut World,
238 );
239240/// Applies any deferred mutations stored in this [`SystemParam`]'s state.
241 /// This is used to apply [`Commands`] during [`ApplyDeferred`](crate::prelude::ApplyDeferred).
242 ///
243 /// [`Commands`]: crate::prelude::Commands
244#[inline]
245 #[expect(
246 unused_variables,
247 reason = "The parameters here are intentionally unused by the default implementation; however, putting underscores here will result in the underscores being copied by rust-analyzer's tab completion."
248)]
249fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {}
250251/// Queues any deferred mutations to be applied at the next [`ApplyDeferred`](crate::prelude::ApplyDeferred).
252#[inline]
253 #[expect(
254 unused_variables,
255 reason = "The parameters here are intentionally unused by the default implementation; however, putting underscores here will result in the underscores being copied by rust-analyzer's tab completion."
256)]
257fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {}
258259/// Creates a parameter to be passed into a [`SystemParamFunction`](super::SystemParamFunction).
260 ///
261 /// This method also validates that the param can be acquired. If validation fails,
262 /// an appropriate [`SystemParamValidationError`] should be returned.
263 /// Systems will convert this to a [`RunSystemError`](super::RunSystemError),
264 /// and the built-in executors will ignore any "skipped" validation results,
265 /// but pass any "invalid" results to the fallback error handler defined in [`bevy_ecs::error`].
266 ///
267 /// For nested [`SystemParam`]s validation will fail if any
268 /// delegated validation fails.
269 ///
270 /// # Safety
271 ///
272 /// - The passed [`UnsafeWorldCell`] must have access to any world data registered
273 /// in [`init_access`](SystemParam::init_access).
274 /// - [`SystemParam::init_access`] must not request conflicting access.
275 /// If `Self` is `ReadOnlySystemParam`, the access is read-only and can never conflict.
276 /// Otherwise, [`SystemParam::init_access`] must be called to ensure it does not panic.
277 /// - `world` must be the same [`World`] that was used to initialize [`state`](SystemParam::init_state).
278unsafe fn get_param<'world, 'state>(
279 state: &'state mut Self::State,
280 system_meta: &SystemMeta,
281 world: UnsafeWorldCell<'world>,
282 change_tick: Tick,
283 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError>;
284}
285286/// A [`SystemParam`] that only reads a given [`World`].
287///
288/// # Safety
289/// This must only be implemented for [`SystemParam`] impls that exclusively read the World passed in to [`SystemParam::get_param`]
290pub unsafe trait ReadOnlySystemParam: SystemParam {}
291292/// Shorthand way of accessing the associated type [`SystemParam::Item`] for a given [`SystemParam`].
293pub type SystemParamItem<'w, 's, P> = <P as SystemParam>::Item<'w, 's>;
294295// SAFETY: QueryState is constrained to read-only fetches, so it only reads World.
296unsafe impl<'w, 's, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam297for Query<'w, 's, D, F>
298{
299}
300301// SAFETY: Relevant query ComponentId access is applied to SystemMeta. If
302// this Query conflicts with any prior access, a panic will occur.
303unsafe impl<D: QueryData + 'static, F: QueryFilter + 'static> SystemParamfor Query<'_, '_, D, F> {
304type State = QueryState<D, F>;
305type Item<'w, 's> = Query<'w, 's, D, F>;
306307fn init_state(world: &mut World) -> Self::State {
308// SAFETY: `SystemParam::init_access` calls `QueryState::init_access`,
309 // `SystemParam::init_access` must be called before `SystemParam::get_param`,
310 // and we only call methods on the `QueryState` in `get_param`.
311unsafe { QueryState::new_unchecked(world) }
312 }
313314fn init_access(
315 state: &Self::State,
316 system_meta: &mut SystemMeta,
317 component_access_set: &mut FilteredAccessSet,
318 world: &mut World,
319 ) {
320state.init_access(Some(system_meta.name()), component_access_set, world.into());
321 }
322323#[inline]
324unsafe fn get_param<'w, 's>(
325 state: &'s mut Self::State,
326 system_meta: &SystemMeta,
327 world: UnsafeWorldCell<'w>,
328 change_tick: Tick,
329 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
330// SAFETY: We have registered all of the query's world accesses,
331 // so the caller ensures that `world` has permission to access any
332 // world data that the query needs.
333 // The caller ensures the world matches the one used in init_state.
334Ok(unsafe { state.query_unchecked_with_ticks(world, system_meta.last_run, change_tick) })
335 }
336}
337338// SAFETY: Relevant query ComponentId access is applied to SystemMeta. If
339// this Query conflicts with any prior access, a panic will occur.
340unsafe impl<'a, 'b, D: IterQueryData + 'static, F: QueryFilter + 'static> SystemParam341for Single<'a, 'b, D, F>
342{
343type State = QueryState<D, F>;
344type Item<'w, 's> = Single<'w, 's, D, F>;
345346fn init_state(world: &mut World) -> Self::State {
347Query::init_state(world)
348 }
349350fn init_access(
351 state: &Self::State,
352 system_meta: &mut SystemMeta,
353 component_access_set: &mut FilteredAccessSet,
354 world: &mut World,
355 ) {
356Query::init_access(state, system_meta, component_access_set, world);
357 }
358359#[inline]
360unsafe fn get_param<'w, 's>(
361 state: &'s mut Self::State,
362 system_meta: &SystemMeta,
363 world: UnsafeWorldCell<'w>,
364 change_tick: Tick,
365 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
366// SAFETY: State ensures that the components it accesses are not accessible somewhere elsewhere.
367 // The caller ensures the world matches the one used in init_state.
368let query =
369unsafe { state.query_unchecked_with_ticks(world, system_meta.last_run, change_tick) };
370match query.single_inner() {
371Ok(single) => Ok(Single {
372 item: single,
373 _filter: PhantomData,
374 }),
375Err(QuerySingleError::NoEntities(_)) => Err(
376SystemParamValidationError::skipped::<Self>("No matching entities"),
377 ),
378Err(QuerySingleError::MultipleEntities(_)) => Err(
379SystemParamValidationError::skipped::<Self>("Multiple matching entities"),
380 ),
381 }
382 }
383}
384385// SAFETY: QueryState is constrained to read-only fetches, so it only reads World.
386unsafe impl<'a, 'b, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam387for Single<'a, 'b, D, F>
388{
389}
390391// SAFETY: Relevant query ComponentId access is applied to SystemMeta. If
392// this Query conflicts with any prior access, a panic will occur.
393unsafe impl<D: QueryData + 'static, F: QueryFilter + 'static> SystemParam394for Populated<'_, '_, D, F>
395{
396type State = QueryState<D, F>;
397type Item<'w, 's> = Populated<'w, 's, D, F>;
398399fn init_state(world: &mut World) -> Self::State {
400Query::init_state(world)
401 }
402403fn init_access(
404 state: &Self::State,
405 system_meta: &mut SystemMeta,
406 component_access_set: &mut FilteredAccessSet,
407 world: &mut World,
408 ) {
409Query::init_access(state, system_meta, component_access_set, world);
410 }
411412#[inline]
413unsafe fn get_param<'w, 's>(
414 state: &'s mut Self::State,
415 system_meta: &SystemMeta,
416 world: UnsafeWorldCell<'w>,
417 change_tick: Tick,
418 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
419// SAFETY: Delegate to existing `SystemParam` implementations.
420let query = unsafe { Query::get_param(state, system_meta, world, change_tick) }?;
421if query.is_empty() {
422Err(SystemParamValidationError::skipped::<Self>(
423"No matching entities",
424 ))
425 } else {
426Ok(Populated(query))
427 }
428 }
429}
430431// SAFETY: QueryState is constrained to read-only fetches, so it only reads World.
432unsafe impl<'w, 's, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam433for Populated<'w, 's, D, F>
434{
435}
436437/// A collection of potentially conflicting [`SystemParam`]s allowed by disjoint access.
438///
439/// Allows systems to safely access and interact with up to 8 mutually exclusive [`SystemParam`]s, such as
440/// two queries that reference the same mutable data or an event reader and writer of the same type.
441///
442/// Each individual [`SystemParam`] can be accessed by using the functions `p0()`, `p1()`, ..., `p7()`,
443/// according to the order they are defined in the `ParamSet`. This ensures that there's either
444/// only one mutable reference to a parameter at a time or any number of immutable references.
445///
446/// # Examples
447///
448/// The following system mutably accesses the same component two times,
449/// which is not allowed due to rust's mutability rules.
450///
451/// ```should_panic
452/// # use bevy_ecs::prelude::*;
453/// #
454/// # #[derive(Component)]
455/// # struct Health;
456/// #
457/// # #[derive(Component)]
458/// # struct Enemy;
459/// #
460/// # #[derive(Component)]
461/// # struct Ally;
462/// #
463/// // This will panic at runtime when the system gets initialized.
464/// fn bad_system(
465/// mut enemies: Query<&mut Health, With<Enemy>>,
466/// mut allies: Query<&mut Health, With<Ally>>,
467/// ) {
468/// // ...
469/// }
470/// #
471/// # let mut bad_system_system = IntoSystem::into_system(bad_system);
472/// # let mut world = World::new();
473/// # bad_system_system.initialize(&mut world);
474/// # bad_system_system.run((), &mut world);
475/// ```
476///
477/// Conflicting `SystemParam`s like these can be placed in a `ParamSet`,
478/// which leverages the borrow checker to ensure that only one of the contained parameters are accessed at a given time.
479///
480/// ```
481/// # use bevy_ecs::prelude::*;
482/// #
483/// # #[derive(Component)]
484/// # struct Health;
485/// #
486/// # #[derive(Component)]
487/// # struct Enemy;
488/// #
489/// # #[derive(Component)]
490/// # struct Ally;
491/// #
492/// // Given the following system
493/// fn fancy_system(
494/// mut set: ParamSet<(
495/// Query<&mut Health, With<Enemy>>,
496/// Query<&mut Health, With<Ally>>,
497/// )>
498/// ) {
499/// // This will access the first `SystemParam`.
500/// for mut health in set.p0().iter_mut() {
501/// // Do your fancy stuff here...
502/// }
503///
504/// // The second `SystemParam`.
505/// // This would fail to compile if the previous parameter was still borrowed.
506/// for mut health in set.p1().iter_mut() {
507/// // Do even fancier stuff here...
508/// }
509/// }
510/// # bevy_ecs::system::assert_is_system(fancy_system);
511/// ```
512///
513/// Of course, `ParamSet`s can be used with any kind of `SystemParam`, not just [queries](Query).
514///
515/// ```
516/// # use bevy_ecs::prelude::*;
517/// #
518/// # #[derive(Message)]
519/// # struct MyMessage;
520/// # impl MyMessage {
521/// # pub fn new() -> Self { Self }
522/// # }
523/// fn message_system(
524/// mut set: ParamSet<(
525/// // PROBLEM: `MessageReader` and `MessageWriter` cannot be used together normally,
526/// // because they both need access to the same message queue.
527/// // SOLUTION: `ParamSet` allows these conflicting parameters to be used safely
528/// // by ensuring only one is accessed at a time.
529/// // Note that a better solution here is to use `MessageMutator`,
530/// // which both reads and writes messages with a single parameter.
531/// MessageReader<MyMessage>,
532/// MessageWriter<MyMessage>,
533/// // PROBLEM: `&World` needs read access to everything, which conflicts with
534/// // any mutable access in the same system.
535/// // SOLUTION: `ParamSet` ensures `&World` is only accessed when we're not
536/// // using the other mutable parameters.
537/// &World,
538/// )>,
539/// ) {
540/// for message in set.p0().read() {
541/// // ...
542/// # let _message = message;
543/// }
544/// set.p1().write(MyMessage::new());
545///
546/// let entities = set.p2().entities();
547/// // ...
548/// # let _entities = entities;
549/// }
550/// # bevy_ecs::system::assert_is_system(message_system);
551/// ```
552pub struct ParamSet<'w, 's, T: SystemParam> {
553 param_states: &'s mut T::State,
554 world: UnsafeWorldCell<'w>,
555 system_meta: SystemMeta,
556 change_tick: Tick,
557}
558559macro_rules! impl_param_set {
560 ($(($index: tt, $param: ident, $fn_name: ident)),*) => {
561// SAFETY: All parameters are constrained to ReadOnlySystemParam, so World is only read
562unsafe impl<'w, 's, $($param,)*> ReadOnlySystemParam for ParamSet<'w, 's, ($($param,)*)>
563where $($param: ReadOnlySystemParam,)*
564 { }
565566// SAFETY: Relevant parameter ComponentId access is applied to SystemMeta. If any ParamState conflicts
567 // with any prior access, a panic will occur.
568unsafe impl<'_w, '_s, $($param: SystemParam,)*> SystemParam for ParamSet<'_w, '_s, ($($param,)*)>
569 {
570type State = ($($param::State,)*);
571type Item<'w, 's> = ParamSet<'w, 's, ($($param,)*)>;
572573#[expect(
574 clippy::allow_attributes,
575 reason = "This is inside a macro meant for tuples; as such, `non_snake_case` won't always lint."
576)]
577 #[allow(
578 non_snake_case,
579 reason = "Certain variable names are provided by the caller, not by us."
580)]
581fn init_state(world: &mut World) -> Self::State {
582 ($($param::init_state(world),)*)
583 }
584585#[expect(
586 clippy::allow_attributes,
587 reason = "This is inside a macro meant for tuples; as such, `non_snake_case` won't always lint."
588)]
589 #[allow(
590 non_snake_case,
591 reason = "Certain variable names are provided by the caller, not by us."
592)]
593fn init_access(state: &Self::State, system_meta: &mut SystemMeta, component_access_set: &mut FilteredAccessSet, world: &mut World) {
594let ($($param,)*) = state;
595 $(
596// Call `init_access` on a clone of the original access set to check for conflicts
597let component_access_set_clone = &mut component_access_set.clone();
598$param::init_access($param, system_meta, component_access_set_clone, world);
599 )*
600 $(
601// Pretend to add the param to the system alone to gather the new access,
602 // then merge its access into the system.
603let mut access_set = FilteredAccessSet::new();
604$param::init_access($param, system_meta, &mut access_set, world);
605 component_access_set.extend(access_set);
606 )*
607 }
608609fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
610 <($($param,)*) as SystemParam>::apply(state, system_meta, world);
611 }
612613fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
614 <($($param,)*) as SystemParam>::queue(state, system_meta, world.reborrow());
615 }
616617#[inline]
618unsafe fn get_param<'w, 's>(
619 state: &'s mut Self::State,
620 system_meta: &SystemMeta,
621 world: UnsafeWorldCell<'w>,
622 change_tick: Tick,
623 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
624// Validate each sub-param eagerly so that the system is correctly
625 // skipped by the executor when any sub-param is unavailable.
626 // PERF: the sub-params will be fetched again lazily when accessed through
627 // the ParamSet, but this is no worse than the previous
628 // validate_param + get_param pattern.
629$(
630// SAFETY: Upheld by caller.
631drop(unsafe { $param::get_param(&mut state.$index, system_meta, world, change_tick) }?);
632 )*
633634Ok(ParamSet {
635 param_states: state,
636 system_meta: system_meta.clone(),
637 world,
638 change_tick,
639 })
640 }
641 }
642643impl<'w, 's, $($param: SystemParam,)*> ParamSet<'w, 's, ($($param,)*)>
644 {
645 $(
646/// Gets exclusive access to the parameter at index
647#[doc = stringify!($index)]
648/// in this [`ParamSet`].
649 /// No other parameters may be accessed while this one is active.
650pub fn $fn_name<'a>(&'a mut self) -> SystemParamItem<'a, 'a, $param> {
651// SAFETY: systems run without conflicts with other systems.
652 // Conflicting params in ParamSet are not accessible at the same time
653 // ParamSets are guaranteed to not conflict with other SystemParams
654unsafe {
655$param::get_param(&mut self.param_states.$index, &self.system_meta, self.world, self.change_tick)
656 }
657 .unwrap_or_else(|err| panic!("ParamSet parameter validation failed: {err}"))
658 }
659 )*
660 }
661 }
662}
663664unsafe impl<'w, 's, P0, P1, P2, P3, P4, P5, P6, P7> ReadOnlySystemParam for
ParamSet<'w, 's, (P0, P1, P2, P3, P4, P5, P6, P7)> where
P0: ReadOnlySystemParam, P1: ReadOnlySystemParam, P2: ReadOnlySystemParam,
P3: ReadOnlySystemParam, P4: ReadOnlySystemParam, P5: ReadOnlySystemParam,
P6: ReadOnlySystemParam, P7: ReadOnlySystemParam {}
unsafe impl<'_w, '_s, P0: SystemParam, P1: SystemParam, P2: SystemParam,
P3: SystemParam, P4: SystemParam, P5: SystemParam, P6: SystemParam,
P7: SystemParam> SystemParam for
ParamSet<'_w, '_s, (P0, P1, P2, P3, P4, P5, P6, P7)> {
type State =
(P0::State, P1::State, P2::State, P3::State, P4::State, P5::State,
P6::State, P7::State);
type Item<'w, 's> = ParamSet<'w, 's, (P0, P1, P2, P3, P4, P5, P6, P7)>;
#[expect(clippy :: allow_attributes, reason =
"This is inside a macro meant for tuples; as such, `non_snake_case` won't always lint.")]
#[allow(non_snake_case, reason =
"Certain variable names are provided by the caller, not by us.")]
fn init_state(world: &mut World) -> Self::State {
(P0::init_state(world), P1::init_state(world), P2::init_state(world),
P3::init_state(world), P4::init_state(world),
P5::init_state(world), P6::init_state(world),
P7::init_state(world))
}
#[expect(clippy :: allow_attributes, reason =
"This is inside a macro meant for tuples; as such, `non_snake_case` won't always lint.")]
#[allow(non_snake_case, reason =
"Certain variable names are provided by the caller, not by us.")]
fn init_access(state: &Self::State, system_meta: &mut SystemMeta,
component_access_set: &mut FilteredAccessSet, world: &mut World) {
let (P0, P1, P2, P3, P4, P5, P6, P7) = state;
let component_access_set_clone = &mut component_access_set.clone();
P0::init_access(P0, system_meta, component_access_set_clone, world);
let component_access_set_clone = &mut component_access_set.clone();
P1::init_access(P1, system_meta, component_access_set_clone, world);
let component_access_set_clone = &mut component_access_set.clone();
P2::init_access(P2, system_meta, component_access_set_clone, world);
let component_access_set_clone = &mut component_access_set.clone();
P3::init_access(P3, system_meta, component_access_set_clone, world);
let component_access_set_clone = &mut component_access_set.clone();
P4::init_access(P4, system_meta, component_access_set_clone, world);
let component_access_set_clone = &mut component_access_set.clone();
P5::init_access(P5, system_meta, component_access_set_clone, world);
let component_access_set_clone = &mut component_access_set.clone();
P6::init_access(P6, system_meta, component_access_set_clone, world);
let component_access_set_clone = &mut component_access_set.clone();
P7::init_access(P7, system_meta, component_access_set_clone, world);
let mut access_set = FilteredAccessSet::new();
P0::init_access(P0, system_meta, &mut access_set, world);
component_access_set.extend(access_set);
let mut access_set = FilteredAccessSet::new();
P1::init_access(P1, system_meta, &mut access_set, world);
component_access_set.extend(access_set);
let mut access_set = FilteredAccessSet::new();
P2::init_access(P2, system_meta, &mut access_set, world);
component_access_set.extend(access_set);
let mut access_set = FilteredAccessSet::new();
P3::init_access(P3, system_meta, &mut access_set, world);
component_access_set.extend(access_set);
let mut access_set = FilteredAccessSet::new();
P4::init_access(P4, system_meta, &mut access_set, world);
component_access_set.extend(access_set);
let mut access_set = FilteredAccessSet::new();
P5::init_access(P5, system_meta, &mut access_set, world);
component_access_set.extend(access_set);
let mut access_set = FilteredAccessSet::new();
P6::init_access(P6, system_meta, &mut access_set, world);
component_access_set.extend(access_set);
let mut access_set = FilteredAccessSet::new();
P7::init_access(P7, system_meta, &mut access_set, world);
component_access_set.extend(access_set);
}
fn apply(state: &mut Self::State, system_meta: &SystemMeta,
world: &mut World) {
<(P0, P1, P2, P3, P4, P5, P6, P7) as
SystemParam>::apply(state, system_meta, world);
}
fn queue(state: &mut Self::State, system_meta: &SystemMeta,
mut world: DeferredWorld) {
<(P0, P1, P2, P3, P4, P5, P6, P7) as
SystemParam>::queue(state, system_meta, world.reborrow());
}
#[inline]
unsafe fn get_param<'w,
's>(state: &'s mut Self::State, system_meta: &SystemMeta,
world: UnsafeWorldCell<'w>, change_tick: Tick)
-> Result<Self::Item<'w, 's>, SystemParamValidationError> {
drop(unsafe {
P0::get_param(&mut state.0, system_meta, world, change_tick)
}?);
drop(unsafe {
P1::get_param(&mut state.1, system_meta, world, change_tick)
}?);
drop(unsafe {
P2::get_param(&mut state.2, system_meta, world, change_tick)
}?);
drop(unsafe {
P3::get_param(&mut state.3, system_meta, world, change_tick)
}?);
drop(unsafe {
P4::get_param(&mut state.4, system_meta, world, change_tick)
}?);
drop(unsafe {
P5::get_param(&mut state.5, system_meta, world, change_tick)
}?);
drop(unsafe {
P6::get_param(&mut state.6, system_meta, world, change_tick)
}?);
drop(unsafe {
P7::get_param(&mut state.7, system_meta, world, change_tick)
}?);
Ok(ParamSet {
param_states: state,
system_meta: system_meta.clone(),
world,
change_tick,
})
}
}
impl<'w, 's, P0: SystemParam, P1: SystemParam, P2: SystemParam,
P3: SystemParam, P4: SystemParam, P5: SystemParam, P6: SystemParam,
P7: SystemParam> ParamSet<'w, 's, (P0, P1, P2, P3, P4, P5, P6, P7)> {
/// Gets exclusive access to the parameter at index
#[doc = "0"]
/// in this [`ParamSet`].
/// No other parameters may be accessed while this one is active.
pub fn p0<'a>(&'a mut self) -> SystemParamItem<'a, 'a, P0> {
unsafe {
P0::get_param(&mut self.param_states.0, &self.system_meta,
self.world, self.change_tick)
}.unwrap_or_else(|err|
{
::core::panicking::panic_fmt(format_args!("ParamSet parameter validation failed: {0}",
err));
})
}
/// Gets exclusive access to the parameter at index
#[doc = "1"]
/// in this [`ParamSet`].
/// No other parameters may be accessed while this one is active.
pub fn p1<'a>(&'a mut self) -> SystemParamItem<'a, 'a, P1> {
unsafe {
P1::get_param(&mut self.param_states.1, &self.system_meta,
self.world, self.change_tick)
}.unwrap_or_else(|err|
{
::core::panicking::panic_fmt(format_args!("ParamSet parameter validation failed: {0}",
err));
})
}
/// Gets exclusive access to the parameter at index
#[doc = "2"]
/// in this [`ParamSet`].
/// No other parameters may be accessed while this one is active.
pub fn p2<'a>(&'a mut self) -> SystemParamItem<'a, 'a, P2> {
unsafe {
P2::get_param(&mut self.param_states.2, &self.system_meta,
self.world, self.change_tick)
}.unwrap_or_else(|err|
{
::core::panicking::panic_fmt(format_args!("ParamSet parameter validation failed: {0}",
err));
})
}
/// Gets exclusive access to the parameter at index
#[doc = "3"]
/// in this [`ParamSet`].
/// No other parameters may be accessed while this one is active.
pub fn p3<'a>(&'a mut self) -> SystemParamItem<'a, 'a, P3> {
unsafe {
P3::get_param(&mut self.param_states.3, &self.system_meta,
self.world, self.change_tick)
}.unwrap_or_else(|err|
{
::core::panicking::panic_fmt(format_args!("ParamSet parameter validation failed: {0}",
err));
})
}
/// Gets exclusive access to the parameter at index
#[doc = "4"]
/// in this [`ParamSet`].
/// No other parameters may be accessed while this one is active.
pub fn p4<'a>(&'a mut self) -> SystemParamItem<'a, 'a, P4> {
unsafe {
P4::get_param(&mut self.param_states.4, &self.system_meta,
self.world, self.change_tick)
}.unwrap_or_else(|err|
{
::core::panicking::panic_fmt(format_args!("ParamSet parameter validation failed: {0}",
err));
})
}
/// Gets exclusive access to the parameter at index
#[doc = "5"]
/// in this [`ParamSet`].
/// No other parameters may be accessed while this one is active.
pub fn p5<'a>(&'a mut self) -> SystemParamItem<'a, 'a, P5> {
unsafe {
P5::get_param(&mut self.param_states.5, &self.system_meta,
self.world, self.change_tick)
}.unwrap_or_else(|err|
{
::core::panicking::panic_fmt(format_args!("ParamSet parameter validation failed: {0}",
err));
})
}
/// Gets exclusive access to the parameter at index
#[doc = "6"]
/// in this [`ParamSet`].
/// No other parameters may be accessed while this one is active.
pub fn p6<'a>(&'a mut self) -> SystemParamItem<'a, 'a, P6> {
unsafe {
P6::get_param(&mut self.param_states.6, &self.system_meta,
self.world, self.change_tick)
}.unwrap_or_else(|err|
{
::core::panicking::panic_fmt(format_args!("ParamSet parameter validation failed: {0}",
err));
})
}
/// Gets exclusive access to the parameter at index
#[doc = "7"]
/// in this [`ParamSet`].
/// No other parameters may be accessed while this one is active.
pub fn p7<'a>(&'a mut self) -> SystemParamItem<'a, 'a, P7> {
unsafe {
P7::get_param(&mut self.param_states.7, &self.system_meta,
self.world, self.change_tick)
}.unwrap_or_else(|err|
{
::core::panicking::panic_fmt(format_args!("ParamSet parameter validation failed: {0}",
err));
})
}
}all_tuples_enumerated!(impl_param_set, 1, 8, P, p);
665666// SAFETY: Res only reads a single World resource
667unsafe impl<'a, T: Resource> ReadOnlySystemParamfor Res<'a, T> {}
668669// SAFETY: Res ComponentId access is applied to SystemMeta. If this Res
670// conflicts with any prior access, a panic will occur.
671unsafe impl<'a, T: Resource> SystemParamfor Res<'a, T> {
672type State = ComponentId;
673type Item<'w, 's> = Res<'w, T>;
674675fn init_state(world: &mut World) -> Self::State {
676world.components_registrator().register_component::<T>()
677 }
678679fn init_access(
680&component_id: &Self::State,
681 system_meta: &mut SystemMeta,
682 component_access_set: &mut FilteredAccessSet,
683 world: &mut World,
684 ) {
685let mut filter = FilteredAccess::default();
686filter.add_read(component_id);
687filter.and_with(IS_RESOURCE);
688689let conflicts = component_access_set.get_conflicts_single(&filter);
690if conflicts.is_empty() {
691component_access_set.add(filter);
692return;
693 }
694695let mut accesses = conflicts.format_conflict_list(world.as_unsafe_world_cell());
696// Access list may be empty (if access to all components requested)
697if !accesses.is_empty() {
698accesses.push(' ');
699 }
700{
::core::panicking::panic_fmt(format_args!("error[B0002]: Res<{0}> in system {1} conflicts with a previous system parameter. Consider removing the duplicate access using `Without<IsResource>` to create disjoint Queries or merging conflicting Queries into a `ParamSet`. See: https://bevy.org/learn/errors/b0002",
DebugName::type_name::<T>(), system_meta.name));
};panic!("error[B0002]: Res<{}> in system {} conflicts with a previous system parameter. Consider removing the duplicate access using `Without<IsResource>` to create disjoint Queries or merging conflicting Queries into a `ParamSet`. See: https://bevy.org/learn/errors/b0002", DebugName::type_name::<T>(), system_meta.name);
701 }
702703#[inline]
704unsafe fn get_param<'w, 's>(
705&mut component_id: &'s mut Self::State,
706 system_meta: &SystemMeta,
707 world: UnsafeWorldCell<'w>,
708 change_tick: Tick,
709 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
710let (ptr, ticks) = world.get_resource_with_ticks(component_id).ok_or_else(|| {
711 SystemParamValidationError::invalid::<Self>("Resource does not exist")
712 })?;
713Ok(Res {
714 value: ptr.deref(),
715 ticks: ComponentTicksRef {
716 added: ticks.added.deref(),
717 changed: ticks.changed.deref(),
718 changed_by: ticks.changed_by.map(|changed_by| changed_by.deref()),
719 last_run: system_meta.last_run,
720 this_run: change_tick,
721 },
722 })
723 }
724}
725726// SAFETY: Res ComponentId access is applied to SystemMeta. If this Res
727// conflicts with any prior access, a panic will occur.
728unsafe impl<'a, T: Resource<Mutability = Mutable>> SystemParamfor ResMut<'a, T> {
729type State = ComponentId;
730type Item<'w, 's> = ResMut<'w, T>;
731732fn init_state(world: &mut World) -> Self::State {
733world.components_registrator().register_component::<T>()
734 }
735736fn init_access(
737&component_id: &Self::State,
738 system_meta: &mut SystemMeta,
739 component_access_set: &mut FilteredAccessSet,
740 world: &mut World,
741 ) {
742let mut filter = FilteredAccess::default();
743filter.add_write(component_id);
744filter.and_with(IS_RESOURCE);
745746let conflicts = component_access_set.get_conflicts_single(&filter);
747if conflicts.is_empty() {
748component_access_set.add(filter);
749return;
750 }
751752let mut accesses = conflicts.format_conflict_list(world.as_unsafe_world_cell());
753// Access list may be empty (if access to all components requested)
754if !accesses.is_empty() {
755accesses.push(' ');
756 }
757{
::core::panicking::panic_fmt(format_args!("error[B0002]: ResMut<{0}> in system {1} conflicts with a previous system parameter. Consider removing the duplicate access or using `Without<IsResource>` to create disjoint Queries or merging conflicting Queries into a `ParamSet`. See: https://bevy.org/learn/errors/b0002",
DebugName::type_name::<T>(), system_meta.name));
};panic!("error[B0002]: ResMut<{}> in system {} conflicts with a previous system parameter. Consider removing the duplicate access or using `Without<IsResource>` to create disjoint Queries or merging conflicting Queries into a `ParamSet`. See: https://bevy.org/learn/errors/b0002", DebugName::type_name::<T>(), system_meta.name);
758 }
759760#[inline]
761unsafe fn get_param<'w, 's>(
762&mut component_id: &'s mut Self::State,
763 system_meta: &SystemMeta,
764 world: UnsafeWorldCell<'w>,
765 change_tick: Tick,
766 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
767let value = world.get_resource_mut_by_id(component_id).ok_or_else(|| {
768 SystemParamValidationError::invalid::<Self>("Resource does not exist")
769 })?;
770Ok(ResMut {
771 value: value.value.deref_mut::<T>(),
772 ticks: ComponentTicksMut {
773 added: value.ticks.added,
774 changed: value.ticks.changed,
775 changed_by: value.ticks.changed_by,
776 last_run: system_meta.last_run,
777 this_run: change_tick,
778 },
779 })
780 }
781}
782783// SAFETY: only reads world
784unsafe impl<'w> ReadOnlySystemParamfor &'w World {}
785786// SAFETY: `read_all` access is set and conflicts result in a panic
787unsafe impl SystemParamfor &'_ World {
788type State = ();
789type Item<'w, 's> = &'w World;
790791fn init_state(_world: &mut World) -> Self::State {}
792793fn init_access(
794 _state: &Self::State,
795 _system_meta: &mut SystemMeta,
796 component_access_set: &mut FilteredAccessSet,
797 _world: &mut World,
798 ) {
799let mut filtered_access = FilteredAccess::default();
800801filtered_access.read_all();
802if !component_access_set803 .get_conflicts_single(&filtered_access)
804 .is_empty()
805 {
806{
::core::panicking::panic_fmt(format_args!("&World conflicts with a previous mutable system parameter. Allowing this would break Rust\'s mutability rules"));
};panic!("&World conflicts with a previous mutable system parameter. Allowing this would break Rust's mutability rules");
807 }
808component_access_set.add(filtered_access);
809 }
810811#[inline]
812unsafe fn get_param<'w, 's>(
813 _state: &'s mut Self::State,
814 _system_meta: &SystemMeta,
815 world: UnsafeWorldCell<'w>,
816 _change_tick: Tick,
817 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
818// SAFETY: Read-only access to the entire world was registered in `init_state`.
819Ok(unsafe { world.world() })
820 }
821}
822823// SAFETY: `DeferredWorld` can read all components and resources but cannot be used to gain any other mutable references.
824unsafe impl<'w> SystemParamfor DeferredWorld<'w> {
825type State = ();
826type Item<'world, 'state> = DeferredWorld<'world>;
827828fn init_state(_world: &mut World) -> Self::State {}
829830fn init_access(
831 _state: &Self::State,
832 system_meta: &mut SystemMeta,
833 component_access_set: &mut FilteredAccessSet,
834 _world: &mut World,
835 ) {
836if !!component_access_set.combined_access().has_any_read() {
{
::core::panicking::panic_fmt(format_args!("DeferredWorld in system {0} conflicts with a previous access.",
system_meta.name));
}
};assert!(
837 !component_access_set.combined_access().has_any_read(),
838"DeferredWorld in system {} conflicts with a previous access.",
839 system_meta.name,
840 );
841component_access_set.write_all();
842 }
843844unsafe fn get_param<'world, 'state>(
845 _state: &'state mut Self::State,
846 _system_meta: &SystemMeta,
847 world: UnsafeWorldCell<'world>,
848 _change_tick: Tick,
849 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
850// SAFETY: Upheld by caller
851Ok(unsafe { world.into_deferred() })
852 }
853}
854855/// A [`SystemParam`] that provides a system-private value of `T` that persists across system calls.
856///
857/// The initial value is created by calling `T`'s [`FromWorld::from_world`] (or [`Default::default`] if `T: Default`).
858///
859/// A local may only be accessed by the system itself and is therefore not visible to other systems.
860/// If two or more systems specify the same local type each will have their own unique local.
861/// If multiple [`SystemParam`]s within the same system each specify the same local type
862/// each will get their own distinct data storage.
863///
864/// The supplied lifetime parameter is the [`SystemParam`]s `'s` lifetime.
865///
866/// # Examples
867///
868/// ```
869/// # use bevy_ecs::prelude::*;
870/// # let world = &mut World::default();
871/// fn counter(mut count: Local<u32>) -> u32 {
872/// *count += 1;
873/// *count
874/// }
875/// let mut counter_system = IntoSystem::into_system(counter);
876/// counter_system.initialize(world);
877///
878/// // Counter is initialized to u32's default value of 0, and increases to 1 on first run.
879/// assert_eq!(counter_system.run((), world).unwrap(), 1);
880/// // Counter gets the same value and increases to 2 on its second call.
881/// assert_eq!(counter_system.run((), world).unwrap(), 2);
882/// ```
883///
884/// A simple way to set a different default value for a local is by wrapping the value with an Option.
885///
886/// ```
887/// # use bevy_ecs::prelude::*;
888/// # let world = &mut World::default();
889/// fn counter_from_10(mut count: Local<Option<u32>>) -> u32 {
890/// let count = count.get_or_insert(10);
891/// *count += 1;
892/// *count
893/// }
894/// let mut counter_system = IntoSystem::into_system(counter_from_10);
895/// counter_system.initialize(world);
896///
897/// // Counter is initialized at 10, and increases to 11 on first run.
898/// assert_eq!(counter_system.run((), world).unwrap(), 11);
899/// // Counter is only increased by 1 on subsequent runs.
900/// assert_eq!(counter_system.run((), world).unwrap(), 12);
901/// ```
902///
903/// A system can have multiple `Local` values with the same type, each with distinct values.
904///
905/// ```
906/// # use bevy_ecs::prelude::*;
907/// # let world = &mut World::default();
908/// fn double_counter(mut count: Local<u32>, mut double_count: Local<u32>) -> (u32, u32) {
909/// *count += 1;
910/// *double_count += 2;
911/// (*count, *double_count)
912/// }
913/// let mut counter_system = IntoSystem::into_system(double_counter);
914/// counter_system.initialize(world);
915///
916/// assert_eq!(counter_system.run((), world).unwrap(), (1, 2));
917/// assert_eq!(counter_system.run((), world).unwrap(), (2, 4));
918/// ```
919///
920/// This example shows that two systems using the same type for their own `Local` get distinct locals.
921///
922/// ```
923/// # use bevy_ecs::prelude::*;
924/// # let world = &mut World::default();
925/// fn write_to_local(mut local: Local<usize>) {
926/// *local = 42;
927/// }
928/// fn read_from_local(local: Local<usize>) -> usize {
929/// *local
930/// }
931/// let mut write_system = IntoSystem::into_system(write_to_local);
932/// let mut read_system = IntoSystem::into_system(read_from_local);
933/// write_system.initialize(world);
934/// read_system.initialize(world);
935///
936/// assert_eq!(read_system.run((), world).unwrap(), 0);
937/// write_system.run((), world);
938/// // The read local is still 0 due to the locals not being shared.
939/// assert_eq!(read_system.run((), world).unwrap(), 0);
940/// ```
941///
942/// You can use a `Local` to avoid reallocating memory every system call.
943///
944/// ```
945/// # use bevy_ecs::prelude::*;
946/// fn some_system(mut vec: Local<Vec<u32>>) {
947/// // Do your regular system logic, using the vec, as normal.
948///
949/// // At end of function, clear the vec's contents so its empty for next system call.
950/// // If it's possible the capacity could get too large, you may want to check and resize that as well.
951/// vec.clear();
952/// }
953/// ```
954///
955/// N.B. A [`Local`]s value cannot be read or written to outside of the containing system.
956/// To add configuration to a system, convert a capturing closure into the system instead:
957///
958/// ```
959/// # use bevy_ecs::prelude::*;
960/// # use bevy_ecs::system::assert_is_system;
961/// struct Config(u32);
962/// #[derive(Resource)]
963/// struct MyU32Wrapper(u32);
964/// fn reset_to_system(value: Config) -> impl FnMut(ResMut<MyU32Wrapper>) {
965/// move |mut val| val.0 = value.0
966/// }
967///
968/// // .add_systems(reset_to_system(my_config))
969/// # assert_is_system(reset_to_system(Config(10)));
970/// ```
971#[derive(#[automatically_derived]
impl<'s, T: ::core::fmt::Debug + FromWorld + Send + 'static>
::core::fmt::Debug for Local<'s, T> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Local",
&&self.0)
}
}Debug)]
972pub struct Local<'s, T: FromWorld + Send + 'static>(pub(crate) &'s mut T);
973974// SAFETY: Local only accesses internal state
975unsafe impl<'s, T: FromWorld + Send + 'static> ReadOnlySystemParamfor Local<'s, T> {}
976977impl<'s, T: FromWorld + Send + 'static> Dereffor Local<'s, T> {
978type Target = T;
979980#[inline]
981fn deref(&self) -> &Self::Target {
982self.0
983}
984}
985986impl<'s, T: FromWorld + Send + 'static> DerefMutfor Local<'s, T> {
987#[inline]
988fn deref_mut(&mut self) -> &mut Self::Target {
989self.0
990}
991}
992993impl<'s, 'a, T: FromWorld + Send + 'static> IntoIteratorfor &'a Local<'s, T>
994where
995&'a T: IntoIterator,
996{
997type Item = <&'a T as IntoIterator>::Item;
998type IntoIter = <&'a T as IntoIterator>::IntoIter;
9991000fn into_iter(self) -> Self::IntoIter {
1001self.0.into_iter()
1002 }
1003}
10041005impl<'s, 'a, T: FromWorld + Send + 'static> IntoIteratorfor &'a mut Local<'s, T>
1006where
1007&'a mut T: IntoIterator,
1008{
1009type Item = <&'a mut T as IntoIterator>::Item;
1010type IntoIter = <&'a mut T as IntoIterator>::IntoIter;
10111012fn into_iter(self) -> Self::IntoIter {
1013self.0.into_iter()
1014 }
1015}
10161017// SAFETY: only local state is accessed
1018unsafe impl<'a, T: FromWorld + Send + 'static> SystemParamfor Local<'a, T> {
1019type State = SyncCell<T>;
1020type Item<'w, 's> = Local<'s, T>;
10211022fn init_state(world: &mut World) -> Self::State {
1023SyncCell::new(T::from_world(world))
1024 }
10251026fn init_access(
1027 _state: &Self::State,
1028 _system_meta: &mut SystemMeta,
1029 _component_access_set: &mut FilteredAccessSet,
1030 _world: &mut World,
1031 ) {
1032 }
10331034#[inline]
1035unsafe fn get_param<'w, 's>(
1036 state: &'s mut Self::State,
1037 _system_meta: &SystemMeta,
1038 _world: UnsafeWorldCell<'w>,
1039 _change_tick: Tick,
1040 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
1041Ok(Local(state.get()))
1042 }
1043}
10441045/// Types that can be used with [`Deferred<T>`] in systems.
1046/// This allows storing system-local data which is used to defer [`World`] mutations.
1047///
1048/// Types that implement `SystemBuffer` should take care to perform as many
1049/// computations up-front as possible. Buffers cannot be applied in parallel,
1050/// so you should try to minimize the time spent in [`SystemBuffer::apply`].
1051pub trait SystemBuffer: FromWorld + Send + 'static {
1052/// Applies any deferred mutations to the [`World`].
1053fn apply(&mut self, system_meta: &SystemMeta, world: &mut World) {
1054self.queue(system_meta, world.into());
1055 }
1056/// Queues any deferred mutations to be applied at the next [`ApplyDeferred`](crate::prelude::ApplyDeferred).
1057 ///
1058 /// To queue structural changes to [`DeferredWorld`], a command queue of the [`DeferredWorld`]
1059 /// should be used via [`commands`](crate::world::DeferredWorld::commands).
1060fn queue(&mut self, _system_meta: &SystemMeta, _world: DeferredWorld);
1061}
10621063/// A [`SystemParam`] that stores a buffer which gets applied to the [`World`] during
1064/// [`ApplyDeferred`](crate::schedule::ApplyDeferred).
1065/// This is used internally by [`Commands`] to defer `World` mutations.
1066///
1067/// [`Commands`]: crate::system::Commands
1068///
1069/// # Examples
1070///
1071/// By using this type to defer mutations, you can avoid mutable `World` access within
1072/// a system, which allows it to run in parallel with more systems.
1073///
1074/// Note that deferring mutations is *not* free, and should only be used if
1075/// the gains in parallelization outweigh the time it takes to apply deferred mutations.
1076/// In general, [`Deferred`] should only be used for mutations that are infrequent,
1077/// or which otherwise take up a small portion of a system's run-time.
1078///
1079/// ```
1080/// # use bevy_ecs::prelude::*;
1081/// # use bevy_ecs::world::DeferredWorld;
1082/// // Tracks whether or not there is a threat the player should be aware of.
1083/// #[derive(Resource, Default)]
1084/// pub struct Alarm(bool);
1085///
1086/// #[derive(Component)]
1087/// pub struct Settlement {
1088/// // ...
1089/// }
1090///
1091/// // A threat from inside the settlement.
1092/// #[derive(Component)]
1093/// pub struct Criminal;
1094///
1095/// // A threat from outside the settlement.
1096/// #[derive(Component)]
1097/// pub struct Monster;
1098///
1099/// # impl Criminal { pub fn is_threat(&self, _: &Settlement) -> bool { true } }
1100///
1101/// use bevy_ecs::system::{Deferred, SystemBuffer, SystemMeta};
1102///
1103/// // Uses deferred mutations to allow signaling the alarm from multiple systems in parallel.
1104/// #[derive(Resource, Default)]
1105/// struct AlarmFlag(bool);
1106///
1107/// impl AlarmFlag {
1108/// /// Sounds the alarm the next time buffers are applied via ApplyDeferred.
1109/// pub fn flag(&mut self) {
1110/// self.0 = true;
1111/// }
1112/// }
1113///
1114/// impl SystemBuffer for AlarmFlag {
1115/// // When `AlarmFlag` is used in a system, this function will get
1116/// // called the next time buffers are applied via ApplyDeferred.
1117/// fn queue(&mut self, system_meta: &SystemMeta, mut world: DeferredWorld) {
1118/// if self.0 {
1119/// world.resource_mut::<Alarm>().0 = true;
1120/// self.0 = false;
1121/// }
1122/// }
1123/// }
1124///
1125/// // Sound the alarm if there are any criminals who pose a threat.
1126/// fn alert_criminal(
1127/// settlement: Single<&Settlement>,
1128/// criminals: Query<&Criminal>,
1129/// mut alarm: Deferred<AlarmFlag>
1130/// ) {
1131/// for criminal in &criminals {
1132/// // Only sound the alarm if the criminal is a threat.
1133/// // For this example, assume that this check is expensive to run.
1134/// // Since the majority of this system's run-time is dominated
1135/// // by calling `is_threat()`, we defer sounding the alarm to
1136/// // allow this system to run in parallel with other alarm systems.
1137/// if criminal.is_threat(*settlement) {
1138/// alarm.flag();
1139/// }
1140/// }
1141/// }
1142///
1143/// // Sound the alarm if there is a monster.
1144/// fn alert_monster(
1145/// monsters: Query<&Monster>,
1146/// mut alarm: ResMut<Alarm>
1147/// ) {
1148/// if monsters.iter().next().is_some() {
1149/// // Since this system does nothing except for sounding the alarm,
1150/// // it would be pointless to defer it, so we sound the alarm directly.
1151/// alarm.0 = true;
1152/// }
1153/// }
1154///
1155/// let mut world = World::new();
1156/// world.init_resource::<Alarm>();
1157/// world.spawn(Settlement {
1158/// // ...
1159/// });
1160///
1161/// let mut schedule = Schedule::default();
1162/// // These two systems have no conflicts and will run in parallel.
1163/// schedule.add_systems((alert_criminal, alert_monster));
1164///
1165/// // There are no criminals or monsters, so the alarm is not sounded.
1166/// schedule.run(&mut world);
1167/// assert_eq!(world.resource::<Alarm>().0, false);
1168///
1169/// // Spawn a monster, which will cause the alarm to be sounded.
1170/// let m_id = world.spawn(Monster).id();
1171/// schedule.run(&mut world);
1172/// assert_eq!(world.resource::<Alarm>().0, true);
1173///
1174/// // Remove the monster and reset the alarm.
1175/// world.entity_mut(m_id).despawn();
1176/// world.resource_mut::<Alarm>().0 = false;
1177///
1178/// // Spawn a criminal, which will cause the alarm to be sounded.
1179/// world.spawn(Criminal);
1180/// schedule.run(&mut world);
1181/// assert_eq!(world.resource::<Alarm>().0, true);
1182/// ```
1183pub struct Deferred<'a, T: SystemBuffer>(pub(crate) &'a mut T);
11841185impl<'a, T: SystemBuffer> Dereffor Deferred<'a, T> {
1186type Target = T;
1187#[inline]
1188fn deref(&self) -> &Self::Target {
1189self.0
1190}
1191}
11921193impl<'a, T: SystemBuffer> DerefMutfor Deferred<'a, T> {
1194#[inline]
1195fn deref_mut(&mut self) -> &mut Self::Target {
1196self.0
1197}
1198}
11991200impl<T: SystemBuffer> Deferred<'_, T> {
1201/// Returns a [`Deferred<T>`] with a smaller lifetime.
1202 /// This is useful if you have `&mut Deferred<T>` but need `Deferred<T>`.
1203pub fn reborrow(&mut self) -> Deferred<'_, T> {
1204Deferred(self.0)
1205 }
1206}
12071208// SAFETY: Only local state is accessed.
1209unsafe impl<T: SystemBuffer> ReadOnlySystemParamfor Deferred<'_, T> {}
12101211// SAFETY: Only local state is accessed.
1212unsafe impl<T: SystemBuffer> SystemParamfor Deferred<'_, T> {
1213type State = SyncCell<T>;
1214type Item<'w, 's> = Deferred<'s, T>;
12151216#[track_caller]
1217fn init_state(world: &mut World) -> Self::State {
1218SyncCell::new(T::from_world(world))
1219 }
12201221fn init_access(
1222 _state: &Self::State,
1223 system_meta: &mut SystemMeta,
1224 _component_access_set: &mut FilteredAccessSet,
1225 _world: &mut World,
1226 ) {
1227system_meta.set_has_deferred();
1228 }
12291230fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1231state.get().apply(system_meta, world);
1232 }
12331234fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
1235state.get().queue(system_meta, world);
1236 }
12371238#[inline]
1239unsafe fn get_param<'w, 's>(
1240 state: &'s mut Self::State,
1241 _system_meta: &SystemMeta,
1242 _world: UnsafeWorldCell<'w>,
1243 _change_tick: Tick,
1244 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
1245Ok(Deferred(state.get()))
1246 }
1247}
12481249/// A dummy type to tell the executor to run the system exclusively.
1250pub struct ExclusiveMarker(PhantomData<()>);
12511252// SAFETY: No world access.
1253unsafe impl SystemParamfor ExclusiveMarker {
1254type State = ();
1255type Item<'w, 's> = Self;
12561257#[inline]
1258fn init_state(_world: &mut World) -> Self::State {}
12591260fn init_access(
1261 _state: &Self::State,
1262 system_meta: &mut SystemMeta,
1263 _component_access_set: &mut FilteredAccessSet,
1264 _world: &mut World,
1265 ) {
1266system_meta.set_exclusive();
1267 }
12681269#[inline]
1270unsafe fn get_param<'world, 'state>(
1271 _state: &'state mut Self::State,
1272 _system_meta: &SystemMeta,
1273 _world: UnsafeWorldCell<'world>,
1274 _change_tick: Tick,
1275 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
1276Ok(Self(PhantomData))
1277 }
1278}
12791280// SAFETY: Does not read any world state
1281unsafe impl ReadOnlySystemParamfor ExclusiveMarker {}
12821283/// A dummy type that is [`!Send`](Send), to force systems to run on the main thread.
1284pub struct NonSendMarker(PhantomData<*mut ()>);
12851286// SAFETY: No world access.
1287unsafe impl SystemParamfor NonSendMarker {
1288type State = ();
1289type Item<'w, 's> = Self;
12901291#[inline]
1292fn init_state(_world: &mut World) -> Self::State {}
12931294fn init_access(
1295 _state: &Self::State,
1296 system_meta: &mut SystemMeta,
1297 _component_access_set: &mut FilteredAccessSet,
1298 _world: &mut World,
1299 ) {
1300system_meta.set_non_send();
1301 }
13021303#[inline]
1304unsafe fn get_param<'world, 'state>(
1305 _state: &'state mut Self::State,
1306 _system_meta: &SystemMeta,
1307 _world: UnsafeWorldCell<'world>,
1308 _change_tick: Tick,
1309 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
1310Ok(Self(PhantomData))
1311 }
1312}
13131314// SAFETY: Does not read any world state
1315unsafe impl ReadOnlySystemParamfor NonSendMarker {}
13161317// SAFETY: Only reads a single World non-send resource
1318unsafe impl<'w, T> ReadOnlySystemParamfor NonSend<'w, T> {}
13191320// SAFETY: NonSendComponentId access is applied to SystemMeta. If this
1321// NonSend conflicts with any prior access, a panic will occur.
1322unsafe impl<'a, T: 'static> SystemParamfor NonSend<'a, T> {
1323type State = ComponentId;
1324type Item<'w, 's> = NonSend<'w, T>;
13251326fn init_state(world: &mut World) -> Self::State {
1327world.components_registrator().register_non_send::<T>()
1328 }
13291330fn init_access(
1331&component_id: &Self::State,
1332 system_meta: &mut SystemMeta,
1333 component_access_set: &mut FilteredAccessSet,
1334 _world: &mut World,
1335 ) {
1336system_meta.set_non_send();
13371338let combined_access = component_access_set.combined_access();
1339if !!combined_access.has_write(component_id) {
{
::core::panicking::panic_fmt(format_args!("error[B0002]: NonSend<{0}> in system {1} conflicts with a previous mutable resource access ({0}). Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",
DebugName::type_name::<T>(), system_meta.name));
}
};assert!(
1340 !combined_access.has_write(component_id),
1341"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",
1342 DebugName::type_name::<T>(),
1343 system_meta.name,
1344 );
1345component_access_set.add_unfiltered_component_read(component_id);
1346 }
13471348#[inline]
1349unsafe fn get_param<'w, 's>(
1350&mut component_id: &'s mut Self::State,
1351 system_meta: &SystemMeta,
1352 world: UnsafeWorldCell<'w>,
1353 change_tick: Tick,
1354 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
1355let (ptr, ticks) = world.get_non_send_with_ticks(component_id).ok_or_else(|| {
1356 SystemParamValidationError::invalid::<Self>("Non-send data not found")
1357 })?;
1358Ok(NonSend {
1359 value: ptr.deref(),
1360 ticks: ComponentTicksRef::from_tick_cells(ticks, system_meta.last_run, change_tick),
1361 })
1362 }
1363}
13641365// SAFETY: NonSendMut ComponentId access is applied to SystemMeta. If this
1366// NonSendMut conflicts with any prior access, a panic will occur.
1367unsafe impl<'a, T: 'static> SystemParamfor NonSendMut<'a, T> {
1368type State = ComponentId;
1369type Item<'w, 's> = NonSendMut<'w, T>;
13701371fn init_state(world: &mut World) -> Self::State {
1372world.components_registrator().register_non_send::<T>()
1373 }
13741375fn init_access(
1376&component_id: &Self::State,
1377 system_meta: &mut SystemMeta,
1378 component_access_set: &mut FilteredAccessSet,
1379 _world: &mut World,
1380 ) {
1381system_meta.set_non_send();
13821383let combined_access = component_access_set.combined_access();
1384if combined_access.has_write(component_id) {
1385{
::core::panicking::panic_fmt(format_args!("error[B0002]: NonSendMut<{0}> in system {1} conflicts with a previous mutable resource access ({0}). Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",
DebugName::type_name::<T>(), system_meta.name));
};panic!(
1386"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",
1387 DebugName::type_name::<T>(), system_meta.name);
1388 } else if combined_access.has_read(component_id) {
1389{
::core::panicking::panic_fmt(format_args!("error[B0002]: NonSendMut<{0}> in system {1} conflicts with a previous immutable resource access ({0}). Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",
DebugName::type_name::<T>(), system_meta.name));
};panic!(
1390"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",
1391 DebugName::type_name::<T>(), system_meta.name);
1392 }
1393component_access_set.add_unfiltered_component_write(component_id);
1394 }
13951396#[inline]
1397unsafe fn get_param<'w, 's>(
1398&mut component_id: &'s mut Self::State,
1399 system_meta: &SystemMeta,
1400 world: UnsafeWorldCell<'w>,
1401 change_tick: Tick,
1402 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
1403let (ptr, ticks) = world.get_non_send_with_ticks(component_id).ok_or_else(|| {
1404 SystemParamValidationError::invalid::<Self>("Non-send data not found")
1405 })?;
1406Ok(NonSendMut {
1407 value: ptr.assert_unique().deref_mut(),
1408 ticks: ComponentTicksMut::from_tick_cells(ticks, system_meta.last_run, change_tick),
1409 })
1410 }
1411}
14121413// SAFETY: Only reads World archetypes
1414unsafe impl<'a> ReadOnlySystemParamfor &'a Archetypes {}
14151416// SAFETY: no component value access
1417unsafe impl<'a> SystemParamfor &'a Archetypes {
1418type State = ();
1419type Item<'w, 's> = &'w Archetypes;
14201421fn init_state(_world: &mut World) -> Self::State {}
14221423fn init_access(
1424 _state: &Self::State,
1425 _system_meta: &mut SystemMeta,
1426 _component_access_set: &mut FilteredAccessSet,
1427 _world: &mut World,
1428 ) {
1429 }
14301431#[inline]
1432unsafe fn get_param<'w, 's>(
1433 _state: &'s mut Self::State,
1434 _system_meta: &SystemMeta,
1435 world: UnsafeWorldCell<'w>,
1436 _change_tick: Tick,
1437 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
1438Ok(world.archetypes())
1439 }
1440}
14411442// SAFETY: Only reads World components
1443unsafe impl<'a> ReadOnlySystemParamfor &'a Components {}
14441445// SAFETY: no component value access
1446unsafe impl<'a> SystemParamfor &'a Components {
1447type State = ();
1448type Item<'w, 's> = &'w Components;
14491450fn init_state(_world: &mut World) -> Self::State {}
14511452fn init_access(
1453 _state: &Self::State,
1454 _system_meta: &mut SystemMeta,
1455 _component_access_set: &mut FilteredAccessSet,
1456 _world: &mut World,
1457 ) {
1458 }
14591460#[inline]
1461unsafe fn get_param<'w, 's>(
1462 _state: &'s mut Self::State,
1463 _system_meta: &SystemMeta,
1464 world: UnsafeWorldCell<'w>,
1465 _change_tick: Tick,
1466 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
1467Ok(world.components())
1468 }
1469}
14701471// SAFETY: Only reads World entities
1472unsafe impl<'a> ReadOnlySystemParamfor &'a Entities {}
14731474// SAFETY: no component value access
1475unsafe impl<'a> SystemParamfor &'a Entities {
1476type State = ();
1477type Item<'w, 's> = &'w Entities;
14781479fn init_state(_world: &mut World) -> Self::State {}
14801481fn init_access(
1482 _state: &Self::State,
1483 _system_meta: &mut SystemMeta,
1484 _component_access_set: &mut FilteredAccessSet,
1485 _world: &mut World,
1486 ) {
1487 }
14881489#[inline]
1490unsafe fn get_param<'w, 's>(
1491 _state: &'s mut Self::State,
1492 _system_meta: &SystemMeta,
1493 world: UnsafeWorldCell<'w>,
1494 _change_tick: Tick,
1495 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
1496Ok(world.entities())
1497 }
1498}
14991500// SAFETY: Only reads World entities
1501unsafe impl<'a> ReadOnlySystemParamfor &'a EntityAllocator {}
15021503// SAFETY: no component value access
1504unsafe impl<'a> SystemParamfor &'a EntityAllocator {
1505type State = ();
1506type Item<'w, 's> = &'w EntityAllocator;
15071508fn init_state(_world: &mut World) -> Self::State {}
15091510fn init_access(
1511 _state: &Self::State,
1512 _system_meta: &mut SystemMeta,
1513 _component_access_set: &mut FilteredAccessSet,
1514 _world: &mut World,
1515 ) {
1516 }
15171518#[inline]
1519unsafe fn get_param<'w, 's>(
1520 _state: &'s mut Self::State,
1521 _system_meta: &SystemMeta,
1522 world: UnsafeWorldCell<'w>,
1523 _change_tick: Tick,
1524 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
1525Ok(world.entity_allocator())
1526 }
1527}
15281529// SAFETY: Only reads World bundles
1530unsafe impl<'a> ReadOnlySystemParamfor &'a Bundles {}
15311532// SAFETY: no component value access
1533unsafe impl<'a> SystemParamfor &'a Bundles {
1534type State = ();
1535type Item<'w, 's> = &'w Bundles;
15361537fn init_state(_world: &mut World) -> Self::State {}
15381539fn init_access(
1540 _state: &Self::State,
1541 _system_meta: &mut SystemMeta,
1542 _component_access_set: &mut FilteredAccessSet,
1543 _world: &mut World,
1544 ) {
1545 }
15461547#[inline]
1548unsafe fn get_param<'w, 's>(
1549 _state: &'s mut Self::State,
1550 _system_meta: &SystemMeta,
1551 world: UnsafeWorldCell<'w>,
1552 _change_tick: Tick,
1553 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
1554Ok(world.bundles())
1555 }
1556}
15571558/// A [`SystemParam`] that reads the previous and current change ticks of the system.
1559///
1560/// A system's change ticks are updated each time it runs:
1561/// - `last_run` copies the previous value of `change_tick`
1562/// - `this_run` copies the current value of [`World::read_change_tick`]
1563///
1564/// Component change ticks that are more recent than `last_run` will be detected by the system.
1565/// Those can be read by calling [`last_changed`](crate::change_detection::DetectChanges::last_changed)
1566/// on a [`Mut<T>`](crate::change_detection::Mut) or [`ResMut<T>`](ResMut).
1567#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SystemChangeTick {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"SystemChangeTick", "last_run", &self.last_run, "this_run",
&&self.this_run)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for SystemChangeTick {
#[inline]
fn clone(&self) -> SystemChangeTick {
let _: ::core::clone::AssertParamIsClone<Tick>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for SystemChangeTick { }Copy)]
1568pub struct SystemChangeTick {
1569 last_run: Tick,
1570 this_run: Tick,
1571}
15721573impl SystemChangeTick {
1574/// Returns the current [`World`] change tick seen by the system.
1575#[inline]
1576pub fn this_run(&self) -> Tick {
1577self.this_run
1578 }
15791580/// Returns the [`World`] change tick seen by the system the previous time it ran.
1581#[inline]
1582pub fn last_run(&self) -> Tick {
1583self.last_run
1584 }
1585}
15861587// SAFETY: Only reads internal system state
1588unsafe impl ReadOnlySystemParamfor SystemChangeTick {}
15891590// SAFETY: `SystemChangeTick` doesn't require any world access
1591unsafe impl SystemParamfor SystemChangeTick {
1592type State = ();
1593type Item<'w, 's> = SystemChangeTick;
15941595fn init_state(_world: &mut World) -> Self::State {}
15961597fn init_access(
1598 _state: &Self::State,
1599 _system_meta: &mut SystemMeta,
1600 _component_access_set: &mut FilteredAccessSet,
1601 _world: &mut World,
1602 ) {
1603 }
16041605#[inline]
1606unsafe fn get_param<'w, 's>(
1607 _state: &'s mut Self::State,
1608 system_meta: &SystemMeta,
1609 _world: UnsafeWorldCell<'w>,
1610 change_tick: Tick,
1611 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
1612Ok(SystemChangeTick {
1613 last_run: system_meta.last_run,
1614 this_run: change_tick,
1615 })
1616 }
1617}
16181619// SAFETY: Delegates to `T`, which ensures the safety requirements are met
1620unsafe impl<T: SystemParam> SystemParamfor Option<T> {
1621type State = T::State;
16221623type Item<'world, 'state> = Option<T::Item<'world, 'state>>;
16241625fn init_state(world: &mut World) -> Self::State {
1626 T::init_state(world)
1627 }
16281629fn init_access(
1630 state: &Self::State,
1631 system_meta: &mut SystemMeta,
1632 component_access_set: &mut FilteredAccessSet,
1633 world: &mut World,
1634 ) {
1635 T::init_access(state, system_meta, component_access_set, world);
1636 }
16371638#[inline]
1639unsafe fn get_param<'world, 'state>(
1640 state: &'state mut Self::State,
1641 system_meta: &SystemMeta,
1642 world: UnsafeWorldCell<'world>,
1643 change_tick: Tick,
1644 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
1645// SAFETY: Upheld by caller
1646Ok(unsafe { T::get_param(state, system_meta, world, change_tick) }.ok())
1647 }
16481649fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1650 T::apply(state, system_meta, world);
1651 }
16521653fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
1654 T::queue(state, system_meta, world);
1655 }
1656}
16571658// SAFETY: Delegates to `T`, which ensures the safety requirements are met
1659unsafe impl<T: ReadOnlySystemParam> ReadOnlySystemParamfor Option<T> {}
16601661// SAFETY: Delegates to `T`, which ensures the safety requirements are met
1662unsafe impl<T: SystemParam> SystemParamfor Result<T, SystemParamValidationError> {
1663type State = T::State;
16641665type Item<'world, 'state> = Result<T::Item<'world, 'state>, SystemParamValidationError>;
16661667fn init_state(world: &mut World) -> Self::State {
1668 T::init_state(world)
1669 }
16701671fn init_access(
1672 state: &Self::State,
1673 system_meta: &mut SystemMeta,
1674 component_access_set: &mut FilteredAccessSet,
1675 world: &mut World,
1676 ) {
1677 T::init_access(state, system_meta, component_access_set, world);
1678 }
16791680#[inline]
1681unsafe fn get_param<'world, 'state>(
1682 state: &'state mut Self::State,
1683 system_meta: &SystemMeta,
1684 world: UnsafeWorldCell<'world>,
1685 change_tick: Tick,
1686 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
1687// SAFETY: Upheld by caller
1688Ok(unsafe { T::get_param(state, system_meta, world, change_tick) })
1689 }
16901691fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1692 T::apply(state, system_meta, world);
1693 }
16941695fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
1696 T::queue(state, system_meta, world);
1697 }
1698}
16991700// SAFETY: Delegates to `T`, which ensures the safety requirements are met
1701unsafe impl<T: ReadOnlySystemParam> ReadOnlySystemParamfor Result<T, SystemParamValidationError> {}
17021703/// A [`SystemParam`] that wraps another parameter and causes its system to skip instead of failing when the parameter is invalid.
1704///
1705/// # Example
1706///
1707/// ```
1708/// # use bevy_ecs::prelude::*;
1709/// # #[derive(Resource)]
1710/// # struct SomeResource;
1711/// // This system will fail if `SomeResource` is not present.
1712/// fn fails_on_missing_resource(res: Res<SomeResource>) {}
1713///
1714/// // This system will skip without error if `SomeResource` is not present.
1715/// fn skips_on_missing_resource(res: If<Res<SomeResource>>) {
1716/// // The inner parameter is available using `Deref`
1717/// let some_resource: &SomeResource = &res;
1718/// }
1719/// # bevy_ecs::system::assert_is_system(skips_on_missing_resource);
1720/// ```
1721#[derive(#[automatically_derived]
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for If<T> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f, "If", &&self.0)
}
}Debug)]
1722pub struct If<T>(pub T);
17231724impl<T> If<T> {
1725/// Returns the inner `T`.
1726 ///
1727 /// The inner value is `pub`, so you can also obtain it by destructuring the parameter:
1728 ///
1729 /// ```
1730 /// # use bevy_ecs::prelude::*;
1731 /// # #[derive(Resource)]
1732 /// # struct SomeResource;
1733 /// fn skips_on_missing_resource(If(res): If<Res<SomeResource>>) {
1734 /// let some_resource: Res<SomeResource> = res;
1735 /// }
1736 /// # bevy_ecs::system::assert_is_system(skips_on_missing_resource);
1737 /// ```
1738pub fn into_inner(self) -> T {
1739self.0
1740}
1741}
17421743impl<T> Dereffor If<T> {
1744type Target = T;
1745fn deref(&self) -> &Self::Target {
1746&self.0
1747}
1748}
17491750impl<T> DerefMutfor If<T> {
1751fn deref_mut(&mut self) -> &mut Self::Target {
1752&mut self.0
1753}
1754}
17551756// SAFETY: Delegates to `T`, which ensures the safety requirements are met
1757unsafe impl<T: SystemParam> SystemParamfor If<T> {
1758type State = T::State;
17591760type Item<'world, 'state> = If<T::Item<'world, 'state>>;
17611762fn init_state(world: &mut World) -> Self::State {
1763 T::init_state(world)
1764 }
17651766fn init_access(
1767 state: &Self::State,
1768 system_meta: &mut SystemMeta,
1769 component_access_set: &mut FilteredAccessSet,
1770 world: &mut World,
1771 ) {
1772 T::init_access(state, system_meta, component_access_set, world);
1773 }
17741775#[inline]
1776unsafe fn get_param<'world, 'state>(
1777 state: &'state mut Self::State,
1778 system_meta: &SystemMeta,
1779 world: UnsafeWorldCell<'world>,
1780 change_tick: Tick,
1781 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
1782// SAFETY: Upheld by caller.
1783unsafe { T::get_param(state, system_meta, world, change_tick) }
1784 .map(If)
1785 .map_err(|mut e| {
1786e.skipped = true;
1787e1788 })
1789 }
17901791fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1792 T::apply(state, system_meta, world);
1793 }
17941795fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
1796 T::queue(state, system_meta, world);
1797 }
1798}
17991800// SAFETY: Delegates to `T`, which ensures the safety requirements are met
1801unsafe impl<T: ReadOnlySystemParam> ReadOnlySystemParamfor If<T> {}
18021803// SAFETY: Registers access for each element of `state`.
1804// If any one conflicts, it will panic.
1805unsafe impl<T: SystemParam> SystemParamfor Vec<T> {
1806type State = Vec<T::State>;
18071808type Item<'world, 'state> = Vec<T::Item<'world, 'state>>;
18091810fn init_state(_world: &mut World) -> Self::State {
1811Vec::new()
1812 }
18131814fn init_access(
1815 state: &Self::State,
1816 system_meta: &mut SystemMeta,
1817 component_access_set: &mut FilteredAccessSet,
1818 world: &mut World,
1819 ) {
1820for state in state {
1821 T::init_access(state, system_meta, component_access_set, world);
1822 }
1823 }
18241825#[inline]
1826unsafe fn get_param<'world, 'state>(
1827 state: &'state mut Self::State,
1828 system_meta: &SystemMeta,
1829 world: UnsafeWorldCell<'world>,
1830 change_tick: Tick,
1831 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
1832state1833 .iter_mut()
1834// SAFETY:
1835 // - 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.
1836 // - The caller ensures this was the world used to initialize our state, and we used that world to initialize parameter states
1837.map(|state| unsafe { T::get_param(state, system_meta, world, change_tick) })
1838 .collect()
1839 }
18401841fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1842for state in state {
1843 T::apply(state, system_meta, world);
1844 }
1845 }
18461847fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
1848for state in state {
1849 T::queue(state, system_meta, world.reborrow());
1850 }
1851 }
1852}
18531854// SAFETY: Registers access for each element of `state`.
1855// If any one conflicts with a previous parameter,
1856// the call passing a copy of the current access will panic.
1857unsafe impl<T: SystemParam> SystemParamfor ParamSet<'_, '_, Vec<T>> {
1858type State = Vec<T::State>;
18591860type Item<'world, 'state> = ParamSet<'world, 'state, Vec<T>>;
18611862fn init_state(_world: &mut World) -> Self::State {
1863Vec::new()
1864 }
18651866fn init_access(
1867 state: &Self::State,
1868 system_meta: &mut SystemMeta,
1869 component_access_set: &mut FilteredAccessSet,
1870 world: &mut World,
1871 ) {
1872for state in state {
1873// Call `init_access` on a clone of the original access set to check for conflicts
1874let component_access_set_clone = &mut component_access_set.clone();
1875 T::init_access(state, system_meta, component_access_set_clone, world);
1876 }
1877for state in state {
1878// Pretend to add the param to the system alone to gather the new access,
1879 // then merge its access into the system.
1880let mut access_set = FilteredAccessSet::new();
1881 T::init_access(state, system_meta, &mut access_set, world);
1882 component_access_set.extend(access_set);
1883 }
1884 }
18851886#[inline]
1887unsafe fn get_param<'world, 'state>(
1888 state: &'state mut Self::State,
1889 system_meta: &SystemMeta,
1890 world: UnsafeWorldCell<'world>,
1891 change_tick: Tick,
1892 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
1893// Validate each sub-param eagerly so that the system is correctly
1894 // skipped by the executor when any sub-param is unavailable.
1895 // PERF: the sub-params will be fetched again lazily when accessed through
1896 // the ParamSet, but this is no worse than the previous
1897 // validate_param + get_param pattern.
1898for s in state.iter_mut() {
1899// SAFETY: Upheld by caller.
1900drop(unsafe { T::get_param(s, system_meta, world, change_tick) }?);
1901 }
19021903Ok(ParamSet {
1904 param_states: state,
1905 system_meta: system_meta.clone(),
1906world,
1907change_tick,
1908 })
1909 }
19101911fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1912for state in state {
1913 T::apply(state, system_meta, world);
1914 }
1915 }
19161917fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
1918for state in state {
1919 T::queue(state, system_meta, world.reborrow());
1920 }
1921 }
1922}
19231924impl<T: SystemParam> ParamSet<'_, '_, Vec<T>> {
1925/// Accesses the parameter at the given index.
1926 /// No other parameters may be accessed while this one is active.
1927pub fn get_mut(&mut self, index: usize) -> T::Item<'_, '_> {
1928// SAFETY:
1929 // - We initialized the access for each parameter, so the caller ensures we have access to any world data needed by any param.
1930 // We have mutable access to the ParamSet, so no other params in the set are active.
1931 // - The caller of `get_param` ensured that this was the world used to initialize our state, and we used that world to initialize parameter states
1932unsafe {
1933 T::get_param(
1934&mut self.param_states[index],
1935&self.system_meta,
1936self.world,
1937self.change_tick,
1938 )
1939 .unwrap()
1940 }
1941 }
19421943/// Calls a closure for each parameter in the set.
1944pub fn for_each(&mut self, mut f: impl FnMut(T::Item<'_, '_>)) {
1945self.param_states.iter_mut().for_each(|state| {
1946f(
1947// SAFETY:
1948 // - We initialized the access for each parameter, so the caller ensures we have access to any world data needed by any param.
1949 // We have mutable access to the ParamSet, so no other params in the set are active.
1950 // - The caller of `get_param` ensured that this was the world used to initialize our state, and we used that world to initialize parameter states
1951unsafe { T::get_param(state, &self.system_meta, self.world, self.change_tick) }
1952 .unwrap_or_else(|err| {
::core::panicking::panic_fmt(format_args!("ParamSet parameter validation failed: {0}",
err));
}panic!("ParamSet parameter validation failed: {err}")),
1953 );
1954 });
1955 }
1956}
19571958macro_rules! impl_system_param_tuple {
1959 ($(#[$meta:meta])* $($param: ident),*) => {
1960 $(#[$meta])*
1961// SAFETY: tuple consists only of ReadOnlySystemParams
1962unsafe impl<$($param: ReadOnlySystemParam),*> ReadOnlySystemParam for ($($param,)*) {}
19631964#[expect(
1965 clippy::allow_attributes,
1966 reason = "This is in a macro, and as such, the below lints may not always apply."
1967)]
1968 #[allow(
1969 non_snake_case,
1970 reason = "Certain variable names are provided by the caller, not by us."
1971)]
1972 #[allow(
1973 unused_variables,
1974 reason = "Zero-length tuples won't use some of the parameters."
1975)]
1976 #[allow(clippy::unused_unit, reason = "Zero length tuple is unit.")]
1977$(#[$meta])*
1978// SAFETY: implementers of each `SystemParam` in the tuple have validated their impls
1979unsafe impl<$($param: SystemParam),*> SystemParam for ($($param,)*) {
1980type State = ($($param::State,)*);
1981type Item<'w, 's> = ($($param::Item::<'w, 's>,)*);
19821983#[inline]
1984 #[track_caller]
1985fn init_state(world: &mut World) -> Self::State {
1986 ($($param::init_state(world),)*)
1987 }
19881989fn init_access(state: &Self::State, _system_meta: &mut SystemMeta, _component_access_set: &mut FilteredAccessSet, _world: &mut World) {
1990let ($($param,)*) = state;
1991 $($param::init_access($param, _system_meta, _component_access_set, _world);)*
1992 }
19931994#[inline]
1995fn apply(($($param,)*): &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1996 $($param::apply($param, system_meta, world);)*
1997 }
19981999#[inline]
2000 #[allow(
2001 unused_mut,
2002 reason = "The `world` parameter is unused for zero-length tuples; however, it must be mutable for other lengths of tuples."
2003)]
2004fn queue(($($param,)*): &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
2005 $($param::queue($param, system_meta, world.reborrow());)*
2006 }
20072008#[inline]
2009 #[track_caller]
2010unsafe fn get_param<'w, 's>(
2011 state: &'s mut Self::State,
2012 system_meta: &SystemMeta,
2013 world: UnsafeWorldCell<'w>,
2014 change_tick: Tick,
2015 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
2016let ($($param,)*) = state;
20172018#[allow(
2019 unused_unsafe,
2020 reason = "Zero-length tuples won't have any params to validate."
2021)]
2022// SAFETY: Upheld by caller
2023unsafe {
2024#[allow(
2025 clippy::unused_unit,
2026 reason = "Zero-length tuples won't have any params to get."
2027)]
2028Ok(($($param::get_param($param, system_meta, world, change_tick)?,)*))
2029 }
2030 }
2031 }
2032 };
2033}
20342035#[doc(hidden)]
unsafe impl<P0: ReadOnlySystemParam, P1: ReadOnlySystemParam,
P2: ReadOnlySystemParam, P3: ReadOnlySystemParam, P4: ReadOnlySystemParam,
P5: ReadOnlySystemParam, P6: ReadOnlySystemParam, P7: ReadOnlySystemParam,
P8: ReadOnlySystemParam, P9: ReadOnlySystemParam,
P10: ReadOnlySystemParam, P11: ReadOnlySystemParam,
P12: ReadOnlySystemParam, P13: ReadOnlySystemParam,
P14: ReadOnlySystemParam, P15: ReadOnlySystemParam> ReadOnlySystemParam
for (P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15)
{
}
#[expect(clippy :: allow_attributes, reason =
"This is in a macro, and as such, the below lints may not always apply.")]
#[allow(non_snake_case, reason =
"Certain variable names are provided by the caller, not by us.")]
#[allow(unused_variables, reason =
"Zero-length tuples won't use some of the parameters.")]
#[allow(clippy :: unused_unit, reason = "Zero length tuple is unit.")]
#[doc(hidden)]
unsafe impl<P0: SystemParam, P1: SystemParam, P2: SystemParam,
P3: SystemParam, P4: SystemParam, P5: SystemParam, P6: SystemParam,
P7: SystemParam, P8: SystemParam, P9: SystemParam, P10: SystemParam,
P11: SystemParam, P12: SystemParam, P13: SystemParam, P14: SystemParam,
P15: SystemParam> SystemParam for
(P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15) {
type State =
(P0::State, P1::State, P2::State, P3::State, P4::State, P5::State,
P6::State, P7::State, P8::State, P9::State, P10::State, P11::State,
P12::State, P13::State, P14::State, P15::State);
type Item<'w, 's> =
(P0::Item<'w, 's>, P1::Item<'w, 's>, P2::Item<'w, 's>,
P3::Item<'w, 's>, P4::Item<'w, 's>, P5::Item<'w, 's>,
P6::Item<'w, 's>, P7::Item<'w, 's>, P8::Item<'w, 's>,
P9::Item<'w, 's>, P10::Item<'w, 's>, P11::Item<'w, 's>,
P12::Item<'w, 's>, P13::Item<'w, 's>, P14::Item<'w, 's>,
P15::Item<'w, 's>);
#[inline]
#[track_caller]
fn init_state(world: &mut World) -> Self::State {
(P0::init_state(world), P1::init_state(world), P2::init_state(world),
P3::init_state(world), P4::init_state(world),
P5::init_state(world), P6::init_state(world),
P7::init_state(world), P8::init_state(world),
P9::init_state(world), P10::init_state(world),
P11::init_state(world), P12::init_state(world),
P13::init_state(world), P14::init_state(world),
P15::init_state(world))
}
fn init_access(state: &Self::State, _system_meta: &mut SystemMeta,
_component_access_set: &mut FilteredAccessSet, _world: &mut World) {
let (P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14,
P15) = state;
P0::init_access(P0, _system_meta, _component_access_set, _world);
P1::init_access(P1, _system_meta, _component_access_set, _world);
P2::init_access(P2, _system_meta, _component_access_set, _world);
P3::init_access(P3, _system_meta, _component_access_set, _world);
P4::init_access(P4, _system_meta, _component_access_set, _world);
P5::init_access(P5, _system_meta, _component_access_set, _world);
P6::init_access(P6, _system_meta, _component_access_set, _world);
P7::init_access(P7, _system_meta, _component_access_set, _world);
P8::init_access(P8, _system_meta, _component_access_set, _world);
P9::init_access(P9, _system_meta, _component_access_set, _world);
P10::init_access(P10, _system_meta, _component_access_set, _world);
P11::init_access(P11, _system_meta, _component_access_set, _world);
P12::init_access(P12, _system_meta, _component_access_set, _world);
P13::init_access(P13, _system_meta, _component_access_set, _world);
P14::init_access(P14, _system_meta, _component_access_set, _world);
P15::init_access(P15, _system_meta, _component_access_set, _world);
}
#[inline]
fn apply((P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14,
P15): &mut Self::State, system_meta: &SystemMeta,
world: &mut World) {
P0::apply(P0, system_meta, world);
P1::apply(P1, system_meta, world);
P2::apply(P2, system_meta, world);
P3::apply(P3, system_meta, world);
P4::apply(P4, system_meta, world);
P5::apply(P5, system_meta, world);
P6::apply(P6, system_meta, world);
P7::apply(P7, system_meta, world);
P8::apply(P8, system_meta, world);
P9::apply(P9, system_meta, world);
P10::apply(P10, system_meta, world);
P11::apply(P11, system_meta, world);
P12::apply(P12, system_meta, world);
P13::apply(P13, system_meta, world);
P14::apply(P14, system_meta, world);
P15::apply(P15, system_meta, world);
}
#[inline]
#[allow(unused_mut, reason =
"The `world` parameter is unused for zero-length tuples; however, it must be mutable for other lengths of tuples.")]
fn queue((P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14,
P15): &mut Self::State, system_meta: &SystemMeta,
mut world: DeferredWorld) {
P0::queue(P0, system_meta, world.reborrow());
P1::queue(P1, system_meta, world.reborrow());
P2::queue(P2, system_meta, world.reborrow());
P3::queue(P3, system_meta, world.reborrow());
P4::queue(P4, system_meta, world.reborrow());
P5::queue(P5, system_meta, world.reborrow());
P6::queue(P6, system_meta, world.reborrow());
P7::queue(P7, system_meta, world.reborrow());
P8::queue(P8, system_meta, world.reborrow());
P9::queue(P9, system_meta, world.reborrow());
P10::queue(P10, system_meta, world.reborrow());
P11::queue(P11, system_meta, world.reborrow());
P12::queue(P12, system_meta, world.reborrow());
P13::queue(P13, system_meta, world.reborrow());
P14::queue(P14, system_meta, world.reborrow());
P15::queue(P15, system_meta, world.reborrow());
}
#[inline]
#[track_caller]
unsafe fn get_param<'w,
's>(state: &'s mut Self::State, system_meta: &SystemMeta,
world: UnsafeWorldCell<'w>, change_tick: Tick)
-> Result<Self::Item<'w, 's>, SystemParamValidationError> {
let (P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14,
P15) = state;
#[allow(unused_unsafe, reason =
"Zero-length tuples won't have any params to validate.")]
unsafe {
#[allow(clippy :: unused_unit, reason =
"Zero-length tuples won't have any params to get.")]
Ok((P0::get_param(P0, system_meta, world, change_tick)?,
P1::get_param(P1, system_meta, world, change_tick)?,
P2::get_param(P2, system_meta, world, change_tick)?,
P3::get_param(P3, system_meta, world, change_tick)?,
P4::get_param(P4, system_meta, world, change_tick)?,
P5::get_param(P5, system_meta, world, change_tick)?,
P6::get_param(P6, system_meta, world, change_tick)?,
P7::get_param(P7, system_meta, world, change_tick)?,
P8::get_param(P8, system_meta, world, change_tick)?,
P9::get_param(P9, system_meta, world, change_tick)?,
P10::get_param(P10, system_meta, world, change_tick)?,
P11::get_param(P11, system_meta, world, change_tick)?,
P12::get_param(P12, system_meta, world, change_tick)?,
P13::get_param(P13, system_meta, world, change_tick)?,
P14::get_param(P14, system_meta, world, change_tick)?,
P15::get_param(P15, system_meta, world, change_tick)?))
}
}
}all_tuples!(
2036#[doc(fake_variadic)]
2037impl_system_param_tuple,
20380,
203916,
2040 P
2041);
20422043/// Contains type aliases for built-in [`SystemParam`]s with `'static` lifetimes.
2044/// This makes it more convenient to refer to these types in contexts where
2045/// explicit lifetime annotations are required.
2046///
2047/// Note that this is entirely safe and tracks lifetimes correctly.
2048/// This purely exists for convenience.
2049///
2050/// You can't instantiate a static `SystemParam`, you'll always end up with
2051/// `Res<'w, T>`, `ResMut<'w, T>` or `&'w T` bound to the lifetime of the provided
2052/// `&'w World`.
2053///
2054/// [`SystemParam`]: super::SystemParam
2055pub mod lifetimeless {
2056/// A [`Query`](super::Query) with `'static` lifetimes.
2057pub type SQuery<D, F = ()> = super::Query<'static, 'static, D, F>;
2058/// A shorthand for writing `&'static T`.
2059pub type Read<T> = &'static T;
2060/// A shorthand for writing `&'static mut T`.
2061pub type Write<T> = &'static mut T;
2062/// A [`Res`](super::Res) with `'static` lifetimes.
2063pub type SRes<T> = super::Res<'static, T>;
2064/// A [`ResMut`](super::ResMut) with `'static` lifetimes.
2065pub type SResMut<T> = super::ResMut<'static, T>;
2066/// [`Commands`](crate::system::Commands) with `'static` lifetimes.
2067pub type SCommands = crate::system::Commands<'static, 'static>;
2068}
20692070/// A helper for using system parameters in generic contexts
2071///
2072/// This type is a [`SystemParam`] adapter which always has
2073/// `Self::Item == Self` (ignoring lifetimes for brevity),
2074/// no matter the argument [`SystemParam`] (`P`) (other than
2075/// that `P` must be `'static`)
2076///
2077/// This makes it useful for having arbitrary [`SystemParam`] type arguments
2078/// to function systems, or for generic types using the [`derive@SystemParam`]
2079/// derive:
2080///
2081/// ```
2082/// # use bevy_ecs::prelude::*;
2083/// use bevy_ecs::system::{SystemParam, StaticSystemParam};
2084/// #[derive(SystemParam)]
2085/// struct GenericParam<'w,'s, T: SystemParam + 'static> {
2086/// field: StaticSystemParam<'w, 's, T>,
2087/// }
2088/// fn do_thing_generically<T: SystemParam + 'static>(t: StaticSystemParam<T>) {}
2089///
2090/// fn check_always_is_system<T: SystemParam + 'static>(){
2091/// bevy_ecs::system::assert_is_system(do_thing_generically::<T>);
2092/// }
2093/// ```
2094/// Note that in a real case you'd generally want
2095/// additional bounds on `P`, for your use of the parameter
2096/// to have a reason to be generic.
2097///
2098/// For example, using this would allow a type to be generic over
2099/// whether a resource is accessed mutably or not, with
2100/// impls being bounded on [`P: Deref<Target=MyType>`](Deref), and
2101/// [`P: DerefMut<Target=MyType>`](DerefMut) depending on whether the
2102/// method requires mutable access or not.
2103///
2104/// The method which doesn't use this type will not compile:
2105/// ```compile_fail
2106/// # use bevy_ecs::prelude::*;
2107/// # use bevy_ecs::system::{SystemParam, StaticSystemParam};
2108///
2109/// fn do_thing_generically<T: SystemParam + 'static>(t: T) {}
2110///
2111/// #[derive(SystemParam)]
2112/// struct GenericParam<'w, 's, T: SystemParam> {
2113/// field: T,
2114/// // Use the lifetimes in this type, or they will be unbound.
2115/// phantom: std::marker::PhantomData<&'w &'s ()>
2116/// }
2117/// # fn check_always_is_system<T: SystemParam + 'static>(){
2118/// # bevy_ecs::system::assert_is_system(do_thing_generically::<T>);
2119/// # }
2120/// ```
2121pub struct StaticSystemParam<'w, 's, P: SystemParam>(SystemParamItem<'w, 's, P>);
21222123impl<'w, 's, P: SystemParam> Dereffor StaticSystemParam<'w, 's, P> {
2124type Target = SystemParamItem<'w, 's, P>;
21252126fn deref(&self) -> &Self::Target {
2127&self.0
2128}
2129}
21302131impl<'w, 's, P: SystemParam> DerefMutfor StaticSystemParam<'w, 's, P> {
2132fn deref_mut(&mut self) -> &mut Self::Target {
2133&mut self.0
2134}
2135}
21362137impl<'w, 's, P: SystemParam> StaticSystemParam<'w, 's, P> {
2138/// Get the value of the parameter
2139pub fn into_inner(self) -> SystemParamItem<'w, 's, P> {
2140self.0
2141}
2142}
21432144// SAFETY: This doesn't add any more reads, and the delegated fetch confirms it
2145unsafe impl<'w, 's, P: ReadOnlySystemParam + 'static> ReadOnlySystemParam2146for StaticSystemParam<'w, 's, P>
2147{
2148}
21492150// SAFETY: all methods are just delegated to `P`'s `SystemParam` implementation
2151unsafe impl<P: SystemParam + 'static> SystemParamfor StaticSystemParam<'_, '_, P> {
2152type State = P::State;
2153type Item<'world, 'state> = StaticSystemParam<'world, 'state, P>;
21542155fn init_state(world: &mut World) -> Self::State {
2156 P::init_state(world)
2157 }
21582159fn init_access(
2160 state: &Self::State,
2161 system_meta: &mut SystemMeta,
2162 component_access_set: &mut FilteredAccessSet,
2163 world: &mut World,
2164 ) {
2165 P::init_access(state, system_meta, component_access_set, world);
2166 }
21672168fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
2169 P::apply(state, system_meta, world);
2170 }
21712172fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
2173 P::queue(state, system_meta, world);
2174 }
21752176#[inline]
2177unsafe fn get_param<'world, 'state>(
2178 state: &'state mut Self::State,
2179 system_meta: &SystemMeta,
2180 world: UnsafeWorldCell<'world>,
2181 change_tick: Tick,
2182 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
2183// SAFETY: Defer to the safety of P::SystemParam
2184unsafe { P::get_param(state, system_meta, world, change_tick) }.map(StaticSystemParam)
2185 }
2186}
21872188// SAFETY: No world access.
2189unsafe impl<T: ?Sized> SystemParamfor PhantomData<T> {
2190type State = ();
2191type Item<'world, 'state> = Self;
21922193fn init_state(_world: &mut World) -> Self::State {}
21942195fn init_access(
2196 _state: &Self::State,
2197 _system_meta: &mut SystemMeta,
2198 _component_access_set: &mut FilteredAccessSet,
2199 _world: &mut World,
2200 ) {
2201 }
22022203#[inline]
2204unsafe fn get_param<'world, 'state>(
2205 _state: &'state mut Self::State,
2206 _system_meta: &SystemMeta,
2207 _world: UnsafeWorldCell<'world>,
2208 _change_tick: Tick,
2209 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
2210Ok(PhantomData)
2211 }
2212}
22132214// SAFETY: No world access.
2215unsafe impl<T: ?Sized> ReadOnlySystemParamfor PhantomData<T> {}
22162217/// A [`SystemParam`] with a type that can be configured at runtime.
2218///
2219/// To be useful, this must be configured using a [`DynParamBuilder`](crate::system::DynParamBuilder) to build the system using a [`SystemParamBuilder`](crate::prelude::SystemParamBuilder).
2220///
2221/// # Examples
2222///
2223/// ```
2224/// # use bevy_ecs::{prelude::*, system::*};
2225/// #
2226/// # #[derive(Default, Resource)]
2227/// # struct A;
2228/// #
2229/// # #[derive(Default, Resource)]
2230/// # struct B;
2231/// #
2232/// # let mut world = World::new();
2233/// # world.init_resource::<A>();
2234/// # world.init_resource::<B>();
2235/// #
2236/// // If the inner parameter doesn't require any special building, use `ParamBuilder`.
2237/// // Either specify the type parameter on `DynParamBuilder::new()` ...
2238/// let system = (DynParamBuilder::new::<Res<A>>(ParamBuilder),)
2239/// .build_state(&mut world)
2240/// .build_system(expects_res_a);
2241/// # world.run_system_once(system);
2242///
2243/// // ... or use a factory method on `ParamBuilder` that returns a specific type.
2244/// let system = (DynParamBuilder::new(ParamBuilder::resource::<A>()),)
2245/// .build_state(&mut world)
2246/// .build_system(expects_res_a);
2247/// # world.run_system_once(system);
2248///
2249/// fn expects_res_a(mut param: DynSystemParam) {
2250/// // Use the `downcast` methods to retrieve the inner parameter.
2251/// // They will return `None` if the type does not match.
2252/// assert!(param.is::<Res<A>>());
2253/// assert!(!param.is::<Res<B>>());
2254/// assert!(param.downcast_mut::<Res<B>>().is_none());
2255/// let res = param.downcast_mut::<Res<A>>().unwrap();
2256/// // The type parameter can be left out if it can be determined from use.
2257/// let res: Res<A> = param.downcast().unwrap();
2258/// }
2259///
2260/// let system = (
2261/// // If the inner parameter also requires building,
2262/// // pass the appropriate `SystemParamBuilder`.
2263/// DynParamBuilder::new(LocalBuilder(10usize)),
2264/// // `DynSystemParam` is just an ordinary `SystemParam`,
2265/// // and can be combined with other parameters as usual!
2266/// ParamBuilder::query(),
2267/// )
2268/// .build_state(&mut world)
2269/// .build_system(|param: DynSystemParam, query: Query<()>| {
2270/// let local: Local<usize> = param.downcast::<Local<usize>>().unwrap();
2271/// assert_eq!(*local, 10);
2272/// });
2273/// # world.run_system_once(system);
2274/// ```
2275pub struct DynSystemParam<'w, 's> {
2276/// A `ParamState<T>` wrapping the state for the underlying system param.
2277state: &'s mut dyn Any,
2278 world: UnsafeWorldCell<'w>,
2279 system_meta: SystemMeta,
2280 change_tick: Tick,
2281}
22822283impl<'w, 's> DynSystemParam<'w, 's> {
2284/// # Safety
2285 /// - `state` must be a `ParamState<T>` for some inner `T: SystemParam`.
2286 /// - The passed [`UnsafeWorldCell`] must have access to any world data registered
2287 /// in [`init_state`](SystemParam::init_state) for the inner system param.
2288 /// - `world` must be the same `World` that was used to initialize
2289 /// [`state`](SystemParam::init_state) for the inner system param.
2290unsafe fn new(
2291 state: &'s mut dyn Any,
2292 world: UnsafeWorldCell<'w>,
2293 system_meta: SystemMeta,
2294 change_tick: Tick,
2295 ) -> Self {
2296Self {
2297state,
2298world,
2299system_meta,
2300change_tick,
2301 }
2302 }
23032304/// Returns `true` if the inner system param is the same as `T`.
2305pub fn is<T: SystemParam>(&self) -> bool2306// See downcast() function for an explanation of the where clause
2307where
2308T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,
2309 {
2310self.state.is::<ParamState<T::Item<'static, 'static>>>()
2311 }
23122313/// Returns the inner system param if it is the correct type.
2314 /// This consumes the dyn param, so the returned param can have its original world and state lifetimes.
2315pub fn downcast<T: SystemParam>(self) -> Option<T>
2316// See downcast() function for an explanation of the where clause
2317where
2318T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,
2319 {
2320// SAFETY:
2321 // - `DynSystemParam::new()` ensures `state` is a `ParamState<T>`, that the world matches,
2322 // and that it has access required by the inner system param.
2323 // - This consumes the `DynSystemParam`, so it is the only use of `world` with this access and it is available for `'w`.
2324unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }
2325 }
23262327/// Returns the inner system parameter if it is the correct type.
2328 /// This borrows the dyn param, so the returned param is only valid for the duration of that borrow.
2329pub fn downcast_mut<'a, T: SystemParam>(&'a mut self) -> Option<T>
2330// See downcast() function for an explanation of the where clause
2331where
2332T::Item<'static, 'static>: SystemParam<Item<'a, 'a> = T> + 'static,
2333 {
2334// SAFETY:
2335 // - `DynSystemParam::new()` ensures `state` is a `ParamState<T>`, that the world matches,
2336 // and that it has access required by the inner system param.
2337 // - This exclusively borrows the `DynSystemParam` for `'_`, so it is the only use of `world` with this access for `'_`.
2338unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }
2339 }
23402341/// Returns the inner system parameter if it is the correct type.
2342 /// This borrows the dyn param, so the returned param is only valid for the duration of that borrow,
2343 /// but since it only performs read access it can keep the original world lifetime.
2344 /// This can be useful with methods like [`Query::iter_inner()`] or [`Res::into_inner()`]
2345 /// to obtain references with the original world lifetime.
2346pub fn downcast_mut_inner<'a, T: ReadOnlySystemParam>(&'a mut self) -> Option<T>
2347// See downcast() function for an explanation of the where clause
2348where
2349T::Item<'static, 'static>: SystemParam<Item<'w, 'a> = T> + 'static,
2350 {
2351// SAFETY:
2352 // - `DynSystemParam::new()` ensures `state` is a `ParamState<T>`, that the world matches,
2353 // and that it has access required by the inner system param.
2354 // - The inner system param only performs read access, so it's safe to copy that access for the full `'w` lifetime.
2355unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }
2356 }
2357}
23582359/// # Safety
2360/// - `state` must be a `ParamState<T>` for some inner `T: SystemParam`.
2361/// - The passed [`UnsafeWorldCell`] must have access to any world data registered
2362/// in [`init_state`](SystemParam::init_state) for the inner system param.
2363/// - `world` must be the same `World` that was used to initialize
2364/// [`state`](SystemParam::init_state) for the inner system param.
2365unsafe fn downcast<'w, 's, T: SystemParam>(
2366 state: &'s mut dyn Any,
2367 system_meta: &SystemMeta,
2368 world: UnsafeWorldCell<'w>,
2369 change_tick: Tick,
2370) -> Option<T>
2371// We need a 'static version of the SystemParam to use with `Any::downcast_mut()`,
2372// and we need a <'w, 's> version to actually return.
2373// The type parameter T must be the one we return in order to get type inference from the return value.
2374// So we use `T::Item<'static, 'static>` as the 'static version, and require that it be 'static.
2375// That means the return value will be T::Item<'static, 'static>::Item<'w, 's>,
2376// so we constrain that to be equal to T.
2377// Every actual `SystemParam` implementation has `T::Item == T` up to lifetimes,
2378// so they should all work with this constraint.
2379where
2380T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,
2381{
2382state2383 .downcast_mut::<ParamState<T::Item<'static, 'static>>>()
2384 .and_then(|state| {
2385// SAFETY:
2386 // - The caller ensures the world has access for the underlying system param,
2387 // and since the downcast succeeded, the underlying system param is T.
2388 // - The caller ensures the `world` matches.
2389unsafe { T::Item::get_param(&mut state.0, system_meta, world, change_tick) }.ok()
2390 })
2391}
23922393/// The [`SystemParam::State`] for a [`DynSystemParam`].
2394pub struct DynSystemParamState(Box<dyn DynParamState>);
23952396impl DynSystemParamState {
2397pub(crate) fn new<T: SystemParam + 'static>(state: T::State) -> Self {
2398Self(Box::new(ParamState::<T>(state)))
2399 }
2400}
24012402/// Allows a [`SystemParam::State`] to be used as a trait object for implementing [`DynSystemParam`].
2403trait DynParamState: Sync + Send + Any {
2404/// Applies any deferred mutations stored in this [`SystemParam`]'s state.
2405 /// This is used to apply [`Commands`] during [`ApplyDeferred`](crate::prelude::ApplyDeferred).
2406 ///
2407 /// [`Commands`]: crate::prelude::Commands
2408fn apply(&mut self, system_meta: &SystemMeta, world: &mut World);
24092410/// Queues any deferred mutations to be applied at the next [`ApplyDeferred`](crate::prelude::ApplyDeferred).
2411fn queue(&mut self, system_meta: &SystemMeta, world: DeferredWorld);
24122413/// Registers any [`World`] access used by this [`SystemParam`]
2414fn init_access(
2415&self,
2416 system_meta: &mut SystemMeta,
2417 component_access_set: &mut FilteredAccessSet,
2418 world: &mut World,
2419 );
24202421/// Validates the inner parameter by calling [`SystemParam::get_param`] and discarding the value.
2422 ///
2423 /// # Safety
2424 /// Refer to [`SystemParam::get_param`].
2425unsafe fn validate(
2426&mut self,
2427 system_meta: &SystemMeta,
2428 world: UnsafeWorldCell,
2429 change_tick: Tick,
2430 ) -> Result<(), SystemParamValidationError>;
2431}
24322433/// A wrapper around a [`SystemParam::State`] that can be used as a trait object in a [`DynSystemParam`].
2434struct ParamState<T: SystemParam>(T::State);
24352436impl<T: SystemParam + 'static> DynParamStatefor ParamState<T> {
2437fn apply(&mut self, system_meta: &SystemMeta, world: &mut World) {
2438 T::apply(&mut self.0, system_meta, world);
2439 }
24402441fn queue(&mut self, system_meta: &SystemMeta, world: DeferredWorld) {
2442 T::queue(&mut self.0, system_meta, world);
2443 }
24442445fn init_access(
2446&self,
2447 system_meta: &mut SystemMeta,
2448 component_access_set: &mut FilteredAccessSet,
2449 world: &mut World,
2450 ) {
2451 T::init_access(&self.0, system_meta, component_access_set, world);
2452 }
24532454unsafe fn validate(
2455&mut self,
2456 system_meta: &SystemMeta,
2457 world: UnsafeWorldCell,
2458 change_tick: Tick,
2459 ) -> Result<(), SystemParamValidationError> {
2460// SAFETY: Upheld by caller.
2461unsafe { T::get_param(&mut self.0, system_meta, world, change_tick) }.map(drop)
2462 }
2463}
24642465// SAFETY: Delegates to the wrapped parameter, which ensures the safety requirements are met
2466unsafe impl SystemParamfor DynSystemParam<'_, '_> {
2467type State = DynSystemParamState;
24682469type Item<'world, 'state> = DynSystemParam<'world, 'state>;
24702471fn init_state(_world: &mut World) -> Self::State {
2472DynSystemParamState::new::<()>(())
2473 }
24742475fn init_access(
2476 state: &Self::State,
2477 system_meta: &mut SystemMeta,
2478 component_access_set: &mut FilteredAccessSet,
2479 world: &mut World,
2480 ) {
2481state2482 .0
2483.init_access(system_meta, component_access_set, world);
2484 }
24852486#[inline]
2487unsafe fn get_param<'world, 'state>(
2488 state: &'state mut Self::State,
2489 system_meta: &SystemMeta,
2490 world: UnsafeWorldCell<'world>,
2491 change_tick: Tick,
2492 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
2493// Validate the inner parameter eagerly so that systems using DynSystemParam
2494 // are correctly skipped by the executor when the inner param is unavailable.
2495 // SAFETY: Upheld by caller.
2496unsafe { state.0.validate(system_meta, world, change_tick) }?;
2497// SAFETY:
2498 // - `state.0` is a boxed `ParamState<T>`.
2499 // - `init_access` calls `DynParamState::init_access`, which calls `init_access` on the inner parameter,
2500 // so the caller ensures the world has the necessary access.
2501 // - The caller ensures that the provided world is the same and has the required access.
2502Ok(unsafe {
2503DynSystemParam::new(state.0.as_mut(), world, system_meta.clone(), change_tick)
2504 })
2505 }
25062507fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
2508state.0.apply(system_meta, world);
2509 }
25102511fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
2512state.0.queue(system_meta, world);
2513 }
2514}
25152516// SAFETY: Resource ComponentId access is applied to the access. If this FilteredResources
2517// conflicts with any prior access, a panic will occur.
2518unsafe impl SystemParamfor FilteredResources<'_, '_> {
2519type State = Access;
25202521type Item<'world, 'state> = FilteredResources<'world, 'state>;
25222523fn init_state(_world: &mut World) -> Self::State {
2524Access::new()
2525 }
25262527fn init_access(
2528 access: &Self::State,
2529 system_meta: &mut SystemMeta,
2530 component_access_set: &mut FilteredAccessSet,
2531 world: &mut World,
2532 ) {
2533let combined_access = component_access_set.combined_access();
2534let conflicts = combined_access.get_conflicts(access);
2535if !conflicts.is_empty() {
2536let accesses = conflicts.format_conflict_list(world.into());
2537let system_name = &system_meta.name;
2538{
::core::panicking::panic_fmt(format_args!("error[B0002]: FilteredResources in system {0} accesses resources(s){1} in a way that conflicts with a previous system parameter. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",
system_name, accesses));
};panic!("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");
2539 }
25402541let mut filter = FilteredAccess::matches_everything();
2542filter.access_mut().extend(access);
2543filter.and_with(IS_RESOURCE);
2544component_access_set.add(filter);
2545 }
25462547unsafe fn get_param<'world, 'state>(
2548 state: &'state mut Self::State,
2549 system_meta: &SystemMeta,
2550 world: UnsafeWorldCell<'world>,
2551 change_tick: Tick,
2552 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
2553// SAFETY: The caller ensures that `world` has access to anything registered in `init_access`,
2554 // and we registered all resource access in `state``.
2555Ok(unsafe { FilteredResources::new(world, state, system_meta.last_run, change_tick) })
2556 }
2557}
25582559// SAFETY: FilteredResources only reads resources.
2560unsafe impl ReadOnlySystemParamfor FilteredResources<'_, '_> {}
25612562// SAFETY: Resource ComponentId access is applied to the access. If this FilteredResourcesMut
2563// conflicts with any prior access, a panic will occur.
2564unsafe impl SystemParamfor FilteredResourcesMut<'_, '_> {
2565type State = Access;
25662567type Item<'world, 'state> = FilteredResourcesMut<'world, 'state>;
25682569fn init_state(_world: &mut World) -> Self::State {
2570Access::new()
2571 }
25722573fn init_access(
2574 access: &Self::State,
2575 system_meta: &mut SystemMeta,
2576 component_access_set: &mut FilteredAccessSet,
2577 world: &mut World,
2578 ) {
2579let combined_access = component_access_set.combined_access();
2580let conflicts = combined_access.get_conflicts(access);
2581if !conflicts.is_empty() {
2582let accesses = conflicts.format_conflict_list(world.into());
2583let system_name = &system_meta.name;
2584{
::core::panicking::panic_fmt(format_args!("error[B0002]: FilteredResourcesMut in system {0} accesses resources(s){1} in a way that conflicts with a previous system parameter. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",
system_name, accesses));
};panic!("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");
2585 }
25862587let mut filter = FilteredAccess::matches_everything();
2588filter.access_mut().extend(access);
2589filter.and_with(IS_RESOURCE);
2590component_access_set.add(filter);
2591 }
25922593unsafe fn get_param<'world, 'state>(
2594 state: &'state mut Self::State,
2595 system_meta: &SystemMeta,
2596 world: UnsafeWorldCell<'world>,
2597 change_tick: Tick,
2598 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
2599// SAFETY: The caller ensures that `world` has access to anything registered in `init_access`,
2600 // and we registered all resource access in `state``.
2601Ok(unsafe { FilteredResourcesMut::new(world, state, system_meta.last_run, change_tick) })
2602 }
2603}
26042605/// An error that occurs when a system parameter is not valid,
2606/// used by system executors to determine what to do with a system.
2607///
2608/// Returned as an error from [`SystemParam::get_param`],
2609/// and handled using the unified error handling mechanisms defined in [`bevy_ecs::error`].
2610#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SystemParamValidationError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field4_finish(f,
"SystemParamValidationError", "skipped", &self.skipped, "message",
&self.message, "param", &self.param, "field", &&self.field)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for SystemParamValidationError {
#[inline]
fn eq(&self, other: &SystemParamValidationError) -> bool {
self.skipped == other.skipped && self.message == other.message &&
self.param == other.param && self.field == other.field
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for SystemParamValidationError {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<bool>;
let _: ::core::cmp::AssertParamIsEq<Cow<'static, str>>;
let _: ::core::cmp::AssertParamIsEq<DebugName>;
let _: ::core::cmp::AssertParamIsEq<Cow<'static, str>>;
}
}Eq, #[automatically_derived]
impl ::core::clone::Clone for SystemParamValidationError {
#[inline]
fn clone(&self) -> SystemParamValidationError {
SystemParamValidationError {
skipped: ::core::clone::Clone::clone(&self.skipped),
message: ::core::clone::Clone::clone(&self.message),
param: ::core::clone::Clone::clone(&self.param),
field: ::core::clone::Clone::clone(&self.field),
}
}
}Clone, #[allow(unused_qualifications)]
#[automatically_derived]
impl ::thiserror::__private18::Error for SystemParamValidationError { }Error)]
2611pub struct SystemParamValidationError {
2612/// Whether the system should be skipped.
2613 ///
2614 /// If `false`, the error should be handled.
2615 /// By default, this will result in a panic. See [`error`](`crate::error`) for more information.
2616 ///
2617 /// This is the default behavior, and is suitable for system params that should *always* be valid,
2618 /// either because sensible fallback behavior exists (like [`Query`]) or because
2619 /// failures in validation should be considered a bug in the user's logic that must be immediately addressed (like [`Res`]).
2620 ///
2621 /// If `true`, the system should be skipped.
2622 /// This is set by wrapping the system param in [`If`],
2623 /// and indicates that the system is intended to only operate in certain application states.
2624pub skipped: bool,
26252626/// A message describing the validation error.
2627pub message: Cow<'static, str>,
26282629/// A string identifying the invalid parameter.
2630 /// This is usually the type name of the parameter.
2631pub param: DebugName,
26322633/// A string identifying the field within a parameter using `#[derive(SystemParam)]`.
2634 /// This will be an empty string for other parameters.
2635 ///
2636 /// This will be printed after `param` in the `Display` impl, and should include a `::` prefix if non-empty.
2637pub field: Cow<'static, str>,
2638}
26392640impl SystemParamValidationError {
2641/// Constructs a `SystemParamValidationError` that skips the system.
2642 /// The parameter name is initialized to the type name of `T`, so a `SystemParam` should usually pass `Self`.
2643pub fn skipped<T>(message: impl Into<Cow<'static, str>>) -> Self {
2644Self::new::<T>(true, message, Cow::Borrowed(""))
2645 }
26462647/// Constructs a `SystemParamValidationError` for an invalid parameter that should be treated as an error.
2648 /// The parameter name is initialized to the type name of `T`, so a `SystemParam` should usually pass `Self`.
2649pub fn invalid<T>(message: impl Into<Cow<'static, str>>) -> Self {
2650Self::new::<T>(false, message, Cow::Borrowed(""))
2651 }
26522653/// Constructs a `SystemParamValidationError` for an invalid parameter.
2654 /// The parameter name is initialized to the type name of `T`, so a `SystemParam` should usually pass `Self`.
2655pub fn new<T>(
2656 skipped: bool,
2657 message: impl Into<Cow<'static, str>>,
2658 field: impl Into<Cow<'static, str>>,
2659 ) -> Self {
2660Self {
2661skipped,
2662 message: message.into(),
2663 param: DebugName::type_name::<T>(),
2664 field: field.into(),
2665 }
2666 }
26672668pub(crate) const EMPTY: Self = Self {
2669 skipped: false,
2670 message: Cow::Borrowed(""),
2671 param: DebugName::borrowed(""),
2672 field: Cow::Borrowed(""),
2673 };
2674}
26752676impl Displayfor SystemParamValidationError {
2677fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
2678fmt.write_fmt(format_args!("Parameter `{0}{1}` failed validation: {2}",
self.param.shortname(), self.field, self.message))write!(
2679 fmt,
2680"Parameter `{}{}` failed validation: {}",
2681self.param.shortname(),
2682self.field,
2683self.message
2684 )?;
2685if !self.skipped {
2686fmt.write_fmt(format_args!("\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."))write!(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.")?;
2687 }
2688Ok(())
2689 }
2690}
26912692#[cfg(test)]
2693mod tests {
2694use super::*;
2695use crate::query::Without;
2696use crate::resource::IsResource;
2697use crate::system::assert_is_system;
2698use crate::world::EntityMut;
2699use core::cell::RefCell;
27002701#[test]
2702 #[should_panic]
2703fn non_send_alias() {
2704#[derive(Resource)]
2705struct A(usize);
2706fn my_system(mut res0: NonSendMut<A>, mut res1: NonSendMut<A>) {
2707 res0.0 += 1;
2708 res1.0 += 1;
2709 }
2710let mut world = World::new();
2711 world.insert_non_send(A(42));
2712let mut schedule = crate::schedule::Schedule::default();
2713 schedule.add_systems(my_system);
2714 schedule.run(&mut world);
2715 }
27162717#[test]
2718 #[should_panic]
2719fn non_send_and_entities() {
2720#[derive(Resource)]
2721struct A(usize);
2722fn my_system(mut ns: NonSendMut<A>, _: Query<EntityMut>) {
2723 ns.0 += 1;
2724 }
2725 assert_is_system(my_system);
2726 }
27272728#[test]
2729 #[should_panic]
2730fn res_and_entities() {
2731#[derive(Resource)]
2732struct A(usize);
2733fn my_system(mut res: ResMut<A>, _: Query<EntityMut>) {
2734 res.0 += 1;
2735 }
2736 assert_is_system(my_system);
2737 }
27382739#[test]
2740fn res_and_entities_filtered() {
2741#[derive(Resource)]
2742struct A(usize);
2743fn res_system(mut res: ResMut<A>, _: Query<EntityMut, Without<IsResource>>) {
2744 res.0 += 1;
2745 }
2746 assert_is_system(res_system);
27472748fn non_send_system(mut ns: NonSendMut<A>, _: Query<EntityMut, Without<A>>) {
2749 ns.0 += 1;
2750 }
27512752 assert_is_system(non_send_system);
2753 }
27542755// Compile test for https://github.com/bevyengine/bevy/pull/2838.
2756#[test]
2757fn system_param_generic_bounds() {
2758#[derive(SystemParam)]
2759pub struct SpecialQuery<
2760'w,
2761's,
2762 D: QueryData + Send + Sync + 'static,
2763 F: QueryFilter + Send + Sync + 'static = (),
2764 > {
2765 _query: Query<'w, 's, D, F>,
2766 }
27672768fn my_system(_: SpecialQuery<(), ()>) {}
2769 assert_is_system(my_system);
2770 }
27712772// Compile tests for https://github.com/bevyengine/bevy/pull/6694.
2773#[test]
2774fn system_param_flexibility() {
2775#[derive(SystemParam)]
2776pub struct SpecialRes<'w, T: Resource> {
2777 _res: Res<'w, T>,
2778 }
27792780#[derive(SystemParam)]
2781pub struct SpecialLocal<'s, T: FromWorld + Send + 'static> {
2782 _local: Local<'s, T>,
2783 }
27842785#[derive(Resource)]
2786struct R;
27872788fn my_system(_: SpecialRes<R>, _: SpecialLocal<u32>) {}
2789 assert_is_system(my_system);
2790 }
27912792#[derive(Resource)]
2793pub struct R<const I: usize>;
27942795// Compile test for https://github.com/bevyengine/bevy/pull/7001.
2796#[test]
2797fn system_param_const_generics() {
2798#[expect(
2799 dead_code,
2800 reason = "This struct is used to ensure that const generics are supported as a SystemParam; thus, the inner value never needs to be read."
2801)]
2802 #[derive(SystemParam)]
2803pub struct ConstGenericParam<'w, const I: usize>(Res<'w, R<I>>);
28042805fn my_system(_: ConstGenericParam<0>, _: ConstGenericParam<1000>) {}
2806 assert_is_system(my_system);
2807 }
28082809// Compile test for https://github.com/bevyengine/bevy/pull/6867.
2810#[test]
2811fn system_param_field_limit() {
2812#[derive(SystemParam)]
2813pub struct LongParam<'w> {
2814// Each field should be a distinct type so there will
2815 // be an error if the derive messes up the field order.
2816_r0: Res<'w, R<0>>,
2817 _r1: Res<'w, R<1>>,
2818 _r2: Res<'w, R<2>>,
2819 _r3: Res<'w, R<3>>,
2820 _r4: Res<'w, R<4>>,
2821 _r5: Res<'w, R<5>>,
2822 _r6: Res<'w, R<6>>,
2823 _r7: Res<'w, R<7>>,
2824 _r8: Res<'w, R<8>>,
2825 _r9: Res<'w, R<9>>,
2826 _r10: Res<'w, R<10>>,
2827 _r11: Res<'w, R<11>>,
2828 _r12: Res<'w, R<12>>,
2829 _r13: Res<'w, R<13>>,
2830 _r14: Res<'w, R<14>>,
2831 _r15: Res<'w, R<15>>,
2832 _r16: Res<'w, R<16>>,
2833 }
28342835fn long_system(_: LongParam) {}
2836 assert_is_system(long_system);
2837 }
28382839// Compile test for https://github.com/bevyengine/bevy/pull/6919.
2840 // Regression test for https://github.com/bevyengine/bevy/issues/7447.
2841#[test]
2842fn system_param_phantom_data() {
2843#[derive(SystemParam)]
2844struct PhantomParam<'w, T: Resource, Marker: 'static> {
2845 _foo: Res<'w, T>,
2846 marker: PhantomData<&'w Marker>,
2847 }
28482849fn my_system(_: PhantomParam<R<0>, ()>) {}
2850 assert_is_system(my_system);
2851 }
28522853// Compile tests for https://github.com/bevyengine/bevy/pull/6957.
2854#[test]
2855fn system_param_struct_variants() {
2856#[derive(SystemParam)]
2857pub struct UnitParam;
28582859#[expect(
2860 dead_code,
2861 reason = "This struct is used to ensure that tuple structs are supported as a SystemParam; thus, the inner values never need to be read."
2862)]
2863 #[derive(SystemParam)]
2864pub struct TupleParam<'w, 's, R: Resource, L: FromWorld + Send + 'static>(
2865 Res<'w, R>,
2866 Local<'s, L>,
2867 );
28682869fn my_system(_: UnitParam, _: TupleParam<R<0>, u32>) {}
2870 assert_is_system(my_system);
2871 }
28722873// Regression test for https://github.com/bevyengine/bevy/issues/4200.
2874#[test]
2875fn system_param_private_fields() {
2876#[derive(Resource)]
2877struct PrivateResource;
28782879#[expect(
2880 dead_code,
2881 reason = "This struct is used to ensure that SystemParam's derive can't leak private fields; thus, the inner values never need to be read."
2882)]
2883 #[derive(SystemParam)]
2884pub struct EncapsulatedParam<'w>(Res<'w, PrivateResource>);
28852886fn my_system(_: EncapsulatedParam) {}
2887 assert_is_system(my_system);
2888 }
28892890// Regression test for https://github.com/bevyengine/bevy/issues/7103.
2891#[test]
2892fn system_param_where_clause() {
2893#[derive(SystemParam)]
2894pub struct WhereParam<'w, 's, D>
2895where
2896D: 'static + QueryData,
2897 {
2898 _q: Query<'w, 's, D, ()>,
2899 }
29002901fn my_system(_: WhereParam<()>) {}
2902 assert_is_system(my_system);
2903 }
29042905// Regression test for https://github.com/bevyengine/bevy/issues/1727.
2906#[test]
2907fn system_param_name_collision() {
2908#[derive(Resource)]
2909pub struct FetchState;
29102911#[derive(SystemParam)]
2912pub struct Collide<'w> {
2913 _x: Res<'w, FetchState>,
2914 }
29152916fn my_system(_: Collide) {}
2917 assert_is_system(my_system);
2918 }
29192920// Regression test for https://github.com/bevyengine/bevy/issues/8192.
2921#[test]
2922fn system_param_invariant_lifetime() {
2923#[derive(SystemParam)]
2924pub struct InvariantParam<'w, 's> {
2925 _set: ParamSet<'w, 's, (Query<'w, 's, ()>,)>,
2926 }
29272928fn my_system(_: InvariantParam) {}
2929 assert_is_system(my_system);
2930 }
29312932// Compile test for https://github.com/bevyengine/bevy/pull/9589.
2933#[test]
2934fn non_sync_local() {
2935fn non_sync_system(cell: Local<RefCell<u8>>) {
2936assert_eq!(*cell.borrow(), 0);
2937 }
29382939let mut world = World::new();
2940let mut schedule = crate::schedule::Schedule::default();
2941 schedule.add_systems(non_sync_system);
2942 schedule.run(&mut world);
2943 }
29442945// Regression test for https://github.com/bevyengine/bevy/issues/10207.
2946#[test]
2947fn param_set_non_send_first() {
2948fn non_send_param_set(mut p: ParamSet<(NonSend<*mut u8>, ())>) {
2949let _ = p.p0();
2950 p.p1();
2951 }
29522953let mut world = World::new();
2954 world.insert_non_send(core::ptr::null_mut::<u8>());
2955let mut schedule = crate::schedule::Schedule::default();
2956 schedule.add_systems((non_send_param_set, non_send_param_set, non_send_param_set));
2957 schedule.run(&mut world);
2958 }
29592960// Regression test for https://github.com/bevyengine/bevy/issues/10207.
2961#[test]
2962fn param_set_non_send_second() {
2963fn non_send_param_set(mut p: ParamSet<((), NonSendMut<*mut u8>)>) {
2964 p.p0();
2965let _ = p.p1();
2966 }
29672968let mut world = World::new();
2969 world.insert_non_send(core::ptr::null_mut::<u8>());
2970let mut schedule = crate::schedule::Schedule::default();
2971 schedule.add_systems((non_send_param_set, non_send_param_set, non_send_param_set));
2972 schedule.run(&mut world);
2973 }
29742975fn _dyn_system_param_type_inference(mut p: DynSystemParam) {
2976// Make sure the downcast() methods are able to infer their type parameters from the use of the return type.
2977 // This is just a compilation test, so there is nothing to run.
2978let _query: Query<()> = p.downcast_mut().unwrap();
2979let _query: Query<()> = p.downcast_mut_inner().unwrap();
2980let _query: Query<()> = p.downcast().unwrap();
2981 }
29822983#[test]
2984 #[should_panic]
2985fn missing_resource_error() {
2986#[derive(Resource)]
2987pub struct MissingResource;
29882989let mut schedule = crate::schedule::Schedule::default();
2990 schedule.add_systems(res_system);
2991let mut world = World::new();
2992 schedule.run(&mut world);
29932994fn res_system(_: Res<MissingResource>) {}
2995 }
29962997#[test]
2998 #[should_panic]
2999fn missing_message_error() {
3000use crate::prelude::{Message, MessageReader};
30013002#[derive(Message)]
3003pub struct MissingEvent;
30043005let mut schedule = crate::schedule::Schedule::default();
3006 schedule.add_systems(message_system);
3007let mut world = World::new();
3008 schedule.run(&mut world);
30093010fn message_system(_: MessageReader<MissingEvent>) {}
3011 }
3012}