1pub use crate::change_detection::{NonSend, NonSendMut, Res, ResMut};
2use crate::{
3 archetype::Archetypes,
4 bundle::Bundles,
5 change_detection::{ComponentTicksMut, ComponentTicksRef, Tick},
6 component::{ComponentId, Components},
7 entity::{Entities, EntityAllocator},
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::{borrow::Cow, boxed::Box, vec::Vec};
21pub use bevy_ecs_macros::SystemParam;
22use bevy_platform::cell::SyncCell;
23use bevy_ptr::UnsafeCellDeref;
24use bevy_utils::prelude::DebugName;
25use core::{
26 any::Any,
27 fmt::{Debug, Display},
28 marker::PhantomData,
29 ops::{Deref, DerefMut},
30};
31use thiserror::Error;
32
33use super::Populated;
34use variadics_please::{all_tuples, all_tuples_enumerated};
35
36pub unsafe trait SystemParam: Sized {
214 type State: Send + Sync + 'static;
216
217 type Item<'world, 'state>: SystemParam<State = Self::State>;
222
223 fn init_state(world: &mut World) -> Self::State;
225
226 fn init_access(
228 state: &Self::State,
229 system_meta: &mut SystemMeta,
230 component_access_set: &mut FilteredAccessSet,
231 world: &mut World,
232 );
233
234 #[inline]
239 #[expect(
240 unused_variables,
241 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."
242 )]
243 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {}
244
245 #[inline]
247 #[expect(
248 unused_variables,
249 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."
250 )]
251 fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {}
252
253 #[expect(
287 unused_variables,
288 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."
289 )]
290 unsafe fn validate_param(
291 state: &mut Self::State,
292 system_meta: &SystemMeta,
293 world: UnsafeWorldCell,
294 ) -> Result<(), SystemParamValidationError> {
295 Ok(())
296 }
297
298 unsafe fn get_param<'world, 'state>(
306 state: &'state mut Self::State,
307 system_meta: &SystemMeta,
308 world: UnsafeWorldCell<'world>,
309 change_tick: Tick,
310 ) -> Self::Item<'world, 'state>;
311}
312
313pub unsafe trait ReadOnlySystemParam: SystemParam {}
318
319pub type SystemParamItem<'w, 's, P> = <P as SystemParam>::Item<'w, 's>;
321
322unsafe impl<'w, 's, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam
324 for Query<'w, 's, D, F>
325{
326}
327
328unsafe impl<D: QueryData + 'static, F: QueryFilter + 'static> SystemParam for Query<'_, '_, D, F> {
331 type State = QueryState<D, F>;
332 type Item<'w, 's> = Query<'w, 's, D, F>;
333
334 fn init_state(world: &mut World) -> Self::State {
335 QueryState::new(world)
336 }
337
338 fn init_access(
339 state: &Self::State,
340 system_meta: &mut SystemMeta,
341 component_access_set: &mut FilteredAccessSet,
342 world: &mut World,
343 ) {
344 assert_component_access_compatibility(
345 &system_meta.name,
346 DebugName::type_name::<D>(),
347 DebugName::type_name::<F>(),
348 component_access_set,
349 &state.component_access,
350 world,
351 );
352 component_access_set.add(state.component_access.clone());
353 }
354
355 #[inline]
356 unsafe fn get_param<'w, 's>(
357 state: &'s mut Self::State,
358 system_meta: &SystemMeta,
359 world: UnsafeWorldCell<'w>,
360 change_tick: Tick,
361 ) -> Self::Item<'w, 's> {
362 unsafe { state.query_unchecked_with_ticks(world, system_meta.last_run, change_tick) }
367 }
368}
369
370fn assert_component_access_compatibility(
371 system_name: &DebugName,
372 query_type: DebugName,
373 filter_type: DebugName,
374 system_access: &FilteredAccessSet,
375 current: &FilteredAccess,
376 world: &World,
377) {
378 let conflicts = system_access.get_conflicts_single(current);
379 if conflicts.is_empty() {
380 return;
381 }
382 let mut accesses = conflicts.format_conflict_list(world);
383 if !accesses.is_empty() {
385 accesses.push(' ');
386 }
387 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://bevy.org/learn/errors/b0001", query_type.shortname(), filter_type.shortname());
388}
389
390unsafe impl<'a, 'b, D: QueryData + 'static, F: QueryFilter + 'static> SystemParam
393 for Single<'a, 'b, D, F>
394{
395 type State = QueryState<D, F>;
396 type Item<'w, 's> = Single<'w, 's, D, F>;
397
398 fn init_state(world: &mut World) -> Self::State {
399 Query::init_state(world)
400 }
401
402 fn init_access(
403 state: &Self::State,
404 system_meta: &mut SystemMeta,
405 component_access_set: &mut FilteredAccessSet,
406 world: &mut World,
407 ) {
408 Query::init_access(state, system_meta, component_access_set, world);
409 }
410
411 #[inline]
412 unsafe fn get_param<'w, 's>(
413 state: &'s mut Self::State,
414 system_meta: &SystemMeta,
415 world: UnsafeWorldCell<'w>,
416 change_tick: Tick,
417 ) -> Self::Item<'w, 's> {
418 let query =
421 unsafe { state.query_unchecked_with_ticks(world, system_meta.last_run, change_tick) };
422 let single = query
423 .single_inner()
424 .expect("The query was expected to contain exactly one matching entity.");
425 Single {
426 item: single,
427 _filter: PhantomData,
428 }
429 }
430
431 #[inline]
432 unsafe fn validate_param(
433 state: &mut Self::State,
434 system_meta: &SystemMeta,
435 world: UnsafeWorldCell,
436 ) -> Result<(), SystemParamValidationError> {
437 let query = unsafe {
441 state.query_unchecked_with_ticks(world, system_meta.last_run, world.change_tick())
442 };
443 match query.single_inner() {
444 Ok(_) => Ok(()),
445 Err(QuerySingleError::NoEntities(_)) => Err(
446 SystemParamValidationError::skipped::<Self>("No matching entities"),
447 ),
448 Err(QuerySingleError::MultipleEntities(_)) => Err(
449 SystemParamValidationError::skipped::<Self>("Multiple matching entities"),
450 ),
451 }
452 }
453}
454
455unsafe impl<'a, 'b, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam
457 for Single<'a, 'b, D, F>
458{
459}
460
461unsafe impl<D: QueryData + 'static, F: QueryFilter + 'static> SystemParam
464 for Populated<'_, '_, D, F>
465{
466 type State = QueryState<D, F>;
467 type Item<'w, 's> = Populated<'w, 's, D, F>;
468
469 fn init_state(world: &mut World) -> Self::State {
470 Query::init_state(world)
471 }
472
473 fn init_access(
474 state: &Self::State,
475 system_meta: &mut SystemMeta,
476 component_access_set: &mut FilteredAccessSet,
477 world: &mut World,
478 ) {
479 Query::init_access(state, system_meta, component_access_set, world);
480 }
481
482 #[inline]
483 unsafe fn get_param<'w, 's>(
484 state: &'s mut Self::State,
485 system_meta: &SystemMeta,
486 world: UnsafeWorldCell<'w>,
487 change_tick: Tick,
488 ) -> Self::Item<'w, 's> {
489 let query = unsafe { Query::get_param(state, system_meta, world, change_tick) };
491 Populated(query)
492 }
493
494 #[inline]
495 unsafe fn validate_param(
496 state: &mut Self::State,
497 system_meta: &SystemMeta,
498 world: UnsafeWorldCell,
499 ) -> Result<(), SystemParamValidationError> {
500 let query = unsafe {
504 state.query_unchecked_with_ticks(world, system_meta.last_run, world.change_tick())
505 };
506 if query.is_empty() {
507 Err(SystemParamValidationError::skipped::<Self>(
508 "No matching entities",
509 ))
510 } else {
511 Ok(())
512 }
513 }
514}
515
516unsafe impl<'w, 's, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam
518 for Populated<'w, 's, D, F>
519{
520}
521
522pub struct ParamSet<'w, 's, T: SystemParam> {
636 param_states: &'s mut T::State,
637 world: UnsafeWorldCell<'w>,
638 system_meta: SystemMeta,
639 change_tick: Tick,
640}
641
642macro_rules! impl_param_set {
643 ($(($index: tt, $param: ident, $fn_name: ident)),*) => {
644 unsafe impl<'w, 's, $($param,)*> ReadOnlySystemParam for ParamSet<'w, 's, ($($param,)*)>
646 where $($param: ReadOnlySystemParam,)*
647 { }
648
649 unsafe impl<'_w, '_s, $($param: SystemParam,)*> SystemParam for ParamSet<'_w, '_s, ($($param,)*)>
652 {
653 type State = ($($param::State,)*);
654 type Item<'w, 's> = ParamSet<'w, 's, ($($param,)*)>;
655
656 #[expect(
657 clippy::allow_attributes,
658 reason = "This is inside a macro meant for tuples; as such, `non_snake_case` won't always lint."
659 )]
660 #[allow(
661 non_snake_case,
662 reason = "Certain variable names are provided by the caller, not by us."
663 )]
664 fn init_state(world: &mut World) -> Self::State {
665 ($($param::init_state(world),)*)
666 }
667
668 #[expect(
669 clippy::allow_attributes,
670 reason = "This is inside a macro meant for tuples; as such, `non_snake_case` won't always lint."
671 )]
672 #[allow(
673 non_snake_case,
674 reason = "Certain variable names are provided by the caller, not by us."
675 )]
676 fn init_access(state: &Self::State, system_meta: &mut SystemMeta, component_access_set: &mut FilteredAccessSet, world: &mut World) {
677 let ($($param,)*) = state;
678 $(
679 let component_access_set_clone = &mut component_access_set.clone();
681 $param::init_access($param, system_meta, component_access_set_clone, world);
682 )*
683 $(
684 let mut access_set = FilteredAccessSet::new();
687 $param::init_access($param, system_meta, &mut access_set, world);
688 component_access_set.extend(access_set);
689 )*
690 }
691
692 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
693 <($($param,)*) as SystemParam>::apply(state, system_meta, world);
694 }
695
696 fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
697 <($($param,)*) as SystemParam>::queue(state, system_meta, world.reborrow());
698 }
699
700 #[inline]
701 unsafe fn validate_param<'w, 's>(
702 state: &'s mut Self::State,
703 system_meta: &SystemMeta,
704 world: UnsafeWorldCell<'w>,
705 ) -> Result<(), SystemParamValidationError> {
706 unsafe {
708 <($($param,)*) as SystemParam>::validate_param(state, system_meta, world)
709 }
710 }
711
712 #[inline]
713 unsafe fn get_param<'w, 's>(
714 state: &'s mut Self::State,
715 system_meta: &SystemMeta,
716 world: UnsafeWorldCell<'w>,
717 change_tick: Tick,
718 ) -> Self::Item<'w, 's> {
719 ParamSet {
720 param_states: state,
721 system_meta: system_meta.clone(),
722 world,
723 change_tick,
724 }
725 }
726 }
727
728 impl<'w, 's, $($param: SystemParam,)*> ParamSet<'w, 's, ($($param,)*)>
729 {
730 $(
731 #[doc = stringify!($index)]
733 pub fn $fn_name<'a>(&'a mut self) -> SystemParamItem<'a, 'a, $param> {
736 unsafe {
740 $param::get_param(&mut self.param_states.$index, &self.system_meta, self.world, self.change_tick)
741 }
742 }
743 )*
744 }
745 }
746}
747
748all_tuples_enumerated!(impl_param_set, 1, 8, P, p);
749
750unsafe impl<'a, T: Resource> ReadOnlySystemParam for Res<'a, T> {}
752
753unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> {
756 type State = ComponentId;
757 type Item<'w, 's> = Res<'w, T>;
758
759 fn init_state(world: &mut World) -> Self::State {
760 world.components_registrator().register_resource::<T>()
761 }
762
763 fn init_access(
764 &component_id: &Self::State,
765 system_meta: &mut SystemMeta,
766 component_access_set: &mut FilteredAccessSet,
767 _world: &mut World,
768 ) {
769 let combined_access = component_access_set.combined_access();
770 assert!(
771 !combined_access.has_resource_write(component_id),
772 "error[B0002]: Res<{}> in system {} conflicts with a previous ResMut<{0}> access. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",
773 DebugName::type_name::<T>(),
774 system_meta.name,
775 );
776
777 component_access_set.add_unfiltered_resource_read(component_id);
778 }
779
780 #[inline]
781 unsafe fn validate_param(
782 &mut component_id: &mut Self::State,
783 _system_meta: &SystemMeta,
784 world: UnsafeWorldCell,
785 ) -> Result<(), SystemParamValidationError> {
786 if unsafe { world.storages() }
788 .resources
789 .get(component_id)
790 .is_some_and(ResourceData::is_present)
791 {
792 Ok(())
793 } else {
794 Err(SystemParamValidationError::invalid::<Self>(
795 "Resource does not exist",
796 ))
797 }
798 }
799
800 #[inline]
801 unsafe fn get_param<'w, 's>(
802 &mut component_id: &'s mut Self::State,
803 system_meta: &SystemMeta,
804 world: UnsafeWorldCell<'w>,
805 change_tick: Tick,
806 ) -> Self::Item<'w, 's> {
807 let (ptr, ticks) = world
808 .get_resource_with_ticks(component_id)
809 .unwrap_or_else(|| {
810 panic!(
811 "Resource requested by {} does not exist: {}",
812 system_meta.name,
813 DebugName::type_name::<T>()
814 );
815 });
816 Res {
817 value: ptr.deref(),
818 ticks: ComponentTicksRef {
819 added: ticks.added.deref(),
820 changed: ticks.changed.deref(),
821 changed_by: ticks.changed_by.map(|changed_by| changed_by.deref()),
822 last_run: system_meta.last_run,
823 this_run: change_tick,
824 },
825 }
826 }
827}
828
829unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> {
832 type State = ComponentId;
833 type Item<'w, 's> = ResMut<'w, T>;
834
835 fn init_state(world: &mut World) -> Self::State {
836 world.components_registrator().register_resource::<T>()
837 }
838
839 fn init_access(
840 &component_id: &Self::State,
841 system_meta: &mut SystemMeta,
842 component_access_set: &mut FilteredAccessSet,
843 _world: &mut World,
844 ) {
845 let combined_access = component_access_set.combined_access();
846 if combined_access.has_resource_write(component_id) {
847 panic!(
848 "error[B0002]: ResMut<{}> in system {} conflicts with a previous ResMut<{0}> access. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",
849 DebugName::type_name::<T>(), system_meta.name);
850 } else if combined_access.has_resource_read(component_id) {
851 panic!(
852 "error[B0002]: ResMut<{}> in system {} conflicts with a previous Res<{0}> access. Consider removing the duplicate access. See: https://bevy.org/learn/errors/b0002",
853 DebugName::type_name::<T>(), system_meta.name);
854 }
855 component_access_set.add_unfiltered_resource_write(component_id);
856 }
857
858 #[inline]
859 unsafe fn validate_param(
860 &mut component_id: &mut Self::State,
861 _system_meta: &SystemMeta,
862 world: UnsafeWorldCell,
863 ) -> Result<(), SystemParamValidationError> {
864 if unsafe { world.storages() }
866 .resources
867 .get(component_id)
868 .is_some_and(ResourceData::is_present)
869 {
870 Ok(())
871 } else {
872 Err(SystemParamValidationError::invalid::<Self>(
873 "Resource does not exist",
874 ))
875 }
876 }
877
878 #[inline]
879 unsafe fn get_param<'w, 's>(
880 &mut component_id: &'s mut Self::State,
881 system_meta: &SystemMeta,
882 world: UnsafeWorldCell<'w>,
883 change_tick: Tick,
884 ) -> Self::Item<'w, 's> {
885 let value = world
886 .get_resource_mut_by_id(component_id)
887 .unwrap_or_else(|| {
888 panic!(
889 "Resource requested by {} does not exist: {}",
890 system_meta.name,
891 DebugName::type_name::<T>()
892 );
893 });
894 ResMut {
895 value: value.value.deref_mut::<T>(),
896 ticks: ComponentTicksMut {
897 added: value.ticks.added,
898 changed: value.ticks.changed,
899 changed_by: value.ticks.changed_by,
900 last_run: system_meta.last_run,
901 this_run: change_tick,
902 },
903 }
904 }
905}
906
907unsafe impl<'w> ReadOnlySystemParam for &'w World {}
909
910unsafe impl SystemParam for &'_ World {
912 type State = ();
913 type Item<'w, 's> = &'w World;
914
915 fn init_state(_world: &mut World) -> Self::State {}
916
917 fn init_access(
918 _state: &Self::State,
919 _system_meta: &mut SystemMeta,
920 component_access_set: &mut FilteredAccessSet,
921 _world: &mut World,
922 ) {
923 let mut filtered_access = FilteredAccess::default();
924
925 filtered_access.read_all();
926 if !component_access_set
927 .get_conflicts_single(&filtered_access)
928 .is_empty()
929 {
930 panic!("&World conflicts with a previous mutable system parameter. Allowing this would break Rust's mutability rules");
931 }
932 component_access_set.add(filtered_access);
933 }
934
935 #[inline]
936 unsafe fn get_param<'w, 's>(
937 _state: &'s mut Self::State,
938 _system_meta: &SystemMeta,
939 world: UnsafeWorldCell<'w>,
940 _change_tick: Tick,
941 ) -> Self::Item<'w, 's> {
942 unsafe { world.world() }
944 }
945}
946
947unsafe impl<'w> SystemParam for DeferredWorld<'w> {
949 type State = ();
950 type Item<'world, 'state> = DeferredWorld<'world>;
951
952 fn init_state(_world: &mut World) -> Self::State {}
953
954 fn init_access(
955 _state: &Self::State,
956 system_meta: &mut SystemMeta,
957 component_access_set: &mut FilteredAccessSet,
958 _world: &mut World,
959 ) {
960 assert!(
961 !component_access_set.combined_access().has_any_read(),
962 "DeferredWorld in system {} conflicts with a previous access.",
963 system_meta.name,
964 );
965 component_access_set.write_all();
966 }
967
968 unsafe fn get_param<'world, 'state>(
969 _state: &'state mut Self::State,
970 _system_meta: &SystemMeta,
971 world: UnsafeWorldCell<'world>,
972 _change_tick: Tick,
973 ) -> Self::Item<'world, 'state> {
974 unsafe { world.into_deferred() }
976 }
977}
978
979#[derive(Debug)]
1096pub struct Local<'s, T: FromWorld + Send + 'static>(pub(crate) &'s mut T);
1097
1098unsafe impl<'s, T: FromWorld + Send + 'static> ReadOnlySystemParam for Local<'s, T> {}
1100
1101impl<'s, T: FromWorld + Send + 'static> Deref for Local<'s, T> {
1102 type Target = T;
1103
1104 #[inline]
1105 fn deref(&self) -> &Self::Target {
1106 self.0
1107 }
1108}
1109
1110impl<'s, T: FromWorld + Send + 'static> DerefMut for Local<'s, T> {
1111 #[inline]
1112 fn deref_mut(&mut self) -> &mut Self::Target {
1113 self.0
1114 }
1115}
1116
1117impl<'s, 'a, T: FromWorld + Send + 'static> IntoIterator for &'a Local<'s, T>
1118where
1119 &'a T: IntoIterator,
1120{
1121 type Item = <&'a T as IntoIterator>::Item;
1122 type IntoIter = <&'a T as IntoIterator>::IntoIter;
1123
1124 fn into_iter(self) -> Self::IntoIter {
1125 self.0.into_iter()
1126 }
1127}
1128
1129impl<'s, 'a, T: FromWorld + Send + 'static> IntoIterator for &'a mut Local<'s, T>
1130where
1131 &'a mut T: IntoIterator,
1132{
1133 type Item = <&'a mut T as IntoIterator>::Item;
1134 type IntoIter = <&'a mut T as IntoIterator>::IntoIter;
1135
1136 fn into_iter(self) -> Self::IntoIter {
1137 self.0.into_iter()
1138 }
1139}
1140
1141unsafe impl<'a, T: FromWorld + Send + 'static> SystemParam for Local<'a, T> {
1143 type State = SyncCell<T>;
1144 type Item<'w, 's> = Local<'s, T>;
1145
1146 fn init_state(world: &mut World) -> Self::State {
1147 SyncCell::new(T::from_world(world))
1148 }
1149
1150 fn init_access(
1151 _state: &Self::State,
1152 _system_meta: &mut SystemMeta,
1153 _component_access_set: &mut FilteredAccessSet,
1154 _world: &mut World,
1155 ) {
1156 }
1157
1158 #[inline]
1159 unsafe fn get_param<'w, 's>(
1160 state: &'s mut Self::State,
1161 _system_meta: &SystemMeta,
1162 _world: UnsafeWorldCell<'w>,
1163 _change_tick: Tick,
1164 ) -> Self::Item<'w, 's> {
1165 Local(state.get())
1166 }
1167}
1168
1169pub trait SystemBuffer: FromWorld + Send + 'static {
1176 fn apply(&mut self, system_meta: &SystemMeta, world: &mut World);
1178 fn queue(&mut self, _system_meta: &SystemMeta, _world: DeferredWorld) {}
1180}
1181
1182pub struct Deferred<'a, T: SystemBuffer>(pub(crate) &'a mut T);
1302
1303impl<'a, T: SystemBuffer> Deref for Deferred<'a, T> {
1304 type Target = T;
1305 #[inline]
1306 fn deref(&self) -> &Self::Target {
1307 self.0
1308 }
1309}
1310
1311impl<'a, T: SystemBuffer> DerefMut for Deferred<'a, T> {
1312 #[inline]
1313 fn deref_mut(&mut self) -> &mut Self::Target {
1314 self.0
1315 }
1316}
1317
1318impl<T: SystemBuffer> Deferred<'_, T> {
1319 pub fn reborrow(&mut self) -> Deferred<'_, T> {
1322 Deferred(self.0)
1323 }
1324}
1325
1326unsafe impl<T: SystemBuffer> ReadOnlySystemParam for Deferred<'_, T> {}
1328
1329unsafe impl<T: SystemBuffer> SystemParam for Deferred<'_, T> {
1331 type State = SyncCell<T>;
1332 type Item<'w, 's> = Deferred<'s, T>;
1333
1334 #[track_caller]
1335 fn init_state(world: &mut World) -> Self::State {
1336 SyncCell::new(T::from_world(world))
1337 }
1338
1339 fn init_access(
1340 _state: &Self::State,
1341 system_meta: &mut SystemMeta,
1342 _component_access_set: &mut FilteredAccessSet,
1343 _world: &mut World,
1344 ) {
1345 system_meta.set_has_deferred();
1346 }
1347
1348 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1349 state.get().apply(system_meta, world);
1350 }
1351
1352 fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
1353 state.get().queue(system_meta, world);
1354 }
1355
1356 #[inline]
1357 unsafe fn get_param<'w, 's>(
1358 state: &'s mut Self::State,
1359 _system_meta: &SystemMeta,
1360 _world: UnsafeWorldCell<'w>,
1361 _change_tick: Tick,
1362 ) -> Self::Item<'w, 's> {
1363 Deferred(state.get())
1364 }
1365}
1366
1367pub struct ExclusiveMarker(PhantomData<()>);
1369
1370unsafe impl SystemParam for ExclusiveMarker {
1372 type State = ();
1373 type Item<'w, 's> = Self;
1374
1375 #[inline]
1376 fn init_state(_world: &mut World) -> Self::State {}
1377
1378 fn init_access(
1379 _state: &Self::State,
1380 system_meta: &mut SystemMeta,
1381 _component_access_set: &mut FilteredAccessSet,
1382 _world: &mut World,
1383 ) {
1384 system_meta.set_exclusive();
1385 }
1386
1387 #[inline]
1388 unsafe fn get_param<'world, 'state>(
1389 _state: &'state mut Self::State,
1390 _system_meta: &SystemMeta,
1391 _world: UnsafeWorldCell<'world>,
1392 _change_tick: Tick,
1393 ) -> Self::Item<'world, 'state> {
1394 Self(PhantomData)
1395 }
1396}
1397
1398unsafe impl ReadOnlySystemParam for ExclusiveMarker {}
1400
1401pub struct NonSendMarker(PhantomData<*mut ()>);
1403
1404unsafe impl SystemParam for NonSendMarker {
1406 type State = ();
1407 type Item<'w, 's> = Self;
1408
1409 #[inline]
1410 fn init_state(_world: &mut World) -> Self::State {}
1411
1412 fn init_access(
1413 _state: &Self::State,
1414 system_meta: &mut SystemMeta,
1415 _component_access_set: &mut FilteredAccessSet,
1416 _world: &mut World,
1417 ) {
1418 system_meta.set_non_send();
1419 }
1420
1421 #[inline]
1422 unsafe fn get_param<'world, 'state>(
1423 _state: &'state mut Self::State,
1424 _system_meta: &SystemMeta,
1425 _world: UnsafeWorldCell<'world>,
1426 _change_tick: Tick,
1427 ) -> Self::Item<'world, 'state> {
1428 Self(PhantomData)
1429 }
1430}
1431
1432unsafe impl ReadOnlySystemParam for NonSendMarker {}
1434
1435unsafe impl<'w, T> ReadOnlySystemParam for NonSend<'w, T> {}
1437
1438unsafe impl<'a, T: 'static> SystemParam for NonSend<'a, T> {
1441 type State = ComponentId;
1442 type Item<'w, 's> = NonSend<'w, T>;
1443
1444 fn init_state(world: &mut World) -> Self::State {
1445 world.components_registrator().register_non_send::<T>()
1446 }
1447
1448 fn init_access(
1449 &component_id: &Self::State,
1450 system_meta: &mut SystemMeta,
1451 component_access_set: &mut FilteredAccessSet,
1452 _world: &mut World,
1453 ) {
1454 system_meta.set_non_send();
1455
1456 let combined_access = component_access_set.combined_access();
1457 assert!(
1458 !combined_access.has_resource_write(component_id),
1459 "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",
1460 DebugName::type_name::<T>(),
1461 system_meta.name,
1462 );
1463 component_access_set.add_unfiltered_resource_read(component_id);
1464 }
1465
1466 #[inline]
1467 unsafe fn validate_param(
1468 &mut component_id: &mut Self::State,
1469 _system_meta: &SystemMeta,
1470 world: UnsafeWorldCell,
1471 ) -> Result<(), SystemParamValidationError> {
1472 if unsafe { world.storages() }
1474 .non_send_resources
1475 .get(component_id)
1476 .is_some_and(ResourceData::is_present)
1477 {
1478 Ok(())
1479 } else {
1480 Err(SystemParamValidationError::invalid::<Self>(
1481 "Non-send resource does not exist",
1482 ))
1483 }
1484 }
1485
1486 #[inline]
1487 unsafe fn get_param<'w, 's>(
1488 &mut component_id: &'s mut Self::State,
1489 system_meta: &SystemMeta,
1490 world: UnsafeWorldCell<'w>,
1491 change_tick: Tick,
1492 ) -> Self::Item<'w, 's> {
1493 let (ptr, ticks) = world
1494 .get_non_send_with_ticks(component_id)
1495 .unwrap_or_else(|| {
1496 panic!(
1497 "Non-send resource requested by {} does not exist: {}",
1498 system_meta.name,
1499 DebugName::type_name::<T>()
1500 );
1501 });
1502 NonSend {
1503 value: ptr.deref(),
1504 ticks: ComponentTicksRef::from_tick_cells(ticks, system_meta.last_run, change_tick),
1505 }
1506 }
1507}
1508
1509unsafe impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> {
1512 type State = ComponentId;
1513 type Item<'w, 's> = NonSendMut<'w, T>;
1514
1515 fn init_state(world: &mut World) -> Self::State {
1516 world.components_registrator().register_non_send::<T>()
1517 }
1518
1519 fn init_access(
1520 &component_id: &Self::State,
1521 system_meta: &mut SystemMeta,
1522 component_access_set: &mut FilteredAccessSet,
1523 _world: &mut World,
1524 ) {
1525 system_meta.set_non_send();
1526
1527 let combined_access = component_access_set.combined_access();
1528 if combined_access.has_resource_write(component_id) {
1529 panic!(
1530 "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",
1531 DebugName::type_name::<T>(), system_meta.name);
1532 } else if combined_access.has_resource_read(component_id) {
1533 panic!(
1534 "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",
1535 DebugName::type_name::<T>(), system_meta.name);
1536 }
1537 component_access_set.add_unfiltered_resource_write(component_id);
1538 }
1539
1540 #[inline]
1541 unsafe fn validate_param(
1542 &mut component_id: &mut Self::State,
1543 _system_meta: &SystemMeta,
1544 world: UnsafeWorldCell,
1545 ) -> Result<(), SystemParamValidationError> {
1546 if unsafe { world.storages() }
1548 .non_send_resources
1549 .get(component_id)
1550 .is_some_and(ResourceData::is_present)
1551 {
1552 Ok(())
1553 } else {
1554 Err(SystemParamValidationError::invalid::<Self>(
1555 "Non-send resource does not exist",
1556 ))
1557 }
1558 }
1559
1560 #[inline]
1561 unsafe fn get_param<'w, 's>(
1562 &mut component_id: &'s mut Self::State,
1563 system_meta: &SystemMeta,
1564 world: UnsafeWorldCell<'w>,
1565 change_tick: Tick,
1566 ) -> Self::Item<'w, 's> {
1567 let (ptr, ticks) = world
1568 .get_non_send_with_ticks(component_id)
1569 .unwrap_or_else(|| {
1570 panic!(
1571 "Non-send resource requested by {} does not exist: {}",
1572 system_meta.name,
1573 DebugName::type_name::<T>()
1574 );
1575 });
1576 NonSendMut {
1577 value: ptr.assert_unique().deref_mut(),
1578 ticks: ComponentTicksMut::from_tick_cells(ticks, system_meta.last_run, change_tick),
1579 }
1580 }
1581}
1582
1583unsafe impl<'a> ReadOnlySystemParam for &'a Archetypes {}
1585
1586unsafe impl<'a> SystemParam for &'a Archetypes {
1588 type State = ();
1589 type Item<'w, 's> = &'w Archetypes;
1590
1591 fn init_state(_world: &mut World) -> Self::State {}
1592
1593 fn init_access(
1594 _state: &Self::State,
1595 _system_meta: &mut SystemMeta,
1596 _component_access_set: &mut FilteredAccessSet,
1597 _world: &mut World,
1598 ) {
1599 }
1600
1601 #[inline]
1602 unsafe fn get_param<'w, 's>(
1603 _state: &'s mut Self::State,
1604 _system_meta: &SystemMeta,
1605 world: UnsafeWorldCell<'w>,
1606 _change_tick: Tick,
1607 ) -> Self::Item<'w, 's> {
1608 world.archetypes()
1609 }
1610}
1611
1612unsafe impl<'a> ReadOnlySystemParam for &'a Components {}
1614
1615unsafe impl<'a> SystemParam for &'a Components {
1617 type State = ();
1618 type Item<'w, 's> = &'w Components;
1619
1620 fn init_state(_world: &mut World) -> Self::State {}
1621
1622 fn init_access(
1623 _state: &Self::State,
1624 _system_meta: &mut SystemMeta,
1625 _component_access_set: &mut FilteredAccessSet,
1626 _world: &mut World,
1627 ) {
1628 }
1629
1630 #[inline]
1631 unsafe fn get_param<'w, 's>(
1632 _state: &'s mut Self::State,
1633 _system_meta: &SystemMeta,
1634 world: UnsafeWorldCell<'w>,
1635 _change_tick: Tick,
1636 ) -> Self::Item<'w, 's> {
1637 world.components()
1638 }
1639}
1640
1641unsafe impl<'a> ReadOnlySystemParam for &'a Entities {}
1643
1644unsafe impl<'a> SystemParam for &'a Entities {
1646 type State = ();
1647 type Item<'w, 's> = &'w Entities;
1648
1649 fn init_state(_world: &mut World) -> Self::State {}
1650
1651 fn init_access(
1652 _state: &Self::State,
1653 _system_meta: &mut SystemMeta,
1654 _component_access_set: &mut FilteredAccessSet,
1655 _world: &mut World,
1656 ) {
1657 }
1658
1659 #[inline]
1660 unsafe fn get_param<'w, 's>(
1661 _state: &'s mut Self::State,
1662 _system_meta: &SystemMeta,
1663 world: UnsafeWorldCell<'w>,
1664 _change_tick: Tick,
1665 ) -> Self::Item<'w, 's> {
1666 world.entities()
1667 }
1668}
1669
1670unsafe impl<'a> ReadOnlySystemParam for &'a EntityAllocator {}
1672
1673unsafe impl<'a> SystemParam for &'a EntityAllocator {
1675 type State = ();
1676 type Item<'w, 's> = &'w EntityAllocator;
1677
1678 fn init_state(_world: &mut World) -> Self::State {}
1679
1680 fn init_access(
1681 _state: &Self::State,
1682 _system_meta: &mut SystemMeta,
1683 _component_access_set: &mut FilteredAccessSet,
1684 _world: &mut World,
1685 ) {
1686 }
1687
1688 #[inline]
1689 unsafe fn get_param<'w, 's>(
1690 _state: &'s mut Self::State,
1691 _system_meta: &SystemMeta,
1692 world: UnsafeWorldCell<'w>,
1693 _change_tick: Tick,
1694 ) -> Self::Item<'w, 's> {
1695 world.entities_allocator()
1696 }
1697}
1698
1699unsafe impl<'a> ReadOnlySystemParam for &'a Bundles {}
1701
1702unsafe impl<'a> SystemParam for &'a Bundles {
1704 type State = ();
1705 type Item<'w, 's> = &'w Bundles;
1706
1707 fn init_state(_world: &mut World) -> Self::State {}
1708
1709 fn init_access(
1710 _state: &Self::State,
1711 _system_meta: &mut SystemMeta,
1712 _component_access_set: &mut FilteredAccessSet,
1713 _world: &mut World,
1714 ) {
1715 }
1716
1717 #[inline]
1718 unsafe fn get_param<'w, 's>(
1719 _state: &'s mut Self::State,
1720 _system_meta: &SystemMeta,
1721 world: UnsafeWorldCell<'w>,
1722 _change_tick: Tick,
1723 ) -> Self::Item<'w, 's> {
1724 world.bundles()
1725 }
1726}
1727
1728#[derive(Debug, Clone, Copy)]
1738pub struct SystemChangeTick {
1739 last_run: Tick,
1740 this_run: Tick,
1741}
1742
1743impl SystemChangeTick {
1744 #[inline]
1746 pub fn this_run(&self) -> Tick {
1747 self.this_run
1748 }
1749
1750 #[inline]
1752 pub fn last_run(&self) -> Tick {
1753 self.last_run
1754 }
1755}
1756
1757unsafe impl ReadOnlySystemParam for SystemChangeTick {}
1759
1760unsafe impl SystemParam for SystemChangeTick {
1762 type State = ();
1763 type Item<'w, 's> = SystemChangeTick;
1764
1765 fn init_state(_world: &mut World) -> Self::State {}
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 }
1774
1775 #[inline]
1776 unsafe fn get_param<'w, 's>(
1777 _state: &'s mut Self::State,
1778 system_meta: &SystemMeta,
1779 _world: UnsafeWorldCell<'w>,
1780 change_tick: Tick,
1781 ) -> Self::Item<'w, 's> {
1782 SystemChangeTick {
1783 last_run: system_meta.last_run,
1784 this_run: change_tick,
1785 }
1786 }
1787}
1788
1789unsafe impl<T: SystemParam> SystemParam for Option<T> {
1791 type State = T::State;
1792
1793 type Item<'world, 'state> = Option<T::Item<'world, 'state>>;
1794
1795 fn init_state(world: &mut World) -> Self::State {
1796 T::init_state(world)
1797 }
1798
1799 fn init_access(
1800 state: &Self::State,
1801 system_meta: &mut SystemMeta,
1802 component_access_set: &mut FilteredAccessSet,
1803 world: &mut World,
1804 ) {
1805 T::init_access(state, system_meta, component_access_set, world);
1806 }
1807
1808 #[inline]
1809 unsafe fn get_param<'world, 'state>(
1810 state: &'state mut Self::State,
1811 system_meta: &SystemMeta,
1812 world: UnsafeWorldCell<'world>,
1813 change_tick: Tick,
1814 ) -> Self::Item<'world, 'state> {
1815 unsafe {
1817 T::validate_param(state, system_meta, world)
1818 .ok()
1819 .map(|()| T::get_param(state, system_meta, world, change_tick))
1820 }
1821 }
1822
1823 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1824 T::apply(state, system_meta, world);
1825 }
1826
1827 fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
1828 T::queue(state, system_meta, world);
1829 }
1830}
1831
1832unsafe impl<T: ReadOnlySystemParam> ReadOnlySystemParam for Option<T> {}
1834
1835unsafe impl<T: SystemParam> SystemParam for Result<T, SystemParamValidationError> {
1837 type State = T::State;
1838
1839 type Item<'world, 'state> = Result<T::Item<'world, 'state>, SystemParamValidationError>;
1840
1841 fn init_state(world: &mut World) -> Self::State {
1842 T::init_state(world)
1843 }
1844
1845 fn init_access(
1846 state: &Self::State,
1847 system_meta: &mut SystemMeta,
1848 component_access_set: &mut FilteredAccessSet,
1849 world: &mut World,
1850 ) {
1851 T::init_access(state, system_meta, component_access_set, world);
1852 }
1853
1854 #[inline]
1855 unsafe fn get_param<'world, 'state>(
1856 state: &'state mut Self::State,
1857 system_meta: &SystemMeta,
1858 world: UnsafeWorldCell<'world>,
1859 change_tick: Tick,
1860 ) -> Self::Item<'world, 'state> {
1861 unsafe {
1863 T::validate_param(state, system_meta, world)
1864 .map(|()| T::get_param(state, system_meta, world, change_tick))
1865 }
1866 }
1867
1868 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1869 T::apply(state, system_meta, world);
1870 }
1871
1872 fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
1873 T::queue(state, system_meta, world);
1874 }
1875}
1876
1877unsafe impl<T: ReadOnlySystemParam> ReadOnlySystemParam for Result<T, SystemParamValidationError> {}
1879
1880#[derive(Debug)]
1899pub struct If<T>(pub T);
1900
1901impl<T> If<T> {
1902 pub fn into_inner(self) -> T {
1916 self.0
1917 }
1918}
1919
1920impl<T> Deref for If<T> {
1921 type Target = T;
1922 fn deref(&self) -> &Self::Target {
1923 &self.0
1924 }
1925}
1926
1927impl<T> DerefMut for If<T> {
1928 fn deref_mut(&mut self) -> &mut Self::Target {
1929 &mut self.0
1930 }
1931}
1932
1933unsafe impl<T: SystemParam> SystemParam for If<T> {
1935 type State = T::State;
1936
1937 type Item<'world, 'state> = If<T::Item<'world, 'state>>;
1938
1939 fn init_state(world: &mut World) -> Self::State {
1940 T::init_state(world)
1941 }
1942
1943 fn init_access(
1944 state: &Self::State,
1945 system_meta: &mut SystemMeta,
1946 component_access_set: &mut FilteredAccessSet,
1947 world: &mut World,
1948 ) {
1949 T::init_access(state, system_meta, component_access_set, world);
1950 }
1951
1952 #[inline]
1953 unsafe fn validate_param(
1954 state: &mut Self::State,
1955 system_meta: &SystemMeta,
1956 world: UnsafeWorldCell,
1957 ) -> Result<(), SystemParamValidationError> {
1958 unsafe { T::validate_param(state, system_meta, world) }.map_err(|mut e| {
1960 e.skipped = true;
1961 e
1962 })
1963 }
1964
1965 #[inline]
1966 unsafe fn get_param<'world, 'state>(
1967 state: &'state mut Self::State,
1968 system_meta: &SystemMeta,
1969 world: UnsafeWorldCell<'world>,
1970 change_tick: Tick,
1971 ) -> Self::Item<'world, 'state> {
1972 If(unsafe { T::get_param(state, system_meta, world, change_tick) })
1974 }
1975
1976 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1977 T::apply(state, system_meta, world);
1978 }
1979
1980 fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
1981 T::queue(state, system_meta, world);
1982 }
1983}
1984
1985unsafe impl<T: ReadOnlySystemParam> ReadOnlySystemParam for If<T> {}
1987
1988unsafe impl<T: SystemParam> SystemParam for Vec<T> {
1991 type State = Vec<T::State>;
1992
1993 type Item<'world, 'state> = Vec<T::Item<'world, 'state>>;
1994
1995 fn init_state(_world: &mut World) -> Self::State {
1996 Vec::new()
1997 }
1998
1999 fn init_access(
2000 state: &Self::State,
2001 system_meta: &mut SystemMeta,
2002 component_access_set: &mut FilteredAccessSet,
2003 world: &mut World,
2004 ) {
2005 for state in state {
2006 T::init_access(state, system_meta, component_access_set, world);
2007 }
2008 }
2009
2010 #[inline]
2011 unsafe fn validate_param(
2012 state: &mut Self::State,
2013 system_meta: &SystemMeta,
2014 world: UnsafeWorldCell,
2015 ) -> Result<(), SystemParamValidationError> {
2016 for state in state {
2017 unsafe { T::validate_param(state, system_meta, world)? };
2019 }
2020 Ok(())
2021 }
2022
2023 #[inline]
2024 unsafe fn get_param<'world, 'state>(
2025 state: &'state mut Self::State,
2026 system_meta: &SystemMeta,
2027 world: UnsafeWorldCell<'world>,
2028 change_tick: Tick,
2029 ) -> Self::Item<'world, 'state> {
2030 state
2031 .iter_mut()
2032 .map(|state| unsafe { T::get_param(state, system_meta, world, change_tick) })
2036 .collect()
2037 }
2038
2039 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
2040 for state in state {
2041 T::apply(state, system_meta, world);
2042 }
2043 }
2044
2045 fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
2046 for state in state {
2047 T::queue(state, system_meta, world.reborrow());
2048 }
2049 }
2050}
2051
2052unsafe impl<T: SystemParam> SystemParam for ParamSet<'_, '_, Vec<T>> {
2056 type State = Vec<T::State>;
2057
2058 type Item<'world, 'state> = ParamSet<'world, 'state, Vec<T>>;
2059
2060 fn init_state(_world: &mut World) -> Self::State {
2061 Vec::new()
2062 }
2063
2064 fn init_access(
2065 state: &Self::State,
2066 system_meta: &mut SystemMeta,
2067 component_access_set: &mut FilteredAccessSet,
2068 world: &mut World,
2069 ) {
2070 for state in state {
2071 let component_access_set_clone = &mut component_access_set.clone();
2073 T::init_access(state, system_meta, component_access_set_clone, world);
2074 }
2075 for state in state {
2076 let mut access_set = FilteredAccessSet::new();
2079 T::init_access(state, system_meta, &mut access_set, world);
2080 component_access_set.extend(access_set);
2081 }
2082 }
2083
2084 #[inline]
2085 unsafe fn get_param<'world, 'state>(
2086 state: &'state mut Self::State,
2087 system_meta: &SystemMeta,
2088 world: UnsafeWorldCell<'world>,
2089 change_tick: Tick,
2090 ) -> Self::Item<'world, 'state> {
2091 ParamSet {
2092 param_states: state,
2093 system_meta: system_meta.clone(),
2094 world,
2095 change_tick,
2096 }
2097 }
2098
2099 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
2100 for state in state {
2101 T::apply(state, system_meta, world);
2102 }
2103 }
2104
2105 fn queue(state: &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
2106 for state in state {
2107 T::queue(state, system_meta, world.reborrow());
2108 }
2109 }
2110}
2111
2112impl<T: SystemParam> ParamSet<'_, '_, Vec<T>> {
2113 pub fn get_mut(&mut self, index: usize) -> T::Item<'_, '_> {
2116 unsafe {
2121 T::get_param(
2122 &mut self.param_states[index],
2123 &self.system_meta,
2124 self.world,
2125 self.change_tick,
2126 )
2127 }
2128 }
2129
2130 pub fn for_each(&mut self, mut f: impl FnMut(T::Item<'_, '_>)) {
2132 self.param_states.iter_mut().for_each(|state| {
2133 f(
2134 unsafe { T::get_param(state, &self.system_meta, self.world, self.change_tick) },
2139 );
2140 });
2141 }
2142}
2143
2144macro_rules! impl_system_param_tuple {
2145 ($(#[$meta:meta])* $($param: ident),*) => {
2146 $(#[$meta])*
2147 unsafe impl<$($param: ReadOnlySystemParam),*> ReadOnlySystemParam for ($($param,)*) {}
2149
2150 #[expect(
2151 clippy::allow_attributes,
2152 reason = "This is in a macro, and as such, the below lints may not always apply."
2153 )]
2154 #[allow(
2155 non_snake_case,
2156 reason = "Certain variable names are provided by the caller, not by us."
2157 )]
2158 #[allow(
2159 unused_variables,
2160 reason = "Zero-length tuples won't use some of the parameters."
2161 )]
2162 #[allow(clippy::unused_unit, reason = "Zero length tuple is unit.")]
2163 $(#[$meta])*
2164 unsafe impl<$($param: SystemParam),*> SystemParam for ($($param,)*) {
2166 type State = ($($param::State,)*);
2167 type Item<'w, 's> = ($($param::Item::<'w, 's>,)*);
2168
2169 #[inline]
2170 #[track_caller]
2171 fn init_state(world: &mut World) -> Self::State {
2172 ($($param::init_state(world),)*)
2173 }
2174
2175 fn init_access(state: &Self::State, _system_meta: &mut SystemMeta, _component_access_set: &mut FilteredAccessSet, _world: &mut World) {
2176 let ($($param,)*) = state;
2177 $($param::init_access($param, _system_meta, _component_access_set, _world);)*
2178 }
2179
2180 #[inline]
2181 fn apply(($($param,)*): &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
2182 $($param::apply($param, system_meta, world);)*
2183 }
2184
2185 #[inline]
2186 #[allow(
2187 unused_mut,
2188 reason = "The `world` parameter is unused for zero-length tuples; however, it must be mutable for other lengths of tuples."
2189 )]
2190 fn queue(($($param,)*): &mut Self::State, system_meta: &SystemMeta, mut world: DeferredWorld) {
2191 $($param::queue($param, system_meta, world.reborrow());)*
2192 }
2193
2194 #[inline]
2195 unsafe fn validate_param(
2196 state: &mut Self::State,
2197 system_meta: &SystemMeta,
2198 world: UnsafeWorldCell,
2199 ) -> Result<(), SystemParamValidationError> {
2200 let ($($param,)*) = state;
2201
2202 #[allow(
2203 unused_unsafe,
2204 reason = "Zero-length tuples won't have any params to validate."
2205 )]
2206 unsafe {
2208 $(
2209 $param::validate_param($param, system_meta, world)?;
2210 )*
2211 }
2212 Ok(())
2213 }
2214
2215 #[inline]
2216 #[track_caller]
2217 unsafe fn get_param<'w, 's>(
2218 state: &'s mut Self::State,
2219 system_meta: &SystemMeta,
2220 world: UnsafeWorldCell<'w>,
2221 change_tick: Tick,
2222 ) -> Self::Item<'w, 's> {
2223 let ($($param,)*) = state;
2224
2225 #[allow(
2226 unused_unsafe,
2227 reason = "Zero-length tuples won't have any params to validate."
2228 )]
2229 unsafe {
2231 #[allow(
2232 clippy::unused_unit,
2233 reason = "Zero-length tuples won't have any params to get."
2234 )]
2235 ($($param::get_param($param, system_meta, world, change_tick),)*)
2236 }
2237 }
2238 }
2239 };
2240}
2241
2242all_tuples!(
2243 #[doc(fake_variadic)]
2244 impl_system_param_tuple,
2245 0,
2246 16,
2247 P
2248);
2249
2250pub mod lifetimeless {
2263 pub type SQuery<D, F = ()> = super::Query<'static, 'static, D, F>;
2265 pub type Read<T> = &'static T;
2267 pub type Write<T> = &'static mut T;
2269 pub type SRes<T> = super::Res<'static, T>;
2271 pub type SResMut<T> = super::ResMut<'static, T>;
2273 pub type SCommands = crate::system::Commands<'static, 'static>;
2275}
2276
2277pub struct StaticSystemParam<'w, 's, P: SystemParam>(SystemParamItem<'w, 's, P>);
2329
2330impl<'w, 's, P: SystemParam> Deref for StaticSystemParam<'w, 's, P> {
2331 type Target = SystemParamItem<'w, 's, P>;
2332
2333 fn deref(&self) -> &Self::Target {
2334 &self.0
2335 }
2336}
2337
2338impl<'w, 's, P: SystemParam> DerefMut for StaticSystemParam<'w, 's, P> {
2339 fn deref_mut(&mut self) -> &mut Self::Target {
2340 &mut self.0
2341 }
2342}
2343
2344impl<'w, 's, P: SystemParam> StaticSystemParam<'w, 's, P> {
2345 pub fn into_inner(self) -> SystemParamItem<'w, 's, P> {
2347 self.0
2348 }
2349}
2350
2351unsafe impl<'w, 's, P: ReadOnlySystemParam + 'static> ReadOnlySystemParam
2353 for StaticSystemParam<'w, 's, P>
2354{
2355}
2356
2357unsafe impl<P: SystemParam + 'static> SystemParam for StaticSystemParam<'_, '_, P> {
2359 type State = P::State;
2360 type Item<'world, 'state> = StaticSystemParam<'world, 'state, P>;
2361
2362 fn init_state(world: &mut World) -> Self::State {
2363 P::init_state(world)
2364 }
2365
2366 fn init_access(
2367 state: &Self::State,
2368 system_meta: &mut SystemMeta,
2369 component_access_set: &mut FilteredAccessSet,
2370 world: &mut World,
2371 ) {
2372 P::init_access(state, system_meta, component_access_set, world);
2373 }
2374
2375 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
2376 P::apply(state, system_meta, world);
2377 }
2378
2379 fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
2380 P::queue(state, system_meta, world);
2381 }
2382
2383 #[inline]
2384 unsafe fn validate_param(
2385 state: &mut Self::State,
2386 system_meta: &SystemMeta,
2387 world: UnsafeWorldCell,
2388 ) -> Result<(), SystemParamValidationError> {
2389 unsafe { P::validate_param(state, system_meta, world) }
2391 }
2392
2393 #[inline]
2394 unsafe fn get_param<'world, 'state>(
2395 state: &'state mut Self::State,
2396 system_meta: &SystemMeta,
2397 world: UnsafeWorldCell<'world>,
2398 change_tick: Tick,
2399 ) -> Self::Item<'world, 'state> {
2400 StaticSystemParam(unsafe { P::get_param(state, system_meta, world, change_tick) })
2402 }
2403}
2404
2405unsafe impl<T: ?Sized> SystemParam for PhantomData<T> {
2407 type State = ();
2408 type Item<'world, 'state> = Self;
2409
2410 fn init_state(_world: &mut World) -> Self::State {}
2411
2412 fn init_access(
2413 _state: &Self::State,
2414 _system_meta: &mut SystemMeta,
2415 _component_access_set: &mut FilteredAccessSet,
2416 _world: &mut World,
2417 ) {
2418 }
2419
2420 #[inline]
2421 unsafe fn get_param<'world, 'state>(
2422 _state: &'state mut Self::State,
2423 _system_meta: &SystemMeta,
2424 _world: UnsafeWorldCell<'world>,
2425 _change_tick: Tick,
2426 ) -> Self::Item<'world, 'state> {
2427 PhantomData
2428 }
2429}
2430
2431unsafe impl<T: ?Sized> ReadOnlySystemParam for PhantomData<T> {}
2433
2434pub struct DynSystemParam<'w, 's> {
2493 state: &'s mut dyn Any,
2495 world: UnsafeWorldCell<'w>,
2496 system_meta: SystemMeta,
2497 change_tick: Tick,
2498}
2499
2500impl<'w, 's> DynSystemParam<'w, 's> {
2501 unsafe fn new(
2508 state: &'s mut dyn Any,
2509 world: UnsafeWorldCell<'w>,
2510 system_meta: SystemMeta,
2511 change_tick: Tick,
2512 ) -> Self {
2513 Self {
2514 state,
2515 world,
2516 system_meta,
2517 change_tick,
2518 }
2519 }
2520
2521 pub fn is<T: SystemParam>(&self) -> bool
2523 where
2525 T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,
2526 {
2527 self.state.is::<ParamState<T::Item<'static, 'static>>>()
2528 }
2529
2530 pub fn downcast<T: SystemParam>(self) -> Option<T>
2533 where
2535 T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,
2536 {
2537 unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }
2542 }
2543
2544 pub fn downcast_mut<'a, T: SystemParam>(&'a mut self) -> Option<T>
2547 where
2549 T::Item<'static, 'static>: SystemParam<Item<'a, 'a> = T> + 'static,
2550 {
2551 unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }
2556 }
2557
2558 pub fn downcast_mut_inner<'a, T: ReadOnlySystemParam>(&'a mut self) -> Option<T>
2564 where
2566 T::Item<'static, 'static>: SystemParam<Item<'w, 'a> = T> + 'static,
2567 {
2568 unsafe { downcast::<T>(self.state, &self.system_meta, self.world, self.change_tick) }
2573 }
2574}
2575
2576unsafe fn downcast<'w, 's, T: SystemParam>(
2583 state: &'s mut dyn Any,
2584 system_meta: &SystemMeta,
2585 world: UnsafeWorldCell<'w>,
2586 change_tick: Tick,
2587) -> Option<T>
2588where
2597 T::Item<'static, 'static>: SystemParam<Item<'w, 's> = T> + 'static,
2598{
2599 state
2600 .downcast_mut::<ParamState<T::Item<'static, 'static>>>()
2601 .map(|state| {
2602 unsafe { T::Item::get_param(&mut state.0, system_meta, world, change_tick) }
2607 })
2608}
2609
2610pub struct DynSystemParamState(Box<dyn DynParamState>);
2612
2613impl DynSystemParamState {
2614 pub(crate) fn new<T: SystemParam + 'static>(state: T::State) -> Self {
2615 Self(Box::new(ParamState::<T>(state)))
2616 }
2617}
2618
2619trait DynParamState: Sync + Send + Any {
2621 fn apply(&mut self, system_meta: &SystemMeta, world: &mut World);
2626
2627 fn queue(&mut self, system_meta: &SystemMeta, world: DeferredWorld);
2629
2630 fn init_access(
2632 &self,
2633 system_meta: &mut SystemMeta,
2634 component_access_set: &mut FilteredAccessSet,
2635 world: &mut World,
2636 );
2637
2638 unsafe fn validate_param(
2643 &mut self,
2644 system_meta: &SystemMeta,
2645 world: UnsafeWorldCell,
2646 ) -> Result<(), SystemParamValidationError>;
2647}
2648
2649struct ParamState<T: SystemParam>(T::State);
2651
2652impl<T: SystemParam + 'static> DynParamState for ParamState<T> {
2653 fn apply(&mut self, system_meta: &SystemMeta, world: &mut World) {
2654 T::apply(&mut self.0, system_meta, world);
2655 }
2656
2657 fn queue(&mut self, system_meta: &SystemMeta, world: DeferredWorld) {
2658 T::queue(&mut self.0, system_meta, world);
2659 }
2660
2661 fn init_access(
2662 &self,
2663 system_meta: &mut SystemMeta,
2664 component_access_set: &mut FilteredAccessSet,
2665 world: &mut World,
2666 ) {
2667 T::init_access(&self.0, system_meta, component_access_set, world);
2668 }
2669
2670 unsafe fn validate_param(
2671 &mut self,
2672 system_meta: &SystemMeta,
2673 world: UnsafeWorldCell,
2674 ) -> Result<(), SystemParamValidationError> {
2675 unsafe { T::validate_param(&mut self.0, system_meta, world) }
2677 }
2678}
2679
2680unsafe impl SystemParam for DynSystemParam<'_, '_> {
2682 type State = DynSystemParamState;
2683
2684 type Item<'world, 'state> = DynSystemParam<'world, 'state>;
2685
2686 fn init_state(_world: &mut World) -> Self::State {
2687 DynSystemParamState::new::<()>(())
2688 }
2689
2690 fn init_access(
2691 state: &Self::State,
2692 system_meta: &mut SystemMeta,
2693 component_access_set: &mut FilteredAccessSet,
2694 world: &mut World,
2695 ) {
2696 state
2697 .0
2698 .init_access(system_meta, component_access_set, world);
2699 }
2700
2701 #[inline]
2702 unsafe fn validate_param(
2703 state: &mut Self::State,
2704 system_meta: &SystemMeta,
2705 world: UnsafeWorldCell,
2706 ) -> Result<(), SystemParamValidationError> {
2707 unsafe { state.0.validate_param(system_meta, world) }
2709 }
2710
2711 #[inline]
2712 unsafe fn get_param<'world, 'state>(
2713 state: &'state mut Self::State,
2714 system_meta: &SystemMeta,
2715 world: UnsafeWorldCell<'world>,
2716 change_tick: Tick,
2717 ) -> Self::Item<'world, 'state> {
2718 unsafe { DynSystemParam::new(state.0.as_mut(), world, system_meta.clone(), change_tick) }
2724 }
2725
2726 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
2727 state.0.apply(system_meta, world);
2728 }
2729
2730 fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
2731 state.0.queue(system_meta, world);
2732 }
2733}
2734
2735unsafe impl SystemParam for FilteredResources<'_, '_> {
2738 type State = Access;
2739
2740 type Item<'world, 'state> = FilteredResources<'world, 'state>;
2741
2742 fn init_state(_world: &mut World) -> Self::State {
2743 Access::new()
2744 }
2745
2746 fn init_access(
2747 access: &Self::State,
2748 system_meta: &mut SystemMeta,
2749 component_access_set: &mut FilteredAccessSet,
2750 world: &mut World,
2751 ) {
2752 let combined_access = component_access_set.combined_access();
2753 let conflicts = combined_access.get_conflicts(access);
2754 if !conflicts.is_empty() {
2755 let accesses = conflicts.format_conflict_list(world);
2756 let system_name = &system_meta.name;
2757 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");
2758 }
2759
2760 if access.has_read_all_resources() {
2761 component_access_set.add_unfiltered_read_all_resources();
2762 } else {
2763 for component_id in access.resource_reads_and_writes() {
2764 component_access_set.add_unfiltered_resource_read(component_id);
2765 }
2766 }
2767 }
2768
2769 unsafe fn get_param<'world, 'state>(
2770 state: &'state mut Self::State,
2771 system_meta: &SystemMeta,
2772 world: UnsafeWorldCell<'world>,
2773 change_tick: Tick,
2774 ) -> Self::Item<'world, 'state> {
2775 unsafe { FilteredResources::new(world, state, system_meta.last_run, change_tick) }
2778 }
2779}
2780
2781unsafe impl ReadOnlySystemParam for FilteredResources<'_, '_> {}
2783
2784unsafe impl SystemParam for FilteredResourcesMut<'_, '_> {
2787 type State = Access;
2788
2789 type Item<'world, 'state> = FilteredResourcesMut<'world, 'state>;
2790
2791 fn init_state(_world: &mut World) -> Self::State {
2792 Access::new()
2793 }
2794
2795 fn init_access(
2796 access: &Self::State,
2797 system_meta: &mut SystemMeta,
2798 component_access_set: &mut FilteredAccessSet,
2799 world: &mut World,
2800 ) {
2801 let combined_access = component_access_set.combined_access();
2802 let conflicts = combined_access.get_conflicts(access);
2803 if !conflicts.is_empty() {
2804 let accesses = conflicts.format_conflict_list(world);
2805 let system_name = &system_meta.name;
2806 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");
2807 }
2808
2809 if access.has_read_all_resources() {
2810 component_access_set.add_unfiltered_read_all_resources();
2811 } else {
2812 for component_id in access.resource_reads() {
2813 component_access_set.add_unfiltered_resource_read(component_id);
2814 }
2815 }
2816
2817 if access.has_write_all_resources() {
2818 component_access_set.add_unfiltered_write_all_resources();
2819 } else {
2820 for component_id in access.resource_writes() {
2821 component_access_set.add_unfiltered_resource_write(component_id);
2822 }
2823 }
2824 }
2825
2826 unsafe fn get_param<'world, 'state>(
2827 state: &'state mut Self::State,
2828 system_meta: &SystemMeta,
2829 world: UnsafeWorldCell<'world>,
2830 change_tick: Tick,
2831 ) -> Self::Item<'world, 'state> {
2832 unsafe { FilteredResourcesMut::new(world, state, system_meta.last_run, change_tick) }
2835 }
2836}
2837
2838#[derive(Debug, PartialEq, Eq, Clone, Error)]
2844pub struct SystemParamValidationError {
2845 pub skipped: bool,
2858
2859 pub message: Cow<'static, str>,
2861
2862 pub param: DebugName,
2865
2866 pub field: Cow<'static, str>,
2871}
2872
2873impl SystemParamValidationError {
2874 pub fn skipped<T>(message: impl Into<Cow<'static, str>>) -> Self {
2877 Self::new::<T>(true, message, Cow::Borrowed(""))
2878 }
2879
2880 pub fn invalid<T>(message: impl Into<Cow<'static, str>>) -> Self {
2883 Self::new::<T>(false, message, Cow::Borrowed(""))
2884 }
2885
2886 pub fn new<T>(
2889 skipped: bool,
2890 message: impl Into<Cow<'static, str>>,
2891 field: impl Into<Cow<'static, str>>,
2892 ) -> Self {
2893 Self {
2894 skipped,
2895 message: message.into(),
2896 param: DebugName::type_name::<T>(),
2897 field: field.into(),
2898 }
2899 }
2900
2901 pub(crate) const EMPTY: Self = Self {
2902 skipped: false,
2903 message: Cow::Borrowed(""),
2904 param: DebugName::borrowed(""),
2905 field: Cow::Borrowed(""),
2906 };
2907}
2908
2909impl Display for SystemParamValidationError {
2910 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
2911 write!(
2912 fmt,
2913 "Parameter `{}{}` failed validation: {}",
2914 self.param.shortname(),
2915 self.field,
2916 self.message
2917 )?;
2918 if !self.skipped {
2919 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.")?;
2920 }
2921 Ok(())
2922 }
2923}
2924
2925#[cfg(test)]
2926mod tests {
2927 use super::*;
2928 use crate::system::assert_is_system;
2929 use core::cell::RefCell;
2930
2931 #[test]
2932 #[should_panic]
2933 fn non_send_alias() {
2934 #[derive(Resource)]
2935 struct A(usize);
2936 fn my_system(mut res0: NonSendMut<A>, mut res1: NonSendMut<A>) {
2937 res0.0 += 1;
2938 res1.0 += 1;
2939 }
2940 let mut world = World::new();
2941 world.insert_non_send_resource(A(42));
2942 let mut schedule = crate::schedule::Schedule::default();
2943 schedule.add_systems(my_system);
2944 schedule.run(&mut world);
2945 }
2946
2947 #[test]
2949 fn system_param_generic_bounds() {
2950 #[derive(SystemParam)]
2951 pub struct SpecialQuery<
2952 'w,
2953 's,
2954 D: QueryData + Send + Sync + 'static,
2955 F: QueryFilter + Send + Sync + 'static = (),
2956 > {
2957 _query: Query<'w, 's, D, F>,
2958 }
2959
2960 fn my_system(_: SpecialQuery<(), ()>) {}
2961 assert_is_system(my_system);
2962 }
2963
2964 #[test]
2966 fn system_param_flexibility() {
2967 #[derive(SystemParam)]
2968 pub struct SpecialRes<'w, T: Resource> {
2969 _res: Res<'w, T>,
2970 }
2971
2972 #[derive(SystemParam)]
2973 pub struct SpecialLocal<'s, T: FromWorld + Send + 'static> {
2974 _local: Local<'s, T>,
2975 }
2976
2977 #[derive(Resource)]
2978 struct R;
2979
2980 fn my_system(_: SpecialRes<R>, _: SpecialLocal<u32>) {}
2981 assert_is_system(my_system);
2982 }
2983
2984 #[derive(Resource)]
2985 pub struct R<const I: usize>;
2986
2987 #[test]
2989 fn system_param_const_generics() {
2990 #[expect(
2991 dead_code,
2992 reason = "This struct is used to ensure that const generics are supported as a SystemParam; thus, the inner value never needs to be read."
2993 )]
2994 #[derive(SystemParam)]
2995 pub struct ConstGenericParam<'w, const I: usize>(Res<'w, R<I>>);
2996
2997 fn my_system(_: ConstGenericParam<0>, _: ConstGenericParam<1000>) {}
2998 assert_is_system(my_system);
2999 }
3000
3001 #[test]
3003 fn system_param_field_limit() {
3004 #[derive(SystemParam)]
3005 pub struct LongParam<'w> {
3006 _r0: Res<'w, R<0>>,
3009 _r1: Res<'w, R<1>>,
3010 _r2: Res<'w, R<2>>,
3011 _r3: Res<'w, R<3>>,
3012 _r4: Res<'w, R<4>>,
3013 _r5: Res<'w, R<5>>,
3014 _r6: Res<'w, R<6>>,
3015 _r7: Res<'w, R<7>>,
3016 _r8: Res<'w, R<8>>,
3017 _r9: Res<'w, R<9>>,
3018 _r10: Res<'w, R<10>>,
3019 _r11: Res<'w, R<11>>,
3020 _r12: Res<'w, R<12>>,
3021 _r13: Res<'w, R<13>>,
3022 _r14: Res<'w, R<14>>,
3023 _r15: Res<'w, R<15>>,
3024 _r16: Res<'w, R<16>>,
3025 }
3026
3027 fn long_system(_: LongParam) {}
3028 assert_is_system(long_system);
3029 }
3030
3031 #[test]
3034 fn system_param_phantom_data() {
3035 #[derive(SystemParam)]
3036 struct PhantomParam<'w, T: Resource, Marker: 'static> {
3037 _foo: Res<'w, T>,
3038 marker: PhantomData<&'w Marker>,
3039 }
3040
3041 fn my_system(_: PhantomParam<R<0>, ()>) {}
3042 assert_is_system(my_system);
3043 }
3044
3045 #[test]
3047 fn system_param_struct_variants() {
3048 #[derive(SystemParam)]
3049 pub struct UnitParam;
3050
3051 #[expect(
3052 dead_code,
3053 reason = "This struct is used to ensure that tuple structs are supported as a SystemParam; thus, the inner values never need to be read."
3054 )]
3055 #[derive(SystemParam)]
3056 pub struct TupleParam<'w, 's, R: Resource, L: FromWorld + Send + 'static>(
3057 Res<'w, R>,
3058 Local<'s, L>,
3059 );
3060
3061 fn my_system(_: UnitParam, _: TupleParam<R<0>, u32>) {}
3062 assert_is_system(my_system);
3063 }
3064
3065 #[test]
3067 fn system_param_private_fields() {
3068 #[derive(Resource)]
3069 struct PrivateResource;
3070
3071 #[expect(
3072 dead_code,
3073 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."
3074 )]
3075 #[derive(SystemParam)]
3076 pub struct EncapsulatedParam<'w>(Res<'w, PrivateResource>);
3077
3078 fn my_system(_: EncapsulatedParam) {}
3079 assert_is_system(my_system);
3080 }
3081
3082 #[test]
3084 fn system_param_where_clause() {
3085 #[derive(SystemParam)]
3086 pub struct WhereParam<'w, 's, D>
3087 where
3088 D: 'static + QueryData,
3089 {
3090 _q: Query<'w, 's, D, ()>,
3091 }
3092
3093 fn my_system(_: WhereParam<()>) {}
3094 assert_is_system(my_system);
3095 }
3096
3097 #[test]
3099 fn system_param_name_collision() {
3100 #[derive(Resource)]
3101 pub struct FetchState;
3102
3103 #[derive(SystemParam)]
3104 pub struct Collide<'w> {
3105 _x: Res<'w, FetchState>,
3106 }
3107
3108 fn my_system(_: Collide) {}
3109 assert_is_system(my_system);
3110 }
3111
3112 #[test]
3114 fn system_param_invariant_lifetime() {
3115 #[derive(SystemParam)]
3116 pub struct InvariantParam<'w, 's> {
3117 _set: ParamSet<'w, 's, (Query<'w, 's, ()>,)>,
3118 }
3119
3120 fn my_system(_: InvariantParam) {}
3121 assert_is_system(my_system);
3122 }
3123
3124 #[test]
3126 fn non_sync_local() {
3127 fn non_sync_system(cell: Local<RefCell<u8>>) {
3128 assert_eq!(*cell.borrow(), 0);
3129 }
3130
3131 let mut world = World::new();
3132 let mut schedule = crate::schedule::Schedule::default();
3133 schedule.add_systems(non_sync_system);
3134 schedule.run(&mut world);
3135 }
3136
3137 #[test]
3139 fn param_set_non_send_first() {
3140 fn non_send_param_set(mut p: ParamSet<(NonSend<*mut u8>, ())>) {
3141 let _ = p.p0();
3142 p.p1();
3143 }
3144
3145 let mut world = World::new();
3146 world.insert_non_send_resource(core::ptr::null_mut::<u8>());
3147 let mut schedule = crate::schedule::Schedule::default();
3148 schedule.add_systems((non_send_param_set, non_send_param_set, non_send_param_set));
3149 schedule.run(&mut world);
3150 }
3151
3152 #[test]
3154 fn param_set_non_send_second() {
3155 fn non_send_param_set(mut p: ParamSet<((), NonSendMut<*mut u8>)>) {
3156 p.p0();
3157 let _ = p.p1();
3158 }
3159
3160 let mut world = World::new();
3161 world.insert_non_send_resource(core::ptr::null_mut::<u8>());
3162 let mut schedule = crate::schedule::Schedule::default();
3163 schedule.add_systems((non_send_param_set, non_send_param_set, non_send_param_set));
3164 schedule.run(&mut world);
3165 }
3166
3167 fn _dyn_system_param_type_inference(mut p: DynSystemParam) {
3168 let _query: Query<()> = p.downcast_mut().unwrap();
3171 let _query: Query<()> = p.downcast_mut_inner().unwrap();
3172 let _query: Query<()> = p.downcast().unwrap();
3173 }
3174
3175 #[test]
3176 #[should_panic]
3177 fn missing_resource_error() {
3178 #[derive(Resource)]
3179 pub struct MissingResource;
3180
3181 let mut schedule = crate::schedule::Schedule::default();
3182 schedule.add_systems(res_system);
3183 let mut world = World::new();
3184 schedule.run(&mut world);
3185
3186 fn res_system(_: Res<MissingResource>) {}
3187 }
3188
3189 #[test]
3190 #[should_panic]
3191 fn missing_message_error() {
3192 use crate::prelude::{Message, MessageReader};
3193
3194 #[derive(Message)]
3195 pub struct MissingEvent;
3196
3197 let mut schedule = crate::schedule::Schedule::default();
3198 schedule.add_systems(message_system);
3199 let mut world = World::new();
3200 schedule.run(&mut world);
3201
3202 fn message_system(_: MessageReader<MissingEvent>) {}
3203 }
3204}