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