1pub use crate::change_detection::{NonSendMut, Res, ResMut};
2use crate::{
3 archetype::{Archetype, Archetypes},
4 bundle::Bundles,
5 change_detection::{Ticks, TicksMut},
6 component::{ComponentId, ComponentTicks, Components, Tick},
7 entity::Entities,
8 prelude::QueryBuilder,
9 query::{
10 Access, FilteredAccess, FilteredAccessSet, QueryData, QueryFilter, QueryState,
11 ReadOnlyQueryData,
12 },
13 system::{Query, SystemMeta},
14 world::{unsafe_world_cell::UnsafeWorldCell, DeferredWorld, FromWorld, World},
15};
16use bevy_ecs_macros::impl_param_set;
17pub use bevy_ecs_macros::Resource;
18pub use bevy_ecs_macros::SystemParam;
19use bevy_ptr::UnsafeCellDeref;
20use bevy_utils::{all_tuples, synccell::SyncCell};
21use std::{
22 fmt::Debug,
23 marker::PhantomData,
24 ops::{Deref, DerefMut},
25};
26
27pub unsafe trait SystemParam: Sized {
128 type State: Send + Sync + 'static;
130
131 type Item<'world, 'state>: SystemParam<State = Self::State>;
136
137 fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State;
140
141 #[inline]
146 #[allow(unused_variables)]
147 unsafe fn new_archetype(
148 state: &mut Self::State,
149 archetype: &Archetype,
150 system_meta: &mut SystemMeta,
151 ) {
152 }
153
154 #[inline]
159 #[allow(unused_variables)]
160 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {}
161
162 #[inline]
164 #[allow(unused_variables)]
165 fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {}
166
167 unsafe fn get_param<'world, 'state>(
177 state: &'state mut Self::State,
178 system_meta: &SystemMeta,
179 world: UnsafeWorldCell<'world>,
180 change_tick: Tick,
181 ) -> Self::Item<'world, 'state>;
182}
183
184pub trait BuildableSystemParam: SystemParam {
186 type Builder<'b>;
188
189 fn build(
191 world: &mut World,
192 meta: &mut SystemMeta,
193 func: impl FnOnce(&mut Self::Builder<'_>),
194 ) -> Self::State;
195}
196
197pub unsafe trait ReadOnlySystemParam: SystemParam {}
202
203pub type SystemParamItem<'w, 's, P> = <P as SystemParam>::Item<'w, 's>;
205
206unsafe impl<'w, 's, D: ReadOnlyQueryData + 'static, F: QueryFilter + 'static> ReadOnlySystemParam
208 for Query<'w, 's, D, F>
209{
210}
211
212unsafe impl<D: QueryData + 'static, F: QueryFilter + 'static> SystemParam for Query<'_, '_, D, F> {
215 type State = QueryState<D, F>;
216 type Item<'w, 's> = Query<'w, 's, D, F>;
217
218 fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
219 let state = QueryState::new_with_access(world, &mut system_meta.archetype_component_access);
220 assert_component_access_compatibility(
221 &system_meta.name,
222 std::any::type_name::<D>(),
223 std::any::type_name::<F>(),
224 &system_meta.component_access_set,
225 &state.component_access,
226 world,
227 );
228 system_meta
229 .component_access_set
230 .add(state.component_access.clone());
231 state
232 }
233
234 unsafe fn new_archetype(
235 state: &mut Self::State,
236 archetype: &Archetype,
237 system_meta: &mut SystemMeta,
238 ) {
239 state.new_archetype(archetype, &mut system_meta.archetype_component_access);
240 }
241
242 #[inline]
243 unsafe fn get_param<'w, 's>(
244 state: &'s mut Self::State,
245 system_meta: &SystemMeta,
246 world: UnsafeWorldCell<'w>,
247 change_tick: Tick,
248 ) -> Self::Item<'w, 's> {
249 unsafe { Query::new(world, state, system_meta.last_run, change_tick) }
253 }
254}
255
256impl<'w, 's, D: QueryData + 'static, F: QueryFilter + 'static> BuildableSystemParam
257 for Query<'w, 's, D, F>
258{
259 type Builder<'b> = QueryBuilder<'b, D, F>;
260
261 #[inline]
262 fn build(
263 world: &mut World,
264 system_meta: &mut SystemMeta,
265 build: impl FnOnce(&mut Self::Builder<'_>),
266 ) -> Self::State {
267 let mut builder = QueryBuilder::new(world);
268 build(&mut builder);
269 let state = builder.build();
270 assert_component_access_compatibility(
271 &system_meta.name,
272 std::any::type_name::<D>(),
273 std::any::type_name::<F>(),
274 &system_meta.component_access_set,
275 &state.component_access,
276 world,
277 );
278 system_meta
279 .component_access_set
280 .add(state.component_access.clone());
281 state
282 }
283}
284
285fn assert_component_access_compatibility(
286 system_name: &str,
287 query_type: &'static str,
288 filter_type: &'static str,
289 system_access: &FilteredAccessSet<ComponentId>,
290 current: &FilteredAccess<ComponentId>,
291 world: &World,
292) {
293 let conflicts = system_access.get_conflicts_single(current);
294 if conflicts.is_empty() {
295 return;
296 }
297 let conflicting_components = conflicts
298 .into_iter()
299 .map(|component_id| world.components.get_info(component_id).unwrap().name())
300 .collect::<Vec<&str>>();
301 let accesses = conflicting_components.join(", ");
302 panic!("error[B0001]: Query<{query_type}, {filter_type}> in system {system_name} accesses component(s) {accesses} in a way that conflicts with a previous system parameter. Consider using `Without<T>` to create disjoint Queries or merging conflicting Queries into a `ParamSet`. See: https://bevyengine.org/learn/errors/#b0001");
303}
304
305pub struct ParamSet<'w, 's, T: SystemParam> {
415 param_states: &'s mut T::State,
416 world: UnsafeWorldCell<'w>,
417 system_meta: SystemMeta,
418 change_tick: Tick,
419}
420
421impl_param_set!();
422
423#[diagnostic::on_unimplemented(
484 message = "`{Self}` is not a `Resource`",
485 label = "invalid `Resource`",
486 note = "consider annotating `{Self}` with `#[derive(Resource)]`"
487)]
488pub trait Resource: Send + Sync + 'static {}
489
490unsafe impl<'a, T: Resource> ReadOnlySystemParam for Res<'a, T> {}
492
493unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> {
496 type State = ComponentId;
497 type Item<'w, 's> = Res<'w, T>;
498
499 fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
500 let component_id = world.components.init_resource::<T>();
501 world.initialize_resource_internal(component_id);
502
503 let combined_access = system_meta.component_access_set.combined_access();
504 assert!(
505 !combined_access.has_write(component_id),
506 "error[B0002]: Res<{}> in system {} conflicts with a previous ResMut<{0}> access. Consider removing the duplicate access. See: https://bevyengine.org/learn/errors/#b0002",
507 std::any::type_name::<T>(),
508 system_meta.name,
509 );
510 system_meta
511 .component_access_set
512 .add_unfiltered_read(component_id);
513
514 let archetype_component_id = world
515 .get_resource_archetype_component_id(component_id)
516 .unwrap();
517 system_meta
518 .archetype_component_access
519 .add_read(archetype_component_id);
520
521 component_id
522 }
523
524 #[inline]
525 unsafe fn get_param<'w, 's>(
526 &mut component_id: &'s mut Self::State,
527 system_meta: &SystemMeta,
528 world: UnsafeWorldCell<'w>,
529 change_tick: Tick,
530 ) -> Self::Item<'w, 's> {
531 let (ptr, ticks) = world
532 .get_resource_with_ticks(component_id)
533 .unwrap_or_else(|| {
534 panic!(
535 "Resource requested by {} does not exist: {}",
536 system_meta.name,
537 std::any::type_name::<T>()
538 )
539 });
540 Res {
541 value: ptr.deref(),
542 ticks: Ticks {
543 added: ticks.added.deref(),
544 changed: ticks.changed.deref(),
545 last_run: system_meta.last_run,
546 this_run: change_tick,
547 },
548 }
549 }
550}
551
552unsafe impl<'a, T: Resource> ReadOnlySystemParam for Option<Res<'a, T>> {}
554
555unsafe impl<'a, T: Resource> SystemParam for Option<Res<'a, T>> {
557 type State = ComponentId;
558 type Item<'w, 's> = Option<Res<'w, T>>;
559
560 fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
561 Res::<T>::init_state(world, system_meta)
562 }
563
564 #[inline]
565 unsafe fn get_param<'w, 's>(
566 &mut component_id: &'s mut Self::State,
567 system_meta: &SystemMeta,
568 world: UnsafeWorldCell<'w>,
569 change_tick: Tick,
570 ) -> Self::Item<'w, 's> {
571 world
572 .get_resource_with_ticks(component_id)
573 .map(|(ptr, ticks)| Res {
574 value: ptr.deref(),
575 ticks: Ticks {
576 added: ticks.added.deref(),
577 changed: ticks.changed.deref(),
578 last_run: system_meta.last_run,
579 this_run: change_tick,
580 },
581 })
582 }
583}
584
585unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> {
588 type State = ComponentId;
589 type Item<'w, 's> = ResMut<'w, T>;
590
591 fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
592 let component_id = world.components.init_resource::<T>();
593 world.initialize_resource_internal(component_id);
594
595 let combined_access = system_meta.component_access_set.combined_access();
596 if combined_access.has_write(component_id) {
597 panic!(
598 "error[B0002]: ResMut<{}> in system {} conflicts with a previous ResMut<{0}> access. Consider removing the duplicate access. See: https://bevyengine.org/learn/errors/#b0002",
599 std::any::type_name::<T>(), system_meta.name);
600 } else if combined_access.has_read(component_id) {
601 panic!(
602 "error[B0002]: ResMut<{}> in system {} conflicts with a previous Res<{0}> access. Consider removing the duplicate access. See: https://bevyengine.org/learn/errors/#b0002",
603 std::any::type_name::<T>(), system_meta.name);
604 }
605 system_meta
606 .component_access_set
607 .add_unfiltered_write(component_id);
608
609 let archetype_component_id = world
610 .get_resource_archetype_component_id(component_id)
611 .unwrap();
612 system_meta
613 .archetype_component_access
614 .add_write(archetype_component_id);
615
616 component_id
617 }
618
619 #[inline]
620 unsafe fn get_param<'w, 's>(
621 &mut component_id: &'s mut Self::State,
622 system_meta: &SystemMeta,
623 world: UnsafeWorldCell<'w>,
624 change_tick: Tick,
625 ) -> Self::Item<'w, 's> {
626 let value = world
627 .get_resource_mut_by_id(component_id)
628 .unwrap_or_else(|| {
629 panic!(
630 "Resource requested by {} does not exist: {}",
631 system_meta.name,
632 std::any::type_name::<T>()
633 )
634 });
635 ResMut {
636 value: value.value.deref_mut::<T>(),
637 ticks: TicksMut {
638 added: value.ticks.added,
639 changed: value.ticks.changed,
640 last_run: system_meta.last_run,
641 this_run: change_tick,
642 },
643 }
644 }
645}
646
647unsafe impl<'a, T: Resource> SystemParam for Option<ResMut<'a, T>> {
649 type State = ComponentId;
650 type Item<'w, 's> = Option<ResMut<'w, T>>;
651
652 fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
653 ResMut::<T>::init_state(world, system_meta)
654 }
655
656 #[inline]
657 unsafe fn get_param<'w, 's>(
658 &mut component_id: &'s mut Self::State,
659 system_meta: &SystemMeta,
660 world: UnsafeWorldCell<'w>,
661 change_tick: Tick,
662 ) -> Self::Item<'w, 's> {
663 world
664 .get_resource_mut_by_id(component_id)
665 .map(|value| ResMut {
666 value: value.value.deref_mut::<T>(),
667 ticks: TicksMut {
668 added: value.ticks.added,
669 changed: value.ticks.changed,
670 last_run: system_meta.last_run,
671 this_run: change_tick,
672 },
673 })
674 }
675}
676
677unsafe impl<'w> ReadOnlySystemParam for &'w World {}
679
680unsafe impl SystemParam for &'_ World {
682 type State = ();
683 type Item<'w, 's> = &'w World;
684
685 fn init_state(_world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
686 let mut access = Access::default();
687 access.read_all();
688 if !system_meta
689 .archetype_component_access
690 .is_compatible(&access)
691 {
692 panic!("&World conflicts with a previous mutable system parameter. Allowing this would break Rust's mutability rules");
693 }
694 system_meta.archetype_component_access.extend(&access);
695
696 let mut filtered_access = FilteredAccess::default();
697
698 filtered_access.read_all();
699 if !system_meta
700 .component_access_set
701 .get_conflicts_single(&filtered_access)
702 .is_empty()
703 {
704 panic!("&World conflicts with a previous mutable system parameter. Allowing this would break Rust's mutability rules");
705 }
706 system_meta.component_access_set.add(filtered_access);
707 }
708
709 unsafe fn get_param<'w, 's>(
710 _state: &'s mut Self::State,
711 _system_meta: &SystemMeta,
712 world: UnsafeWorldCell<'w>,
713 _change_tick: Tick,
714 ) -> Self::Item<'w, 's> {
715 unsafe { world.world() }
717 }
718}
719
720unsafe impl<'w> SystemParam for DeferredWorld<'w> {
722 type State = ();
723 type Item<'world, 'state> = DeferredWorld<'world>;
724
725 fn init_state(_world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
726 system_meta.component_access_set.read_all();
727 system_meta.component_access_set.write_all();
728 system_meta.set_has_deferred();
729 }
730
731 unsafe fn get_param<'world, 'state>(
732 _state: &'state mut Self::State,
733 _system_meta: &SystemMeta,
734 world: UnsafeWorldCell<'world>,
735 _change_tick: Tick,
736 ) -> Self::Item<'world, 'state> {
737 world.into_deferred()
738 }
739}
740
741#[derive(Debug)]
789pub struct Local<'s, T: FromWorld + Send + 'static>(pub(crate) &'s mut T);
790
791unsafe impl<'s, T: FromWorld + Send + 'static> ReadOnlySystemParam for Local<'s, T> {}
793
794impl<'s, T: FromWorld + Send + 'static> Deref for Local<'s, T> {
795 type Target = T;
796
797 #[inline]
798 fn deref(&self) -> &Self::Target {
799 self.0
800 }
801}
802
803impl<'s, T: FromWorld + Send + 'static> DerefMut for Local<'s, T> {
804 #[inline]
805 fn deref_mut(&mut self) -> &mut Self::Target {
806 self.0
807 }
808}
809
810impl<'s, 'a, T: FromWorld + Send + 'static> IntoIterator for &'a Local<'s, T>
811where
812 &'a T: IntoIterator,
813{
814 type Item = <&'a T as IntoIterator>::Item;
815 type IntoIter = <&'a T as IntoIterator>::IntoIter;
816
817 fn into_iter(self) -> Self::IntoIter {
818 self.0.into_iter()
819 }
820}
821
822impl<'s, 'a, T: FromWorld + Send + 'static> IntoIterator for &'a mut Local<'s, T>
823where
824 &'a mut T: IntoIterator,
825{
826 type Item = <&'a mut T as IntoIterator>::Item;
827 type IntoIter = <&'a mut T as IntoIterator>::IntoIter;
828
829 fn into_iter(self) -> Self::IntoIter {
830 self.0.into_iter()
831 }
832}
833
834unsafe impl<'a, T: FromWorld + Send + 'static> SystemParam for Local<'a, T> {
836 type State = SyncCell<T>;
837 type Item<'w, 's> = Local<'s, T>;
838
839 fn init_state(world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {
840 SyncCell::new(T::from_world(world))
841 }
842
843 #[inline]
844 unsafe fn get_param<'w, 's>(
845 state: &'s mut Self::State,
846 _system_meta: &SystemMeta,
847 _world: UnsafeWorldCell<'w>,
848 _change_tick: Tick,
849 ) -> Self::Item<'w, 's> {
850 Local(state.get())
851 }
852}
853
854impl<'w, T: FromWorld + Send + 'static> BuildableSystemParam for Local<'w, T> {
855 type Builder<'b> = T;
856
857 fn build(
858 world: &mut World,
859 _meta: &mut SystemMeta,
860 func: impl FnOnce(&mut Self::Builder<'_>),
861 ) -> Self::State {
862 let mut value = T::from_world(world);
863 func(&mut value);
864 SyncCell::new(value)
865 }
866}
867
868pub trait SystemBuffer: FromWorld + Send + 'static {
875 fn apply(&mut self, system_meta: &SystemMeta, world: &mut World);
877 fn queue(&mut self, _system_meta: &SystemMeta, _world: DeferredWorld) {}
879}
880
881pub struct Deferred<'a, T: SystemBuffer>(pub(crate) &'a mut T);
1002
1003impl<'a, T: SystemBuffer> Deref for Deferred<'a, T> {
1004 type Target = T;
1005 #[inline]
1006 fn deref(&self) -> &Self::Target {
1007 self.0
1008 }
1009}
1010
1011impl<'a, T: SystemBuffer> DerefMut for Deferred<'a, T> {
1012 #[inline]
1013 fn deref_mut(&mut self) -> &mut Self::Target {
1014 self.0
1015 }
1016}
1017
1018impl<T: SystemBuffer> Deferred<'_, T> {
1019 pub fn reborrow(&mut self) -> Deferred<T> {
1022 Deferred(self.0)
1023 }
1024}
1025
1026unsafe impl<T: SystemBuffer> ReadOnlySystemParam for Deferred<'_, T> {}
1028
1029unsafe impl<T: SystemBuffer> SystemParam for Deferred<'_, T> {
1031 type State = SyncCell<T>;
1032 type Item<'w, 's> = Deferred<'s, T>;
1033
1034 fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
1035 system_meta.set_has_deferred();
1036 SyncCell::new(T::from_world(world))
1037 }
1038
1039 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1040 state.get().apply(system_meta, world);
1041 }
1042
1043 fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
1044 state.get().queue(system_meta, world);
1045 }
1046
1047 unsafe fn get_param<'w, 's>(
1048 state: &'s mut Self::State,
1049 _system_meta: &SystemMeta,
1050 _world: UnsafeWorldCell<'w>,
1051 _change_tick: Tick,
1052 ) -> Self::Item<'w, 's> {
1053 Deferred(state.get())
1054 }
1055}
1056
1057pub struct NonSend<'w, T: 'static> {
1070 pub(crate) value: &'w T,
1071 ticks: ComponentTicks,
1072 last_run: Tick,
1073 this_run: Tick,
1074}
1075
1076unsafe impl<'w, T> ReadOnlySystemParam for NonSend<'w, T> {}
1078
1079impl<'w, T> Debug for NonSend<'w, T>
1080where
1081 T: Debug,
1082{
1083 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1084 f.debug_tuple("NonSend").field(&self.value).finish()
1085 }
1086}
1087
1088impl<'w, T: 'static> NonSend<'w, T> {
1089 pub fn is_added(&self) -> bool {
1091 self.ticks.is_added(self.last_run, self.this_run)
1092 }
1093
1094 pub fn is_changed(&self) -> bool {
1096 self.ticks.is_changed(self.last_run, self.this_run)
1097 }
1098}
1099
1100impl<'w, T> Deref for NonSend<'w, T> {
1101 type Target = T;
1102
1103 fn deref(&self) -> &Self::Target {
1104 self.value
1105 }
1106}
1107impl<'a, T> From<NonSendMut<'a, T>> for NonSend<'a, T> {
1108 fn from(nsm: NonSendMut<'a, T>) -> Self {
1109 Self {
1110 value: nsm.value,
1111 ticks: ComponentTicks {
1112 added: nsm.ticks.added.to_owned(),
1113 changed: nsm.ticks.changed.to_owned(),
1114 },
1115 this_run: nsm.ticks.this_run,
1116 last_run: nsm.ticks.last_run,
1117 }
1118 }
1119}
1120
1121unsafe impl<'a, T: 'static> SystemParam for NonSend<'a, T> {
1124 type State = ComponentId;
1125 type Item<'w, 's> = NonSend<'w, T>;
1126
1127 fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
1128 system_meta.set_non_send();
1129
1130 let component_id = world.components.init_non_send::<T>();
1131 world.initialize_non_send_internal(component_id);
1132
1133 let combined_access = system_meta.component_access_set.combined_access();
1134 assert!(
1135 !combined_access.has_write(component_id),
1136 "error[B0002]: NonSend<{}> in system {} conflicts with a previous mutable resource access ({0}). Consider removing the duplicate access. See: https://bevyengine.org/learn/errors/#b0002",
1137 std::any::type_name::<T>(),
1138 system_meta.name,
1139 );
1140 system_meta
1141 .component_access_set
1142 .add_unfiltered_read(component_id);
1143
1144 let archetype_component_id = world
1145 .get_non_send_archetype_component_id(component_id)
1146 .unwrap();
1147 system_meta
1148 .archetype_component_access
1149 .add_read(archetype_component_id);
1150
1151 component_id
1152 }
1153
1154 #[inline]
1155 unsafe fn get_param<'w, 's>(
1156 &mut component_id: &'s mut Self::State,
1157 system_meta: &SystemMeta,
1158 world: UnsafeWorldCell<'w>,
1159 change_tick: Tick,
1160 ) -> Self::Item<'w, 's> {
1161 let (ptr, ticks) = world
1162 .get_non_send_with_ticks(component_id)
1163 .unwrap_or_else(|| {
1164 panic!(
1165 "Non-send resource requested by {} does not exist: {}",
1166 system_meta.name,
1167 std::any::type_name::<T>()
1168 )
1169 });
1170
1171 NonSend {
1172 value: ptr.deref(),
1173 ticks: ticks.read(),
1174 last_run: system_meta.last_run,
1175 this_run: change_tick,
1176 }
1177 }
1178}
1179
1180unsafe impl<T: 'static> ReadOnlySystemParam for Option<NonSend<'_, T>> {}
1182
1183unsafe impl<T: 'static> SystemParam for Option<NonSend<'_, T>> {
1185 type State = ComponentId;
1186 type Item<'w, 's> = Option<NonSend<'w, T>>;
1187
1188 fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
1189 NonSend::<T>::init_state(world, system_meta)
1190 }
1191
1192 #[inline]
1193 unsafe fn get_param<'w, 's>(
1194 &mut component_id: &'s mut Self::State,
1195 system_meta: &SystemMeta,
1196 world: UnsafeWorldCell<'w>,
1197 change_tick: Tick,
1198 ) -> Self::Item<'w, 's> {
1199 world
1200 .get_non_send_with_ticks(component_id)
1201 .map(|(ptr, ticks)| NonSend {
1202 value: ptr.deref(),
1203 ticks: ticks.read(),
1204 last_run: system_meta.last_run,
1205 this_run: change_tick,
1206 })
1207 }
1208}
1209
1210unsafe impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> {
1213 type State = ComponentId;
1214 type Item<'w, 's> = NonSendMut<'w, T>;
1215
1216 fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
1217 system_meta.set_non_send();
1218
1219 let component_id = world.components.init_non_send::<T>();
1220 world.initialize_non_send_internal(component_id);
1221
1222 let combined_access = system_meta.component_access_set.combined_access();
1223 if combined_access.has_write(component_id) {
1224 panic!(
1225 "error[B0002]: NonSendMut<{}> in system {} conflicts with a previous mutable resource access ({0}). Consider removing the duplicate access. See: https://bevyengine.org/learn/errors/#b0002",
1226 std::any::type_name::<T>(), system_meta.name);
1227 } else if combined_access.has_read(component_id) {
1228 panic!(
1229 "error[B0002]: NonSendMut<{}> in system {} conflicts with a previous immutable resource access ({0}). Consider removing the duplicate access. See: https://bevyengine.org/learn/errors/#b0002",
1230 std::any::type_name::<T>(), system_meta.name);
1231 }
1232 system_meta
1233 .component_access_set
1234 .add_unfiltered_write(component_id);
1235
1236 let archetype_component_id = world
1237 .get_non_send_archetype_component_id(component_id)
1238 .unwrap();
1239 system_meta
1240 .archetype_component_access
1241 .add_write(archetype_component_id);
1242
1243 component_id
1244 }
1245
1246 #[inline]
1247 unsafe fn get_param<'w, 's>(
1248 &mut component_id: &'s mut Self::State,
1249 system_meta: &SystemMeta,
1250 world: UnsafeWorldCell<'w>,
1251 change_tick: Tick,
1252 ) -> Self::Item<'w, 's> {
1253 let (ptr, ticks) = world
1254 .get_non_send_with_ticks(component_id)
1255 .unwrap_or_else(|| {
1256 panic!(
1257 "Non-send resource requested by {} does not exist: {}",
1258 system_meta.name,
1259 std::any::type_name::<T>()
1260 )
1261 });
1262 NonSendMut {
1263 value: ptr.assert_unique().deref_mut(),
1264 ticks: TicksMut::from_tick_cells(ticks, system_meta.last_run, change_tick),
1265 }
1266 }
1267}
1268
1269unsafe impl<'a, T: 'static> SystemParam for Option<NonSendMut<'a, T>> {
1271 type State = ComponentId;
1272 type Item<'w, 's> = Option<NonSendMut<'w, T>>;
1273
1274 fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
1275 NonSendMut::<T>::init_state(world, system_meta)
1276 }
1277
1278 #[inline]
1279 unsafe fn get_param<'w, 's>(
1280 &mut component_id: &'s mut Self::State,
1281 system_meta: &SystemMeta,
1282 world: UnsafeWorldCell<'w>,
1283 change_tick: Tick,
1284 ) -> Self::Item<'w, 's> {
1285 world
1286 .get_non_send_with_ticks(component_id)
1287 .map(|(ptr, ticks)| NonSendMut {
1288 value: ptr.assert_unique().deref_mut(),
1289 ticks: TicksMut::from_tick_cells(ticks, system_meta.last_run, change_tick),
1290 })
1291 }
1292}
1293
1294unsafe impl<'a> ReadOnlySystemParam for &'a Archetypes {}
1296
1297unsafe impl<'a> SystemParam for &'a Archetypes {
1299 type State = ();
1300 type Item<'w, 's> = &'w Archetypes;
1301
1302 fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {}
1303
1304 #[inline]
1305 unsafe fn get_param<'w, 's>(
1306 _state: &'s mut Self::State,
1307 _system_meta: &SystemMeta,
1308 world: UnsafeWorldCell<'w>,
1309 _change_tick: Tick,
1310 ) -> Self::Item<'w, 's> {
1311 world.archetypes()
1312 }
1313}
1314
1315unsafe impl<'a> ReadOnlySystemParam for &'a Components {}
1317
1318unsafe impl<'a> SystemParam for &'a Components {
1320 type State = ();
1321 type Item<'w, 's> = &'w Components;
1322
1323 fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {}
1324
1325 #[inline]
1326 unsafe fn get_param<'w, 's>(
1327 _state: &'s mut Self::State,
1328 _system_meta: &SystemMeta,
1329 world: UnsafeWorldCell<'w>,
1330 _change_tick: Tick,
1331 ) -> Self::Item<'w, 's> {
1332 world.components()
1333 }
1334}
1335
1336unsafe impl<'a> ReadOnlySystemParam for &'a Entities {}
1338
1339unsafe impl<'a> SystemParam for &'a Entities {
1341 type State = ();
1342 type Item<'w, 's> = &'w Entities;
1343
1344 fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {}
1345
1346 #[inline]
1347 unsafe fn get_param<'w, 's>(
1348 _state: &'s mut Self::State,
1349 _system_meta: &SystemMeta,
1350 world: UnsafeWorldCell<'w>,
1351 _change_tick: Tick,
1352 ) -> Self::Item<'w, 's> {
1353 world.entities()
1354 }
1355}
1356
1357unsafe impl<'a> ReadOnlySystemParam for &'a Bundles {}
1359
1360unsafe impl<'a> SystemParam for &'a Bundles {
1362 type State = ();
1363 type Item<'w, 's> = &'w Bundles;
1364
1365 fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {}
1366
1367 #[inline]
1368 unsafe fn get_param<'w, 's>(
1369 _state: &'s mut Self::State,
1370 _system_meta: &SystemMeta,
1371 world: UnsafeWorldCell<'w>,
1372 _change_tick: Tick,
1373 ) -> Self::Item<'w, 's> {
1374 world.bundles()
1375 }
1376}
1377
1378#[derive(Debug)]
1388pub struct SystemChangeTick {
1389 last_run: Tick,
1390 this_run: Tick,
1391}
1392
1393impl SystemChangeTick {
1394 #[inline]
1396 pub fn this_run(&self) -> Tick {
1397 self.this_run
1398 }
1399
1400 #[inline]
1402 pub fn last_run(&self) -> Tick {
1403 self.last_run
1404 }
1405}
1406
1407unsafe impl ReadOnlySystemParam for SystemChangeTick {}
1409
1410unsafe impl SystemParam for SystemChangeTick {
1412 type State = ();
1413 type Item<'w, 's> = SystemChangeTick;
1414
1415 fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {}
1416
1417 unsafe fn get_param<'w, 's>(
1418 _state: &'s mut Self::State,
1419 system_meta: &SystemMeta,
1420 _world: UnsafeWorldCell<'w>,
1421 change_tick: Tick,
1422 ) -> Self::Item<'w, 's> {
1423 SystemChangeTick {
1424 last_run: system_meta.last_run,
1425 this_run: change_tick,
1426 }
1427 }
1428}
1429
1430macro_rules! impl_system_param_tuple {
1431 ($($param: ident),*) => {
1432 unsafe impl<$($param: ReadOnlySystemParam),*> ReadOnlySystemParam for ($($param,)*) {}
1434
1435 #[allow(clippy::undocumented_unsafe_blocks)] #[allow(non_snake_case)]
1438 unsafe impl<$($param: SystemParam),*> SystemParam for ($($param,)*) {
1439 type State = ($($param::State,)*);
1440 type Item<'w, 's> = ($($param::Item::<'w, 's>,)*);
1441
1442 #[inline]
1443 fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {
1444 (($($param::init_state(_world, _system_meta),)*))
1445 }
1446
1447 #[inline]
1448 #[allow(unused_unsafe)]
1449 unsafe fn new_archetype(($($param,)*): &mut Self::State, _archetype: &Archetype, _system_meta: &mut SystemMeta) {
1450 unsafe { $($param::new_archetype($param, _archetype, _system_meta);)* }
1452 }
1453
1454 #[inline]
1455 fn apply(($($param,)*): &mut Self::State, _system_meta: &SystemMeta, _world: &mut World) {
1456 $($param::apply($param, _system_meta, _world);)*
1457 }
1458
1459 #[inline]
1460 fn queue(($($param,)*): &mut Self::State, _system_meta: &SystemMeta, mut _world: DeferredWorld) {
1461 $($param::queue($param, _system_meta, _world.reborrow());)*
1462 }
1463
1464 #[inline]
1465 #[allow(clippy::unused_unit)]
1466 unsafe fn get_param<'w, 's>(
1467 state: &'s mut Self::State,
1468 _system_meta: &SystemMeta,
1469 _world: UnsafeWorldCell<'w>,
1470 _change_tick: Tick,
1471 ) -> Self::Item<'w, 's> {
1472
1473 let ($($param,)*) = state;
1474 ($($param::get_param($param, _system_meta, _world, _change_tick),)*)
1475 }
1476 }
1477 };
1478}
1479
1480all_tuples!(impl_system_param_tuple, 0, 16, P);
1481
1482pub mod lifetimeless {
1495 pub type SQuery<D, F = ()> = super::Query<'static, 'static, D, F>;
1497 pub type Read<T> = &'static T;
1499 pub type Write<T> = &'static mut T;
1501 pub type SRes<T> = super::Res<'static, T>;
1503 pub type SResMut<T> = super::ResMut<'static, T>;
1505 pub type SCommands = crate::system::Commands<'static, 'static>;
1507}
1508
1509pub struct StaticSystemParam<'w, 's, P: SystemParam>(SystemParamItem<'w, 's, P>);
1562
1563impl<'w, 's, P: SystemParam> Deref for StaticSystemParam<'w, 's, P> {
1564 type Target = SystemParamItem<'w, 's, P>;
1565
1566 fn deref(&self) -> &Self::Target {
1567 &self.0
1568 }
1569}
1570
1571impl<'w, 's, P: SystemParam> DerefMut for StaticSystemParam<'w, 's, P> {
1572 fn deref_mut(&mut self) -> &mut Self::Target {
1573 &mut self.0
1574 }
1575}
1576
1577impl<'w, 's, P: SystemParam> StaticSystemParam<'w, 's, P> {
1578 pub fn into_inner(self) -> SystemParamItem<'w, 's, P> {
1580 self.0
1581 }
1582}
1583
1584unsafe impl<'w, 's, P: ReadOnlySystemParam + 'static> ReadOnlySystemParam
1586 for StaticSystemParam<'w, 's, P>
1587{
1588}
1589
1590unsafe impl<P: SystemParam + 'static> SystemParam for StaticSystemParam<'_, '_, P> {
1592 type State = P::State;
1593 type Item<'world, 'state> = StaticSystemParam<'world, 'state, P>;
1594
1595 fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
1596 P::init_state(world, system_meta)
1597 }
1598
1599 unsafe fn new_archetype(
1600 state: &mut Self::State,
1601 archetype: &Archetype,
1602 system_meta: &mut SystemMeta,
1603 ) {
1604 unsafe { P::new_archetype(state, archetype, system_meta) };
1606 }
1607
1608 fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
1609 P::apply(state, system_meta, world);
1610 }
1611
1612 fn queue(state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld) {
1613 P::queue(state, system_meta, world);
1614 }
1615
1616 unsafe fn get_param<'world, 'state>(
1617 state: &'state mut Self::State,
1618 system_meta: &SystemMeta,
1619 world: UnsafeWorldCell<'world>,
1620 change_tick: Tick,
1621 ) -> Self::Item<'world, 'state> {
1622 StaticSystemParam(unsafe { P::get_param(state, system_meta, world, change_tick) })
1624 }
1625}
1626
1627unsafe impl<T: ?Sized> SystemParam for PhantomData<T> {
1629 type State = ();
1630 type Item<'world, 'state> = Self;
1631
1632 fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {}
1633
1634 unsafe fn get_param<'world, 'state>(
1635 _state: &'state mut Self::State,
1636 _system_meta: &SystemMeta,
1637 _world: UnsafeWorldCell<'world>,
1638 _change_tick: Tick,
1639 ) -> Self::Item<'world, 'state> {
1640 PhantomData
1641 }
1642}
1643
1644unsafe impl<T: ?Sized> ReadOnlySystemParam for PhantomData<T> {}
1646
1647#[cfg(test)]
1648mod tests {
1649 use super::*;
1650 use crate::{
1651 self as bevy_ecs, system::assert_is_system,
1653 };
1654 use std::cell::RefCell;
1655
1656 #[test]
1658 fn system_param_generic_bounds() {
1659 #[derive(SystemParam)]
1660 pub struct SpecialQuery<
1661 'w,
1662 's,
1663 D: QueryData + Send + Sync + 'static,
1664 F: QueryFilter + Send + Sync + 'static = (),
1665 > {
1666 _query: Query<'w, 's, D, F>,
1667 }
1668
1669 fn my_system(_: SpecialQuery<(), ()>) {}
1670 assert_is_system(my_system);
1671 }
1672
1673 #[test]
1675 fn system_param_flexibility() {
1676 #[derive(SystemParam)]
1677 pub struct SpecialRes<'w, T: Resource> {
1678 _res: Res<'w, T>,
1679 }
1680
1681 #[derive(SystemParam)]
1682 pub struct SpecialLocal<'s, T: FromWorld + Send + 'static> {
1683 _local: Local<'s, T>,
1684 }
1685
1686 #[derive(Resource)]
1687 struct R;
1688
1689 fn my_system(_: SpecialRes<R>, _: SpecialLocal<u32>) {}
1690 assert_is_system(my_system);
1691 }
1692
1693 #[derive(Resource)]
1694 pub struct R<const I: usize>;
1695
1696 #[test]
1698 fn system_param_const_generics() {
1699 #[allow(dead_code)]
1700 #[derive(SystemParam)]
1701 pub struct ConstGenericParam<'w, const I: usize>(Res<'w, R<I>>);
1702
1703 fn my_system(_: ConstGenericParam<0>, _: ConstGenericParam<1000>) {}
1704 assert_is_system(my_system);
1705 }
1706
1707 #[test]
1709 fn system_param_field_limit() {
1710 #[derive(SystemParam)]
1711 pub struct LongParam<'w> {
1712 _r0: Res<'w, R<0>>,
1715 _r1: Res<'w, R<1>>,
1716 _r2: Res<'w, R<2>>,
1717 _r3: Res<'w, R<3>>,
1718 _r4: Res<'w, R<4>>,
1719 _r5: Res<'w, R<5>>,
1720 _r6: Res<'w, R<6>>,
1721 _r7: Res<'w, R<7>>,
1722 _r8: Res<'w, R<8>>,
1723 _r9: Res<'w, R<9>>,
1724 _r10: Res<'w, R<10>>,
1725 _r11: Res<'w, R<11>>,
1726 _r12: Res<'w, R<12>>,
1727 _r13: Res<'w, R<13>>,
1728 _r14: Res<'w, R<14>>,
1729 _r15: Res<'w, R<15>>,
1730 _r16: Res<'w, R<16>>,
1731 }
1732
1733 fn long_system(_: LongParam) {}
1734 assert_is_system(long_system);
1735 }
1736
1737 #[test]
1740 fn system_param_phantom_data() {
1741 #[derive(SystemParam)]
1742 struct PhantomParam<'w, T: Resource, Marker: 'static> {
1743 _foo: Res<'w, T>,
1744 marker: PhantomData<&'w Marker>,
1745 }
1746
1747 fn my_system(_: PhantomParam<R<0>, ()>) {}
1748 assert_is_system(my_system);
1749 }
1750
1751 #[test]
1753 fn system_param_struct_variants() {
1754 #[derive(SystemParam)]
1755 pub struct UnitParam;
1756
1757 #[allow(dead_code)]
1758 #[derive(SystemParam)]
1759 pub struct TupleParam<'w, 's, R: Resource, L: FromWorld + Send + 'static>(
1760 Res<'w, R>,
1761 Local<'s, L>,
1762 );
1763
1764 fn my_system(_: UnitParam, _: TupleParam<R<0>, u32>) {}
1765 assert_is_system(my_system);
1766 }
1767
1768 #[test]
1770 fn system_param_private_fields() {
1771 #[derive(Resource)]
1772 struct PrivateResource;
1773
1774 #[allow(dead_code)]
1775 #[derive(SystemParam)]
1776 pub struct EncapsulatedParam<'w>(Res<'w, PrivateResource>);
1777
1778 fn my_system(_: EncapsulatedParam) {}
1779 assert_is_system(my_system);
1780 }
1781
1782 #[test]
1784 fn system_param_where_clause() {
1785 #[derive(SystemParam)]
1786 pub struct WhereParam<'w, 's, D>
1787 where
1788 D: 'static + QueryData,
1789 {
1790 _q: Query<'w, 's, D, ()>,
1791 }
1792
1793 fn my_system(_: WhereParam<()>) {}
1794 assert_is_system(my_system);
1795 }
1796
1797 #[test]
1799 fn system_param_name_collision() {
1800 #[derive(Resource)]
1801 pub struct FetchState;
1802
1803 #[derive(SystemParam)]
1804 pub struct Collide<'w> {
1805 _x: Res<'w, FetchState>,
1806 }
1807
1808 fn my_system(_: Collide) {}
1809 assert_is_system(my_system);
1810 }
1811
1812 #[test]
1814 fn system_param_invariant_lifetime() {
1815 #[derive(SystemParam)]
1816 pub struct InvariantParam<'w, 's> {
1817 _set: ParamSet<'w, 's, (Query<'w, 's, ()>,)>,
1818 }
1819
1820 fn my_system(_: InvariantParam) {}
1821 assert_is_system(my_system);
1822 }
1823
1824 #[test]
1826 fn non_sync_local() {
1827 fn non_sync_system(cell: Local<RefCell<u8>>) {
1828 assert_eq!(*cell.borrow(), 0);
1829 }
1830
1831 let mut world = World::new();
1832 let mut schedule = crate::schedule::Schedule::default();
1833 schedule.add_systems(non_sync_system);
1834 schedule.run(&mut world);
1835 }
1836
1837 #[test]
1839 fn param_set_non_send_first() {
1840 fn non_send_param_set(mut p: ParamSet<(NonSend<*mut u8>, ())>) {
1841 let _ = p.p0();
1842 p.p1();
1843 }
1844
1845 let mut world = World::new();
1846 world.insert_non_send_resource(std::ptr::null_mut::<u8>());
1847 let mut schedule = crate::schedule::Schedule::default();
1848 schedule.add_systems((non_send_param_set, non_send_param_set, non_send_param_set));
1849 schedule.run(&mut world);
1850 }
1851
1852 #[test]
1854 fn param_set_non_send_second() {
1855 fn non_send_param_set(mut p: ParamSet<((), NonSendMut<*mut u8>)>) {
1856 p.p0();
1857 let _ = p.p1();
1858 }
1859
1860 let mut world = World::new();
1861 world.insert_non_send_resource(std::ptr::null_mut::<u8>());
1862 let mut schedule = crate::schedule::Schedule::default();
1863 schedule.add_systems((non_send_param_set, non_send_param_set, non_send_param_set));
1864 schedule.run(&mut world);
1865 }
1866}