diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index 53121a6c7f883..2dc8fa0851b5a 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -209,19 +209,19 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream { let mut tokens = TokenStream::new(); let max_params = 8; let params = get_idents(|i| format!("P{i}"), max_params); - let params_fetch = get_idents(|i| format!("PF{i}"), max_params); + let params_state = get_idents(|i| format!("PF{i}"), max_params); let metas = get_idents(|i| format!("m{i}"), max_params); let mut param_fn_muts = Vec::new(); for (i, param) in params.iter().enumerate() { let fn_name = Ident::new(&format!("p{i}"), Span::call_site()); let index = Index::from(i); param_fn_muts.push(quote! { - pub fn #fn_name<'a>(&'a mut self) -> <#param::Fetch as SystemParamFetch<'a, 'a>>::Item { + pub fn #fn_name<'a>(&'a mut self) -> SystemParamItem<'a, 'a, #param> { // SAFETY: systems run without conflicts with other systems. // Conflicting params in ParamSet are not accessible at the same time // ParamSets are guaranteed to not conflict with other SystemParams unsafe { - <#param::Fetch as SystemParamFetch<'a, 'a>>::get_param(&mut self.param_states.#index, &self.system_meta, self.world, self.change_tick) + <#param::State as SystemParamState>::get_param(&mut self.param_states.#index, &self.system_meta, self.world, self.change_tick) } } }); @@ -229,34 +229,36 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream { for param_count in 1..=max_params { let param = ¶ms[0..param_count]; - let param_fetch = ¶ms_fetch[0..param_count]; + let param_state = ¶ms_state[0..param_count]; let meta = &metas[0..param_count]; let param_fn_mut = ¶m_fn_muts[0..param_count]; tokens.extend(TokenStream::from(quote! { impl<'w, 's, #(#param: SystemParam,)*> SystemParam for ParamSet<'w, 's, (#(#param,)*)> { - type Fetch = ParamSetState<(#(#param::Fetch,)*)>; + type State = ParamSetState<(#(#param::State,)*)>; } - // SAFETY: All parameters are constrained to ReadOnlyFetch, so World is only read + // SAFETY: All parameters are constrained to ReadOnlyState, so World is only read - unsafe impl<#(#param_fetch: for<'w1, 's1> SystemParamFetch<'w1, 's1>,)*> ReadOnlySystemParamFetch for ParamSetState<(#(#param_fetch,)*)> - where #(#param_fetch: ReadOnlySystemParamFetch,)* + unsafe impl<'w, 's, #(#param,)*> ReadOnlySystemParam for ParamSet<'w, 's, (#(#param,)*)> + where #(#param: ReadOnlySystemParam,)* { } // SAFETY: Relevant parameter ComponentId and ArchetypeComponentId access is applied to SystemMeta. If any ParamState conflicts // with any prior access, a panic will occur. - unsafe impl<#(#param_fetch: for<'w1, 's1> SystemParamFetch<'w1, 's1>,)*> SystemParamState for ParamSetState<(#(#param_fetch,)*)> + unsafe impl<#(#param_state: SystemParamState,)*> SystemParamState for ParamSetState<(#(#param_state,)*)> { + type Item<'w, 's> = ParamSet<'w, 's, (#(<#param_state as SystemParamState>::Item::<'w, 's>,)*)>; + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { #( // Pretend to add each param to the system alone, see if it conflicts let mut #meta = system_meta.clone(); #meta.component_access_set.clear(); #meta.archetype_component_access.clear(); - #param_fetch::init(world, &mut #meta); - let #param = #param_fetch::init(world, &mut system_meta.clone()); + #param_state::init(world, &mut #meta); + let #param = #param_state::init(world, &mut system_meta.clone()); )* #( system_meta @@ -279,21 +281,14 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream { fn apply(&mut self, world: &mut World) { self.0.apply(world) } - } - - - - impl<'w, 's, #(#param_fetch: for<'w1, 's1> SystemParamFetch<'w1, 's1>,)*> SystemParamFetch<'w, 's> for ParamSetState<(#(#param_fetch,)*)> - { - type Item = ParamSet<'w, 's, (#(<#param_fetch as SystemParamFetch<'w, 's>>::Item,)*)>; #[inline] - unsafe fn get_param( + unsafe fn get_param<'w, 's>( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { ParamSet { param_states: &mut state.0, system_meta: system_meta.clone(), @@ -414,34 +409,48 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { _ => unreachable!(), })); + // Create a where clause for the `ReadOnlySystemParam` impl. + // Ensure that each field implements `ReadOnlySystemParam`. + let mut read_only_generics = generics.clone(); + let read_only_where_clause = read_only_generics.make_where_clause(); + for field_type in &field_types { + read_only_where_clause + .predicates + .push(syn::parse_quote!(#field_type: #path::system::ReadOnlySystemParam)); + } + let struct_name = &ast.ident; - let fetch_struct_visibility = &ast.vis; + let state_struct_visibility = &ast.vis; TokenStream::from(quote! { // We define the FetchState struct in an anonymous scope to avoid polluting the user namespace. - // The struct can still be accessed via SystemParam::Fetch, e.g. EventReaderState can be accessed via - // as SystemParam>::Fetch + // The struct can still be accessed via SystemParam::State, e.g. EventReaderState can be accessed via + // as SystemParam>::State const _: () = { impl<'w, 's, #punctuated_generics> #path::system::SystemParam for #struct_name #ty_generics #where_clause { - type Fetch = State<'w, 's, #punctuated_generic_idents>; + type State = State<'w, 's, #punctuated_generic_idents>; } #[doc(hidden)] type State<'w, 's, #punctuated_generic_idents> = FetchState< - (#(<#field_types as #path::system::SystemParam>::Fetch,)*), + (#(<#field_types as #path::system::SystemParam>::State,)*), #punctuated_generic_idents >; #[doc(hidden)] - #fetch_struct_visibility struct FetchState { + #state_struct_visibility struct FetchState { state: TSystemParamState, marker: std::marker::PhantomData(#punctuated_generic_idents)> } - unsafe impl #path::system::SystemParamState for FetchState #where_clause { + unsafe impl<'__w, '__s, #punctuated_generics> #path::system::SystemParamState for + State<'__w, '__s, #punctuated_generic_idents> + #where_clause { + type Item<'w, 's> = #struct_name #ty_generics; + fn init(world: &mut #path::world::World, system_meta: &mut #path::system::SystemMeta) -> Self { Self { - state: TSystemParamState::init(world, system_meta), + state: #path::system::SystemParamState::init(world, system_meta), marker: std::marker::PhantomData, } } @@ -453,25 +462,22 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { fn apply(&mut self, world: &mut #path::world::World) { self.state.apply(world) } - } - impl<'w, 's, #punctuated_generics> #path::system::SystemParamFetch<'w, 's> for State<'w, 's, #punctuated_generic_idents> #where_clause { - type Item = #struct_name #ty_generics; - unsafe fn get_param( + unsafe fn get_param<'w, 's>( state: &'s mut Self, system_meta: &#path::system::SystemMeta, world: &'w #path::world::World, change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { #struct_name { - #(#fields: <<#field_types as #path::system::SystemParam>::Fetch as #path::system::SystemParamFetch>::get_param(&mut state.state.#field_indices, system_meta, world, change_tick),)* + #(#fields: <<#field_types as #path::system::SystemParam>::State as #path::system::SystemParamState>::get_param(&mut state.state.#field_indices, system_meta, world, change_tick),)* #(#ignored_fields: <#ignored_field_types>::default(),)* } } } - // Safety: The `ParamState` is `ReadOnlySystemParamFetch`, so this can only read from the `World` - unsafe impl #path::system::ReadOnlySystemParamFetch for FetchState #where_clause {} + // Safety: Each field is `ReadOnlySystemParam`, so this can only read from the `World` + unsafe impl<'w, 's, #punctuated_generics> #path::system::ReadOnlySystemParam for #struct_name #ty_generics #read_only_where_clause {} }; }) } diff --git a/crates/bevy_ecs/src/system/commands/parallel_scope.rs b/crates/bevy_ecs/src/system/commands/parallel_scope.rs index 573afa70aae51..5fccd74228061 100644 --- a/crates/bevy_ecs/src/system/commands/parallel_scope.rs +++ b/crates/bevy_ecs/src/system/commands/parallel_scope.rs @@ -5,7 +5,7 @@ use thread_local::ThreadLocal; use crate::{ entity::Entities, prelude::World, - system::{SystemParam, SystemParamFetch, SystemParamState}, + system::{SystemParam, SystemParamState}, }; use super::{CommandQueue, Commands}; @@ -49,27 +49,13 @@ pub struct ParallelCommands<'w, 's> { } impl SystemParam for ParallelCommands<'_, '_> { - type Fetch = ParallelCommandsState; -} - -impl<'w, 's> SystemParamFetch<'w, 's> for ParallelCommandsState { - type Item = ParallelCommands<'w, 's>; - - unsafe fn get_param( - state: &'s mut Self, - _: &crate::system::SystemMeta, - world: &'w World, - _: u32, - ) -> Self::Item { - ParallelCommands { - state, - entities: world.entities(), - } - } + type State = ParallelCommandsState; } // SAFETY: no component or resource access to report unsafe impl SystemParamState for ParallelCommandsState { + type Item<'w, 's> = ParallelCommands<'w, 's>; + fn init(_: &mut World, _: &mut crate::system::SystemMeta) -> Self { Self::default() } @@ -79,6 +65,18 @@ unsafe impl SystemParamState for ParallelCommandsState { cq.get_mut().apply(world); } } + + unsafe fn get_param<'w, 's>( + state: &'s mut Self, + _: &crate::system::SystemMeta, + world: &'w World, + _: u32, + ) -> Self::Item<'w, 's> { + ParallelCommands { + state, + entities: world.entities(), + } + } } impl<'w, 's> ParallelCommands<'w, 's> { diff --git a/crates/bevy_ecs/src/system/exclusive_function_system.rs b/crates/bevy_ecs/src/system/exclusive_function_system.rs index 662d031daa2e3..8b1607c75898e 100644 --- a/crates/bevy_ecs/src/system/exclusive_function_system.rs +++ b/crates/bevy_ecs/src/system/exclusive_function_system.rs @@ -5,9 +5,8 @@ use crate::{ query::Access, schedule::{SystemLabel, SystemLabelId}, system::{ - check_system_change_tick, AsSystemLabel, ExclusiveSystemParam, ExclusiveSystemParamFetch, - ExclusiveSystemParamItem, ExclusiveSystemParamState, IntoSystem, System, SystemMeta, - SystemTypeIdLabel, + check_system_change_tick, AsSystemLabel, ExclusiveSystemParam, ExclusiveSystemParamItem, + ExclusiveSystemParamState, IntoSystem, System, SystemMeta, SystemTypeIdLabel, }, world::{World, WorldId}, }; @@ -25,7 +24,7 @@ where Param: ExclusiveSystemParam, { func: F, - param_state: Option, + param_state: Option, system_meta: SystemMeta, world_id: Option, // NOTE: PhantomData T> gives this safe Send/Sync impls @@ -95,7 +94,7 @@ where let saved_last_tick = world.last_change_tick; world.last_change_tick = self.system_meta.last_change_tick; - let params = ::Fetch::get_param( + let params = ::State::get_param( self.param_state.as_mut().expect(PARAM_MESSAGE), &self.system_meta, ); @@ -130,7 +129,7 @@ where fn initialize(&mut self, world: &mut World) { self.world_id = Some(world.id()); self.system_meta.last_change_tick = world.change_tick().wrapping_sub(MAX_CHANGE_AGE); - self.param_state = Some(::init( + self.param_state = Some(::init( world, &mut self.system_meta, )); diff --git a/crates/bevy_ecs/src/system/exclusive_system_param.rs b/crates/bevy_ecs/src/system/exclusive_system_param.rs index 412474bda03dd..6c52738901254 100644 --- a/crates/bevy_ecs/src/system/exclusive_system_param.rs +++ b/crates/bevy_ecs/src/system/exclusive_system_param.rs @@ -8,111 +8,86 @@ use bevy_ecs_macros::all_tuples; use bevy_utils::synccell::SyncCell; pub trait ExclusiveSystemParam: Sized { - type Fetch: for<'s> ExclusiveSystemParamFetch<'s>; + type State: ExclusiveSystemParamState; } pub type ExclusiveSystemParamItem<'s, P> = - <

::Fetch as ExclusiveSystemParamFetch<'s>>::Item; + <

::State as ExclusiveSystemParamState>::Item<'s>; /// The state of a [`SystemParam`]. -pub trait ExclusiveSystemParamState: Send + Sync { +pub trait ExclusiveSystemParamState: Send + Sync + 'static { + type Item<'s>: ExclusiveSystemParam; + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self; #[inline] fn apply(&mut self, _world: &mut World) {} -} -pub trait ExclusiveSystemParamFetch<'state>: ExclusiveSystemParamState { - type Item: ExclusiveSystemParam; - fn get_param(state: &'state mut Self, system_meta: &SystemMeta) -> Self::Item; + fn get_param<'s>(state: &'s mut Self, system_meta: &SystemMeta) -> Self::Item<'s>; } impl<'a, Q: WorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> ExclusiveSystemParam for &'a mut QueryState { - type Fetch = QueryState; -} - -impl<'s, Q: WorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> ExclusiveSystemParamFetch<'s> - for QueryState -{ - type Item = &'s mut QueryState; - - fn get_param(state: &'s mut Self, _system_meta: &SystemMeta) -> Self::Item { - state - } + type State = QueryState; } impl ExclusiveSystemParamState for QueryState { + type Item<'s> = &'s mut QueryState; + fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self { QueryState::new(world) } -} - -impl<'a, P: SystemParam + 'static> ExclusiveSystemParam for &'a mut SystemState

{ - type Fetch = SystemState

; -} -impl<'s, P: SystemParam + 'static> ExclusiveSystemParamFetch<'s> for SystemState

{ - type Item = &'s mut SystemState

; - - fn get_param(state: &'s mut Self, _system_meta: &SystemMeta) -> Self::Item { + fn get_param<'s>(state: &'s mut Self, _system_meta: &SystemMeta) -> Self::Item<'s> { state } } +impl<'a, P: SystemParam + 'static> ExclusiveSystemParam for &'a mut SystemState

{ + type State = SystemState

; +} + impl ExclusiveSystemParamState for SystemState

{ + type Item<'s> = &'s mut SystemState

; + fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self { SystemState::new(world) } -} -impl<'s, T: FromWorld + Send + Sync + 'static> ExclusiveSystemParam for Local<'s, T> { - type Fetch = LocalState; + fn get_param<'s>(state: &'s mut Self, _system_meta: &SystemMeta) -> Self::Item<'s> { + state + } } -impl<'s, T: FromWorld + Send + Sync + 'static> ExclusiveSystemParamFetch<'s> for LocalState { - type Item = Local<'s, T>; - - fn get_param(state: &'s mut Self, _system_meta: &SystemMeta) -> Self::Item { - Local(state.0.get()) - } +impl<'s, T: FromWorld + Send + Sync + 'static> ExclusiveSystemParam for Local<'s, T> { + type State = LocalState; } impl ExclusiveSystemParamState for LocalState { + type Item<'s> = Local<'s, T>; + fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self { Self(SyncCell::new(T::from_world(world))) } + + fn get_param<'s>(state: &'s mut Self, _system_meta: &SystemMeta) -> Self::Item<'s> { + Local(state.0.get()) + } } macro_rules! impl_exclusive_system_param_tuple { ($($param: ident),*) => { impl<$($param: ExclusiveSystemParam),*> ExclusiveSystemParam for ($($param,)*) { - type Fetch = ($($param::Fetch,)*); + type State = ($($param::State,)*); } #[allow(unused_variables)] #[allow(non_snake_case)] - impl<'s, $($param: ExclusiveSystemParamFetch<'s>),*> ExclusiveSystemParamFetch<'s> for ($($param,)*) { - type Item = ($($param::Item,)*); - - #[inline] - #[allow(clippy::unused_unit)] - fn get_param( - state: &'s mut Self, - system_meta: &SystemMeta, - ) -> Self::Item { - - let ($($param,)*) = state; - ($($param::get_param($param, system_meta),)*) - } - } - - // SAFETY: implementors of each `ExclusiveSystemParamState` in the tuple have validated their impls - #[allow(clippy::undocumented_unsafe_blocks)] // false positive by clippy - #[allow(non_snake_case)] impl<$($param: ExclusiveSystemParamState),*> ExclusiveSystemParamState for ($($param,)*) { + type Item<'s> = ($($param::Item<'s>,)*); + #[inline] fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { (($($param::init(_world, _system_meta),)*)) @@ -123,7 +98,19 @@ macro_rules! impl_exclusive_system_param_tuple { let ($($param,)*) = self; $($param.apply(_world);)* } + + #[inline] + #[allow(clippy::unused_unit)] + fn get_param<'s>( + state: &'s mut Self, + system_meta: &SystemMeta, + ) -> Self::Item<'s> { + + let ($($param,)*) = state; + ($($param::get_param($param, system_meta),)*) + } } + }; } diff --git a/crates/bevy_ecs/src/system/function_system.rs b/crates/bevy_ecs/src/system/function_system.rs index c3f672e718734..3a4c9006ae6d6 100644 --- a/crates/bevy_ecs/src/system/function_system.rs +++ b/crates/bevy_ecs/src/system/function_system.rs @@ -6,8 +6,8 @@ use crate::{ query::{Access, FilteredAccessSet}, schedule::{SystemLabel, SystemLabelId}, system::{ - check_system_change_tick, ReadOnlySystemParamFetch, System, SystemParam, SystemParamFetch, - SystemParamItem, SystemParamState, + check_system_change_tick, ReadOnlySystemParam, System, SystemParam, SystemParamItem, + SystemParamState, }, world::{World, WorldId}, }; @@ -135,7 +135,7 @@ impl SystemMeta { /// ``` pub struct SystemState { meta: SystemMeta, - param_state: ::Fetch, + param_state: ::State, world_id: WorldId, archetype_generation: ArchetypeGeneration, } @@ -144,7 +144,7 @@ impl SystemState { pub fn new(world: &mut World) -> Self { let mut meta = SystemMeta::new::(); meta.last_change_tick = world.change_tick().wrapping_sub(MAX_CHANGE_AGE); - let param_state = ::init(world, &mut meta); + let param_state = ::init(world, &mut meta); Self { meta, param_state, @@ -160,12 +160,9 @@ impl SystemState { /// Retrieve the [`SystemParam`] values. This can only be called when all parameters are read-only. #[inline] - pub fn get<'w, 's>( - &'s mut self, - world: &'w World, - ) -> >::Item + pub fn get<'w, 's>(&'s mut self, world: &'w World) -> SystemParamItem<'w, 's, Param> where - Param::Fetch: ReadOnlySystemParamFetch, + Param: ReadOnlySystemParam, { self.validate_world_and_update_archetypes(world); // SAFETY: Param is read-only and doesn't allow mutable access to World. It also matches the World this SystemState was created with. @@ -174,10 +171,7 @@ impl SystemState { /// Retrieve the mutable [`SystemParam`] values. #[inline] - pub fn get_mut<'w, 's>( - &'s mut self, - world: &'w mut World, - ) -> >::Item { + pub fn get_mut<'w, 's>(&'s mut self, world: &'w mut World) -> SystemParamItem<'w, 's, Param> { self.validate_world_and_update_archetypes(world); // SAFETY: World is uniquely borrowed and matches the World this SystemState was created with. unsafe { self.get_unchecked_manual(world) } @@ -221,9 +215,9 @@ impl SystemState { pub unsafe fn get_unchecked_manual<'w, 's>( &'s mut self, world: &'w World, - ) -> >::Item { + ) -> SystemParamItem<'w, 's, Param> { let change_tick = world.increment_change_tick(); - let param = ::get_param( + let param = ::get_param( &mut self.param_state, &self.meta, world, @@ -315,7 +309,7 @@ where Param: SystemParam, { func: F, - param_state: Option, + param_state: Option, system_meta: SystemMeta, world_id: Option, archetype_generation: ArchetypeGeneration, @@ -400,7 +394,7 @@ where // We update the archetype component access correctly based on `Param`'s requirements // in `update_archetype_component_access`. // Our caller upholds the requirements. - let params = ::Fetch::get_param( + let params = ::State::get_param( self.param_state.as_mut().expect(Self::PARAM_MESSAGE), &self.system_meta, world, @@ -429,7 +423,7 @@ where fn initialize(&mut self, world: &mut World) { self.world_id = Some(world.id()); self.system_meta.last_change_tick = world.change_tick().wrapping_sub(MAX_CHANGE_AGE); - self.param_state = Some(::init( + self.param_state = Some(::init( world, &mut self.system_meta, )); @@ -588,7 +582,7 @@ macro_rules! impl_system_function { where for <'a> &'a mut Func: FnMut(In, $($param),*) -> Out + - FnMut(In, $(<<$param as SystemParam>::Fetch as SystemParamFetch>::Item),*) -> Out, Out: 'static + FnMut(In, $(SystemParamItem<$param>),*) -> Out, Out: 'static { #[inline] fn run(&mut self, input: Input, param_value: SystemParamItem< ($($param,)*)>) -> Out { diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index d52961c4ad86a..8ec8953d486f7 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -72,7 +72,7 @@ use std::{ /// /// ```text /// expected ... [ParamType] -/// found associated type `<<[ParamType] as SystemParam>::Fetch as SystemParamFetch<'_, '_>>::Item` +/// found associated type `<<[ParamType] as SystemParam>::State as SystemParamState>::Item<'_, '_>` /// ``` /// where `[ParamType]` is the type of one of your fields. /// To solve this error, you can wrap the field of type `[ParamType]` with [`StaticSystemParam`] @@ -81,7 +81,7 @@ use std::{ /// ## Details /// /// The derive macro requires that the [`SystemParam`] implementation of -/// each field `F`'s [`Fetch`](`SystemParam::Fetch`)'s [`Item`](`SystemParamFetch::Item`) is itself `F` +/// each field `F`'s [`State`](`SystemParam::State`)'s [`Item`](`SystemParamState::Item`) is itself `F` /// (ignoring lifetimes for simplicity). /// This assumption is due to type inference reasons, so that the derived [`SystemParam`] can be /// used as an argument to a function system. @@ -122,17 +122,17 @@ use std::{ /// [`SyncCell`]: bevy_utils::synccell::SyncCell /// [`Exclusive`]: https://doc.rust-lang.org/nightly/std/sync/struct.Exclusive.html pub trait SystemParam: Sized { - type Fetch: for<'w, 's> SystemParamFetch<'w, 's>; + type State: SystemParamState; } -pub type SystemParamItem<'w, 's, P> = <

::Fetch as SystemParamFetch<'w, 's>>::Item; +pub type SystemParamItem<'w, 's, P> = <

::State as SystemParamState>::Item<'w, 's>; /// The state of a [`SystemParam`]. /// /// # Safety /// /// It is the implementor's responsibility to ensure `system_meta` is populated with the _exact_ -/// [`World`] access used by the [`SystemParamState`] (and associated [`SystemParamFetch`]). +/// [`World`] access used by the [`SystemParamState`]. /// Additionally, it is the implementor's responsibility to ensure there is no /// conflicting access across all [`SystemParam`]'s. pub unsafe trait SystemParamState: Send + Sync + 'static { @@ -141,37 +141,35 @@ pub unsafe trait SystemParamState: Send + Sync + 'static { fn new_archetype(&mut self, _archetype: &Archetype, _system_meta: &mut SystemMeta) {} #[inline] fn apply(&mut self, _world: &mut World) {} -} - -/// A [`SystemParamFetch`] that only reads a given [`World`]. -/// -/// # Safety -/// This must only be implemented for [`SystemParamFetch`] impls that exclusively read the World passed in to [`SystemParamFetch::get_param`] -pub unsafe trait ReadOnlySystemParamFetch {} -pub trait SystemParamFetch<'world, 'state>: SystemParamState { - type Item: SystemParam; + type Item<'world, 'state>: SystemParam; /// # Safety /// /// This call might access any of the input parameters in an unsafe way. Make sure the data /// access is safe in the context of the system scheduler. - unsafe fn get_param( + unsafe fn get_param<'world, 'state>( state: &'state mut Self, system_meta: &SystemMeta, world: &'world World, change_tick: u32, - ) -> Self::Item; + ) -> Self::Item<'world, 'state>; } +/// A [`SystemParam`] that only reads a given [`World`]. +/// +/// # Safety +/// This must only be implemented for [`SystemParam`] impls that exclusively read the World passed in to [`SystemParamState::get_param`] +pub unsafe trait ReadOnlySystemParam: SystemParam {} + impl<'w, 's, Q: WorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> SystemParam for Query<'w, 's, Q, F> { - type Fetch = QueryState; + type State = QueryState; } // SAFETY: QueryState is constrained to read-only fetches, so it only reads World. -unsafe impl ReadOnlySystemParamFetch - for QueryState +unsafe impl<'w, 's, Q: ReadOnlyWorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> + ReadOnlySystemParam for Query<'w, 's, Q, F> { } @@ -180,6 +178,8 @@ unsafe impl ReadOnlySystemParamFet unsafe impl SystemParamState for QueryState { + type Item<'w, 's> = Query<'w, 's, Q, F>; + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { let state = QueryState::new(world); assert_component_access_compatibility( @@ -205,20 +205,14 @@ unsafe impl SystemPara .archetype_component_access .extend(&self.archetype_component_access); } -} - -impl<'w, 's, Q: WorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> SystemParamFetch<'w, 's> - for QueryState -{ - type Item = Query<'w, 's, Q, F>; #[inline] - unsafe fn get_param( + unsafe fn get_param<'w, 's>( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { Query::new(world, state, system_meta.last_change_tick, change_tick) } } @@ -245,13 +239,13 @@ fn assert_component_access_compatibility( } pub struct ParamSet<'w, 's, T: SystemParam> { - param_states: &'s mut T::Fetch, + param_states: &'s mut T::State, world: &'w World, system_meta: SystemMeta, change_tick: u32, } /// The [`SystemParamState`] of [`ParamSet`]. -pub struct ParamSetState SystemParamFetch<'w, 's>>(T); +pub struct ParamSetState(T); impl_param_set!(); @@ -308,7 +302,7 @@ pub struct Res<'w, T: Resource> { } // SAFETY: Res only reads a single World resource -unsafe impl ReadOnlySystemParamFetch for ResState {} +unsafe impl<'w, T: Resource> ReadOnlySystemParam for Res<'w, T> {} impl<'w, T: Resource> Debug for Res<'w, T> where @@ -396,12 +390,14 @@ pub struct ResState { } impl<'a, T: Resource> SystemParam for Res<'a, T> { - type Fetch = ResState; + type State = ResState; } // SAFETY: Res ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this Res // conflicts with any prior access, a panic will occur. unsafe impl SystemParamState for ResState { + type Item<'w, 's> = Res<'w, T>; + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { let component_id = world.initialize_resource::(); let combined_access = system_meta.component_access_set.combined_access(); @@ -426,18 +422,14 @@ unsafe impl SystemParamState for ResState { marker: PhantomData, } } -} - -impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for ResState { - type Item = Res<'w, T>; #[inline] - unsafe fn get_param( + unsafe fn get_param<'w, 's>( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { let (ptr, ticks) = world .get_resource_with_ticks(state.component_id) .unwrap_or_else(|| { @@ -463,30 +455,28 @@ impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for ResState { pub struct OptionResState(ResState); impl<'a, T: Resource> SystemParam for Option> { - type Fetch = OptionResState; + type State = OptionResState; } // SAFETY: Only reads a single World resource -unsafe impl ReadOnlySystemParamFetch for OptionResState {} +unsafe impl<'a, T: Resource> ReadOnlySystemParam for Option> {} // SAFETY: this impl defers to `ResState`, which initializes // and validates the correct world access unsafe impl SystemParamState for OptionResState { + type Item<'w, 's> = Option>; + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { Self(ResState::init(world, system_meta)) } -} - -impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for OptionResState { - type Item = Option>; #[inline] - unsafe fn get_param( + unsafe fn get_param<'w, 's>( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { world .get_resource_with_ticks(state.0.component_id) .map(|(ptr, ticks)| Res { @@ -507,12 +497,14 @@ pub struct ResMutState { } impl<'a, T: Resource> SystemParam for ResMut<'a, T> { - type Fetch = ResMutState; + type State = ResMutState; } // SAFETY: Res ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this Res // conflicts with any prior access, a panic will occur. unsafe impl SystemParamState for ResMutState { + type Item<'w, 's> = ResMut<'w, T>; + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { let component_id = world.initialize_resource::(); let combined_access = system_meta.component_access_set.combined_access(); @@ -540,18 +532,14 @@ unsafe impl SystemParamState for ResMutState { marker: PhantomData, } } -} - -impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for ResMutState { - type Item = ResMut<'w, T>; #[inline] - unsafe fn get_param( + unsafe fn get_param<'w, 's>( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { let value = world .get_resource_unchecked_mut_with_id(state.component_id) .unwrap_or_else(|| { @@ -579,27 +567,25 @@ impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for ResMutState { pub struct OptionResMutState(ResMutState); impl<'a, T: Resource> SystemParam for Option> { - type Fetch = OptionResMutState; + type State = OptionResMutState; } // SAFETY: this impl defers to `ResMutState`, which initializes // and validates the correct world access unsafe impl SystemParamState for OptionResMutState { + type Item<'w, 's> = Option>; + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { Self(ResMutState::init(world, system_meta)) } -} - -impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for OptionResMutState { - type Item = Option>; #[inline] - unsafe fn get_param( + unsafe fn get_param<'w, 's>( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { world .get_resource_unchecked_mut_with_id(state.0.component_id) .map(|value| ResMut { @@ -615,14 +601,16 @@ impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for OptionResMutState { } impl<'w, 's> SystemParam for Commands<'w, 's> { - type Fetch = CommandQueue; + type State = CommandQueue; } // SAFETY: Commands only accesses internal state -unsafe impl ReadOnlySystemParamFetch for CommandQueue {} +unsafe impl<'w, 's> ReadOnlySystemParam for Commands<'w, 's> {} // SAFETY: only local state is accessed unsafe impl SystemParamState for CommandQueue { + type Item<'w, 's> = Commands<'w, 's>; + fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { Default::default() } @@ -630,35 +618,33 @@ unsafe impl SystemParamState for CommandQueue { fn apply(&mut self, world: &mut World) { self.apply(world); } -} - -impl<'w, 's> SystemParamFetch<'w, 's> for CommandQueue { - type Item = Commands<'w, 's>; #[inline] - unsafe fn get_param( + unsafe fn get_param<'w, 's>( state: &'s mut Self, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { Commands::new(state, world) } } /// SAFETY: only reads world -unsafe impl ReadOnlySystemParamFetch for WorldState {} +unsafe impl<'w> ReadOnlySystemParam for &'w World {} /// The [`SystemParamState`] of [`&World`](crate::world::World). #[doc(hidden)] pub struct WorldState; impl<'w> SystemParam for &'w World { - type Fetch = WorldState; + type State = WorldState; } // SAFETY: `read_all` access is set and conflicts result in a panic unsafe impl SystemParamState for WorldState { + type Item<'w, 's> = &'w World; + fn init(_world: &mut World, system_meta: &mut SystemMeta) -> Self { let mut access = Access::default(); access.read_all(); @@ -684,16 +670,13 @@ unsafe impl SystemParamState for WorldState { WorldState } -} -impl<'w, 's> SystemParamFetch<'w, 's> for WorldState { - type Item = &'w World; - unsafe fn get_param( + unsafe fn get_param<'w, 's>( _state: &'s mut Self, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { world } } @@ -744,7 +727,7 @@ impl<'w, 's> SystemParamFetch<'w, 's> for WorldState { pub struct Local<'a, T: FromWorld + Send + 'static>(pub(crate) &'a mut T); // SAFETY: Local only accesses internal state -unsafe impl ReadOnlySystemParamFetch for LocalState {} +unsafe impl<'a, T: FromWorld + Send + 'static> ReadOnlySystemParam for Local<'a, T> {} impl<'a, T: FromWorld + Send + Sync + 'static> Debug for Local<'a, T> where @@ -800,26 +783,24 @@ where pub struct LocalState(pub(crate) SyncCell); impl<'a, T: FromWorld + Send + 'static> SystemParam for Local<'a, T> { - type Fetch = LocalState; + type State = LocalState; } // SAFETY: only local state is accessed unsafe impl SystemParamState for LocalState { + type Item<'w, 's> = Local<'s, T>; + fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self { Self(SyncCell::new(T::from_world(world))) } -} - -impl<'w, 's, T: FromWorld + Send + 'static> SystemParamFetch<'w, 's> for LocalState { - type Item = Local<'s, T>; #[inline] - unsafe fn get_param( + unsafe fn get_param<'w, 's>( state: &'s mut Self, _system_meta: &SystemMeta, _world: &'w World, _change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { Local(state.0.get()) } } @@ -881,7 +862,7 @@ impl<'a, T: Component> IntoIterator for &'a RemovedComponents<'a, T> { } // SAFETY: Only reads World components -unsafe impl ReadOnlySystemParamFetch for RemovedComponentsState {} +unsafe impl<'a, T: Component> ReadOnlySystemParam for RemovedComponents<'a, T> {} /// The [`SystemParamState`] of [`RemovedComponents`]. #[doc(hidden)] @@ -891,30 +872,28 @@ pub struct RemovedComponentsState { } impl<'a, T: Component> SystemParam for RemovedComponents<'a, T> { - type Fetch = RemovedComponentsState; + type State = RemovedComponentsState; } // SAFETY: no component access. removed component entity collections can be read in parallel and are // never mutably borrowed during system execution unsafe impl SystemParamState for RemovedComponentsState { + type Item<'w, 's> = RemovedComponents<'w, T>; + fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self { Self { component_id: world.init_component::(), marker: PhantomData, } } -} - -impl<'w, 's, T: Component> SystemParamFetch<'w, 's> for RemovedComponentsState { - type Item = RemovedComponents<'w, T>; #[inline] - unsafe fn get_param( + unsafe fn get_param<'w, 's>( state: &'s mut Self, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { RemovedComponents { world, component_id: state.component_id, @@ -943,7 +922,7 @@ pub struct NonSend<'w, T: 'static> { } // SAFETY: Only reads a single World non-send resource -unsafe impl ReadOnlySystemParamFetch for NonSendState {} +unsafe impl<'w, T> ReadOnlySystemParam for NonSend<'w, T> {} impl<'w, T> Debug for NonSend<'w, T> where @@ -996,12 +975,14 @@ pub struct NonSendState { } impl<'a, T: 'static> SystemParam for NonSend<'a, T> { - type Fetch = NonSendState; + type State = NonSendState; } // SAFETY: NonSendComponentId and ArchetypeComponentId access is applied to SystemMeta. If this // NonSend conflicts with any prior access, a panic will occur. unsafe impl SystemParamState for NonSendState { + type Item<'w, 's> = NonSend<'w, T>; + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { system_meta.set_non_send(); @@ -1028,18 +1009,14 @@ unsafe impl SystemParamState for NonSendState { marker: PhantomData, } } -} - -impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for NonSendState { - type Item = NonSend<'w, T>; #[inline] - unsafe fn get_param( + unsafe fn get_param<'w, 's>( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { world.validate_non_send_access::(); let (ptr, ticks) = world .get_resource_with_ticks(state.component_id) @@ -1066,30 +1043,28 @@ impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for NonSendState { pub struct OptionNonSendState(NonSendState); impl<'w, T: 'static> SystemParam for Option> { - type Fetch = OptionNonSendState; + type State = OptionNonSendState; } // SAFETY: Only reads a single non-send resource -unsafe impl ReadOnlySystemParamFetch for OptionNonSendState {} +unsafe impl<'w, T: 'static> ReadOnlySystemParam for Option> {} // SAFETY: this impl defers to `NonSendState`, which initializes // and validates the correct world access unsafe impl SystemParamState for OptionNonSendState { + type Item<'w, 's> = Option>; + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { Self(NonSendState::init(world, system_meta)) } -} - -impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for OptionNonSendState { - type Item = Option>; #[inline] - unsafe fn get_param( + unsafe fn get_param<'w, 's>( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { world.validate_non_send_access::(); world .get_resource_with_ticks(state.0.component_id) @@ -1110,12 +1085,14 @@ pub struct NonSendMutState { } impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> { - type Fetch = NonSendMutState; + type State = NonSendMutState; } // SAFETY: NonSendMut ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this // NonSendMut conflicts with any prior access, a panic will occur. unsafe impl SystemParamState for NonSendMutState { + type Item<'w, 's> = NonSendMut<'w, T>; + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { system_meta.set_non_send(); @@ -1145,18 +1122,14 @@ unsafe impl SystemParamState for NonSendMutState { marker: PhantomData, } } -} - -impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for NonSendMutState { - type Item = NonSendMut<'w, T>; #[inline] - unsafe fn get_param( + unsafe fn get_param<'w, 's>( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { world.validate_non_send_access::(); let (ptr, ticks) = world .get_resource_with_ticks(state.component_id) @@ -1180,27 +1153,25 @@ impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for NonSendMutState { pub struct OptionNonSendMutState(NonSendMutState); impl<'a, T: 'static> SystemParam for Option> { - type Fetch = OptionNonSendMutState; + type State = OptionNonSendMutState; } // SAFETY: this impl defers to `NonSendMutState`, which initializes // and validates the correct world access unsafe impl SystemParamState for OptionNonSendMutState { + type Item<'w, 's> = Option>; + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { Self(NonSendMutState::init(world, system_meta)) } -} - -impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for OptionNonSendMutState { - type Item = Option>; #[inline] - unsafe fn get_param( + unsafe fn get_param<'w, 's>( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { world.validate_non_send_access::(); world .get_resource_with_ticks(state.0.component_id) @@ -1212,11 +1183,11 @@ impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for OptionNonSendMutState { } impl<'a> SystemParam for &'a Archetypes { - type Fetch = ArchetypesState; + type State = ArchetypesState; } // SAFETY: Only reads World archetypes -unsafe impl ReadOnlySystemParamFetch for ArchetypesState {} +unsafe impl<'a> ReadOnlySystemParam for &'a Archetypes {} /// The [`SystemParamState`] of [`Archetypes`]. #[doc(hidden)] @@ -1224,31 +1195,29 @@ pub struct ArchetypesState; // SAFETY: no component value access unsafe impl SystemParamState for ArchetypesState { + type Item<'w, 's> = &'w Archetypes; + fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { Self } -} - -impl<'w, 's> SystemParamFetch<'w, 's> for ArchetypesState { - type Item = &'w Archetypes; #[inline] - unsafe fn get_param( + unsafe fn get_param<'w, 's>( _state: &'s mut Self, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { world.archetypes() } } impl<'a> SystemParam for &'a Components { - type Fetch = ComponentsState; + type State = ComponentsState; } // SAFETY: Only reads World components -unsafe impl ReadOnlySystemParamFetch for ComponentsState {} +unsafe impl<'a> ReadOnlySystemParam for &'a Components {} /// The [`SystemParamState`] of [`Components`]. #[doc(hidden)] @@ -1256,31 +1225,29 @@ pub struct ComponentsState; // SAFETY: no component value access unsafe impl SystemParamState for ComponentsState { + type Item<'w, 's> = &'w Components; + fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { Self } -} - -impl<'w, 's> SystemParamFetch<'w, 's> for ComponentsState { - type Item = &'w Components; #[inline] - unsafe fn get_param( + unsafe fn get_param<'w, 's>( _state: &'s mut Self, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { world.components() } } impl<'a> SystemParam for &'a Entities { - type Fetch = EntitiesState; + type State = EntitiesState; } // SAFETY: Only reads World entities -unsafe impl ReadOnlySystemParamFetch for EntitiesState {} +unsafe impl<'a> ReadOnlySystemParam for &'a Entities {} /// The [`SystemParamState`] of [`Entities`]. #[doc(hidden)] @@ -1288,31 +1255,29 @@ pub struct EntitiesState; // SAFETY: no component value access unsafe impl SystemParamState for EntitiesState { + type Item<'w, 's> = &'w Entities; + fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { Self } -} - -impl<'w, 's> SystemParamFetch<'w, 's> for EntitiesState { - type Item = &'w Entities; #[inline] - unsafe fn get_param( + unsafe fn get_param<'w, 's>( _state: &'s mut Self, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { world.entities() } } impl<'a> SystemParam for &'a Bundles { - type Fetch = BundlesState; + type State = BundlesState; } // SAFETY: Only reads World bundles -unsafe impl ReadOnlySystemParamFetch for BundlesState {} +unsafe impl<'a> ReadOnlySystemParam for &'a Bundles {} /// The [`SystemParamState`] of [`Bundles`]. #[doc(hidden)] @@ -1320,21 +1285,19 @@ pub struct BundlesState; // SAFETY: no component value access unsafe impl SystemParamState for BundlesState { + type Item<'w, 's> = &'w Bundles; + fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { Self } -} - -impl<'w, 's> SystemParamFetch<'w, 's> for BundlesState { - type Item = &'w Bundles; #[inline] - unsafe fn get_param( + unsafe fn get_param<'w, 's>( _state: &'s mut Self, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { world.bundles() } } @@ -1369,10 +1332,10 @@ impl SystemChangeTick { } // SAFETY: Only reads internal system state -unsafe impl ReadOnlySystemParamFetch for SystemChangeTickState {} +unsafe impl ReadOnlySystemParam for SystemChangeTick {} impl SystemParam for SystemChangeTick { - type Fetch = SystemChangeTickState; + type State = SystemChangeTickState; } /// The [`SystemParamState`] of [`SystemChangeTick`]. @@ -1381,20 +1344,18 @@ pub struct SystemChangeTickState {} // SAFETY: `SystemParamTickState` doesn't require any world access unsafe impl SystemParamState for SystemChangeTickState { + type Item<'w, 's> = SystemChangeTick; + fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { Self {} } -} - -impl<'w, 's> SystemParamFetch<'w, 's> for SystemChangeTickState { - type Item = SystemChangeTick; - unsafe fn get_param( + unsafe fn get_param<'w, 's>( _state: &'s mut Self, system_meta: &SystemMeta, _world: &'w World, change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { SystemChangeTick { last_change_tick: system_meta.last_change_tick, change_tick, @@ -1450,11 +1411,11 @@ impl<'s> std::fmt::Display for SystemName<'s> { } impl<'s> SystemParam for SystemName<'s> { - type Fetch = SystemNameState; + type State = SystemNameState; } // SAFETY: Only reads internal system state -unsafe impl ReadOnlySystemParamFetch for SystemNameState {} +unsafe impl<'s> ReadOnlySystemParam for SystemName<'s> {} /// The [`SystemParamState`] of [`SystemName`]. #[doc(hidden)] @@ -1464,23 +1425,21 @@ pub struct SystemNameState { // SAFETY: no component value access unsafe impl SystemParamState for SystemNameState { + type Item<'w, 's> = SystemName<'s>; + fn init(_world: &mut World, system_meta: &mut SystemMeta) -> Self { Self { name: system_meta.name.clone(), } } -} - -impl<'w, 's> SystemParamFetch<'w, 's> for SystemNameState { - type Item = SystemName<'s>; #[inline] - unsafe fn get_param( + unsafe fn get_param<'w, 's>( state: &'s mut Self, _system_meta: &SystemMeta, _world: &'w World, _change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { SystemName { name: state.name.as_ref(), } @@ -1490,35 +1449,19 @@ impl<'w, 's> SystemParamFetch<'w, 's> for SystemNameState { macro_rules! impl_system_param_tuple { ($($param: ident),*) => { impl<$($param: SystemParam),*> SystemParam for ($($param,)*) { - type Fetch = ($($param::Fetch,)*); + type State = ($($param::State,)*); } - // SAFETY: tuple consists only of ReadOnlySystemParamFetches - unsafe impl<$($param: ReadOnlySystemParamFetch),*> ReadOnlySystemParamFetch for ($($param,)*) {} + // SAFETY: tuple consists only of ReadOnlySystemParams + unsafe impl<$($param: ReadOnlySystemParam),*> ReadOnlySystemParam for ($($param,)*) {} - #[allow(unused_variables)] - #[allow(non_snake_case)] - impl<'w, 's, $($param: SystemParamFetch<'w, 's>),*> SystemParamFetch<'w, 's> for ($($param,)*) { - type Item = ($($param::Item,)*); - - #[inline] - #[allow(clippy::unused_unit)] - unsafe fn get_param( - state: &'s mut Self, - system_meta: &SystemMeta, - world: &'w World, - change_tick: u32, - ) -> Self::Item { - - let ($($param,)*) = state; - ($($param::get_param($param, system_meta, world, change_tick),)*) - } - } // SAFETY: implementors of each `SystemParamState` in the tuple have validated their impls #[allow(clippy::undocumented_unsafe_blocks)] // false positive by clippy #[allow(non_snake_case)] unsafe impl<$($param: SystemParamState),*> SystemParamState for ($($param,)*) { + type Item<'w, 's> = ($($param::Item::<'w, 's>,)*); + #[inline] fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { (($($param::init(_world, _system_meta),)*)) @@ -1535,6 +1478,19 @@ macro_rules! impl_system_param_tuple { let ($($param,)*) = self; $($param.apply(_world);)* } + + #[inline] + #[allow(clippy::unused_unit)] + unsafe fn get_param<'w, 's>( + state: &'s mut Self, + _system_meta: &SystemMeta, + _world: &'w World, + _change_tick: u32, + ) -> Self::Item<'w, 's> { + + let ($($param,)*) = state; + ($($param::get_param($param, _system_meta, _world, _change_tick),)*) + } } }; } @@ -1553,7 +1509,7 @@ pub mod lifetimeless { /// A helper for using system parameters in generic contexts /// /// This type is a [`SystemParam`] adapter which always has -/// `Self::Fetch::Item == Self` (ignoring lifetimes for brevity), +/// `Self::State::Item == Self` (ignoring lifetimes for brevity), /// no matter the argument [`SystemParam`] (`P`) (other than /// that `P` must be `'static`) /// @@ -1592,7 +1548,7 @@ pub mod lifetimeless { /// fn do_thing_generically(t: T) {} /// /// #[derive(SystemParam)] -/// struct GenericParam<'w,'s, T: SystemParam> { +/// struct GenericParam<'w, 's, T: SystemParam> { /// field: T, /// #[system_param(ignore)] /// // Use the lifetimes in this type, or they will be unbound. @@ -1631,39 +1587,23 @@ impl<'w, 's, P: SystemParam> StaticSystemParam<'w, 's, P> { pub struct StaticSystemParamState(S, PhantomData P>); // SAFETY: This doesn't add any more reads, and the delegated fetch confirms it -unsafe impl ReadOnlySystemParamFetch - for StaticSystemParamState +unsafe impl<'w, 's, P: ReadOnlySystemParam + 'static> ReadOnlySystemParam + for StaticSystemParam<'w, 's, P> { } impl<'world, 'state, P: SystemParam + 'static> SystemParam for StaticSystemParam<'world, 'state, P> { - type Fetch = StaticSystemParamState; -} - -impl<'world, 'state, S: SystemParamFetch<'world, 'state>, P: SystemParam + 'static> - SystemParamFetch<'world, 'state> for StaticSystemParamState -where - P: SystemParam, -{ - type Item = StaticSystemParam<'world, 'state, P>; - - unsafe fn get_param( - state: &'state mut Self, - system_meta: &SystemMeta, - world: &'world World, - change_tick: u32, - ) -> Self::Item { - // SAFETY: We properly delegate SystemParamState - StaticSystemParam(S::get_param(&mut state.0, system_meta, world, change_tick)) - } + type State = StaticSystemParamState; } // SAFETY: all methods are just delegated to `S`'s `SystemParamState` implementation -unsafe impl SystemParamState +unsafe impl + 'static> SystemParamState for StaticSystemParamState { + type Item<'world, 'state> = StaticSystemParam<'world, 'state, P>; + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { Self(S::init(world, system_meta), PhantomData) } @@ -1675,6 +1615,16 @@ unsafe impl SystemParamState fn apply(&mut self, world: &mut World) { self.0.apply(world); } + + unsafe fn get_param<'world, 'state>( + state: &'state mut Self, + system_meta: &SystemMeta, + world: &'world World, + change_tick: u32, + ) -> Self::Item<'world, 'state> { + // SAFETY: We properly delegate SystemParamState + StaticSystemParam(S::get_param(&mut state.0, system_meta, world, change_tick)) + } } #[cfg(test)] diff --git a/crates/bevy_ecs_compile_fail_tests/tests/ui/system_param_derive_readonly.rs b/crates/bevy_ecs_compile_fail_tests/tests/ui/system_param_derive_readonly.rs index 048a1557693f8..7e2baeda2535c 100644 --- a/crates/bevy_ecs_compile_fail_tests/tests/ui/system_param_derive_readonly.rs +++ b/crates/bevy_ecs_compile_fail_tests/tests/ui/system_param_derive_readonly.rs @@ -1,5 +1,5 @@ use bevy_ecs::prelude::*; -use bevy_ecs::system::{ReadOnlySystemParamFetch, SystemParam, SystemState}; +use bevy_ecs::system::{ReadOnlySystemParam, SystemParam, SystemState}; #[derive(Component)] struct Foo; @@ -18,8 +18,8 @@ fn main() { assert_readonly::(); } -fn assert_readonly() +fn assert_readonly

() where -

::Fetch: ReadOnlySystemParamFetch, + P: ReadOnlySystemParam, { } diff --git a/crates/bevy_ecs_compile_fail_tests/tests/ui/system_param_derive_readonly.stderr b/crates/bevy_ecs_compile_fail_tests/tests/ui/system_param_derive_readonly.stderr index 0878af9e4bdd9..e1cee3b0fd2fe 100644 --- a/crates/bevy_ecs_compile_fail_tests/tests/ui/system_param_derive_readonly.stderr +++ b/crates/bevy_ecs_compile_fail_tests/tests/ui/system_param_derive_readonly.stderr @@ -1,8 +1,8 @@ warning: unused import: `SystemState` - --> tests/ui/system_param_derive_readonly.rs:2:63 + --> tests/ui/system_param_derive_readonly.rs:2:58 | -2 | use bevy_ecs::system::{ReadOnlySystemParamFetch, SystemParam, SystemState}; - | ^^^^^^^^^^^ +2 | use bevy_ecs::system::{ReadOnlySystemParam, SystemParam, SystemState}; + | ^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default @@ -23,14 +23,14 @@ error[E0277]: the trait bound `&'static mut Foo: ReadOnlyWorldQuery` is not sati (F0, F1, F2, F3, F4, F5, F6) and $N others = note: `ReadOnlyWorldQuery` is implemented for `&'static Foo`, but not for `&'static mut Foo` - = note: required for `QueryState<&'static mut Foo>` to implement `ReadOnlySystemParamFetch` - = note: 2 redundant requirements hidden - = note: required for `FetchState<(QueryState<&'static mut Foo>,)>` to implement `ReadOnlySystemParamFetch` + = note: required for `bevy_ecs::system::Query<'_, '_, &'static mut Foo>` to implement `ReadOnlySystemParam` + = note: 1 redundant requirement hidden + = note: required for `Mutable<'_, '_>` to implement `ReadOnlySystemParam` note: required by a bound in `assert_readonly` - --> tests/ui/system_param_derive_readonly.rs:23:32 + --> tests/ui/system_param_derive_readonly.rs:23:8 | -21 | fn assert_readonly() +21 | fn assert_readonly

() | --------------- required by a bound in this 22 | where -23 |

::Fetch: ReadOnlySystemParamFetch, - | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_readonly` +23 | P: ReadOnlySystemParam, + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_readonly` diff --git a/crates/bevy_render/src/extract_param.rs b/crates/bevy_render/src/extract_param.rs index cdfb462c2324b..b3d4ba665a55a 100644 --- a/crates/bevy_render/src/extract_param.rs +++ b/crates/bevy_render/src/extract_param.rs @@ -2,8 +2,8 @@ use crate::MainWorld; use bevy_ecs::{ prelude::*, system::{ - ReadOnlySystemParamFetch, ResState, SystemMeta, SystemParam, SystemParamFetch, - SystemParamItem, SystemParamState, SystemState, + ReadOnlySystemParam, ResState, SystemMeta, SystemParam, SystemParamItem, SystemParamState, + SystemState, }, }; use std::ops::{Deref, DerefMut}; @@ -42,18 +42,18 @@ use std::ops::{Deref, DerefMut}; /// /// [`RenderStage::Extract`]: crate::RenderStage::Extract /// [Window]: bevy_window::Window -pub struct Extract<'w, 's, P: SystemParam + 'static> +pub struct Extract<'w, 's, P> where - P::Fetch: ReadOnlySystemParamFetch, + P: ReadOnlySystemParam + 'static, { - item: >::Item, + item: SystemParamItem<'w, 's, P>, } -impl<'w, 's, P: SystemParam> SystemParam for Extract<'w, 's, P> +impl<'w, 's, P> SystemParam for Extract<'w, 's, P> where - P::Fetch: ReadOnlySystemParamFetch, + P: ReadOnlySystemParam, { - type Fetch = ExtractState

; + type State = ExtractState

; } #[doc(hidden)] @@ -64,7 +64,12 @@ pub struct ExtractState { // SAFETY: only accesses MainWorld resource with read only system params using ResState, // which is initialized in init() -unsafe impl SystemParamState for ExtractState

{ +unsafe impl SystemParamState for ExtractState

+where + P: ReadOnlySystemParam + 'static, +{ + type Item<'w, 's> = Extract<'w, 's, P>; + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { let mut main_world = world.resource_mut::(); Self { @@ -72,20 +77,13 @@ unsafe impl SystemParamState for ExtractState

{ main_world_state: ResState::init(world, system_meta), } } -} - -impl<'w, 's, P: SystemParam + 'static> SystemParamFetch<'w, 's> for ExtractState

-where - P::Fetch: ReadOnlySystemParamFetch, -{ - type Item = Extract<'w, 's, P>; - unsafe fn get_param( + unsafe fn get_param<'w, 's>( state: &'s mut Self, system_meta: &SystemMeta, world: &'w World, change_tick: u32, - ) -> Self::Item { + ) -> Self::Item<'w, 's> { let main_world = ResState::::get_param( &mut state.main_world_state, system_meta, @@ -99,9 +97,9 @@ where impl<'w, 's, P: SystemParam> Deref for Extract<'w, 's, P> where - P::Fetch: ReadOnlySystemParamFetch, + P: ReadOnlySystemParam, { - type Target = >::Item; + type Target = SystemParamItem<'w, 's, P>; #[inline] fn deref(&self) -> &Self::Target { @@ -111,7 +109,7 @@ where impl<'w, 's, P: SystemParam> DerefMut for Extract<'w, 's, P> where - P::Fetch: ReadOnlySystemParamFetch, + P: ReadOnlySystemParam, { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { @@ -121,7 +119,7 @@ where impl<'a, 'w, 's, P: SystemParam> IntoIterator for &'a Extract<'w, 's, P> where - P::Fetch: ReadOnlySystemParamFetch, + P: ReadOnlySystemParam, &'a SystemParamItem<'w, 's, P>: IntoIterator, { type Item = <&'a SystemParamItem<'w, 's, P> as IntoIterator>::Item; diff --git a/crates/bevy_render/src/render_phase/draw.rs b/crates/bevy_render/src/render_phase/draw.rs index 1b044197fddca..67ff987b7972d 100644 --- a/crates/bevy_render/src/render_phase/draw.rs +++ b/crates/bevy_render/src/render_phase/draw.rs @@ -7,7 +7,7 @@ use bevy_ecs::{ all_tuples, entity::Entity, system::{ - lifetimeless::SRes, ReadOnlySystemParamFetch, Resource, SystemParam, SystemParamItem, + lifetimeless::SRes, ReadOnlySystemParam, Resource, SystemParam, SystemParamItem, SystemState, }, world::World, @@ -325,7 +325,7 @@ impl> RenderCommandState { impl + Send + Sync + 'static> Draw

for RenderCommandState where - ::Fetch: ReadOnlySystemParamFetch, + C::Param: ReadOnlySystemParam, { /// Prepares the ECS parameters for the wrapped [`RenderCommand`] and then renders it. fn draw<'w>( @@ -348,7 +348,7 @@ pub trait AddRenderCommand { &mut self, ) -> &mut Self where - ::Fetch: ReadOnlySystemParamFetch; + C::Param: ReadOnlySystemParam; } impl AddRenderCommand for App { @@ -356,7 +356,7 @@ impl AddRenderCommand for App { &mut self, ) -> &mut Self where - ::Fetch: ReadOnlySystemParamFetch, + C::Param: ReadOnlySystemParam, { let draw_function = RenderCommandState::::new(&mut self.world); let draw_functions = self