1#![expect(
2 unsafe_op_in_unsafe_fn,
3 reason = "See #11590. To be removed once all applicable unsafe code has an unsafe block with a safety comment."
4)]
5
6pub use crate::change_detection::{NonSend, NonSendMut, Res, ResMut};
7use crate::{
8 archetype::Archetypes,
9 bundle::Bundles,
10 change_detection::{ComponentTicksMut, ComponentTicksRef, Tick},
11 component::{ComponentId, Components, Mutable},
12 entity::{Entities, EntityAllocator},
13 query::{
14 Access, FilteredAccess, FilteredAccessSet, IterQueryData, QueryData, QueryFilter,
15 QuerySingleError, QueryState, ReadOnlyQueryData,
16 },
17 resource::{Resource, IS_RESOURCE},
18 system::{Query, Single, SystemMeta},
19 world::{
20 unsafe_world_cell::UnsafeWorldCell, DeferredWorld, FilteredResources, FilteredResourcesMut,
21 FromWorld, World,
22 },
23};
24use alloc::{borrow::Cow, boxed::Box, vec::Vec};
25pub use bevy_ecs_macros::SystemParam;
26use bevy_platform::cell::SyncCell;
27use bevy_ptr::UnsafeCellDeref;
28use bevy_utils::prelude::DebugName;
29use core::{
30 any::Any,
31 fmt::{Debug, Display},
32 marker::PhantomData,
33 ops::{Deref, DerefMut},
34};
35use smallvec::SmallVec;
36use thiserror::Error;
37
38use super::Populated;
39use variadics_please::{all_tuples, all_tuples_enumerated};
40
41pub unsafe trait SystemParam: Sized {
219 type State: Send + Sync + 'static;
221
222 type Item<'world, 'state>: SystemParam<State = Self::State>;
227
228 fn init_state(world: &mut World) -> Self::State;
230
231 fn init_access(
235 state: &Self::State,
236 system_meta: &mut SystemMeta,
237 component_access_set: &mut FilteredAccessSet,
238 world: &mut World,
239 );
240
241 #[inline]
246 #[expect(
247 unused_variables,
248 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."
249 )]
250 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {}
251
252 #[inline]
254 #[expect(
255 unused_variables,
256 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."
257 )]
258 fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {}
259
260 unsafe fn get_param<'world, 'state>(
280 state: &'state mut Self::State,
281 system_meta: &SystemMeta,
282 world: UnsafeWorldCell<'world>,
283 change_tick: Tick,
284 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError>;
285}
286
287pub unsafe trait ReadOnlySystemParam: SystemParam {}
292
293pub type SystemParamItem<'w, 's, P> = <P as SystemParam>::Item<'w, 's>;
295
296unsafe impl<'w, 's, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam
298 for Query<'w, 's, D, F>
299{
300}
301
302unsafe impl<D: QueryData + 'static, F: QueryFilter + 'static> SystemParam for Query<'_, '_, D, F> {
305 type State = QueryState<D, F>;
306 type Item<'w, 's> = Query<'w, 's, D, F>;
307
308 fn init_state(world: &mut World) -> Self::State {
309 unsafe { QueryState::new_unchecked(world) }
313 }
314
315 fn init_access(
316 state: &Self::State,
317 system_meta: &mut SystemMeta,
318 component_access_set: &mut FilteredAccessSet,
319 world: &mut World,
320 ) {
321 state.init_access(Some(system_meta.name()), component_access_set, world.into());
322 }
323
324 #[inline]
325 unsafe fn get_param<'w, 's>(
326 state: &'s mut Self::State,
327 system_meta: &SystemMeta,
328 world: UnsafeWorldCell<'w>,
329 change_tick: Tick,
330 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
331 Ok(unsafe { state.query_unchecked_with_ticks(world, system_meta.last_run, change_tick) })
336 }
337}
338
339unsafe impl<'a, 'b, D: IterQueryData + 'static, F: QueryFilter + 'static> SystemParam
342 for Single<'a, 'b, D, F>
343{
344 type State = QueryState<D, F>;
345 type Item<'w, 's> = Single<'w, 's, D, F>;
346
347 fn init_state(world: &mut World) -> Self::State {
348 Query::init_state(world)
349 }
350
351 fn init_access(
352 state: &Self::State,
353 system_meta: &mut SystemMeta,
354 component_access_set: &mut FilteredAccessSet,
355 world: &mut World,
356 ) {
357 Query::init_access(state, system_meta, component_access_set, world);
358 }
359
360 #[inline]
361 unsafe fn get_param<'w, 's>(
362 state: &'s mut Self::State,
363 system_meta: &SystemMeta,
364 world: UnsafeWorldCell<'w>,
365 change_tick: Tick,
366 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
367 let query =
370 unsafe { state.query_unchecked_with_ticks(world, system_meta.last_run, change_tick) };
371 match query.single_inner() {
372 Ok(single) => Ok(Single {
373 item: single,
374 _filter: PhantomData,
375 }),
376 Err(QuerySingleError::NoEntities(_)) => Err(
377 SystemParamValidationError::skipped::<Self>("No matching entities"),
378 ),
379 Err(QuerySingleError::MultipleEntities(_)) => Err(
380 SystemParamValidationError::skipped::<Self>("Multiple matching entities"),
381 ),
382 }
383 }
384}
385
386unsafe impl<'a, 'b, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam
388 for Single<'a, 'b, D, F>
389{
390}
391
392unsafe impl<D: QueryData + 'static, F: QueryFilter + 'static> SystemParam
395 for Populated<'_, '_, D, F>
396{
397 type State = QueryState<D, F>;
398 type Item<'w, 's> = Populated<'w, 's, D, F>;
399
400 fn init_state(world: &mut World) -> Self::State {
401 Query::init_state(world)
402 }
403
404 fn init_access(
405 state: &Self::State,
406 system_meta: &mut SystemMeta,
407 component_access_set: &mut FilteredAccessSet,
408 world: &mut World,
409 ) {
410 Query::init_access(state, system_meta, component_access_set, world);
411 }
412
413 #[inline]
414 unsafe fn get_param<'w, 's>(
415 state: &'s mut Self::State,
416 system_meta: &SystemMeta,
417 world: UnsafeWorldCell<'w>,
418 change_tick: Tick,
419 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
420 let query = unsafe { Query::get_param(state, system_meta, world, change_tick) }?;
422 if query.is_empty() {
423 Err(SystemParamValidationError::skipped::<Self>(
424 "No matching entities",
425 ))
426 } else {
427 Ok(Populated(query))
428 }
429 }
430}
431
432unsafe impl<'w, 's, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam
434 for Populated<'w, 's, D, F>
435{
436}
437
438pub struct ParamSet<'w, 's, T: SystemParam> {
554 param_states: &'s mut T::State,
555 world: UnsafeWorldCell<'w>,
556 system_meta: SystemMeta,
557 change_tick: Tick,
558}
559
560macro_rules! impl_param_set {
561 ($(($index: tt, $param: ident, $fn_name: ident)),*) => {
562 unsafe impl<'w, 's, $($param,)*> ReadOnlySystemParam for ParamSet<'w, 's, ($($param,)*)>
564 where $($param: ReadOnlySystemParam,)*
565 { }
566
567 unsafe impl<'_w, '_s, $($param: SystemParam,)*> SystemParam for ParamSet<'_w, '_s, ($($param,)*)>
570 {
571 type State = ($($param::State,)*);
572 type Item<'w, 's> = ParamSet<'w, 's, ($($param,)*)>;
573
574 #[expect(
575 clippy::allow_attributes,
576 reason = "This is inside a macro meant for tuples; as such, `non_snake_case` won't always lint."
577 )]
578 #[allow(
579 non_snake_case,
580 reason = "Certain variable names are provided by the caller, not by us."
581 )]
582 fn init_state(world: &mut World) -> Self::State {
583 ($($param::init_state(world),)*)
584 }
585
586 #[expect(
587 clippy::allow_attributes,
588 reason = "This is inside a macro meant for tuples; as such, `non_snake_case` won't always lint."
589 )]
590 #[allow(
591 non_snake_case,
592 reason = "Certain variable names are provided by the caller, not by us."
593 )]
594 fn init_access(state: &Self::State, system_meta: &mut SystemMeta, component_access_set: &mut FilteredAccessSet, world: &mut World) {
595 let ($($param,)*) = state;
596 $(
597 let component_access_set_clone = &mut component_access_set.clone();
599 $param::init_access($param, system_meta, component_access_set_clone, world);
600 )*
601 $(
602 let mut access_set = FilteredAccessSet::new();
605 $param::init_access($param, system_meta, &mut access_set, world);
606 component_access_set.extend(access_set);
607 )*
608 }
609
610 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
611 <($($param,)*) as SystemParam>::apply(state, system_meta, world);
612 }
613
614 fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
615 <($($param,)*) as SystemParam>::queue(state, system_meta, world.reborrow());
616 }
617
618 #[inline]
619 unsafe fn get_param<'w, 's>(
620 state: &'s mut Self::State,
621 system_meta: &SystemMeta,
622 world: UnsafeWorldCell<'w>,
623 change_tick: Tick,
624 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
625 $(
631 drop(unsafe { $param::get_param(&mut state.$index, system_meta, world, change_tick) }?);
633 )*
634
635 Ok(ParamSet {
636 param_states: state,
637 system_meta: system_meta.clone(),
638 world,
639 change_tick,
640 })
641 }
642 }
643
644 impl<'w, 's, $($param: SystemParam,)*> ParamSet<'w, 's, ($($param,)*)>
645 {
646 $(
647 #[doc = stringify!($index)]
649 pub fn $fn_name<'a>(&'a mut self) -> SystemParamItem<'a, 'a, $param> {
652 unsafe {
656 $param::get_param(&mut self.param_states.$index, &self.system_meta, self.world, self.change_tick)
657 }
658 .unwrap_or_else(|err| panic!("ParamSet parameter validation failed: {err}"))
659 }
660 )*
661 }
662 }
663}
664
665all_tuples_enumerated!(impl_param_set, 1, 8, P, p);
666
667unsafe impl<'a, T: Resource> ReadOnlySystemParam for Res<'a, T> {}
669
670unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> {
673 type State = ComponentId;
674 type Item<'w, 's> = Res<'w, T>;
675
676 fn init_state(world: &mut World) -> Self::State {
677 world.components_registrator().register_component::<T>()
678 }
679
680 fn init_access(
681 &component_id: &Self::State,
682 system_meta: &mut SystemMeta,
683 component_access_set: &mut FilteredAccessSet,
684 world: &mut World,
685 ) {
686 let mut filter = FilteredAccess::default();
687 filter.add_read(component_id);
688 filter.and_with(IS_RESOURCE);
689
690 let conflicts = component_access_set.get_conflicts_single(&filter);
691 if conflicts.is_empty() {
692 component_access_set.add(filter);
693 return;
694 }
695
696 let mut accesses = conflicts.format_conflict_list(world.as_unsafe_world_cell());
697 if !accesses.is_empty() {
699 accesses.push(' ');
700 }
701 panic!("error[B0002]: Res<{}> in system {} conflicts with a previous system parameter. Consider removing the duplicate access using `Without<IsResource>` to create disjoint Queries or merging conflicting Queries into a `ParamSet`. See: https://bevy.org/learn/errors/b0002", DebugName::type_name::<T>(), system_meta.name);
702 }
703
704 #[inline]
705 unsafe fn get_param<'w, 's>(
706 &mut component_id: &'s mut Self::State,
707 system_meta: &SystemMeta,
708 world: UnsafeWorldCell<'w>,
709 change_tick: Tick,
710 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
711 let (ptr, ticks) = world.get_resource_with_ticks(component_id).ok_or_else(|| {
712 SystemParamValidationError::invalid::<Self>("Resource does not exist")
713 })?;
714 Ok(Res {
715 value: ptr.deref(),
716 ticks: ComponentTicksRef {
717 added: ticks.added.deref(),
718 changed: ticks.changed.deref(),
719 changed_by: ticks.changed_by.map(|changed_by| changed_by.deref()),
720 last_run: system_meta.last_run,
721 this_run: change_tick,
722 },
723 })
724 }
725}
726
727unsafe impl<'a, T: Resource<Mutability = Mutable>> SystemParam for ResMut<'a, T> {
730 type State = ComponentId;
731 type Item<'w, 's> = ResMut<'w, T>;
732
733 fn init_state(world: &mut World) -> Self::State {
734 world.components_registrator().register_component::<T>()
735 }
736
737 fn init_access(
738 &component_id: &Self::State,
739 system_meta: &mut SystemMeta,
740 component_access_set: &mut FilteredAccessSet,
741 world: &mut World,
742 ) {
743 let mut filter = FilteredAccess::default();
744 filter.add_write(component_id);
745 filter.and_with(IS_RESOURCE);
746
747 let conflicts = component_access_set.get_conflicts_single(&filter);
748 if conflicts.is_empty() {
749 component_access_set.add(filter);
750 return;
751 }
752
753 let mut accesses = conflicts.format_conflict_list(world.as_unsafe_world_cell());
754 if !accesses.is_empty() {
756 accesses.push(' ');
757 }
758 panic!("error[B0002]: ResMut<{}> in system {} conflicts with a previous system parameter. Consider removing the duplicate access or using `Without<IsResource>` to create disjoint Queries or merging conflicting Queries into a `ParamSet`. See: https://bevy.org/learn/errors/b0002", DebugName::type_name::<T>(), system_meta.name);
759 }
760
761 #[inline]
762 unsafe fn get_param<'w, 's>(
763 &mut component_id: &'s mut Self::State,
764 system_meta: &SystemMeta,
765 world: UnsafeWorldCell<'w>,
766 change_tick: Tick,
767 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
768 let value = world.get_resource_mut_by_id(component_id).ok_or_else(|| {
769 SystemParamValidationError::invalid::<Self>("Resource does not exist")
770 })?;
771 Ok(ResMut {
772 value: value.value.deref_mut::<T>(),
773 ticks: ComponentTicksMut {
774 added: value.ticks.added,
775 changed: value.ticks.changed,
776 changed_by: value.ticks.changed_by,
777 last_run: system_meta.last_run,
778 this_run: change_tick,
779 },
780 })
781 }
782}
783
784unsafe impl<'w> ReadOnlySystemParam for &'w World {}
786
787unsafe impl SystemParam for &'_ World {
789 type State = ();
790 type Item<'w, 's> = &'w World;
791
792 fn init_state(_world: &mut World) -> Self::State {}
793
794 fn init_access(
795 _state: &Self::State,
796 _system_meta: &mut SystemMeta,
797 component_access_set: &mut FilteredAccessSet,
798 _world: &mut World,
799 ) {
800 let mut filtered_access = FilteredAccess::default();
801
802 filtered_access.read_all();
803 if !component_access_set
804 .get_conflicts_single(&filtered_access)
805 .is_empty()
806 {
807 panic!("&World conflicts with a previous mutable system parameter. Allowing this would break Rust's mutability rules");
808 }
809 component_access_set.add(filtered_access);
810 }
811
812 #[inline]
813 unsafe fn get_param<'w, 's>(
814 _state: &'s mut Self::State,
815 _system_meta: &SystemMeta,
816 world: UnsafeWorldCell<'w>,
817 _change_tick: Tick,
818 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
819 Ok(unsafe { world.world() })
821 }
822}
823
824unsafe impl<'w> SystemParam for DeferredWorld<'w> {
826 type State = ();
827 type Item<'world, 'state> = DeferredWorld<'world>;
828
829 fn init_state(_world: &mut World) -> Self::State {}
830
831 fn init_access(
832 _state: &Self::State,
833 system_meta: &mut SystemMeta,
834 component_access_set: &mut FilteredAccessSet,
835 _world: &mut World,
836 ) {
837 assert!(
838 !component_access_set.combined_access().has_any_read(),
839 "DeferredWorld in system {} conflicts with a previous access.",
840 system_meta.name,
841 );
842 component_access_set.write_all();
843 }
844
845 unsafe fn get_param<'world, 'state>(
846 _state: &'state mut Self::State,
847 _system_meta: &SystemMeta,
848 world: UnsafeWorldCell<'world>,
849 _change_tick: Tick,
850 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
851 Ok(unsafe { world.into_deferred() })
853 }
854}
855
856#[derive(Debug)]
973pub struct Local<'s, T: FromWorld + Send + 'static>(pub(crate) &'s mut T);
974
975unsafe impl<'s, T: FromWorld + Send + 'static> ReadOnlySystemParam for Local<'s, T> {}
977
978impl<'s, T: FromWorld + Send + 'static> Deref for Local<'s, T> {
979 type Target = T;
980
981 #[inline]
982 fn deref(&self) -> &Self::Target {
983 self.0
984 }
985}
986
987impl<'s, T: FromWorld + Send + 'static> DerefMut for Local<'s, T> {
988 #[inline]
989 fn deref_mut(&mut self) -> &mut Self::Target {
990 self.0
991 }
992}
993
994impl<'s, 'a, T: FromWorld + Send + 'static> IntoIterator for &'a Local<'s, T>
995where
996 &'a T: IntoIterator,
997{
998 type Item = <&'a T as IntoIterator>::Item;
999 type IntoIter = <&'a T as IntoIterator>::IntoIter;
1000
1001 fn into_iter(self) -> Self::IntoIter {
1002 self.0.into_iter()
1003 }
1004}
1005
1006impl<'s, 'a, T: FromWorld + Send + 'static> IntoIterator for &'a mut Local<'s, T>
1007where
1008 &'a mut T: IntoIterator,
1009{
1010 type Item = <&'a mut T as IntoIterator>::Item;
1011 type IntoIter = <&'a mut T as IntoIterator>::IntoIter;
1012
1013 fn into_iter(self) -> Self::IntoIter {
1014 self.0.into_iter()
1015 }
1016}
1017
1018unsafe impl<'a, T: FromWorld + Send + 'static> SystemParam for Local<'a, T> {
1020 type State = SyncCell<T>;
1021 type Item<'w, 's> = Local<'s, T>;
1022
1023 fn init_state(world: &mut World) -> Self::State {
1024 SyncCell::new(T::from_world(world))
1025 }
1026
1027 fn init_access(
1028 _state: &Self::State,
1029 _system_meta: &mut SystemMeta,
1030 _component_access_set: &mut FilteredAccessSet,
1031 _world: &mut World,
1032 ) {
1033 }
1034
1035 #[inline]
1036 unsafe fn get_param<'w, 's>(
1037 state: &'s mut Self::State,
1038 _system_meta: &SystemMeta,
1039 _world: UnsafeWorldCell<'w>,
1040 _change_tick: Tick,
1041 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
1042 Ok(Local(state.get()))
1043 }
1044}
1045
1046pub trait SystemBuffer: FromWorld + Send + 'static {
1053 fn apply(&mut self, system_meta: &SystemMeta, world: &mut World) {
1055 self.queue(system_meta, world.into());
1056 }
1057 fn queue(&mut self, _system_meta: &SystemMeta, _world: DeferredWorld);
1062}
1063
1064pub struct Deferred<'a, T: SystemBuffer>(pub(crate) &'a mut T);
1185
1186impl<'a, T: SystemBuffer> Deref for Deferred<'a, T> {
1187 type Target = T;
1188 #[inline]
1189 fn deref(&self) -> &Self::Target {
1190 self.0
1191 }
1192}
1193
1194impl<'a, T: SystemBuffer> DerefMut for Deferred<'a, T> {
1195 #[inline]
1196 fn deref_mut(&mut self) -> &mut Self::Target {
1197 self.0
1198 }
1199}
1200
1201impl<T: SystemBuffer> Deferred<'_, T> {
1202 pub fn reborrow(&mut self) -> Deferred<'_, T> {
1205 Deferred(self.0)
1206 }
1207}
1208
1209unsafe impl<T: SystemBuffer> ReadOnlySystemParam for Deferred<'_, T> {}
1211
1212unsafe impl<T: SystemBuffer> SystemParam for Deferred<'_, T> {
1214 type State = SyncCell<T>;
1215 type Item<'w, 's> = Deferred<'s, T>;
1216
1217 #[track_caller]
1218 fn init_state(world: &mut World) -> Self::State {
1219 SyncCell::new(T::from_world(world))
1220 }
1221
1222 fn init_access(
1223 _state: &Self::State,
1224 system_meta: &mut SystemMeta,
1225 _component_access_set: &mut FilteredAccessSet,
1226 _world: &mut World,
1227 ) {
1228 system_meta.set_has_deferred();
1229 }
1230
1231 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1232 state.get().apply(system_meta, world);
1233 }
1234
1235 fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
1236 state.get().queue(system_meta, world);
1237 }
1238
1239 #[inline]
1240 unsafe fn get_param<'w, 's>(
1241 state: &'s mut Self::State,
1242 _system_meta: &SystemMeta,
1243 _world: UnsafeWorldCell<'w>,
1244 _change_tick: Tick,
1245 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
1246 Ok(Deferred(state.get()))
1247 }
1248}
1249
1250pub struct ExclusiveMarker(PhantomData<()>);
1252
1253unsafe impl SystemParam for ExclusiveMarker {
1255 type State = ();
1256 type Item<'w, 's> = Self;
1257
1258 #[inline]
1259 fn init_state(_world: &mut World) -> Self::State {}
1260
1261 fn init_access(
1262 _state: &Self::State,
1263 system_meta: &mut SystemMeta,
1264 _component_access_set: &mut FilteredAccessSet,
1265 _world: &mut World,
1266 ) {
1267 system_meta.set_exclusive();
1268 }
1269
1270 #[inline]
1271 unsafe fn get_param<'world, 'state>(
1272 _state: &'state mut Self::State,
1273 _system_meta: &SystemMeta,
1274 _world: UnsafeWorldCell<'world>,
1275 _change_tick: Tick,
1276 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
1277 Ok(Self(PhantomData))
1278 }
1279}
1280
1281unsafe impl ReadOnlySystemParam for ExclusiveMarker {}
1283
1284pub struct NonSendMarker(PhantomData<*mut ()>);
1286
1287unsafe impl SystemParam for NonSendMarker {
1289 type State = ();
1290 type Item<'w, 's> = Self;
1291
1292 #[inline]
1293 fn init_state(_world: &mut World) -> Self::State {}
1294
1295 fn init_access(
1296 _state: &Self::State,
1297 system_meta: &mut SystemMeta,
1298 _component_access_set: &mut FilteredAccessSet,
1299 _world: &mut World,
1300 ) {
1301 system_meta.set_non_send();
1302 }
1303
1304 #[inline]
1305 unsafe fn get_param<'world, 'state>(
1306 _state: &'state mut Self::State,
1307 _system_meta: &SystemMeta,
1308 _world: UnsafeWorldCell<'world>,
1309 _change_tick: Tick,
1310 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
1311 Ok(Self(PhantomData))
1312 }
1313}
1314
1315unsafe impl ReadOnlySystemParam for NonSendMarker {}
1317
1318unsafe impl<'w, T> ReadOnlySystemParam for NonSend<'w, T> {}
1320
1321unsafe impl<'a, T: 'static> SystemParam for NonSend<'a, T> {
1324 type State = ComponentId;
1325 type Item<'w, 's> = NonSend<'w, T>;
1326
1327 fn init_state(world: &mut World) -> Self::State {
1328 world.components_registrator().register_non_send::<T>()
1329 }
1330
1331 fn init_access(
1332 &component_id: &Self::State,
1333 system_meta: &mut SystemMeta,
1334 component_access_set: &mut FilteredAccessSet,
1335 _world: &mut World,
1336 ) {
1337 system_meta.set_non_send();
1338
1339 let combined_access = component_access_set.combined_access();
1340 assert!(
1341 !combined_access.has_write(component_id),
1342 "error[B0002]: NonSend<{}> in system {} conflicts with a previous mutable resource access ({0}). Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",
1343 DebugName::type_name::<T>(),
1344 system_meta.name,
1345 );
1346 component_access_set.add_unfiltered_component_read(component_id);
1347 }
1348
1349 #[inline]
1350 unsafe fn get_param<'w, 's>(
1351 &mut component_id: &'s mut Self::State,
1352 system_meta: &SystemMeta,
1353 world: UnsafeWorldCell<'w>,
1354 change_tick: Tick,
1355 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
1356 let (ptr, ticks) = world.get_non_send_with_ticks(component_id).ok_or_else(|| {
1357 SystemParamValidationError::invalid::<Self>("Non-send data not found")
1358 })?;
1359 Ok(NonSend {
1360 value: ptr.deref(),
1361 ticks: ComponentTicksRef::from_tick_cells(ticks, system_meta.last_run, change_tick),
1362 })
1363 }
1364}
1365
1366unsafe impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> {
1369 type State = ComponentId;
1370 type Item<'w, 's> = NonSendMut<'w, T>;
1371
1372 fn init_state(world: &mut World) -> Self::State {
1373 world.components_registrator().register_non_send::<T>()
1374 }
1375
1376 fn init_access(
1377 &component_id: &Self::State,
1378 system_meta: &mut SystemMeta,
1379 component_access_set: &mut FilteredAccessSet,
1380 _world: &mut World,
1381 ) {
1382 system_meta.set_non_send();
1383
1384 let combined_access = component_access_set.combined_access();
1385 if combined_access.has_write(component_id) {
1386 panic!(
1387 "error[B0002]: NonSendMut<{}> in system {} conflicts with a previous mutable resource access ({0}). Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",
1388 DebugName::type_name::<T>(), system_meta.name);
1389 } else if combined_access.has_read(component_id) {
1390 panic!(
1391 "error[B0002]: NonSendMut<{}> in system {} conflicts with a previous immutable resource access ({0}). Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",
1392 DebugName::type_name::<T>(), system_meta.name);
1393 }
1394 component_access_set.add_unfiltered_component_write(component_id);
1395 }
1396
1397 #[inline]
1398 unsafe fn get_param<'w, 's>(
1399 &mut component_id: &'s mut Self::State,
1400 system_meta: &SystemMeta,
1401 world: UnsafeWorldCell<'w>,
1402 change_tick: Tick,
1403 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
1404 let (ptr, ticks) = world.get_non_send_with_ticks(component_id).ok_or_else(|| {
1405 SystemParamValidationError::invalid::<Self>("Non-send data not found")
1406 })?;
1407 Ok(NonSendMut {
1408 value: ptr.assert_unique().deref_mut(),
1409 ticks: ComponentTicksMut::from_tick_cells(ticks, system_meta.last_run, change_tick),
1410 })
1411 }
1412}
1413
1414unsafe impl<'a> ReadOnlySystemParam for &'a Archetypes {}
1416
1417unsafe impl<'a> SystemParam for &'a Archetypes {
1419 type State = ();
1420 type Item<'w, 's> = &'w Archetypes;
1421
1422 fn init_state(_world: &mut World) -> Self::State {}
1423
1424 fn init_access(
1425 _state: &Self::State,
1426 _system_meta: &mut SystemMeta,
1427 _component_access_set: &mut FilteredAccessSet,
1428 _world: &mut World,
1429 ) {
1430 }
1431
1432 #[inline]
1433 unsafe fn get_param<'w, 's>(
1434 _state: &'s mut Self::State,
1435 _system_meta: &SystemMeta,
1436 world: UnsafeWorldCell<'w>,
1437 _change_tick: Tick,
1438 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
1439 Ok(world.archetypes())
1440 }
1441}
1442
1443unsafe impl<'a> ReadOnlySystemParam for &'a Components {}
1445
1446unsafe impl<'a> SystemParam for &'a Components {
1448 type State = ();
1449 type Item<'w, 's> = &'w Components;
1450
1451 fn init_state(_world: &mut World) -> Self::State {}
1452
1453 fn init_access(
1454 _state: &Self::State,
1455 _system_meta: &mut SystemMeta,
1456 _component_access_set: &mut FilteredAccessSet,
1457 _world: &mut World,
1458 ) {
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 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
1468 Ok(world.components())
1469 }
1470}
1471
1472unsafe impl<'a> ReadOnlySystemParam for &'a Entities {}
1474
1475unsafe impl<'a> SystemParam for &'a Entities {
1477 type State = ();
1478 type Item<'w, 's> = &'w Entities;
1479
1480 fn init_state(_world: &mut World) -> Self::State {}
1481
1482 fn init_access(
1483 _state: &Self::State,
1484 _system_meta: &mut SystemMeta,
1485 _component_access_set: &mut FilteredAccessSet,
1486 _world: &mut World,
1487 ) {
1488 }
1489
1490 #[inline]
1491 unsafe fn get_param<'w, 's>(
1492 _state: &'s mut Self::State,
1493 _system_meta: &SystemMeta,
1494 world: UnsafeWorldCell<'w>,
1495 _change_tick: Tick,
1496 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
1497 Ok(world.entities())
1498 }
1499}
1500
1501unsafe impl<'a> ReadOnlySystemParam for &'a EntityAllocator {}
1503
1504unsafe impl<'a> SystemParam for &'a EntityAllocator {
1506 type State = ();
1507 type Item<'w, 's> = &'w EntityAllocator;
1508
1509 fn init_state(_world: &mut World) -> Self::State {}
1510
1511 fn init_access(
1512 _state: &Self::State,
1513 _system_meta: &mut SystemMeta,
1514 _component_access_set: &mut FilteredAccessSet,
1515 _world: &mut World,
1516 ) {
1517 }
1518
1519 #[inline]
1520 unsafe fn get_param<'w, 's>(
1521 _state: &'s mut Self::State,
1522 _system_meta: &SystemMeta,
1523 world: UnsafeWorldCell<'w>,
1524 _change_tick: Tick,
1525 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
1526 Ok(world.entity_allocator())
1527 }
1528}
1529
1530unsafe impl<'a> ReadOnlySystemParam for &'a Bundles {}
1532
1533unsafe impl<'a> SystemParam for &'a Bundles {
1535 type State = ();
1536 type Item<'w, 's> = &'w Bundles;
1537
1538 fn init_state(_world: &mut World) -> Self::State {}
1539
1540 fn init_access(
1541 _state: &Self::State,
1542 _system_meta: &mut SystemMeta,
1543 _component_access_set: &mut FilteredAccessSet,
1544 _world: &mut World,
1545 ) {
1546 }
1547
1548 #[inline]
1549 unsafe fn get_param<'w, 's>(
1550 _state: &'s mut Self::State,
1551 _system_meta: &SystemMeta,
1552 world: UnsafeWorldCell<'w>,
1553 _change_tick: Tick,
1554 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
1555 Ok(world.bundles())
1556 }
1557}
1558
1559#[derive(Debug, Clone, Copy)]
1569pub struct SystemChangeTick {
1570 last_run: Tick,
1571 this_run: Tick,
1572}
1573
1574impl SystemChangeTick {
1575 #[inline]
1577 pub fn this_run(&self) -> Tick {
1578 self.this_run
1579 }
1580
1581 #[inline]
1583 pub fn last_run(&self) -> Tick {
1584 self.last_run
1585 }
1586}
1587
1588unsafe impl ReadOnlySystemParam for SystemChangeTick {}
1590
1591unsafe impl SystemParam for SystemChangeTick {
1593 type State = ();
1594 type Item<'w, 's> = SystemChangeTick;
1595
1596 fn init_state(_world: &mut World) -> Self::State {}
1597
1598 fn init_access(
1599 _state: &Self::State,
1600 _system_meta: &mut SystemMeta,
1601 _component_access_set: &mut FilteredAccessSet,
1602 _world: &mut World,
1603 ) {
1604 }
1605
1606 #[inline]
1607 unsafe fn get_param<'w, 's>(
1608 _state: &'s mut Self::State,
1609 system_meta: &SystemMeta,
1610 _world: UnsafeWorldCell<'w>,
1611 change_tick: Tick,
1612 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
1613 Ok(SystemChangeTick {
1614 last_run: system_meta.last_run,
1615 this_run: change_tick,
1616 })
1617 }
1618}
1619
1620unsafe impl<T: SystemParam> SystemParam for Option<T> {
1622 type State = T::State;
1623
1624 type Item<'world, 'state> = Option<T::Item<'world, 'state>>;
1625
1626 fn init_state(world: &mut World) -> Self::State {
1627 T::init_state(world)
1628 }
1629
1630 fn init_access(
1631 state: &Self::State,
1632 system_meta: &mut SystemMeta,
1633 component_access_set: &mut FilteredAccessSet,
1634 world: &mut World,
1635 ) {
1636 T::init_access(state, system_meta, component_access_set, world);
1637 }
1638
1639 #[inline]
1640 unsafe fn get_param<'world, 'state>(
1641 state: &'state mut Self::State,
1642 system_meta: &SystemMeta,
1643 world: UnsafeWorldCell<'world>,
1644 change_tick: Tick,
1645 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
1646 Ok(unsafe { T::get_param(state, system_meta, world, change_tick) }.ok())
1648 }
1649
1650 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1651 T::apply(state, system_meta, world);
1652 }
1653
1654 fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
1655 T::queue(state, system_meta, world);
1656 }
1657}
1658
1659unsafe impl<T: ReadOnlySystemParam> ReadOnlySystemParam for Option<T> {}
1661
1662unsafe impl<T: SystemParam> SystemParam for Result<T, SystemParamValidationError> {
1664 type State = T::State;
1665
1666 type Item<'world, 'state> = Result<T::Item<'world, 'state>, SystemParamValidationError>;
1667
1668 fn init_state(world: &mut World) -> Self::State {
1669 T::init_state(world)
1670 }
1671
1672 fn init_access(
1673 state: &Self::State,
1674 system_meta: &mut SystemMeta,
1675 component_access_set: &mut FilteredAccessSet,
1676 world: &mut World,
1677 ) {
1678 T::init_access(state, system_meta, component_access_set, world);
1679 }
1680
1681 #[inline]
1682 unsafe fn get_param<'world, 'state>(
1683 state: &'state mut Self::State,
1684 system_meta: &SystemMeta,
1685 world: UnsafeWorldCell<'world>,
1686 change_tick: Tick,
1687 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
1688 Ok(unsafe { T::get_param(state, system_meta, world, change_tick) })
1690 }
1691
1692 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1693 T::apply(state, system_meta, world);
1694 }
1695
1696 fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
1697 T::queue(state, system_meta, world);
1698 }
1699}
1700
1701unsafe impl<T: ReadOnlySystemParam> ReadOnlySystemParam for Result<T, SystemParamValidationError> {}
1703
1704#[derive(Debug)]
1723pub struct If<T>(pub T);
1724
1725impl<T> If<T> {
1726 pub fn into_inner(self) -> T {
1740 self.0
1741 }
1742}
1743
1744impl<T> Deref for If<T> {
1745 type Target = T;
1746 fn deref(&self) -> &Self::Target {
1747 &self.0
1748 }
1749}
1750
1751impl<T> DerefMut for If<T> {
1752 fn deref_mut(&mut self) -> &mut Self::Target {
1753 &mut self.0
1754 }
1755}
1756
1757unsafe impl<T: SystemParam> SystemParam for If<T> {
1759 type State = T::State;
1760
1761 type Item<'world, 'state> = If<T::Item<'world, 'state>>;
1762
1763 fn init_state(world: &mut World) -> Self::State {
1764 T::init_state(world)
1765 }
1766
1767 fn init_access(
1768 state: &Self::State,
1769 system_meta: &mut SystemMeta,
1770 component_access_set: &mut FilteredAccessSet,
1771 world: &mut World,
1772 ) {
1773 T::init_access(state, system_meta, component_access_set, world);
1774 }
1775
1776 #[inline]
1777 unsafe fn get_param<'world, 'state>(
1778 state: &'state mut Self::State,
1779 system_meta: &SystemMeta,
1780 world: UnsafeWorldCell<'world>,
1781 change_tick: Tick,
1782 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
1783 unsafe { T::get_param(state, system_meta, world, change_tick) }
1785 .map(If)
1786 .map_err(|mut e| {
1787 e.skipped = true;
1788 e
1789 })
1790 }
1791
1792 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1793 T::apply(state, system_meta, world);
1794 }
1795
1796 fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
1797 T::queue(state, system_meta, world);
1798 }
1799}
1800
1801unsafe impl<T: ReadOnlySystemParam> ReadOnlySystemParam for If<T> {}
1803
1804unsafe impl<T: SystemParam> SystemParam for Vec<T> {
1807 type State = Vec<T::State>;
1808
1809 type Item<'world, 'state> = Vec<T::Item<'world, 'state>>;
1810
1811 fn init_state(_world: &mut World) -> Self::State {
1812 Vec::new()
1813 }
1814
1815 fn init_access(
1816 state: &Self::State,
1817 system_meta: &mut SystemMeta,
1818 component_access_set: &mut FilteredAccessSet,
1819 world: &mut World,
1820 ) {
1821 for state in state {
1822 T::init_access(state, system_meta, component_access_set, world);
1823 }
1824 }
1825
1826 #[inline]
1827 unsafe fn get_param<'world, 'state>(
1828 state: &'state mut Self::State,
1829 system_meta: &SystemMeta,
1830 world: UnsafeWorldCell<'world>,
1831 change_tick: Tick,
1832 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
1833 state
1834 .iter_mut()
1835 .map(|state| unsafe { T::get_param(state, system_meta, world, change_tick) })
1839 .collect()
1840 }
1841
1842 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1843 for state in state {
1844 T::apply(state, system_meta, world);
1845 }
1846 }
1847
1848 fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
1849 for state in state {
1850 T::queue(state, system_meta, world.reborrow());
1851 }
1852 }
1853}
1854
1855unsafe impl<T: SystemParam> SystemParam for ParamSet<'_, '_, Vec<T>> {
1859 type State = Vec<T::State>;
1860
1861 type Item<'world, 'state> = ParamSet<'world, 'state, Vec<T>>;
1862
1863 fn init_state(_world: &mut World) -> Self::State {
1864 Vec::new()
1865 }
1866
1867 fn init_access(
1868 state: &Self::State,
1869 system_meta: &mut SystemMeta,
1870 component_access_set: &mut FilteredAccessSet,
1871 world: &mut World,
1872 ) {
1873 for state in state {
1874 let component_access_set_clone = &mut component_access_set.clone();
1876 T::init_access(state, system_meta, component_access_set_clone, world);
1877 }
1878 for state in state {
1879 let mut access_set = FilteredAccessSet::new();
1882 T::init_access(state, system_meta, &mut access_set, world);
1883 component_access_set.extend(access_set);
1884 }
1885 }
1886
1887 #[inline]
1888 unsafe fn get_param<'world, 'state>(
1889 state: &'state mut Self::State,
1890 system_meta: &SystemMeta,
1891 world: UnsafeWorldCell<'world>,
1892 change_tick: Tick,
1893 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
1894 for s in state.iter_mut() {
1900 drop(unsafe { T::get_param(s, system_meta, world, change_tick) }?);
1902 }
1903
1904 Ok(ParamSet {
1905 param_states: state,
1906 system_meta: system_meta.clone(),
1907 world,
1908 change_tick,
1909 })
1910 }
1911
1912 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1913 for state in state {
1914 T::apply(state, system_meta, world);
1915 }
1916 }
1917
1918 fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
1919 for state in state {
1920 T::queue(state, system_meta, world.reborrow());
1921 }
1922 }
1923}
1924
1925impl<T: SystemParam> ParamSet<'_, '_, Vec<T>> {
1926 pub fn get_mut(&mut self, index: usize) -> T::Item<'_, '_> {
1929 unsafe {
1934 T::get_param(
1935 &mut self.param_states[index],
1936 &self.system_meta,
1937 self.world,
1938 self.change_tick,
1939 )
1940 .unwrap()
1941 }
1942 }
1943
1944 pub fn for_each(&mut self, mut f: impl FnMut(T::Item<'_, '_>)) {
1946 self.param_states.iter_mut().for_each(|state| {
1947 f(
1948 unsafe { T::get_param(state, &self.system_meta, self.world, self.change_tick) }
1953 .unwrap_or_else(|err| panic!("ParamSet parameter validation failed: {err}")),
1954 );
1955 });
1956 }
1957}
1958
1959unsafe impl<T: SystemParam, const N: usize> SystemParam for SmallVec<[T; N]> {
1962 type State = SmallVec<[T::State; N]>;
1963
1964 type Item<'world, 'state> = SmallVec<[T::Item<'world, 'state>; N]>;
1965
1966 fn init_state(_world: &mut World) -> Self::State {
1967 SmallVec::new()
1968 }
1969
1970 fn init_access(
1971 state: &Self::State,
1972 system_meta: &mut SystemMeta,
1973 component_access_set: &mut FilteredAccessSet,
1974 world: &mut World,
1975 ) {
1976 for state in state {
1977 T::init_access(state, system_meta, component_access_set, world);
1978 }
1979 }
1980
1981 #[inline]
1982 unsafe fn get_param<'world, 'state>(
1983 state: &'state mut Self::State,
1984 system_meta: &SystemMeta,
1985 world: UnsafeWorldCell<'world>,
1986 change_tick: Tick,
1987 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
1988 state
1989 .iter_mut()
1990 .map(|state| unsafe { T::get_param(state, system_meta, world, change_tick) })
1994 .collect()
1995 }
1996
1997 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1998 for state in state {
1999 T::apply(state, system_meta, world);
2000 }
2001 }
2002
2003 fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
2004 for state in state {
2005 T::queue(state, system_meta, world.reborrow());
2006 }
2007 }
2008}
2009
2010macro_rules! impl_system_param_tuple {
2011 ($(#[$meta:meta])* $($param: ident),*) => {
2012 $(#[$meta])*
2013 unsafe impl<$($param: ReadOnlySystemParam),*> ReadOnlySystemParam for ($($param,)*) {}
2015
2016 #[expect(
2017 clippy::allow_attributes,
2018 reason = "This is in a macro, and as such, the below lints may not always apply."
2019 )]
2020 #[allow(
2021 non_snake_case,
2022 reason = "Certain variable names are provided by the caller, not by us."
2023 )]
2024 #[allow(
2025 unused_variables,
2026 reason = "Zero-length tuples won't use some of the parameters."
2027 )]
2028 #[allow(clippy::unused_unit, reason = "Zero length tuple is unit.")]
2029 $(#[$meta])*
2030 unsafe impl<$($param: SystemParam),*> SystemParam for ($($param,)*) {
2032 type State = ($($param::State,)*);
2033 type Item<'w, 's> = ($($param::Item::<'w, 's>,)*);
2034
2035 #[inline]
2036 #[track_caller]
2037 fn init_state(world: &mut World) -> Self::State {
2038 ($($param::init_state(world),)*)
2039 }
2040
2041 fn init_access(state: &Self::State, _system_meta: &mut SystemMeta, _component_access_set: &mut FilteredAccessSet, _world: &mut World) {
2042 let ($($param,)*) = state;
2043 $($param::init_access($param, _system_meta, _component_access_set, _world);)*
2044 }
2045
2046 #[inline]
2047 fn apply(($($param,)*): &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
2048 $($param::apply($param, system_meta, world);)*
2049 }
2050
2051 #[inline]
2052 #[allow(
2053 unused_mut,
2054 reason = "The `world` parameter is unused for zero-length tuples; however, it must be mutable for other lengths of tuples."
2055 )]
2056 fn queue(($($param,)*): &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
2057 $($param::queue($param, system_meta, world.reborrow());)*
2058 }
2059
2060 #[inline]
2061 #[track_caller]
2062 unsafe fn get_param<'w, 's>(
2063 state: &'s mut Self::State,
2064 system_meta: &SystemMeta,
2065 world: UnsafeWorldCell<'w>,
2066 change_tick: Tick,
2067 ) -> Result<Self::Item<'w, 's>, SystemParamValidationError> {
2068 let ($($param,)*) = state;
2069
2070 #[allow(
2071 unused_unsafe,
2072 reason = "Zero-length tuples won't have any params to validate."
2073 )]
2074 unsafe {
2076 #[allow(
2077 clippy::unused_unit,
2078 reason = "Zero-length tuples won't have any params to get."
2079 )]
2080 Ok(($($param::get_param($param, system_meta, world, change_tick)?,)*))
2081 }
2082 }
2083 }
2084 };
2085}
2086
2087all_tuples!(
2088 #[doc(fake_variadic)]
2089 impl_system_param_tuple,
2090 0,
2091 16,
2092 P
2093);
2094
2095pub mod lifetimeless {
2108 pub type SQuery<D, F = ()> = super::Query<'static, 'static, D, F>;
2110 pub type Read<T> = &'static T;
2112 pub type Write<T> = &'static mut T;
2114 pub type SRes<T> = super::Res<'static, T>;
2116 pub type SResMut<T> = super::ResMut<'static, T>;
2118 pub type SCommands = crate::system::Commands<'static, 'static>;
2120}
2121
2122pub struct StaticSystemParam<'w, 's, P: SystemParam>(SystemParamItem<'w, 's, P>);
2174
2175impl<'w, 's, P: SystemParam> Deref for StaticSystemParam<'w, 's, P> {
2176 type Target = SystemParamItem<'w, 's, P>;
2177
2178 fn deref(&self) -> &Self::Target {
2179 &self.0
2180 }
2181}
2182
2183impl<'w, 's, P: SystemParam> DerefMut for StaticSystemParam<'w, 's, P> {
2184 fn deref_mut(&mut self) -> &mut Self::Target {
2185 &mut self.0
2186 }
2187}
2188
2189impl<'w, 's, P: SystemParam> StaticSystemParam<'w, 's, P> {
2190 pub fn into_inner(self) -> SystemParamItem<'w, 's, P> {
2192 self.0
2193 }
2194}
2195
2196unsafe impl<'w, 's, P: ReadOnlySystemParam + 'static> ReadOnlySystemParam
2198 for StaticSystemParam<'w, 's, P>
2199{
2200}
2201
2202unsafe impl<P: SystemParam + 'static> SystemParam for StaticSystemParam<'_, '_, P> {
2204 type State = P::State;
2205 type Item<'world, 'state> = StaticSystemParam<'world, 'state, P>;
2206
2207 fn init_state(world: &mut World) -> Self::State {
2208 P::init_state(world)
2209 }
2210
2211 fn init_access(
2212 state: &Self::State,
2213 system_meta: &mut SystemMeta,
2214 component_access_set: &mut FilteredAccessSet,
2215 world: &mut World,
2216 ) {
2217 P::init_access(state, system_meta, component_access_set, world);
2218 }
2219
2220 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
2221 P::apply(state, system_meta, world);
2222 }
2223
2224 fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
2225 P::queue(state, system_meta, world);
2226 }
2227
2228 #[inline]
2229 unsafe fn get_param<'world, 'state>(
2230 state: &'state mut Self::State,
2231 system_meta: &SystemMeta,
2232 world: UnsafeWorldCell<'world>,
2233 change_tick: Tick,
2234 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
2235 unsafe { P::get_param(state, system_meta, world, change_tick) }.map(StaticSystemParam)
2237 }
2238}
2239
2240unsafe impl<T: ?Sized> SystemParam for PhantomData<T> {
2242 type State = ();
2243 type Item<'world, 'state> = Self;
2244
2245 fn init_state(_world: &mut World) -> Self::State {}
2246
2247 fn init_access(
2248 _state: &Self::State,
2249 _system_meta: &mut SystemMeta,
2250 _component_access_set: &mut FilteredAccessSet,
2251 _world: &mut World,
2252 ) {
2253 }
2254
2255 #[inline]
2256 unsafe fn get_param<'world, 'state>(
2257 _state: &'state mut Self::State,
2258 _system_meta: &SystemMeta,
2259 _world: UnsafeWorldCell<'world>,
2260 _change_tick: Tick,
2261 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
2262 Ok(PhantomData)
2263 }
2264}
2265
2266unsafe impl<T: ?Sized> ReadOnlySystemParam for PhantomData<T> {}
2268
2269pub struct DynSystemParam<'w, 's> {
2328 state: &'s mut dyn Any,
2330 world: UnsafeWorldCell<'w>,
2331 system_meta: SystemMeta,
2332 change_tick: Tick,
2333}
2334
2335impl<'w, 's> DynSystemParam<'w, 's> {
2336 unsafe fn new(
2343 state: &'s mut dyn Any,
2344 world: UnsafeWorldCell<'w>,
2345 system_meta: SystemMeta,
2346 change_tick: Tick,
2347 ) -> Self {
2348 Self {
2349 state,
2350 world,
2351 system_meta,
2352 change_tick,
2353 }
2354 }
2355
2356 pub fn is<T: SystemParam>(&self) -> bool
2358 where
2360 T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,
2361 {
2362 self.state.is::<ParamState<T::Item<'static, 'static>>>()
2363 }
2364
2365 pub fn downcast<T: SystemParam>(self) -> Option<T>
2368 where
2370 T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,
2371 {
2372 unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }
2377 }
2378
2379 pub fn downcast_mut<'a, T: SystemParam>(&'a mut self) -> Option<T>
2382 where
2384 T::Item<'static, 'static>: SystemParam<Item<'a, 'a> = T> + 'static,
2385 {
2386 unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }
2391 }
2392
2393 pub fn downcast_mut_inner<'a, T: ReadOnlySystemParam>(&'a mut self) -> Option<T>
2399 where
2401 T::Item<'static, 'static>: SystemParam<Item<'w, 'a> = T> + 'static,
2402 {
2403 unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }
2408 }
2409}
2410
2411unsafe fn downcast<'w, 's, T: SystemParam>(
2418 state: &'s mut dyn Any,
2419 system_meta: &SystemMeta,
2420 world: UnsafeWorldCell<'w>,
2421 change_tick: Tick,
2422) -> Option<T>
2423where
2432 T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,
2433{
2434 state
2435 .downcast_mut::<ParamState<T::Item<'static, 'static>>>()
2436 .and_then(|state| {
2437 unsafe { T::Item::get_param(&mut state.0, system_meta, world, change_tick) }.ok()
2442 })
2443}
2444
2445pub struct DynSystemParamState(Box<dyn DynParamState>);
2447
2448impl DynSystemParamState {
2449 pub(crate) fn new<T: SystemParam + 'static>(state: T::State) -> Self {
2450 Self(Box::new(ParamState::<T>(state)))
2451 }
2452}
2453
2454trait DynParamState: Sync + Send + Any {
2456 fn apply(&mut self, system_meta: &SystemMeta, world: &mut World);
2461
2462 fn queue(&mut self, system_meta: &SystemMeta, world: DeferredWorld);
2464
2465 fn init_access(
2467 &self,
2468 system_meta: &mut SystemMeta,
2469 component_access_set: &mut FilteredAccessSet,
2470 world: &mut World,
2471 );
2472
2473 unsafe fn validate(
2478 &mut self,
2479 system_meta: &SystemMeta,
2480 world: UnsafeWorldCell,
2481 change_tick: Tick,
2482 ) -> Result<(), SystemParamValidationError>;
2483}
2484
2485struct ParamState<T: SystemParam>(T::State);
2487
2488impl<T: SystemParam + 'static> DynParamState for ParamState<T> {
2489 fn apply(&mut self, system_meta: &SystemMeta, world: &mut World) {
2490 T::apply(&mut self.0, system_meta, world);
2491 }
2492
2493 fn queue(&mut self, system_meta: &SystemMeta, world: DeferredWorld) {
2494 T::queue(&mut self.0, system_meta, world);
2495 }
2496
2497 fn init_access(
2498 &self,
2499 system_meta: &mut SystemMeta,
2500 component_access_set: &mut FilteredAccessSet,
2501 world: &mut World,
2502 ) {
2503 T::init_access(&self.0, system_meta, component_access_set, world);
2504 }
2505
2506 unsafe fn validate(
2507 &mut self,
2508 system_meta: &SystemMeta,
2509 world: UnsafeWorldCell,
2510 change_tick: Tick,
2511 ) -> Result<(), SystemParamValidationError> {
2512 unsafe { T::get_param(&mut self.0, system_meta, world, change_tick) }.map(drop)
2514 }
2515}
2516
2517unsafe impl SystemParam for DynSystemParam<'_, '_> {
2519 type State = DynSystemParamState;
2520
2521 type Item<'world, 'state> = DynSystemParam<'world, 'state>;
2522
2523 fn init_state(_world: &mut World) -> Self::State {
2524 DynSystemParamState::new::<()>(())
2525 }
2526
2527 fn init_access(
2528 state: &Self::State,
2529 system_meta: &mut SystemMeta,
2530 component_access_set: &mut FilteredAccessSet,
2531 world: &mut World,
2532 ) {
2533 state
2534 .0
2535 .init_access(system_meta, component_access_set, world);
2536 }
2537
2538 #[inline]
2539 unsafe fn get_param<'world, 'state>(
2540 state: &'state mut Self::State,
2541 system_meta: &SystemMeta,
2542 world: UnsafeWorldCell<'world>,
2543 change_tick: Tick,
2544 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
2545 unsafe { state.0.validate(system_meta, world, change_tick) }?;
2549 Ok(unsafe {
2555 DynSystemParam::new(state.0.as_mut(), world, system_meta.clone(), change_tick)
2556 })
2557 }
2558
2559 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
2560 state.0.apply(system_meta, world);
2561 }
2562
2563 fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
2564 state.0.queue(system_meta, world);
2565 }
2566}
2567
2568unsafe impl SystemParam for FilteredResources<'_, '_> {
2571 type State = Access;
2572
2573 type Item<'world, 'state> = FilteredResources<'world, 'state>;
2574
2575 fn init_state(_world: &mut World) -> Self::State {
2576 Access::new()
2577 }
2578
2579 fn init_access(
2580 access: &Self::State,
2581 system_meta: &mut SystemMeta,
2582 component_access_set: &mut FilteredAccessSet,
2583 world: &mut World,
2584 ) {
2585 let combined_access = component_access_set.combined_access();
2586 let conflicts = combined_access.get_conflicts(access);
2587 if !conflicts.is_empty() {
2588 let accesses = conflicts.format_conflict_list(world.into());
2589 let system_name = &system_meta.name;
2590 panic!("error[B0002]: FilteredResources in system {system_name} accesses resources(s){accesses} in a way that conflicts with a previous system parameter. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002");
2591 }
2592
2593 let mut filter = FilteredAccess::matches_everything();
2594 filter.access_mut().extend(access);
2595 filter.and_with(IS_RESOURCE);
2596 component_access_set.add(filter);
2597 }
2598
2599 unsafe fn get_param<'world, 'state>(
2600 state: &'state mut Self::State,
2601 system_meta: &SystemMeta,
2602 world: UnsafeWorldCell<'world>,
2603 change_tick: Tick,
2604 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
2605 Ok(unsafe { FilteredResources::new(world, state, system_meta.last_run, change_tick) })
2608 }
2609}
2610
2611unsafe impl ReadOnlySystemParam for FilteredResources<'_, '_> {}
2613
2614unsafe impl SystemParam for FilteredResourcesMut<'_, '_> {
2617 type State = Access;
2618
2619 type Item<'world, 'state> = FilteredResourcesMut<'world, 'state>;
2620
2621 fn init_state(_world: &mut World) -> Self::State {
2622 Access::new()
2623 }
2624
2625 fn init_access(
2626 access: &Self::State,
2627 system_meta: &mut SystemMeta,
2628 component_access_set: &mut FilteredAccessSet,
2629 world: &mut World,
2630 ) {
2631 let combined_access = component_access_set.combined_access();
2632 let conflicts = combined_access.get_conflicts(access);
2633 if !conflicts.is_empty() {
2634 let accesses = conflicts.format_conflict_list(world.into());
2635 let system_name = &system_meta.name;
2636 panic!("error[B0002]: FilteredResourcesMut in system {system_name} accesses resources(s){accesses} in a way that conflicts with a previous system parameter. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002");
2637 }
2638
2639 let mut filter = FilteredAccess::matches_everything();
2640 filter.access_mut().extend(access);
2641 filter.and_with(IS_RESOURCE);
2642 component_access_set.add(filter);
2643 }
2644
2645 unsafe fn get_param<'world, 'state>(
2646 state: &'state mut Self::State,
2647 system_meta: &SystemMeta,
2648 world: UnsafeWorldCell<'world>,
2649 change_tick: Tick,
2650 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
2651 Ok(unsafe { FilteredResourcesMut::new(world, state, system_meta.last_run, change_tick) })
2654 }
2655}
2656
2657#[derive(Debug, PartialEq, Eq, Clone, Error)]
2663pub struct SystemParamValidationError {
2664 pub skipped: bool,
2677
2678 pub message: Cow<'static, str>,
2680
2681 pub param: DebugName,
2684
2685 pub field: Cow<'static, str>,
2690}
2691
2692impl SystemParamValidationError {
2693 pub fn skipped<T>(message: impl Into<Cow<'static, str>>) -> Self {
2696 Self::new::<T>(true, message, Cow::Borrowed(""))
2697 }
2698
2699 pub fn invalid<T>(message: impl Into<Cow<'static, str>>) -> Self {
2702 Self::new::<T>(false, message, Cow::Borrowed(""))
2703 }
2704
2705 pub fn new<T>(
2708 skipped: bool,
2709 message: impl Into<Cow<'static, str>>,
2710 field: impl Into<Cow<'static, str>>,
2711 ) -> Self {
2712 Self {
2713 skipped,
2714 message: message.into(),
2715 param: DebugName::type_name::<T>(),
2716 field: field.into(),
2717 }
2718 }
2719
2720 pub(crate) const EMPTY: Self = Self {
2721 skipped: false,
2722 message: Cow::Borrowed(""),
2723 param: DebugName::borrowed(""),
2724 field: Cow::Borrowed(""),
2725 };
2726}
2727
2728impl Display for SystemParamValidationError {
2729 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
2730 write!(
2731 fmt,
2732 "Parameter `{}{}` failed validation: {}",
2733 self.param.shortname(),
2734 self.field,
2735 self.message
2736 )?;
2737 if !self.skipped {
2738 write!(fmt, "\nIf this is an expected state, wrap the parameter in `Option<T>` and handle `None` when it happens, or wrap the parameter in `If<T>` to skip the system when it happens.")?;
2739 }
2740 Ok(())
2741 }
2742}
2743
2744#[cfg(test)]
2745mod tests {
2746 use super::*;
2747 use crate::query::Without;
2748 use crate::resource::IsResource;
2749 use crate::system::assert_is_system;
2750 use crate::world::EntityMut;
2751 use core::cell::RefCell;
2752
2753 #[test]
2754 #[should_panic]
2755 fn non_send_alias() {
2756 #[derive(Resource)]
2757 struct A(usize);
2758 fn my_system(mut res0: NonSendMut<A>, mut res1: NonSendMut<A>) {
2759 res0.0 += 1;
2760 res1.0 += 1;
2761 }
2762 let mut world = World::new();
2763 world.insert_non_send(A(42));
2764 let mut schedule = crate::schedule::Schedule::default();
2765 schedule.add_systems(my_system);
2766 schedule.run(&mut world);
2767 }
2768
2769 #[test]
2770 #[should_panic]
2771 fn non_send_and_entities() {
2772 #[derive(Resource)]
2773 struct A(usize);
2774 fn my_system(mut ns: NonSendMut<A>, _: Query<EntityMut>) {
2775 ns.0 += 1;
2776 }
2777 assert_is_system(my_system);
2778 }
2779
2780 #[test]
2781 #[should_panic]
2782 fn res_and_entities() {
2783 #[derive(Resource)]
2784 struct A(usize);
2785 fn my_system(mut res: ResMut<A>, _: Query<EntityMut>) {
2786 res.0 += 1;
2787 }
2788 assert_is_system(my_system);
2789 }
2790
2791 #[test]
2792 fn res_and_entities_filtered() {
2793 #[derive(Resource)]
2794 struct A(usize);
2795 fn res_system(mut res: ResMut<A>, _: Query<EntityMut, Without<IsResource>>) {
2796 res.0 += 1;
2797 }
2798 assert_is_system(res_system);
2799
2800 fn non_send_system(mut ns: NonSendMut<A>, _: Query<EntityMut, Without<A>>) {
2801 ns.0 += 1;
2802 }
2803
2804 assert_is_system(non_send_system);
2805 }
2806
2807 #[test]
2809 fn system_param_generic_bounds() {
2810 #[derive(SystemParam)]
2811 pub struct SpecialQuery<
2812 'w,
2813 's,
2814 D: QueryData + Send + Sync + 'static,
2815 F: QueryFilter + Send + Sync + 'static = (),
2816 > {
2817 _query: Query<'w, 's, D, F>,
2818 }
2819
2820 fn my_system(_: SpecialQuery<(), ()>) {}
2821 assert_is_system(my_system);
2822 }
2823
2824 #[test]
2826 fn system_param_flexibility() {
2827 #[derive(SystemParam)]
2828 pub struct SpecialRes<'w, T: Resource> {
2829 _res: Res<'w, T>,
2830 }
2831
2832 #[derive(SystemParam)]
2833 pub struct SpecialLocal<'s, T: FromWorld + Send + 'static> {
2834 _local: Local<'s, T>,
2835 }
2836
2837 #[derive(Resource)]
2838 struct R;
2839
2840 fn my_system(_: SpecialRes<R>, _: SpecialLocal<u32>) {}
2841 assert_is_system(my_system);
2842 }
2843
2844 #[derive(Resource)]
2845 pub struct R<const I: usize>;
2846
2847 #[test]
2849 fn system_param_const_generics() {
2850 #[expect(
2851 dead_code,
2852 reason = "This struct is used to ensure that const generics are supported as a SystemParam; thus, the inner value never needs to be read."
2853 )]
2854 #[derive(SystemParam)]
2855 pub struct ConstGenericParam<'w, const I: usize>(Res<'w, R<I>>);
2856
2857 fn my_system(_: ConstGenericParam<0>, _: ConstGenericParam<1000>) {}
2858 assert_is_system(my_system);
2859 }
2860
2861 #[test]
2863 fn system_param_field_limit() {
2864 #[derive(SystemParam)]
2865 pub struct LongParam<'w> {
2866 _r0: Res<'w, R<0>>,
2869 _r1: Res<'w, R<1>>,
2870 _r2: Res<'w, R<2>>,
2871 _r3: Res<'w, R<3>>,
2872 _r4: Res<'w, R<4>>,
2873 _r5: Res<'w, R<5>>,
2874 _r6: Res<'w, R<6>>,
2875 _r7: Res<'w, R<7>>,
2876 _r8: Res<'w, R<8>>,
2877 _r9: Res<'w, R<9>>,
2878 _r10: Res<'w, R<10>>,
2879 _r11: Res<'w, R<11>>,
2880 _r12: Res<'w, R<12>>,
2881 _r13: Res<'w, R<13>>,
2882 _r14: Res<'w, R<14>>,
2883 _r15: Res<'w, R<15>>,
2884 _r16: Res<'w, R<16>>,
2885 }
2886
2887 fn long_system(_: LongParam) {}
2888 assert_is_system(long_system);
2889 }
2890
2891 #[test]
2894 fn system_param_phantom_data() {
2895 #[derive(SystemParam)]
2896 struct PhantomParam<'w, T: Resource, Marker: 'static> {
2897 _foo: Res<'w, T>,
2898 marker: PhantomData<&'w Marker>,
2899 }
2900
2901 fn my_system(_: PhantomParam<R<0>, ()>) {}
2902 assert_is_system(my_system);
2903 }
2904
2905 #[test]
2907 fn system_param_struct_variants() {
2908 #[derive(SystemParam)]
2909 pub struct UnitParam;
2910
2911 #[expect(
2912 dead_code,
2913 reason = "This struct is used to ensure that tuple structs are supported as a SystemParam; thus, the inner values never need to be read."
2914 )]
2915 #[derive(SystemParam)]
2916 pub struct TupleParam<'w, 's, R: Resource, L: FromWorld + Send + 'static>(
2917 Res<'w, R>,
2918 Local<'s, L>,
2919 );
2920
2921 fn my_system(_: UnitParam, _: TupleParam<R<0>, u32>) {}
2922 assert_is_system(my_system);
2923 }
2924
2925 #[test]
2927 fn system_param_private_fields() {
2928 #[derive(Resource)]
2929 struct PrivateResource;
2930
2931 #[expect(
2932 dead_code,
2933 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."
2934 )]
2935 #[derive(SystemParam)]
2936 pub struct EncapsulatedParam<'w>(Res<'w, PrivateResource>);
2937
2938 fn my_system(_: EncapsulatedParam) {}
2939 assert_is_system(my_system);
2940 }
2941
2942 #[test]
2944 fn system_param_where_clause() {
2945 #[derive(SystemParam)]
2946 pub struct WhereParam<'w, 's, D>
2947 where
2948 D: 'static + QueryData,
2949 {
2950 _q: Query<'w, 's, D, ()>,
2951 }
2952
2953 fn my_system(_: WhereParam<()>) {}
2954 assert_is_system(my_system);
2955 }
2956
2957 #[test]
2959 fn system_param_name_collision() {
2960 #[derive(Resource)]
2961 pub struct FetchState;
2962
2963 #[derive(SystemParam)]
2964 pub struct Collide<'w> {
2965 _x: Res<'w, FetchState>,
2966 }
2967
2968 fn my_system(_: Collide) {}
2969 assert_is_system(my_system);
2970 }
2971
2972 #[test]
2974 fn system_param_invariant_lifetime() {
2975 #[derive(SystemParam)]
2976 pub struct InvariantParam<'w, 's> {
2977 _set: ParamSet<'w, 's, (Query<'w, 's, ()>,)>,
2978 }
2979
2980 fn my_system(_: InvariantParam) {}
2981 assert_is_system(my_system);
2982 }
2983
2984 #[test]
2986 fn non_sync_local() {
2987 fn non_sync_system(cell: Local<RefCell<u8>>) {
2988 assert_eq!(*cell.borrow(), 0);
2989 }
2990
2991 let mut world = World::new();
2992 let mut schedule = crate::schedule::Schedule::default();
2993 schedule.add_systems(non_sync_system);
2994 schedule.run(&mut world);
2995 }
2996
2997 #[test]
2999 fn param_set_non_send_first() {
3000 fn non_send_param_set(mut p: ParamSet<(NonSend<*mut u8>, ())>) {
3001 let _ = p.p0();
3002 p.p1();
3003 }
3004
3005 let mut world = World::new();
3006 world.insert_non_send(core::ptr::null_mut::<u8>());
3007 let mut schedule = crate::schedule::Schedule::default();
3008 schedule.add_systems((non_send_param_set, non_send_param_set, non_send_param_set));
3009 schedule.run(&mut world);
3010 }
3011
3012 #[test]
3014 fn param_set_non_send_second() {
3015 fn non_send_param_set(mut p: ParamSet<((), NonSendMut<*mut u8>)>) {
3016 p.p0();
3017 let _ = p.p1();
3018 }
3019
3020 let mut world = World::new();
3021 world.insert_non_send(core::ptr::null_mut::<u8>());
3022 let mut schedule = crate::schedule::Schedule::default();
3023 schedule.add_systems((non_send_param_set, non_send_param_set, non_send_param_set));
3024 schedule.run(&mut world);
3025 }
3026
3027 fn _dyn_system_param_type_inference(mut p: DynSystemParam) {
3028 let _query: Query<()> = p.downcast_mut().unwrap();
3031 let _query: Query<()> = p.downcast_mut_inner().unwrap();
3032 let _query: Query<()> = p.downcast().unwrap();
3033 }
3034
3035 #[test]
3036 #[should_panic]
3037 fn missing_resource_error() {
3038 #[derive(Resource)]
3039 pub struct MissingResource;
3040
3041 let mut schedule = crate::schedule::Schedule::default();
3042 schedule.add_systems(res_system);
3043 let mut world = World::new();
3044 schedule.run(&mut world);
3045
3046 fn res_system(_: Res<MissingResource>) {}
3047 }
3048
3049 #[test]
3050 #[should_panic]
3051 fn missing_message_error() {
3052 use crate::prelude::{Message, MessageReader};
3053
3054 #[derive(Message)]
3055 pub struct MissingEvent;
3056
3057 let mut schedule = crate::schedule::Schedule::default();
3058 schedule.add_systems(message_system);
3059 let mut world = World::new();
3060 schedule.run(&mut world);
3061
3062 fn message_system(_: MessageReader<MissingEvent>) {}
3063 }
3064}