From d38a4db3d0c7157f1d9428fcfd1a9a1983dc865b Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 7 Dec 2022 08:12:05 -0500 Subject: [PATCH 01/49] simplify `Extract` bounds --- crates/bevy_render/src/extract_param.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/crates/bevy_render/src/extract_param.rs b/crates/bevy_render/src/extract_param.rs index b3d4ba665a55a..f854938d8e3a6 100644 --- a/crates/bevy_render/src/extract_param.rs +++ b/crates/bevy_render/src/extract_param.rs @@ -49,10 +49,7 @@ where item: SystemParamItem<'w, 's, P>, } -impl<'w, 's, P> SystemParam for Extract<'w, 's, P> -where - P: ReadOnlySystemParam, -{ +impl<'w, 's, P: ReadOnlySystemParam> SystemParam for Extract<'w, 's, P> { type State = ExtractState

; } @@ -64,10 +61,7 @@ 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

-where - P: ReadOnlySystemParam + 'static, -{ +unsafe impl SystemParamState for ExtractState

{ type Item<'w, 's> = Extract<'w, 's, P>; fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { From 5913ea0f14d5c23ac8089182868c83bd13c03914 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Tue, 6 Dec 2022 19:01:52 -0500 Subject: [PATCH 02/49] flatten `SystemParam` --- crates/bevy_ecs/macros/src/lib.rs | 112 +++-- .../src/system/commands/parallel_scope.rs | 23 +- crates/bevy_ecs/src/system/function_system.rs | 27 +- crates/bevy_ecs/src/system/system_param.rs | 411 ++++++++---------- crates/bevy_render/src/extract_param.rs | 43 +- 5 files changed, 271 insertions(+), 345 deletions(-) diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index 010a0e33108de..cc8533ff647a4 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -216,7 +216,6 @@ 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_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() { @@ -228,7 +227,7 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream { // Conflicting params in ParamSet are not accessible at the same time // ParamSets are guaranteed to not conflict with other SystemParams unsafe { - <#param::State as SystemParamState>::get_param(&mut self.param_states.#index, &self.system_meta, self.world, self.change_tick) + <#param as SystemParam>::get_param(&mut self.param_states.#index, &self.system_meta, self.world, self.change_tick) } } }); @@ -236,36 +235,25 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream { for param_count in 1..=max_params { let param = ¶ms[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,)*)> + unsafe impl<'_w, '_s, #(#param: SystemParam,)*> SystemParam for ParamSet<'_w, '_s, (#(#param,)*)> + where #( + for<'w, 's> #param::Item::<'w, 's>: SystemParam, + )* { type State = ParamSetState<(#(#param::State,)*)>; - } - - // SAFETY: All parameters are constrained to ReadOnlyState, so World is only read - - 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_state: SystemParamState,)*> SystemParamState for ParamSetState<(#(#param_state,)*)> - { - type Item<'w, 's> = ParamSet<'w, 's, (#(<#param_state as SystemParamState>::Item::<'w, 's>,)*)>; + type Item<'w, 's> = ParamSet<'w, 's, (#(#param::Item<'w, 's>,)*)>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { #( // 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_state::init(world, &mut #meta); - let #param = #param_state::init(world, &mut system_meta.clone()); + #param::init(world, &mut #meta); + let #param = #param::init(world, &mut system_meta.clone()); )* #( system_meta @@ -278,20 +266,20 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream { ParamSetState((#(#param,)*)) } - fn new_archetype(&mut self, archetype: &Archetype, system_meta: &mut SystemMeta) { - let (#(#param,)*) = &mut self.0; + fn new_archetype(state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta) { + let (#(#param,)*) = &mut state.0; #( - #param.new_archetype(archetype, system_meta); + <#param as SystemParam>::new_archetype(#param, archetype, system_meta); )* } - fn apply(&mut self, world: &mut World) { - self.0.apply(world) + fn apply(state: &mut Self::State, world: &mut World) { + <(#(#param,)*)>::apply(&mut state.0, world); } #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self, + state: &'s mut Self::State, system_meta: &SystemMeta, world: &'w World, change_tick: u32, @@ -305,9 +293,13 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream { } } + // SAFETY: All parameters are constrained to ReadOnlyState, so World is only read + unsafe impl<'w, 's, #(#param,)*> ReadOnlySystemParam for ParamSet<'w, 's, (#(#param,)*)> + where #(#param: ReadOnlySystemParam,)* + { } + impl<'w, 's, #(#param: SystemParam,)*> ParamSet<'w, 's, (#(#param,)*)> { - #(#param_fn_mut)* } })); @@ -401,6 +393,12 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { .filter(|g| matches!(g, GenericParam::Type(_))) .collect(); + let mut shadowed_lifetimes: Vec<_> = generics.lifetimes().map(|x| x.lifetime.clone()).collect(); + for lifetime in &mut shadowed_lifetimes { + let shadowed_ident = format_ident!("_{}", lifetime.ident); + lifetime.ident = shadowed_ident; + } + let mut punctuated_generics = Punctuated::<_, Token![,]>::new(); punctuated_generics.extend(lifetimeless_generics.iter().map(|g| match g { GenericParam::Type(g) => GenericParam::Type(TypeParam { @@ -434,56 +432,56 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { // 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 State = State<'w, 's, #punctuated_generic_idents>; - } - - #[doc(hidden)] - type State<'w, 's, #punctuated_generic_idents> = FetchState< - (#(<#field_types as #path::system::SystemParam>::State,)*), - #punctuated_generic_idents - >; - - #[doc(hidden)] - #state_struct_visibility struct FetchState { - state: TSystemParamState, - marker: std::marker::PhantomData(#punctuated_generic_idents)> - } - - unsafe impl<'__w, '__s, #punctuated_generics> #path::system::SystemParamState for - State<'__w, '__s, #punctuated_generic_idents> - #where_clause { + unsafe impl<'_w, '_s, #punctuated_generics> #path::system::SystemParam for #struct_name <#(#shadowed_lifetimes,)* #punctuated_generic_idents> #where_clause { + type State = State<'_w, '_s, #punctuated_generic_idents>; type Item<'w, 's> = #struct_name #ty_generics; - fn init(world: &mut #path::world::World, system_meta: &mut #path::system::SystemMeta) -> Self { - Self { - state: #path::system::SystemParamState::init(world, system_meta), + fn init(world: &mut #path::world::World, system_meta: &mut #path::system::SystemMeta) -> Self::State { + FetchState { + state: >::init(world, system_meta), marker: std::marker::PhantomData, } } - fn new_archetype(&mut self, archetype: &#path::archetype::Archetype, system_meta: &mut #path::system::SystemMeta) { - self.state.new_archetype(archetype, system_meta) + fn new_archetype(state: &mut Self::State, archetype: &#path::archetype::Archetype, system_meta: &mut #path::system::SystemMeta) { + >::new_archetype(&mut state.state, archetype, system_meta) } - fn apply(&mut self, world: &mut #path::world::World) { - self.state.apply(world) + fn apply(state: &mut Self::State, world: &mut #path::world::World) { + >::apply(&mut state.state, world); } unsafe fn get_param<'w, 's>( - state: &'s mut Self, + state: &'s mut Self::State, system_meta: &#path::system::SystemMeta, world: &'w #path::world::World, change_tick: u32, ) -> Self::Item<'w, 's> { #struct_name { - #(#fields: <<#field_types as #path::system::SystemParam>::State as #path::system::SystemParamState>::get_param(&mut state.state.#field_indices, system_meta, world, change_tick),)* + #(#fields: <#field_types as #path::system::SystemParam>::get_param(&mut state.state.#field_indices, system_meta, world, change_tick),)* #(#ignored_fields: <#ignored_field_types>::default(),)* } } } - // Safety: Each field is `ReadOnlySystemParam`, so this can only read from the `World` + #[doc(hidden)] + type State<'w, 's, #punctuated_generic_idents> = FetchState< + (#(<#field_types as #path::system::SystemParam>::State,)*), + #punctuated_generic_idents + >; + + #[doc(hidden)] + type FieldsTuple<'w, 's, #punctuated_generic_idents> = ( + #(#field_types,)* + ); + + #[doc(hidden)] + #state_struct_visibility struct FetchState { + state: TSystemParamState, + marker: std::marker::PhantomData(#punctuated_generic_idents)> + } + + // Safety: The `ParamState` 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 5fccd74228061..c980b81546d39 100644 --- a/crates/bevy_ecs/src/system/commands/parallel_scope.rs +++ b/crates/bevy_ecs/src/system/commands/parallel_scope.rs @@ -2,11 +2,7 @@ use std::cell::Cell; use thread_local::ThreadLocal; -use crate::{ - entity::Entities, - prelude::World, - system::{SystemParam, SystemParamState}, -}; +use crate::{entity::Entities, prelude::World, system::SystemParam}; use super::{CommandQueue, Commands}; @@ -48,26 +44,23 @@ pub struct ParallelCommands<'w, 's> { entities: &'w Entities, } -impl SystemParam for ParallelCommands<'_, '_> { - type State = ParallelCommandsState; -} - // SAFETY: no component or resource access to report -unsafe impl SystemParamState for ParallelCommandsState { +unsafe impl SystemParam for ParallelCommands<'_, '_> { + type State = ParallelCommandsState; type Item<'w, 's> = ParallelCommands<'w, 's>; - fn init(_: &mut World, _: &mut crate::system::SystemMeta) -> Self { - Self::default() + fn init(_: &mut World, _: &mut crate::system::SystemMeta) -> Self::State { + ParallelCommandsState::default() } - fn apply(&mut self, world: &mut World) { - for cq in &mut self.thread_local_storage { + fn apply(state: &mut Self::State, world: &mut World) { + for cq in &mut state.thread_local_storage { cq.get_mut().apply(world); } } unsafe fn get_param<'w, 's>( - state: &'s mut Self, + state: &'s mut Self::State, _: &crate::system::SystemMeta, world: &'w World, _: u32, diff --git a/crates/bevy_ecs/src/system/function_system.rs b/crates/bevy_ecs/src/system/function_system.rs index 3a4c9006ae6d6..b5ae963bb23ac 100644 --- a/crates/bevy_ecs/src/system/function_system.rs +++ b/crates/bevy_ecs/src/system/function_system.rs @@ -5,10 +5,7 @@ use crate::{ prelude::FromWorld, query::{Access, FilteredAccessSet}, schedule::{SystemLabel, SystemLabelId}, - system::{ - check_system_change_tick, ReadOnlySystemParam, System, SystemParam, SystemParamItem, - SystemParamState, - }, + system::{check_system_change_tick, ReadOnlySystemParam, System, SystemParam, SystemParamItem}, world::{World, WorldId}, }; use bevy_ecs_macros::all_tuples; @@ -144,7 +141,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, @@ -182,7 +179,7 @@ impl SystemState { /// This function should be called manually after the values returned by [`SystemState::get`] and [`SystemState::get_mut`] /// are finished being used. pub fn apply(&mut self, world: &mut World) { - self.param_state.apply(world); + Param::apply(&mut self.param_state, world); } #[inline] @@ -198,7 +195,8 @@ impl SystemState { let archetype_index_range = old_generation.value()..new_generation.value(); for archetype_index in archetype_index_range { - self.param_state.new_archetype( + Param::new_archetype( + &mut self.param_state, &archetypes[ArchetypeId::new(archetype_index)], &mut self.meta, ); @@ -217,7 +215,7 @@ impl SystemState { world: &'w World, ) -> 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, @@ -394,7 +392,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 = ::State::get_param( + let params = ::get_param( self.param_state.as_mut().expect(Self::PARAM_MESSAGE), &self.system_meta, world, @@ -416,17 +414,14 @@ where #[inline] fn apply_buffers(&mut self, world: &mut World) { let param_state = self.param_state.as_mut().expect(Self::PARAM_MESSAGE); - param_state.apply(world); + Param::apply(param_state, world); } #[inline] 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( - world, - &mut self.system_meta, - )); + self.param_state = Some(::init(world, &mut self.system_meta)); } fn update_archetype_component_access(&mut self, world: &World) { @@ -437,7 +432,9 @@ where let archetype_index_range = old_generation.value()..new_generation.value(); for archetype_index in archetype_index_range { - self.param_state.as_mut().unwrap().new_archetype( + let param_state = self.param_state.as_mut().unwrap(); + Param::new_archetype( + param_state, &archetypes[ArchetypeId::new(archetype_index)], &mut self.system_meta, ); diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index c9ef8ab840eb3..2537462bf3dfc 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -121,13 +121,6 @@ use std::{ /// /// [`SyncCell`]: bevy_utils::synccell::SyncCell /// [`Exclusive`]: https://doc.rust-lang.org/nightly/std/sync/struct.Exclusive.html -pub trait SystemParam: Sized { - type State: SystemParamState; -} - -pub type SystemParamItem<'w, 's, P> = <

::State as SystemParamState>::Item<'w, 's>; - -/// The state of a [`SystemParam`]. /// /// # Safety /// @@ -135,20 +128,29 @@ pub type SystemParamItem<'w, 's, P> = <

::State as SystemParamS /// [`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 { - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self; +pub unsafe trait SystemParam: Sized { + type State: Send + Sync + 'static; + type Item<'world, 'state>; + + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State; + #[inline] - fn new_archetype(&mut self, _archetype: &Archetype, _system_meta: &mut SystemMeta) {} + fn new_archetype( + _state: &mut Self::State, + _archetype: &Archetype, + _system_meta: &mut SystemMeta, + ) { + } + #[inline] - fn apply(&mut self, _world: &mut World) {} + fn apply(_state: &mut Self::State, _world: &mut World) {} - 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<'world, 'state>( - state: &'state mut Self, + state: &'state mut Self::State, system_meta: &SystemMeta, world: &'world World, change_tick: u32, @@ -161,11 +163,7 @@ pub unsafe trait SystemParamState: Send + Sync + 'static { /// 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 State = QueryState; -} +pub type SystemParamItem<'w, 's, P> =

::Item<'w, 's>; // SAFETY: QueryState is constrained to read-only fetches, so it only reads World. unsafe impl<'w, 's, Q: ReadOnlyWorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> @@ -173,14 +171,14 @@ unsafe impl<'w, 's, Q: ReadOnlyWorldQuery + 'static, F: ReadOnlyWorldQuery + 'st { } -// SAFETY: Relevant query ComponentId and ArchetypeComponentId access is applied to SystemMeta. If -// this QueryState conflicts with any prior access, a panic will occur. -unsafe impl SystemParamState - for QueryState +// SAFETY: QueryState is constrained to read-only fetches, so it only reads World. +unsafe impl<'_w, '_s, Q: WorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> SystemParam + for Query<'_w, '_s, Q, F> { + type State = QueryState; type Item<'w, 's> = Query<'w, 's, Q, F>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { let state = QueryState::new(world); assert_component_access_compatibility( &system_meta.name, @@ -199,16 +197,16 @@ unsafe impl SystemPara state } - fn new_archetype(&mut self, archetype: &Archetype, system_meta: &mut SystemMeta) { - self.new_archetype(archetype); + fn new_archetype(state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta) { + state.new_archetype(archetype); system_meta .archetype_component_access - .extend(&self.archetype_component_access); + .extend(&state.archetype_component_access); } #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self, + state: &'s mut Self::State, system_meta: &SystemMeta, world: &'w World, change_tick: u32, @@ -245,7 +243,7 @@ pub struct ParamSet<'w, 's, T: SystemParam> { change_tick: u32, } /// The [`SystemParamState`] of [`ParamSet`]. -pub struct ParamSetState(T); +pub struct ParamSetState(T); impl_param_set!(); @@ -301,9 +299,6 @@ pub struct Res<'w, T: Resource> { change_tick: u32, } -// SAFETY: Res only reads a single World resource -unsafe impl<'w, T: Resource> ReadOnlySystemParam for Res<'w, T> {} - impl<'w, T: Resource> Debug for Res<'w, T> where T: Debug, @@ -389,16 +384,16 @@ pub struct ResState { marker: PhantomData, } -impl<'a, T: Resource> SystemParam for Res<'a, T> { - type State = ResState; -} +// SAFETY: Res only reads a single World resource +unsafe impl<'a, T: Resource> ReadOnlySystemParam for Res<'a, T> {} // 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 { +unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> { + type State = ResState; type Item<'w, 's> = Res<'w, T>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { let component_id = world.initialize_resource::(); let combined_access = system_meta.component_access_set.combined_access(); assert!( @@ -417,7 +412,7 @@ unsafe impl SystemParamState for ResState { system_meta .archetype_component_access .add_read(archetype_component_id); - Self { + ResState { component_id, marker: PhantomData, } @@ -425,7 +420,7 @@ unsafe impl SystemParamState for ResState { #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self, + state: &'s mut Self::State, system_meta: &SystemMeta, world: &'w World, change_tick: u32, @@ -454,25 +449,22 @@ unsafe impl SystemParamState for ResState { #[doc(hidden)] pub struct OptionResState(ResState); -impl<'a, T: Resource> SystemParam for Option> { - type State = OptionResState; -} - // SAFETY: Only reads a single World resource 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 { +unsafe impl<'a, T: Resource> SystemParam for Option> { + type State = OptionResState; type Item<'w, 's> = Option>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { - Self(ResState::init(world, system_meta)) + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + OptionResState(Res::init(world, system_meta)) } #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self, + state: &'s mut Self::State, system_meta: &SystemMeta, world: &'w World, change_tick: u32, @@ -496,16 +488,13 @@ pub struct ResMutState { marker: PhantomData, } -impl<'a, T: Resource> SystemParam for ResMut<'a, T> { - 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 { +unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> { + type State = ResMutState; type Item<'w, 's> = ResMut<'w, T>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { let component_id = world.initialize_resource::(); let combined_access = system_meta.component_access_set.combined_access(); if combined_access.has_write(component_id) { @@ -527,7 +516,7 @@ unsafe impl SystemParamState for ResMutState { system_meta .archetype_component_access .add_write(archetype_component_id); - Self { + ResMutState { component_id, marker: PhantomData, } @@ -535,7 +524,7 @@ unsafe impl SystemParamState for ResMutState { #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self, + state: &'s mut Self::State, system_meta: &SystemMeta, world: &'w World, change_tick: u32, @@ -566,22 +555,19 @@ unsafe impl SystemParamState for ResMutState { #[doc(hidden)] pub struct OptionResMutState(ResMutState); -impl<'a, T: Resource> SystemParam for Option> { - type State = OptionResMutState; -} - // SAFETY: this impl defers to `ResMutState`, which initializes // and validates the correct world access -unsafe impl SystemParamState for OptionResMutState { +unsafe impl<'a, T: Resource> SystemParam for Option> { + type State = OptionResMutState; type Item<'w, 's> = Option>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { - Self(ResMutState::init(world, system_meta)) + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + OptionResMutState(ResMut::init(world, system_meta)) } #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self, + state: &'s mut Self::State, system_meta: &SystemMeta, world: &'w World, change_tick: u32, @@ -600,28 +586,25 @@ unsafe impl SystemParamState for OptionResMutState { } } -impl<'w, 's> SystemParam for Commands<'w, 's> { - type State = CommandQueue; -} - // SAFETY: Commands only accesses internal state unsafe impl<'w, 's> ReadOnlySystemParam for Commands<'w, 's> {} // SAFETY: only local state is accessed -unsafe impl SystemParamState for CommandQueue { +unsafe impl<'_w, '_s> SystemParam for Commands<'_w, '_s> { + type State = CommandQueue; type Item<'w, 's> = Commands<'w, 's>; - fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { + fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { Default::default() } - fn apply(&mut self, world: &mut World) { - self.apply(world); + fn apply(state: &mut Self::State, world: &mut World) { + state.apply(world); } #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self, + state: &'s mut Self::State, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, @@ -637,15 +620,12 @@ unsafe impl<'w> ReadOnlySystemParam for &'w World {} #[doc(hidden)] pub struct WorldState; -impl<'w> SystemParam for &'w World { - type State = WorldState; -} - // SAFETY: `read_all` access is set and conflicts result in a panic -unsafe impl SystemParamState for WorldState { +unsafe impl<'_w> SystemParam for &'_w World { + type State = WorldState; type Item<'w, 's> = &'w World; - fn init(_world: &mut World, system_meta: &mut SystemMeta) -> Self { + fn init(_world: &mut World, system_meta: &mut SystemMeta) -> Self::State { let mut access = Access::default(); access.read_all(); if !system_meta @@ -672,7 +652,7 @@ unsafe impl SystemParamState for WorldState { } unsafe fn get_param<'w, 's>( - _state: &'s mut Self, + _state: &'s mut Self::State, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, @@ -782,21 +762,18 @@ where #[doc(hidden)] pub struct LocalState(pub(crate) SyncCell); -impl<'a, T: FromWorld + Send + 'static> SystemParam for Local<'a, T> { - type State = LocalState; -} - // SAFETY: only local state is accessed -unsafe impl SystemParamState for LocalState { +unsafe impl<'a, T: FromWorld + Send + 'static> SystemParam for Local<'a, T> { + type State = 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))) + fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { + LocalState(SyncCell::new(T::from_world(world))) } #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self, + state: &'s mut Self::State, _system_meta: &SystemMeta, _world: &'w World, _change_tick: u32, @@ -870,17 +847,14 @@ pub struct RemovedComponentsState { marker: PhantomData, } -impl<'a, T: Component> SystemParam for RemovedComponents<'a, T> { - 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 { +unsafe impl<'a, T: Component> SystemParam for RemovedComponents<'a, T> { + type State = RemovedComponentsState; type Item<'w, 's> = RemovedComponents<'w, T>; - fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self { - Self { + fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { + RemovedComponentsState { component_id: world.init_component::(), marker: PhantomData, } @@ -888,7 +862,7 @@ unsafe impl SystemParamState for RemovedComponentsState { #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self, + state: &'s mut Self::State, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, @@ -973,16 +947,13 @@ pub struct NonSendState { marker: PhantomData T>, } -impl<'a, T: 'static> SystemParam for NonSend<'a, T> { - 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 { +unsafe impl<'a, T: 'static> SystemParam for NonSend<'a, T> { + type State = NonSendState; type Item<'w, 's> = NonSend<'w, T>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { system_meta.set_non_send(); let component_id = world.initialize_non_send_resource::(); @@ -1003,7 +974,7 @@ unsafe impl SystemParamState for NonSendState { system_meta .archetype_component_access .add_read(archetype_component_id); - Self { + NonSendState { component_id, marker: PhantomData, } @@ -1011,7 +982,7 @@ unsafe impl SystemParamState for NonSendState { #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self, + state: &'s mut Self::State, system_meta: &SystemMeta, world: &'w World, change_tick: u32, @@ -1041,25 +1012,22 @@ unsafe impl SystemParamState for NonSendState { #[doc(hidden)] pub struct OptionNonSendState(NonSendState); -impl<'w, T: 'static> SystemParam for Option> { - type State = OptionNonSendState; -} - // SAFETY: Only reads a single non-send resource 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 { +unsafe impl<'_w, T: 'static> SystemParam for Option> { + type State = OptionNonSendState; type Item<'w, 's> = Option>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { - Self(NonSendState::init(world, system_meta)) + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + OptionNonSendState(NonSend::init(world, system_meta)) } #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self, + state: &'s mut Self::State, system_meta: &SystemMeta, world: &'w World, change_tick: u32, @@ -1076,6 +1044,9 @@ unsafe impl SystemParamState for OptionNonSendState { } } +// SAFETY: Only reads a single non-send resource +unsafe impl<'a, T: 'static> ReadOnlySystemParam for NonSendMut<'a, T> {} + /// The [`SystemParamState`] of [`NonSendMut`]. #[doc(hidden)] pub struct NonSendMutState { @@ -1083,16 +1054,13 @@ pub struct NonSendMutState { marker: PhantomData T>, } -impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> { - 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 { +unsafe impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> { + type State = NonSendMutState; type Item<'w, 's> = NonSendMut<'w, T>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { system_meta.set_non_send(); let component_id = world.initialize_non_send_resource::(); @@ -1116,7 +1084,7 @@ unsafe impl SystemParamState for NonSendMutState { system_meta .archetype_component_access .add_write(archetype_component_id); - Self { + NonSendMutState { component_id, marker: PhantomData, } @@ -1124,7 +1092,7 @@ unsafe impl SystemParamState for NonSendMutState { #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self, + state: &'s mut Self::State, system_meta: &SystemMeta, world: &'w World, change_tick: u32, @@ -1151,22 +1119,19 @@ unsafe impl SystemParamState for NonSendMutState { #[doc(hidden)] pub struct OptionNonSendMutState(NonSendMutState); -impl<'a, T: 'static> SystemParam for Option> { - type State = OptionNonSendMutState; -} - // SAFETY: this impl defers to `NonSendMutState`, which initializes // and validates the correct world access -unsafe impl SystemParamState for OptionNonSendMutState { +unsafe impl<'a, T: 'static> SystemParam for Option> { + type State = OptionNonSendMutState; type Item<'w, 's> = Option>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { - Self(NonSendMutState::init(world, system_meta)) + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + OptionNonSendMutState(NonSendMut::init(world, system_meta)) } #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self, + state: &'s mut Self::State, system_meta: &SystemMeta, world: &'w World, change_tick: u32, @@ -1181,8 +1146,24 @@ unsafe impl SystemParamState for OptionNonSendMutState { } } -impl<'a> SystemParam for &'a Archetypes { +// SAFETY: no component value access +unsafe impl<'a> SystemParam for &'a Archetypes { type State = ArchetypesState; + type Item<'w, 's> = &'w Archetypes; + + fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { + ArchetypesState + } + + #[inline] + unsafe fn get_param<'w, 's>( + _state: &'s mut Self::State, + _system_meta: &SystemMeta, + world: &'w World, + _change_tick: u32, + ) -> Self::Item<'w, 's> { + world.archetypes() + } } // SAFETY: Only reads World archetypes @@ -1193,28 +1174,25 @@ unsafe impl<'a> ReadOnlySystemParam for &'a Archetypes {} pub struct ArchetypesState; // SAFETY: no component value access -unsafe impl SystemParamState for ArchetypesState { - type Item<'w, 's> = &'w Archetypes; +unsafe impl<'a> SystemParam for &'a Components { + type State = ComponentsState; + type Item<'w, 's> = &'w Components; - fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { - Self + fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { + ComponentsState } #[inline] unsafe fn get_param<'w, 's>( - _state: &'s mut Self, + _state: &'s mut Self::State, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, ) -> Self::Item<'w, 's> { - world.archetypes() + world.components() } } -impl<'a> SystemParam for &'a Components { - type State = ComponentsState; -} - // SAFETY: Only reads World components unsafe impl<'a> ReadOnlySystemParam for &'a Components {} @@ -1223,28 +1201,25 @@ unsafe impl<'a> ReadOnlySystemParam for &'a Components {} pub struct ComponentsState; // SAFETY: no component value access -unsafe impl SystemParamState for ComponentsState { - type Item<'w, 's> = &'w Components; +unsafe impl<'a> SystemParam for &'a Entities { + type State = EntitiesState; + type Item<'w, 's> = &'w Entities; - fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { - Self + fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { + EntitiesState } #[inline] unsafe fn get_param<'w, 's>( - _state: &'s mut Self, + _state: &'s mut Self::State, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, ) -> Self::Item<'w, 's> { - world.components() + world.entities() } } -impl<'a> SystemParam for &'a Entities { - type State = EntitiesState; -} - // SAFETY: Only reads World entities unsafe impl<'a> ReadOnlySystemParam for &'a Entities {} @@ -1253,28 +1228,25 @@ unsafe impl<'a> ReadOnlySystemParam for &'a Entities {} pub struct EntitiesState; // SAFETY: no component value access -unsafe impl SystemParamState for EntitiesState { - type Item<'w, 's> = &'w Entities; +unsafe impl<'a> SystemParam for &'a Bundles { + type State = BundlesState; + type Item<'w, 's> = &'w Bundles; - fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { - Self + fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { + BundlesState } #[inline] unsafe fn get_param<'w, 's>( - _state: &'s mut Self, + _state: &'s mut Self::State, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, ) -> Self::Item<'w, 's> { - world.entities() + world.bundles() } } -impl<'a> SystemParam for &'a Bundles { - type State = BundlesState; -} - // SAFETY: Only reads World bundles unsafe impl<'a> ReadOnlySystemParam for &'a Bundles {} @@ -1282,25 +1254,6 @@ unsafe impl<'a> ReadOnlySystemParam for &'a Bundles {} #[doc(hidden)] 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 - } - - #[inline] - unsafe fn get_param<'w, 's>( - _state: &'s mut Self, - _system_meta: &SystemMeta, - world: &'w World, - _change_tick: u32, - ) -> Self::Item<'w, 's> { - world.bundles() - } -} - /// A [`SystemParam`] that reads the previous and current change ticks of the system. /// /// A system's change ticks are updated each time it runs: @@ -1333,24 +1286,17 @@ impl SystemChangeTick { // SAFETY: Only reads internal system state unsafe impl ReadOnlySystemParam for SystemChangeTick {} -impl SystemParam for SystemChangeTick { - type State = SystemChangeTickState; -} - -/// The [`SystemParamState`] of [`SystemChangeTick`]. -#[doc(hidden)] -pub struct SystemChangeTickState {} - // SAFETY: `SystemParamTickState` doesn't require any world access -unsafe impl SystemParamState for SystemChangeTickState { +unsafe impl SystemParam for SystemChangeTick { + type State = SystemChangeTickState; type Item<'w, 's> = SystemChangeTick; - fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { - Self {} + fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { + SystemChangeTickState {} } unsafe fn get_param<'w, 's>( - _state: &'s mut Self, + _state: &'s mut Self::State, system_meta: &SystemMeta, _world: &'w World, change_tick: u32, @@ -1362,6 +1308,10 @@ unsafe impl SystemParamState for SystemChangeTickState { } } +/// The [`SystemParamState`] of [`SystemChangeTick`]. +#[doc(hidden)] +pub struct SystemChangeTickState {} + /// Name of the system that corresponds to this [`crate::system::SystemState`]. /// /// This is not a reliable identifier, it is more so useful for debugging @@ -1409,32 +1359,20 @@ impl<'s> std::fmt::Display for SystemName<'s> { } } -impl<'s> SystemParam for SystemName<'s> { - type State = SystemNameState; -} - -// SAFETY: Only reads internal system state -unsafe impl<'s> ReadOnlySystemParam for SystemName<'s> {} - -/// The [`SystemParamState`] of [`SystemName`]. -#[doc(hidden)] -pub struct SystemNameState { - name: Cow<'static, str>, -} - // SAFETY: no component value access -unsafe impl SystemParamState for SystemNameState { +unsafe impl<'_s> SystemParam for SystemName<'_s> { + type State = SystemNameState; type Item<'w, 's> = SystemName<'s>; - fn init(_world: &mut World, system_meta: &mut SystemMeta) -> Self { - Self { + fn init(_world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + SystemNameState { name: system_meta.name.clone(), } } #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self, + state: &'s mut Self::State, _system_meta: &SystemMeta, _world: &'w World, _change_tick: u32, @@ -1445,43 +1383,51 @@ unsafe impl SystemParamState for SystemNameState { } } +// SAFETY: Only reads internal system state +unsafe impl<'s> ReadOnlySystemParam for SystemName<'s> {} + +/// The [`SystemParamState`] of [`SystemName`]. +#[doc(hidden)] +pub struct SystemNameState { + name: Cow<'static, str>, +} + macro_rules! impl_system_param_tuple { ($($param: ident),*) => { - impl<$($param: SystemParam),*> SystemParam for ($($param,)*) { - type State = ($($param::State,)*); - } // SAFETY: tuple consists only of ReadOnlySystemParams unsafe impl<$($param: ReadOnlySystemParam),*> ReadOnlySystemParam for ($($param,)*) {} - // 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,)*) { + unsafe impl<$($param: SystemParam),*> SystemParam for ($($param,)*) { + type State = ($($param::State,)*); type Item<'w, 's> = ($($param::Item::<'w, 's>,)*); #[inline] - fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { + fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { (($($param::init(_world, _system_meta),)*)) } #[inline] - fn new_archetype(&mut self, _archetype: &Archetype, _system_meta: &mut SystemMeta) { - let ($($param,)*) = self; - $($param.new_archetype(_archetype, _system_meta);)* + fn new_archetype(($($param,)*): &mut Self::State, _archetype: &Archetype, _system_meta: &mut SystemMeta) { + $( + <$param as SystemParam>::new_archetype($param, _archetype, _system_meta); + )* } #[inline] - fn apply(&mut self, _world: &mut World) { - let ($($param,)*) = self; - $($param.apply(_world);)* + fn apply(($($param,)*): &mut Self::State, _world: &mut World) { + $( + <$param as SystemParam>::apply($param, _world); + )* } #[inline] #[allow(clippy::unused_unit)] unsafe fn get_param<'w, 's>( - state: &'s mut Self, + state: &'s mut Self::State, _system_meta: &SystemMeta, _world: &'w World, _change_tick: u32, @@ -1558,7 +1504,7 @@ pub mod lifetimeless { /// # } /// ``` /// -pub struct StaticSystemParam<'w, 's, P: SystemParam>(SystemParamItem<'w, 's, P>); +pub struct StaticSystemParam<'w, 's, P: SystemParam + 's>(SystemParamItem<'w, 's, P>); impl<'w, 's, P: SystemParam> Deref for StaticSystemParam<'w, 's, P> { type Target = SystemParamItem<'w, 's, P>; @@ -1591,38 +1537,31 @@ unsafe impl<'w, 's, P: ReadOnlySystemParam + 'static> ReadOnlySystemParam { } -impl<'world, 'state, P: SystemParam + 'static> SystemParam - for StaticSystemParam<'world, 'state, P> -{ - type State = StaticSystemParamState; -} - // SAFETY: all methods are just delegated to `S`'s `SystemParamState` implementation -unsafe impl + 'static> SystemParamState - for StaticSystemParamState -{ +unsafe impl<'_w, '_s, P: SystemParam + 'static> SystemParam for StaticSystemParam<'_w, '_s, P> { + type State = 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) + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + StaticSystemParamState(P::init(world, system_meta), PhantomData) } - fn new_archetype(&mut self, archetype: &Archetype, system_meta: &mut SystemMeta) { - self.0.new_archetype(archetype, system_meta); + fn new_archetype(state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta) { + P::new_archetype(&mut state.0, archetype, system_meta); } - fn apply(&mut self, world: &mut World) { - self.0.apply(world); + fn apply(state: &mut Self::State, world: &mut World) { + P::apply(&mut state.0, world); } unsafe fn get_param<'world, 'state>( - state: &'state mut Self, + state: &'state mut Self::State, 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)) + StaticSystemParam(P::get_param(&mut state.0, system_meta, world, change_tick)) } } diff --git a/crates/bevy_render/src/extract_param.rs b/crates/bevy_render/src/extract_param.rs index f854938d8e3a6..ec71736747550 100644 --- a/crates/bevy_render/src/extract_param.rs +++ b/crates/bevy_render/src/extract_param.rs @@ -2,8 +2,7 @@ use crate::MainWorld; use bevy_ecs::{ prelude::*, system::{ - ReadOnlySystemParam, ResState, SystemMeta, SystemParam, SystemParamItem, SystemParamState, - SystemState, + ReadOnlySystemParam, ResState, SystemMeta, SystemParam, SystemParamItem, SystemState, }, }; use std::ops::{Deref, DerefMut}; @@ -49,36 +48,30 @@ where item: SystemParamItem<'w, 's, P>, } -impl<'w, 's, P: ReadOnlySystemParam> SystemParam for Extract<'w, 's, P> { - type State = ExtractState

; -} - -#[doc(hidden)] -pub struct ExtractState { - state: SystemState

, - main_world_state: ResState, -} - -// SAFETY: only accesses MainWorld resource with read only system params using ResState, +// SAFETY: only accesses MainWorld resource with read only system params using Res, // which is initialized in init() -unsafe impl SystemParamState for ExtractState

{ +unsafe impl<'_w, '_s, P> SystemParam for Extract<'_w, '_s, P> +where + P: ReadOnlySystemParam, +{ + type State = ExtractState

; type Item<'w, 's> = Extract<'w, 's, P>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { let mut main_world = world.resource_mut::(); - Self { + ExtractState { state: SystemState::new(&mut main_world), - main_world_state: ResState::init(world, system_meta), + main_world_state: Res::init(world, system_meta), } } unsafe fn get_param<'w, 's>( - state: &'s mut Self, + state: &'s mut Self::State, system_meta: &SystemMeta, world: &'w World, change_tick: u32, ) -> Self::Item<'w, 's> { - let main_world = ResState::::get_param( + let main_world = Res::::get_param( &mut state.main_world_state, system_meta, world, @@ -89,7 +82,13 @@ unsafe impl SystemParamState for ExtractState< } } -impl<'w, 's, P: SystemParam> Deref for Extract<'w, 's, P> +#[doc(hidden)] +pub struct ExtractState { + state: SystemState

, + main_world_state: ResState, +} + +impl<'w, 's, P> Deref for Extract<'w, 's, P> where P: ReadOnlySystemParam, { @@ -101,7 +100,7 @@ where } } -impl<'w, 's, P: SystemParam> DerefMut for Extract<'w, 's, P> +impl<'w, 's, P> DerefMut for Extract<'w, 's, P> where P: ReadOnlySystemParam, { @@ -111,7 +110,7 @@ where } } -impl<'a, 'w, 's, P: SystemParam> IntoIterator for &'a Extract<'w, 's, P> +impl<'a, 'w, 's, P> IntoIterator for &'a Extract<'w, 's, P> where P: ReadOnlySystemParam, &'a SystemParamItem<'w, 's, P>: IntoIterator, From d24d2a9207797fd29a2fc8a4685ac45ea79e1aa2 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Tue, 6 Dec 2022 20:05:02 -0500 Subject: [PATCH 03/49] Add a test case for ignored/marker type params --- crates/bevy_ecs/src/system/system_param.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 2537462bf3dfc..a81aecd77bfc0 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -1597,4 +1597,11 @@ mod tests { #[derive(SystemParam)] pub struct UnitParam {} + + #[derive(SystemParam)] + struct MyParam<'w, T: Resource, Marker: 'static> { + _foo: Res<'w, T>, + #[system_param(ignore)] + marker: PhantomData, + } } From c9d45d60e689afb58340a52480f653be99ab0b39 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Tue, 6 Dec 2022 20:06:46 -0500 Subject: [PATCH 04/49] impl `SystemParam` for `PhantomData` --- crates/bevy_ecs/src/system/system_param.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index a81aecd77bfc0..228776396eb4d 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -1565,6 +1565,26 @@ unsafe impl<'_w, '_s, P: SystemParam + 'static> SystemParam for StaticSystemPara } } +// SAFETY: PhantomData accesses no World data +unsafe impl SystemParam for PhantomData { + type State = (); + type Item<'world, 'state> = Self; + + fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} + + unsafe fn get_param<'world, 'state>( + _state: &'state mut Self::State, + _system_meta: &SystemMeta, + _world: &'world World, + _change_tick: u32, + ) -> Self::Item<'world, 'state> { + Self + } +} + +// SAFETY: PhantomData accesses no World data +unsafe impl ReadOnlySystemParam for PhantomData {} + #[cfg(test)] mod tests { use super::*; From e6a21d0dc3870754be119f43015817788aef6a46 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Tue, 6 Dec 2022 20:07:01 -0500 Subject: [PATCH 05/49] add a marker param --- crates/bevy_ecs/macros/src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index cc8533ff647a4..431a5dbafea84 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -466,13 +466,17 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { #[doc(hidden)] type State<'w, 's, #punctuated_generic_idents> = FetchState< - (#(<#field_types as #path::system::SystemParam>::State,)*), + ( + #(<#field_types as #path::system::SystemParam>::State,)* + (), // State for the `PhantomData` param. + ), #punctuated_generic_idents >; #[doc(hidden)] type FieldsTuple<'w, 's, #punctuated_generic_idents> = ( #(#field_types,)* + std::marker::PhantomData (#punctuated_generic_idents)>, ); #[doc(hidden)] From 1928bf6d2af5fcec98fc407676708e1c7e1f3de3 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Tue, 6 Dec 2022 21:43:00 -0500 Subject: [PATCH 06/49] remove trivial `State` types --- crates/bevy_ecs/src/system/system_param.rs | 209 ++++++--------------- crates/bevy_render/src/extract_param.rs | 8 +- 2 files changed, 58 insertions(+), 159 deletions(-) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 228776396eb4d..5cabdcd6717e8 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -130,7 +130,7 @@ use std::{ /// conflicting access across all [`SystemParam`]'s. pub unsafe trait SystemParam: Sized { type State: Send + Sync + 'static; - type Item<'world, 'state>; + type Item<'world, 'state>: SystemParam; fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State; @@ -377,20 +377,13 @@ where } } -/// The [`SystemParamState`] of [`Res`]. -#[doc(hidden)] -pub struct ResState { - component_id: ComponentId, - marker: PhantomData, -} - // SAFETY: Res only reads a single World resource unsafe impl<'a, T: Resource> ReadOnlySystemParam for Res<'a, T> {} // SAFETY: Res ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this Res // conflicts with any prior access, a panic will occur. unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> { - type State = ResState; + type State = ComponentId; type Item<'w, 's> = Res<'w, T>; fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { @@ -412,21 +405,19 @@ unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> { system_meta .archetype_component_access .add_read(archetype_component_id); - ResState { - component_id, - marker: PhantomData, - } + + component_id } #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self::State, + &mut component_id: &'s mut Self::State, system_meta: &SystemMeta, world: &'w World, change_tick: u32, ) -> Self::Item<'w, 's> { let (ptr, ticks) = world - .get_resource_with_ticks(state.component_id) + .get_resource_with_ticks(component_id) .unwrap_or_else(|| { panic!( "Resource requested by {} does not exist: {}", @@ -444,33 +435,25 @@ unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> { } } -/// The [`SystemParamState`] of [`Option>`]. -/// See: [`Res`] -#[doc(hidden)] -pub struct OptionResState(ResState); - -// SAFETY: Only reads a single World resource -unsafe impl<'a, T: Resource> ReadOnlySystemParam for Option> {} - // SAFETY: this impl defers to `ResState`, which initializes // and validates the correct world access unsafe impl<'a, T: Resource> SystemParam for Option> { - type State = OptionResState; + type State = ComponentId; type Item<'w, 's> = Option>; fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { - OptionResState(Res::init(world, system_meta)) + Res::::init(world, system_meta) } #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self::State, + &mut component_id: &'s mut Self::State, system_meta: &SystemMeta, world: &'w World, change_tick: u32, ) -> Self::Item<'w, 's> { world - .get_resource_with_ticks(state.0.component_id) + .get_resource_with_ticks(component_id) .map(|(ptr, ticks)| Res { value: ptr.deref(), added: ticks.added.deref(), @@ -481,17 +464,13 @@ unsafe impl<'a, T: Resource> SystemParam for Option> { } } -/// The [`SystemParamState`] of [`ResMut`]. -#[doc(hidden)] -pub struct ResMutState { - component_id: ComponentId, - marker: PhantomData, -} +// SAFETY: Only reads a single World resource +unsafe impl<'a, T: Resource> ReadOnlySystemParam for Option> {} // SAFETY: Res ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this Res // conflicts with any prior access, a panic will occur. unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> { - type State = ResMutState; + type State = ComponentId; type Item<'w, 's> = ResMut<'w, T>; fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { @@ -516,21 +495,19 @@ unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> { system_meta .archetype_component_access .add_write(archetype_component_id); - ResMutState { - component_id, - marker: PhantomData, - } + + component_id } #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self::State, + &mut component_id: &'s mut Self::State, system_meta: &SystemMeta, world: &'w World, change_tick: u32, ) -> Self::Item<'w, 's> { let value = world - .get_resource_unchecked_mut_with_id(state.component_id) + .get_resource_unchecked_mut_with_id(component_id) .unwrap_or_else(|| { panic!( "Resource requested by {} does not exist: {}", @@ -550,30 +527,25 @@ unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> { } } -/// The [`SystemParamState`] of [`Option>`]. -/// See: [`ResMut`] -#[doc(hidden)] -pub struct OptionResMutState(ResMutState); - // SAFETY: this impl defers to `ResMutState`, which initializes // and validates the correct world access unsafe impl<'a, T: Resource> SystemParam for Option> { - type State = OptionResMutState; + type State = ComponentId; type Item<'w, 's> = Option>; fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { - OptionResMutState(ResMut::init(world, system_meta)) + ResMut::::init(world, system_meta) } #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self::State, + &mut component_id: &'s mut Self::State, system_meta: &SystemMeta, world: &'w World, change_tick: u32, ) -> Self::Item<'w, 's> { world - .get_resource_unchecked_mut_with_id(state.0.component_id) + .get_resource_unchecked_mut_with_id(component_id) .map(|value| ResMut { value: value.value, ticks: Ticks { @@ -616,13 +588,9 @@ unsafe impl<'_w, '_s> SystemParam for Commands<'_w, '_s> { /// SAFETY: only reads world unsafe impl<'w> ReadOnlySystemParam for &'w World {} -/// The [`SystemParamState`] of [`&World`](crate::world::World). -#[doc(hidden)] -pub struct WorldState; - // SAFETY: `read_all` access is set and conflicts result in a panic unsafe impl<'_w> SystemParam for &'_w World { - type State = WorldState; + type State = (); type Item<'w, 's> = &'w World; fn init(_world: &mut World, system_meta: &mut SystemMeta) -> Self::State { @@ -647,8 +615,6 @@ unsafe impl<'_w> SystemParam for &'_w World { panic!("&World conflicts with a previous mutable system parameter. Allowing this would break Rust's mutability rules"); } system_meta.component_access_set.add(filtered_access); - - WorldState } unsafe fn get_param<'w, 's>( @@ -940,17 +906,10 @@ impl<'a, T> From> for NonSend<'a, T> { } } -/// The [`SystemParamState`] of [`NonSend`]. -#[doc(hidden)] -pub struct NonSendState { - component_id: ComponentId, - marker: PhantomData T>, -} - // SAFETY: NonSendComponentId and ArchetypeComponentId access is applied to SystemMeta. If this // NonSend conflicts with any prior access, a panic will occur. unsafe impl<'a, T: 'static> SystemParam for NonSend<'a, T> { - type State = NonSendState; + type State = ComponentId; type Item<'w, 's> = NonSend<'w, T>; fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { @@ -974,22 +933,20 @@ unsafe impl<'a, T: 'static> SystemParam for NonSend<'a, T> { system_meta .archetype_component_access .add_read(archetype_component_id); - NonSendState { - component_id, - marker: PhantomData, - } + + component_id } #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self::State, + &mut component_id: &'s mut Self::State, system_meta: &SystemMeta, world: &'w World, change_tick: u32, ) -> Self::Item<'w, 's> { world.validate_non_send_access::(); let (ptr, ticks) = world - .get_resource_with_ticks(state.component_id) + .get_resource_with_ticks(component_id) .unwrap_or_else(|| { panic!( "Non-send resource requested by {} does not exist: {}", @@ -1007,34 +964,26 @@ unsafe impl<'a, T: 'static> SystemParam for NonSend<'a, T> { } } -/// The [`SystemParamState`] of [`Option>`]. -/// See: [`NonSend`] -#[doc(hidden)] -pub struct OptionNonSendState(NonSendState); - -// SAFETY: Only reads a single non-send resource -unsafe impl<'w, T: 'static> ReadOnlySystemParam for Option> {} - // SAFETY: this impl defers to `NonSendState`, which initializes // and validates the correct world access unsafe impl<'_w, T: 'static> SystemParam for Option> { - type State = OptionNonSendState; + type State = ComponentId; type Item<'w, 's> = Option>; fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { - OptionNonSendState(NonSend::init(world, system_meta)) + NonSend::::init(world, system_meta) } #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self::State, + &mut component_id: &'s mut Self::State, system_meta: &SystemMeta, world: &'w World, change_tick: u32, ) -> Self::Item<'w, 's> { world.validate_non_send_access::(); world - .get_resource_with_ticks(state.0.component_id) + .get_resource_with_ticks(component_id) .map(|(ptr, ticks)| NonSend { value: ptr.deref(), ticks: ticks.read(), @@ -1047,17 +996,10 @@ unsafe impl<'_w, T: 'static> SystemParam for Option> { // SAFETY: Only reads a single non-send resource unsafe impl<'a, T: 'static> ReadOnlySystemParam for NonSendMut<'a, T> {} -/// The [`SystemParamState`] of [`NonSendMut`]. -#[doc(hidden)] -pub struct NonSendMutState { - component_id: ComponentId, - marker: PhantomData T>, -} - // SAFETY: NonSendMut ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this // NonSendMut conflicts with any prior access, a panic will occur. unsafe impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> { - type State = NonSendMutState; + type State = ComponentId; type Item<'w, 's> = NonSendMut<'w, T>; fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { @@ -1084,22 +1026,20 @@ unsafe impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> { system_meta .archetype_component_access .add_write(archetype_component_id); - NonSendMutState { - component_id, - marker: PhantomData, - } + + component_id } #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self::State, + &mut component_id: &'s mut Self::State, system_meta: &SystemMeta, world: &'w World, change_tick: u32, ) -> Self::Item<'w, 's> { world.validate_non_send_access::(); let (ptr, ticks) = world - .get_resource_with_ticks(state.component_id) + .get_resource_with_ticks(component_id) .unwrap_or_else(|| { panic!( "Non-send resource requested by {} does not exist: {}", @@ -1114,31 +1054,26 @@ unsafe impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> { } } -/// The [`SystemParamState`] of [`Option>`]. -/// See: [`NonSendMut`] -#[doc(hidden)] -pub struct OptionNonSendMutState(NonSendMutState); - // SAFETY: this impl defers to `NonSendMutState`, which initializes // and validates the correct world access unsafe impl<'a, T: 'static> SystemParam for Option> { - type State = OptionNonSendMutState; + type State = ComponentId; type Item<'w, 's> = Option>; fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { - OptionNonSendMutState(NonSendMut::init(world, system_meta)) + NonSendMut::::init(world, system_meta) } #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self::State, + &mut component_id: &'s mut Self::State, system_meta: &SystemMeta, world: &'w World, change_tick: u32, ) -> Self::Item<'w, 's> { world.validate_non_send_access::(); world - .get_resource_with_ticks(state.0.component_id) + .get_resource_with_ticks(component_id) .map(|(ptr, ticks)| NonSendMut { value: ptr.assert_unique().deref_mut(), ticks: Ticks::from_tick_cells(ticks, system_meta.last_change_tick, change_tick), @@ -1148,12 +1083,10 @@ unsafe impl<'a, T: 'static> SystemParam for Option> { // SAFETY: no component value access unsafe impl<'a> SystemParam for &'a Archetypes { - type State = ArchetypesState; + type State = (); type Item<'w, 's> = &'w Archetypes; - fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { - ArchetypesState - } + fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} #[inline] unsafe fn get_param<'w, 's>( @@ -1169,18 +1102,12 @@ unsafe impl<'a> SystemParam for &'a Archetypes { // SAFETY: Only reads World archetypes unsafe impl<'a> ReadOnlySystemParam for &'a Archetypes {} -/// The [`SystemParamState`] of [`Archetypes`]. -#[doc(hidden)] -pub struct ArchetypesState; - // SAFETY: no component value access unsafe impl<'a> SystemParam for &'a Components { - type State = ComponentsState; + type State = (); type Item<'w, 's> = &'w Components; - fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { - ComponentsState - } + fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} #[inline] unsafe fn get_param<'w, 's>( @@ -1196,18 +1123,12 @@ unsafe impl<'a> SystemParam for &'a Components { // SAFETY: Only reads World components unsafe impl<'a> ReadOnlySystemParam for &'a Components {} -/// The [`SystemParamState`] of [`Components`]. -#[doc(hidden)] -pub struct ComponentsState; - // SAFETY: no component value access unsafe impl<'a> SystemParam for &'a Entities { - type State = EntitiesState; + type State = (); type Item<'w, 's> = &'w Entities; - fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { - EntitiesState - } + fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} #[inline] unsafe fn get_param<'w, 's>( @@ -1223,18 +1144,12 @@ unsafe impl<'a> SystemParam for &'a Entities { // SAFETY: Only reads World entities unsafe impl<'a> ReadOnlySystemParam for &'a Entities {} -/// The [`SystemParamState`] of [`Entities`]. -#[doc(hidden)] -pub struct EntitiesState; - // SAFETY: no component value access unsafe impl<'a> SystemParam for &'a Bundles { - type State = BundlesState; + type State = (); type Item<'w, 's> = &'w Bundles; - fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { - BundlesState - } + fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} #[inline] unsafe fn get_param<'w, 's>( @@ -1250,10 +1165,6 @@ unsafe impl<'a> SystemParam for &'a Bundles { // SAFETY: Only reads World bundles unsafe impl<'a> ReadOnlySystemParam for &'a Bundles {} -/// The [`SystemParamState`] of [`Bundles`]. -#[doc(hidden)] -pub struct BundlesState; - /// A [`SystemParam`] that reads the previous and current change ticks of the system. /// /// A system's change ticks are updated each time it runs: @@ -1288,12 +1199,10 @@ unsafe impl ReadOnlySystemParam for SystemChangeTick {} // SAFETY: `SystemParamTickState` doesn't require any world access unsafe impl SystemParam for SystemChangeTick { - type State = SystemChangeTickState; + type State = (); type Item<'w, 's> = SystemChangeTick; - fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { - SystemChangeTickState {} - } + fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} unsafe fn get_param<'w, 's>( _state: &'s mut Self::State, @@ -1308,10 +1217,6 @@ unsafe impl SystemParam for SystemChangeTick { } } -/// The [`SystemParamState`] of [`SystemChangeTick`]. -#[doc(hidden)] -pub struct SystemChangeTickState {} - /// Name of the system that corresponds to this [`crate::system::SystemState`]. /// /// This is not a reliable identifier, it is more so useful for debugging @@ -1527,10 +1432,6 @@ impl<'w, 's, P: SystemParam> StaticSystemParam<'w, 's, P> { } } -/// The [`SystemParamState`] of [`StaticSystemParam`]. -#[doc(hidden)] -pub struct StaticSystemParamState(S, PhantomData P>); - // SAFETY: This doesn't add any more reads, and the delegated fetch confirms it unsafe impl<'w, 's, P: ReadOnlySystemParam + 'static> ReadOnlySystemParam for StaticSystemParam<'w, 's, P> @@ -1539,19 +1440,19 @@ unsafe impl<'w, 's, P: ReadOnlySystemParam + 'static> ReadOnlySystemParam // SAFETY: all methods are just delegated to `S`'s `SystemParamState` implementation unsafe impl<'_w, '_s, P: SystemParam + 'static> SystemParam for StaticSystemParam<'_w, '_s, P> { - type State = StaticSystemParamState; + type State = P::State; type Item<'world, 'state> = StaticSystemParam<'world, 'state, P>; fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { - StaticSystemParamState(P::init(world, system_meta), PhantomData) + P::init(world, system_meta) } fn new_archetype(state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta) { - P::new_archetype(&mut state.0, archetype, system_meta); + P::new_archetype(state, archetype, system_meta); } fn apply(state: &mut Self::State, world: &mut World) { - P::apply(&mut state.0, world); + P::apply(state, world); } unsafe fn get_param<'world, 'state>( @@ -1561,7 +1462,7 @@ unsafe impl<'_w, '_s, P: SystemParam + 'static> SystemParam for StaticSystemPara change_tick: u32, ) -> Self::Item<'world, 'state> { // SAFETY: We properly delegate SystemParamState - StaticSystemParam(P::get_param(&mut state.0, system_meta, world, change_tick)) + StaticSystemParam(P::get_param(state, system_meta, world, change_tick)) } } diff --git a/crates/bevy_render/src/extract_param.rs b/crates/bevy_render/src/extract_param.rs index ec71736747550..4b3334caf74a1 100644 --- a/crates/bevy_render/src/extract_param.rs +++ b/crates/bevy_render/src/extract_param.rs @@ -1,9 +1,7 @@ use crate::MainWorld; use bevy_ecs::{ prelude::*, - system::{ - ReadOnlySystemParam, ResState, SystemMeta, SystemParam, SystemParamItem, SystemState, - }, + system::{ReadOnlySystemParam, SystemMeta, SystemParam, SystemParamItem, SystemState}, }; use std::ops::{Deref, DerefMut}; @@ -61,7 +59,7 @@ where let mut main_world = world.resource_mut::(); ExtractState { state: SystemState::new(&mut main_world), - main_world_state: Res::init(world, system_meta), + main_world_state: Res::::init(world, system_meta), } } @@ -85,7 +83,7 @@ where #[doc(hidden)] pub struct ExtractState { state: SystemState

, - main_world_state: ResState, + main_world_state: as SystemParam>::State, } impl<'w, 's, P> Deref for Extract<'w, 's, P> From 2e3b75faf2ae55c00dfd2e8b163ebce0860d3ad0 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Tue, 6 Dec 2022 21:56:50 -0500 Subject: [PATCH 07/49] don't generate state struct in the `SystemParam` derive --- crates/bevy_ecs/macros/src/lib.rs | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index 431a5dbafea84..c0cc153498381 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -425,7 +425,6 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { } let struct_name = &ast.ident; - let state_struct_visibility = &ast.vis; TokenStream::from(quote! { // We define the FetchState struct in an anonymous scope to avoid polluting the user namespace. @@ -433,22 +432,19 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { // as SystemParam>::State const _: () = { unsafe impl<'_w, '_s, #punctuated_generics> #path::system::SystemParam for #struct_name <#(#shadowed_lifetimes,)* #punctuated_generic_idents> #where_clause { - type State = State<'_w, '_s, #punctuated_generic_idents>; + type State = as #path::system::SystemParam>::State; type Item<'w, 's> = #struct_name #ty_generics; fn init(world: &mut #path::world::World, system_meta: &mut #path::system::SystemMeta) -> Self::State { - FetchState { - state: >::init(world, system_meta), - marker: std::marker::PhantomData, - } + >::init(world, system_meta) } fn new_archetype(state: &mut Self::State, archetype: &#path::archetype::Archetype, system_meta: &mut #path::system::SystemMeta) { - >::new_archetype(&mut state.state, archetype, system_meta) + >::new_archetype(state, archetype, system_meta) } fn apply(state: &mut Self::State, world: &mut #path::world::World) { - >::apply(&mut state.state, world); + >::apply( state, world); } unsafe fn get_param<'w, 's>( @@ -458,33 +454,18 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { change_tick: u32, ) -> Self::Item<'w, 's> { #struct_name { - #(#fields: <#field_types as #path::system::SystemParam>::get_param(&mut state.state.#field_indices, system_meta, world, change_tick),)* + #(#fields: <#field_types as #path::system::SystemParam>::get_param(&mut state.#field_indices, system_meta, world, change_tick),)* #(#ignored_fields: <#ignored_field_types>::default(),)* } } } - #[doc(hidden)] - type State<'w, 's, #punctuated_generic_idents> = FetchState< - ( - #(<#field_types as #path::system::SystemParam>::State,)* - (), // State for the `PhantomData` param. - ), - #punctuated_generic_idents - >; - #[doc(hidden)] type FieldsTuple<'w, 's, #punctuated_generic_idents> = ( #(#field_types,)* std::marker::PhantomData (#punctuated_generic_idents)>, ); - #[doc(hidden)] - #state_struct_visibility struct FetchState { - state: TSystemParamState, - marker: std::marker::PhantomData(#punctuated_generic_idents)> - } - // Safety: The `ParamState` 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 {} }; From d6a81dc27d154f155a07bb37a5fe47cf984afa88 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Tue, 6 Dec 2022 22:07:14 -0500 Subject: [PATCH 08/49] remove `ParamSetState` --- crates/bevy_ecs/macros/src/lib.rs | 10 +++++----- crates/bevy_ecs/src/system/system_param.rs | 2 -- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index c0cc153498381..cab703eb054c4 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -243,7 +243,7 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream { for<'w, 's> #param::Item::<'w, 's>: SystemParam, )* { - type State = ParamSetState<(#(#param::State,)*)>; + type State = (#(#param::State,)*); type Item<'w, 's> = ParamSet<'w, 's, (#(#param::Item<'w, 's>,)*)>; fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { @@ -263,18 +263,18 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream { .archetype_component_access .extend(&#meta.archetype_component_access); )* - ParamSetState((#(#param,)*)) + (#(#param,)*) } fn new_archetype(state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta) { - let (#(#param,)*) = &mut state.0; + let (#(#param,)*) = state; #( <#param as SystemParam>::new_archetype(#param, archetype, system_meta); )* } fn apply(state: &mut Self::State, world: &mut World) { - <(#(#param,)*)>::apply(&mut state.0, world); + <(#(#param,)*)>::apply(state, world); } #[inline] @@ -285,7 +285,7 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream { change_tick: u32, ) -> Self::Item<'w, 's> { ParamSet { - param_states: &mut state.0, + param_states: state, system_meta: system_meta.clone(), world, change_tick, diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 5cabdcd6717e8..1bb777768b8d5 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -242,8 +242,6 @@ pub struct ParamSet<'w, 's, T: SystemParam> { system_meta: SystemMeta, change_tick: u32, } -/// The [`SystemParamState`] of [`ParamSet`]. -pub struct ParamSetState(T); impl_param_set!(); From 2ffed09e727e62a111145b7b091c652e956f1903 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Fri, 9 Dec 2022 22:16:18 -0500 Subject: [PATCH 09/49] reduce macro churn --- crates/bevy_ecs/macros/src/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index cab703eb054c4..176714a973762 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -238,6 +238,11 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream { let meta = &metas[0..param_count]; let param_fn_mut = ¶m_fn_muts[0..param_count]; tokens.extend(TokenStream::from(quote! { + // SAFETY: All parameters are constrained to ReadOnlySystemParam, so World is only read + unsafe impl<'w, 's, #(#param,)*> ReadOnlySystemParam for ParamSet<'w, 's, (#(#param,)*)> + where #(#param: ReadOnlySystemParam,)* + { } + unsafe impl<'_w, '_s, #(#param: SystemParam,)*> SystemParam for ParamSet<'_w, '_s, (#(#param,)*)> where #( for<'w, 's> #param::Item::<'w, 's>: SystemParam, @@ -293,11 +298,6 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream { } } - // SAFETY: All parameters are constrained to ReadOnlyState, so World is only read - unsafe impl<'w, 's, #(#param,)*> ReadOnlySystemParam for ParamSet<'w, 's, (#(#param,)*)> - where #(#param: ReadOnlySystemParam,)* - { } - impl<'w, 's, #(#param: SystemParam,)*> ParamSet<'w, 's, (#(#param,)*)> { #(#param_fn_mut)* @@ -466,7 +466,7 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { std::marker::PhantomData (#punctuated_generic_idents)>, ); - // Safety: The `ParamState` is `ReadOnlySystemParam`, so this can only read from the `World` + // 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 {} }; }) From d6d619a2d6ba73cb0a63e5ba15f4fc8910379a59 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Fri, 9 Dec 2022 22:17:48 -0500 Subject: [PATCH 10/49] undelete a safety comment --- crates/bevy_ecs/macros/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index 176714a973762..979963814e0dd 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -243,6 +243,8 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream { 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<'_w, '_s, #(#param: SystemParam,)*> SystemParam for ParamSet<'_w, '_s, (#(#param,)*)> where #( for<'w, 's> #param::Item::<'w, 's>: SystemParam, From f58cb66f0905dc4d1d1fc14b049cfed55dd8a7f9 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Fri, 9 Dec 2022 22:33:45 -0500 Subject: [PATCH 11/49] simplify `SystemParam` derive --- crates/bevy_ecs/macros/src/lib.rs | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index 979963814e0dd..733358c318d0d 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -433,28 +433,28 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { // The struct can still be accessed via SystemParam::State, e.g. EventReaderState can be accessed via // as SystemParam>::State const _: () = { - unsafe impl<'_w, '_s, #punctuated_generics> #path::system::SystemParam for #struct_name <#(#shadowed_lifetimes,)* #punctuated_generic_idents> #where_clause { - type State = as #path::system::SystemParam>::State; - type Item<'w, 's> = #struct_name #ty_generics; + unsafe impl<'w, 's, #punctuated_generics> #path::system::SystemParam for #struct_name #ty_generics #where_clause { + type State = <(#(#field_types,)*) as #path::system::SystemParam>::State; + type Item<'_w, '_s> = #struct_name <#(#shadowed_lifetimes,)* #punctuated_generic_idents>; fn init(world: &mut #path::world::World, system_meta: &mut #path::system::SystemMeta) -> Self::State { - >::init(world, system_meta) + <(#(#field_types,)*) as #path::system::SystemParam>::init(world, system_meta) } fn new_archetype(state: &mut Self::State, archetype: &#path::archetype::Archetype, system_meta: &mut #path::system::SystemMeta) { - >::new_archetype(state, archetype, system_meta) + <(#(#field_types,)*) as #path::system::SystemParam>::new_archetype(state, archetype, system_meta) } fn apply(state: &mut Self::State, world: &mut #path::world::World) { - >::apply( state, world); + <(#(#field_types,)*) as #path::system::SystemParam>::apply( state, world); } - unsafe fn get_param<'w, 's>( - state: &'s mut Self::State, + unsafe fn get_param<'w2, 's2>( + state: &'s2 mut Self::State, system_meta: &#path::system::SystemMeta, - world: &'w #path::world::World, + world: &'w2 #path::world::World, change_tick: u32, - ) -> Self::Item<'w, 's> { + ) -> Self::Item<'w2, 's2> { #struct_name { #(#fields: <#field_types as #path::system::SystemParam>::get_param(&mut state.#field_indices, system_meta, world, change_tick),)* #(#ignored_fields: <#ignored_field_types>::default(),)* @@ -462,12 +462,6 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { } } - #[doc(hidden)] - type FieldsTuple<'w, 's, #punctuated_generic_idents> = ( - #(#field_types,)* - std::marker::PhantomData (#punctuated_generic_idents)>, - ); - // 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 {} }; From 5939101f7a6c0975b97eaa941e606eab901f4320 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Fri, 9 Dec 2022 22:33:59 -0500 Subject: [PATCH 12/49] Revert "impl `SystemParam` for `PhantomData`" This reverts commit 35439b089fb7ed32850c1279ead2cbab3e187125. --- crates/bevy_ecs/src/system/system_param.rs | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 1bb777768b8d5..aacf7ba703de6 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -1464,26 +1464,6 @@ unsafe impl<'_w, '_s, P: SystemParam + 'static> SystemParam for StaticSystemPara } } -// SAFETY: PhantomData accesses no World data -unsafe impl SystemParam for PhantomData { - type State = (); - type Item<'world, 'state> = Self; - - fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} - - unsafe fn get_param<'world, 'state>( - _state: &'state mut Self::State, - _system_meta: &SystemMeta, - _world: &'world World, - _change_tick: u32, - ) -> Self::Item<'world, 'state> { - Self - } -} - -// SAFETY: PhantomData accesses no World data -unsafe impl ReadOnlySystemParam for PhantomData {} - #[cfg(test)] mod tests { use super::*; From 31d07a912e045530d826b87cfcb376ad1bf3c8c7 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Fri, 9 Dec 2022 22:51:25 -0500 Subject: [PATCH 13/49] simplify `ExclusiveSystemParam` --- .../src/system/exclusive_function_system.rs | 11 ++-- .../src/system/exclusive_system_param.rs | 66 +++++++------------ 2 files changed, 28 insertions(+), 49 deletions(-) diff --git a/crates/bevy_ecs/src/system/exclusive_function_system.rs b/crates/bevy_ecs/src/system/exclusive_function_system.rs index 8b1607c75898e..272b9bce17eff 100644 --- a/crates/bevy_ecs/src/system/exclusive_function_system.rs +++ b/crates/bevy_ecs/src/system/exclusive_function_system.rs @@ -6,7 +6,7 @@ use crate::{ schedule::{SystemLabel, SystemLabelId}, system::{ check_system_change_tick, AsSystemLabel, ExclusiveSystemParam, ExclusiveSystemParamItem, - ExclusiveSystemParamState, IntoSystem, System, SystemMeta, SystemTypeIdLabel, + IntoSystem, System, SystemMeta, SystemTypeIdLabel, }, world::{World, WorldId}, }; @@ -94,7 +94,7 @@ where let saved_last_tick = world.last_change_tick; world.last_change_tick = self.system_meta.last_change_tick; - let params = ::State::get_param( + let params = Param::get_param( self.param_state.as_mut().expect(PARAM_MESSAGE), &self.system_meta, ); @@ -122,17 +122,14 @@ where #[inline] fn apply_buffers(&mut self, world: &mut World) { let param_state = self.param_state.as_mut().expect(PARAM_MESSAGE); - param_state.apply(world); + Param::apply(param_state, world); } #[inline] 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( - world, - &mut self.system_meta, - )); + self.param_state = Some(Param::init(world, &mut self.system_meta)); } fn update_archetype_component_access(&mut self, _world: &World) {} diff --git a/crates/bevy_ecs/src/system/exclusive_system_param.rs b/crates/bevy_ecs/src/system/exclusive_system_param.rs index 6c52738901254..a88355a7f03fa 100644 --- a/crates/bevy_ecs/src/system/exclusive_system_param.rs +++ b/crates/bevy_ecs/src/system/exclusive_system_param.rs @@ -8,101 +8,84 @@ use bevy_ecs_macros::all_tuples; use bevy_utils::synccell::SyncCell; pub trait ExclusiveSystemParam: Sized { - type State: ExclusiveSystemParamState; -} - -pub type ExclusiveSystemParamItem<'s, P> = - <

::State as ExclusiveSystemParamState>::Item<'s>; - -/// The state of a [`SystemParam`]. -pub trait ExclusiveSystemParamState: Send + Sync + 'static { - type Item<'s>: ExclusiveSystemParam; + type State: Send + Sync + 'static; + type Item<'s>: ExclusiveSystemParam; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self; + fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State; #[inline] - fn apply(&mut self, _world: &mut World) {} + fn apply(_state: &mut Self::State, _world: &mut World) {} - fn get_param<'s>(state: &'s mut Self, system_meta: &SystemMeta) -> Self::Item<'s>; + fn get_param<'s>(state: &'s mut Self::State, system_meta: &SystemMeta) -> Self::Item<'s>; } +pub type ExclusiveSystemParamItem<'s, P> =

::Item<'s>; + impl<'a, Q: WorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> ExclusiveSystemParam for &'a mut QueryState { type State = QueryState; -} - -impl ExclusiveSystemParamState - for QueryState -{ type Item<'s> = &'s mut QueryState; - fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self { + fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { QueryState::new(world) } - fn get_param<'s>(state: &'s mut Self, _system_meta: &SystemMeta) -> Self::Item<'s> { + fn get_param<'s>(state: &'s mut Self::State, _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 { + fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { SystemState::new(world) } - fn get_param<'s>(state: &'s mut Self, _system_meta: &SystemMeta) -> Self::Item<'s> { + fn get_param<'s>(state: &'s mut Self::State, _system_meta: &SystemMeta) -> Self::Item<'s> { state } } -impl<'s, T: FromWorld + Send + Sync + 'static> ExclusiveSystemParam for Local<'s, T> { +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 init(world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { + LocalState(SyncCell::new(T::from_world(world))) } - fn get_param<'s>(state: &'s mut Self, _system_meta: &SystemMeta) -> Self::Item<'s> { + fn get_param<'s>(state: &'s mut Self::State, _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 State = ($($param::State,)*); - } - #[allow(unused_variables)] #[allow(non_snake_case)] - impl<$($param: ExclusiveSystemParamState),*> ExclusiveSystemParamState for ($($param,)*) { + impl<$($param: ExclusiveSystemParam),*> ExclusiveSystemParam for ($($param,)*) { + type State = ($($param::State,)*); type Item<'s> = ($($param::Item<'s>,)*); #[inline] - fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self { + fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { (($($param::init(_world, _system_meta),)*)) } #[inline] - fn apply(&mut self, _world: &mut World) { - let ($($param,)*) = self; - $($param.apply(_world);)* + fn apply(state: &mut Self::State, _world: &mut World) { + let ($($param,)*) = state; + $( + <$param as ExclusiveSystemParam>::apply($param, _world); + )* } #[inline] #[allow(clippy::unused_unit)] fn get_param<'s>( - state: &'s mut Self, + state: &'s mut Self::State, system_meta: &SystemMeta, ) -> Self::Item<'s> { @@ -110,7 +93,6 @@ macro_rules! impl_exclusive_system_param_tuple { ($($param::get_param($param, system_meta),)*) } } - }; } From 4d3178029e08fe461bcf81aeafab0495e05d43ab Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Fri, 9 Dec 2022 22:54:24 -0500 Subject: [PATCH 14/49] yeet `LocalState` --- crates/bevy_ecs/src/system/exclusive_system_param.rs | 8 ++++---- crates/bevy_ecs/src/system/system_param.rs | 10 +++------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/crates/bevy_ecs/src/system/exclusive_system_param.rs b/crates/bevy_ecs/src/system/exclusive_system_param.rs index a88355a7f03fa..c5863afb9b620 100644 --- a/crates/bevy_ecs/src/system/exclusive_system_param.rs +++ b/crates/bevy_ecs/src/system/exclusive_system_param.rs @@ -1,7 +1,7 @@ use crate::{ prelude::{FromWorld, QueryState}, query::{ReadOnlyWorldQuery, WorldQuery}, - system::{Local, LocalState, SystemMeta, SystemParam, SystemState}, + system::{Local, SystemMeta, SystemParam, SystemState}, world::World, }; use bevy_ecs_macros::all_tuples; @@ -49,15 +49,15 @@ impl<'a, P: SystemParam + 'static> ExclusiveSystemParam for &'a mut SystemState< } impl<'_s, T: FromWorld + Send + Sync + 'static> ExclusiveSystemParam for Local<'_s, T> { - type State = LocalState; + type State = SyncCell; type Item<'s> = Local<'s, T>; fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { - LocalState(SyncCell::new(T::from_world(world))) + SyncCell::new(T::from_world(world)) } fn get_param<'s>(state: &'s mut Self::State, _system_meta: &SystemMeta) -> Self::Item<'s> { - Local(state.0.get()) + Local(state.get()) } } diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index aacf7ba703de6..4d4dc3ee1c4d3 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -722,17 +722,13 @@ where } } -/// The [`SystemParamState`] of [`Local`]. -#[doc(hidden)] -pub struct LocalState(pub(crate) SyncCell); - // SAFETY: only local state is accessed unsafe impl<'a, T: FromWorld + Send + 'static> SystemParam for Local<'a, T> { - type State = LocalState; + type State = SyncCell; type Item<'w, 's> = Local<'s, T>; fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { - LocalState(SyncCell::new(T::from_world(world))) + SyncCell::new(T::from_world(world)) } #[inline] @@ -742,7 +738,7 @@ unsafe impl<'a, T: FromWorld + Send + 'static> SystemParam for Local<'a, T> { _world: &'w World, _change_tick: u32, ) -> Self::Item<'w, 's> { - Local(state.0.get()) + Local(state.get()) } } From 4492780bd06f1f29bc8c80a796ac46ab28468aad Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Fri, 9 Dec 2022 23:09:13 -0500 Subject: [PATCH 15/49] revert a `StaticSystemParam` bound --- crates/bevy_ecs/src/system/system_param.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 4d4dc3ee1c4d3..3cea17543f733 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -1403,7 +1403,7 @@ pub mod lifetimeless { /// # } /// ``` /// -pub struct StaticSystemParam<'w, 's, P: SystemParam + 's>(SystemParamItem<'w, 's, P>); +pub struct StaticSystemParam<'w, 's, P: SystemParam>(SystemParamItem<'w, 's, P>); impl<'w, 's, P: SystemParam> Deref for StaticSystemParam<'w, 's, P> { type Target = SystemParamItem<'w, 's, P>; From 5d1223d8dfb8efca9dc53075fd6d6f447fc85ed1 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Fri, 9 Dec 2022 23:38:38 -0500 Subject: [PATCH 16/49] remove a useless bound from `ParamSet` --- crates/bevy_ecs/macros/src/lib.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index 733358c318d0d..70423f0cabe8c 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -246,9 +246,6 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream { // 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<'_w, '_s, #(#param: SystemParam,)*> SystemParam for ParamSet<'_w, '_s, (#(#param,)*)> - where #( - for<'w, 's> #param::Item::<'w, 's>: SystemParam, - )* { type State = (#(#param::State,)*); type Item<'w, 's> = ParamSet<'w, 's, (#(#param::Item<'w, 's>,)*)>; From 2c75ad4a8244a6bfd91ee1032f5fedccb01cde90 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Mon, 12 Dec 2022 00:09:07 -0500 Subject: [PATCH 17/49] add docs to `SystemParam::Item` --- crates/bevy_ecs/src/system/system_param.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index be1532a6a619c..1b3d4df2434fa 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -130,6 +130,11 @@ use std::{ /// conflicting access across all [`SystemParam`]'s. pub unsafe trait SystemParam: Sized { type State: Send + Sync + 'static; + + /// The item type returned when constructing this system param. + /// The value of this associated type should be `Self`, instantiated with new lifetimes. + /// + /// You could think of `SystemParam::Item<'w, 's>` as being an *operation* that changes the lifetimes bound to a type. type Item<'world, 'state>: SystemParam; fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State; From c166192c661db0c555909c70aba4212ddb187b14 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Mon, 12 Dec 2022 00:11:56 -0500 Subject: [PATCH 18/49] fix safety comment rebase error --- crates/bevy_ecs/src/system/system_param.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 1b3d4df2434fa..7b1603be79470 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -177,7 +177,8 @@ unsafe impl<'w, 's, Q: ReadOnlyWorldQuery + 'static, F: ReadOnlyWorldQuery + 'st { } -// SAFETY: QueryState is constrained to read-only fetches, so it only reads World. +// SAFETY: Relevant query ComponentId and ArchetypeComponentId access is applied to SystemMeta. If +// this Query conflicts with any prior access, a panic will occur. unsafe impl<'_w, '_s, Q: WorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> SystemParam for Query<'_w, '_s, Q, F> { From 21e62a4357d5f6c6b71f07c31494e8a8381657a2 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Mon, 12 Dec 2022 00:15:51 -0500 Subject: [PATCH 19/49] use elided lifetimes --- crates/bevy_ecs/src/system/system_param.rs | 14 +++++++------- crates/bevy_render/src/extract_param.rs | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 7b1603be79470..63b3fb1fb3fb3 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -179,8 +179,8 @@ unsafe impl<'w, 's, Q: ReadOnlyWorldQuery + 'static, F: ReadOnlyWorldQuery + 'st // SAFETY: Relevant query ComponentId and ArchetypeComponentId access is applied to SystemMeta. If // this Query conflicts with any prior access, a panic will occur. -unsafe impl<'_w, '_s, Q: WorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> SystemParam - for Query<'_w, '_s, Q, F> +unsafe impl SystemParam + for Query<'_, '_, Q, F> { type State = QueryState; type Item<'w, 's> = Query<'w, 's, Q, F>; @@ -567,7 +567,7 @@ unsafe impl<'a, T: Resource> SystemParam for Option> { unsafe impl<'w, 's> ReadOnlySystemParam for Commands<'w, 's> {} // SAFETY: only local state is accessed -unsafe impl<'_w, '_s> SystemParam for Commands<'_w, '_s> { +unsafe impl SystemParam for Commands<'_, '_> { type State = CommandQueue; type Item<'w, 's> = Commands<'w, 's>; @@ -598,7 +598,7 @@ unsafe impl<'_w, '_s> SystemParam for Commands<'_w, '_s> { unsafe impl<'w> ReadOnlySystemParam for &'w World {} // SAFETY: `read_all` access is set and conflicts result in a panic -unsafe impl<'_w> SystemParam for &'_w World { +unsafe impl SystemParam for &'_ World { type State = (); type Item<'w, 's> = &'w World; @@ -971,7 +971,7 @@ unsafe impl<'a, T: 'static> SystemParam for NonSend<'a, T> { // SAFETY: this impl defers to `NonSendState`, which initializes // and validates the correct world access -unsafe impl<'_w, T: 'static> SystemParam for Option> { +unsafe impl SystemParam for Option> { type State = ComponentId; type Item<'w, 's> = Option>; @@ -1270,7 +1270,7 @@ impl<'s> std::fmt::Display for SystemName<'s> { } // SAFETY: no component value access -unsafe impl<'_s> SystemParam for SystemName<'_s> { +unsafe impl SystemParam for SystemName<'_> { type State = SystemNameState; type Item<'w, 's> = SystemName<'s>; @@ -1444,7 +1444,7 @@ unsafe impl<'w, 's, P: ReadOnlySystemParam + 'static> ReadOnlySystemParam } // SAFETY: all methods are just delegated to `S`'s `SystemParamState` implementation -unsafe impl<'_w, '_s, P: SystemParam + 'static> SystemParam for StaticSystemParam<'_w, '_s, P> { +unsafe impl SystemParam for StaticSystemParam<'_, '_, P> { type State = P::State; type Item<'world, 'state> = StaticSystemParam<'world, 'state, P>; diff --git a/crates/bevy_render/src/extract_param.rs b/crates/bevy_render/src/extract_param.rs index 4b3334caf74a1..ebdb7976b9973 100644 --- a/crates/bevy_render/src/extract_param.rs +++ b/crates/bevy_render/src/extract_param.rs @@ -48,7 +48,7 @@ where // SAFETY: only accesses MainWorld resource with read only system params using Res, // which is initialized in init() -unsafe impl<'_w, '_s, P> SystemParam for Extract<'_w, '_s, P> +unsafe impl

SystemParam for Extract<'_, '_, P> where P: ReadOnlySystemParam, { From 65a949fe290a0fa17f1cd0905caa37b29f3d4c5e Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Mon, 12 Dec 2022 00:21:11 -0500 Subject: [PATCH 20/49] fix a doc link --- crates/bevy_ecs/src/system/system_param.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 63b3fb1fb3fb3..656238fd12994 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -125,9 +125,9 @@ use std::{ /// # Safety /// /// It is the implementor's responsibility to ensure `system_meta` is populated with the _exact_ -/// [`World`] access used by the [`SystemParamState`]. +/// [`World`] access used by this [`SystemParam`]. /// Additionally, it is the implementor's responsibility to ensure there is no -/// conflicting access across all [`SystemParam`]'s. +/// conflicting access across all `SystemParam`'s. pub unsafe trait SystemParam: Sized { type State: Send + Sync + 'static; From 0c18690c0d2bf8341482fd432beb30df9fd30280 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Mon, 12 Dec 2022 00:27:40 -0500 Subject: [PATCH 21/49] churn bad --- crates/bevy_ecs/src/system/system_param.rs | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 656238fd12994..c56c7dc68b53e 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -440,6 +440,9 @@ unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> { } } +// SAFETY: Only reads a single World resource +unsafe impl<'a, T: Resource> ReadOnlySystemParam for Option> {} + // SAFETY: this impl defers to `ResState`, which initializes // and validates the correct world access unsafe impl<'a, T: Resource> SystemParam for Option> { @@ -469,9 +472,6 @@ unsafe impl<'a, T: Resource> SystemParam for Option> { } } -// SAFETY: Only reads a single World resource -unsafe impl<'a, T: Resource> ReadOnlySystemParam for Option> {} - // SAFETY: Res ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this Res // conflicts with any prior access, a panic will occur. unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> { @@ -1086,6 +1086,9 @@ unsafe impl<'a, T: 'static> SystemParam for Option> { } } +// SAFETY: Only reads World archetypes +unsafe impl<'a> ReadOnlySystemParam for &'a Archetypes {} + // SAFETY: no component value access unsafe impl<'a> SystemParam for &'a Archetypes { type State = (); @@ -1104,8 +1107,8 @@ unsafe impl<'a> SystemParam for &'a Archetypes { } } -// SAFETY: Only reads World archetypes -unsafe impl<'a> ReadOnlySystemParam for &'a Archetypes {} +// SAFETY: Only reads World components +unsafe impl<'a> ReadOnlySystemParam for &'a Components {} // SAFETY: no component value access unsafe impl<'a> SystemParam for &'a Components { @@ -1125,8 +1128,8 @@ unsafe impl<'a> SystemParam for &'a Components { } } -// SAFETY: Only reads World components -unsafe impl<'a> ReadOnlySystemParam for &'a Components {} +// SAFETY: Only reads World entities +unsafe impl<'a> ReadOnlySystemParam for &'a Entities {} // SAFETY: no component value access unsafe impl<'a> SystemParam for &'a Entities { @@ -1146,8 +1149,8 @@ unsafe impl<'a> SystemParam for &'a Entities { } } -// SAFETY: Only reads World entities -unsafe impl<'a> ReadOnlySystemParam for &'a Entities {} +// SAFETY: Only reads World bundles +unsafe impl<'a> ReadOnlySystemParam for &'a Bundles {} // SAFETY: no component value access unsafe impl<'a> SystemParam for &'a Bundles { @@ -1167,9 +1170,6 @@ unsafe impl<'a> SystemParam for &'a Bundles { } } -// SAFETY: Only reads World bundles -unsafe impl<'a> ReadOnlySystemParam for &'a Bundles {} - /// A [`SystemParam`] that reads the previous and current change ticks of the system. /// /// A system's change ticks are updated each time it runs: From 2789f2865b1fdce0d46ba3044c99050a0642e988 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Mon, 12 Dec 2022 10:30:01 -0500 Subject: [PATCH 22/49] be more specific about a type --- crates/bevy_ecs/src/system/system_param.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index c56c7dc68b53e..e3494aee3b699 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -134,7 +134,7 @@ pub unsafe trait SystemParam: Sized { /// The item type returned when constructing this system param. /// The value of this associated type should be `Self`, instantiated with new lifetimes. /// - /// You could think of `SystemParam::Item<'w, 's>` as being an *operation* that changes the lifetimes bound to a type. + /// You could think of `SystemParam::Item<'w, 's>` as being an *operation* that changes the lifetimes bound to `Self`. type Item<'world, 'state>: SystemParam; fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State; From 87b696be255c62b9905369d7c6b52a0898eea535 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Mon, 12 Dec 2022 11:09:53 -0500 Subject: [PATCH 23/49] simplify `ParamSet::Item` --- crates/bevy_ecs/macros/src/lib.rs | 2 +- crates/bevy_ecs/src/system/function_system.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index eaffa4a403ce4..ee6d4492bee49 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -248,7 +248,7 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream { unsafe impl<'_w, '_s, #(#param: SystemParam,)*> SystemParam for ParamSet<'_w, '_s, (#(#param,)*)> { type State = (#(#param::State,)*); - type Item<'w, 's> = ParamSet<'w, 's, (#(#param::Item<'w, 's>,)*)>; + type Item<'w, 's> = ParamSet<'w, 's, (#(#param,)*)>; fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { #( diff --git a/crates/bevy_ecs/src/system/function_system.rs b/crates/bevy_ecs/src/system/function_system.rs index f151d7b5003bb..85a0024638798 100644 --- a/crates/bevy_ecs/src/system/function_system.rs +++ b/crates/bevy_ecs/src/system/function_system.rs @@ -511,7 +511,7 @@ impl Copy for SystemTypeIdLabel {} /// pub fn pipe( /// mut a: A, /// mut b: B, -/// ) -> impl FnMut(In, ParamSet<(SystemParamItem, SystemParamItem)>) -> BOut +/// ) -> impl FnMut(In, ParamSet<(AParam, BParam)>) -> BOut /// where /// // We need A and B to be systems, add those bounds /// A: SystemParamFunction, From bd7a0c21ba38a5ca236400e41d413c5c3f014df5 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Mon, 12 Dec 2022 11:48:16 -0500 Subject: [PATCH 24/49] remove doc references to `SystemParamState` --- .../src/system/commands/parallel_scope.rs | 2 +- crates/bevy_ecs/src/system/system_param.rs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/bevy_ecs/src/system/commands/parallel_scope.rs b/crates/bevy_ecs/src/system/commands/parallel_scope.rs index c21c03bc9d5b4..34fef0d0b5c73 100644 --- a/crates/bevy_ecs/src/system/commands/parallel_scope.rs +++ b/crates/bevy_ecs/src/system/commands/parallel_scope.rs @@ -12,7 +12,7 @@ use super::{CommandQueue, Commands}; #[doc(hidden)] #[derive(Default)] -/// The internal [`SystemParamState`] of the [`ParallelCommands`] type +/// The internal [`SystemParam`] state of the [`ParallelCommands`] type pub struct ParallelCommandsState { thread_local_storage: ThreadLocal>, } diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index e3494aee3b699..f8ddbb848bdc2 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>::State as SystemParamState>::Item<'_, '_>` +/// found associated type `<[ParamType] as SystemParam>::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 [`State`](`SystemParam::State`)'s [`Item`](`SystemParamState::Item`) is itself `F` +/// each field `F`'s [`Item`](`SystemParam::Item`)'s 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. @@ -166,7 +166,7 @@ pub unsafe trait SystemParam: Sized { /// 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`] +/// This must only be implemented for [`SystemParam`] impls that exclusively read the World passed in to [`SystemParam::get_param`] pub unsafe trait ReadOnlySystemParam: SystemParam {} pub type SystemParamItem<'w, 's, P> =

::Item<'w, 's>; @@ -811,7 +811,7 @@ impl<'a, T: Component> IntoIterator for &'a RemovedComponents<'a, T> { // SAFETY: Only reads World components unsafe impl<'a, T: Component> ReadOnlySystemParam for RemovedComponents<'a, T> {} -/// The [`SystemParamState`] of [`RemovedComponents`]. +/// The [`SystemParam`] state of [`RemovedComponents`]. #[doc(hidden)] pub struct RemovedComponentsState { component_id: ComponentId, @@ -1296,7 +1296,7 @@ unsafe impl SystemParam for SystemName<'_> { // SAFETY: Only reads internal system state unsafe impl<'s> ReadOnlySystemParam for SystemName<'s> {} -/// The [`SystemParamState`] of [`SystemName`]. +/// The [`SystemParam`] state of [`SystemName`]. #[doc(hidden)] pub struct SystemNameState { name: Cow<'static, str>, @@ -1308,7 +1308,7 @@ macro_rules! impl_system_param_tuple { // SAFETY: tuple consists only of ReadOnlySystemParams unsafe impl<$($param: ReadOnlySystemParam),*> ReadOnlySystemParam for ($($param,)*) {} - // SAFETY: implementors of each `SystemParamState` in the tuple have validated their impls + // SAFETY: implementors of each `SystemParam` in the tuple have validated their impls #[allow(clippy::undocumented_unsafe_blocks)] // false positive by clippy #[allow(non_snake_case)] unsafe impl<$($param: SystemParam),*> SystemParam for ($($param,)*) { @@ -1443,7 +1443,7 @@ unsafe impl<'w, 's, P: ReadOnlySystemParam + 'static> ReadOnlySystemParam { } -// SAFETY: all methods are just delegated to `S`'s `SystemParamState` implementation +// SAFETY: all methods are just delegated to `P`'s `SystemParam` implementation unsafe impl SystemParam for StaticSystemParam<'_, '_, P> { type State = P::State; type Item<'world, 'state> = StaticSystemParam<'world, 'state, P>; @@ -1466,7 +1466,7 @@ unsafe impl SystemParam for StaticSystemParam<'_, '_, world: &'world World, change_tick: u32, ) -> Self::Item<'world, 'state> { - // SAFETY: We properly delegate SystemParamState + // SAFETY: Defer to the safety of P::SystemParam StaticSystemParam(P::get_param(state, system_meta, world, change_tick)) } } From b3eb7852662681e36b6db55137244539eed5ffbf Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Mon, 12 Dec 2022 12:41:53 -0500 Subject: [PATCH 25/49] fix outdated comments --- crates/bevy_ecs/macros/src/lib.rs | 3 --- crates/bevy_ecs/src/system/system_param.rs | 14 +++++--------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index ee6d4492bee49..98648b124ac40 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -426,9 +426,6 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { let struct_name = &ast.ident; 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::State, e.g. EventReaderState can be accessed via - // as SystemParam>::State const _: () = { unsafe impl<'w, 's, #punctuated_generics> #path::system::SystemParam for #struct_name #ty_generics #where_clause { type State = <(#(#field_types,)*) as #path::system::SystemParam>::State; diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index f8ddbb848bdc2..32505ca96b302 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -443,8 +443,7 @@ unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> { // SAFETY: Only reads a single World resource unsafe impl<'a, T: Resource> ReadOnlySystemParam for Option> {} -// SAFETY: this impl defers to `ResState`, which initializes -// and validates the correct world access +// SAFETY: this impl defers to `Res`, which initializes and validates the correct world access. unsafe impl<'a, T: Resource> SystemParam for Option> { type State = ComponentId; type Item<'w, 's> = Option>; @@ -532,8 +531,7 @@ unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> { } } -// SAFETY: this impl defers to `ResMutState`, which initializes -// and validates the correct world access +// SAFETY: this impl defers to `ResMut`, which initializes and validates the correct world access. unsafe impl<'a, T: Resource> SystemParam for Option> { type State = ComponentId; type Item<'w, 's> = Option>; @@ -969,8 +967,7 @@ unsafe impl<'a, T: 'static> SystemParam for NonSend<'a, T> { } } -// SAFETY: this impl defers to `NonSendState`, which initializes -// and validates the correct world access +// SAFETY: this impl defers to `NonSend`, which initializes and validates the correct world access. unsafe impl SystemParam for Option> { type State = ComponentId; type Item<'w, 's> = Option>; @@ -1059,8 +1056,7 @@ unsafe impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> { } } -// SAFETY: this impl defers to `NonSendMutState`, which initializes -// and validates the correct world access +// SAFETY: this impl defers to `NonSendMut`, which initializes and validates the correct world access. unsafe impl<'a, T: 'static> SystemParam for Option> { type State = ComponentId; type Item<'w, 's> = Option>; @@ -1202,7 +1198,7 @@ impl SystemChangeTick { // SAFETY: Only reads internal system state unsafe impl ReadOnlySystemParam for SystemChangeTick {} -// SAFETY: `SystemParamTickState` doesn't require any world access +// SAFETY: `SystemChangeTick` doesn't require any world access unsafe impl SystemParam for SystemChangeTick { type State = (); type Item<'w, 's> = SystemChangeTick; From 741849741354313dc601ef6ee5cbd3657a8ea374 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Mon, 12 Dec 2022 13:21:18 -0500 Subject: [PATCH 26/49] be more specific about a safety invariant --- crates/bevy_ecs/src/system/system_param.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 32505ca96b302..4e97ba325133b 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -124,8 +124,9 @@ use std::{ /// /// # Safety /// -/// It is the implementor's responsibility to ensure `system_meta` is populated with the _exact_ -/// [`World`] access used by this [`SystemParam`]. +/// The implementor must ensure that [`SystemParam::init`] correctly registers all +/// [`World`] accesses used by this [`SystemParam`] with the provided [`system_meta`](SystemMeta). +/// /// Additionally, it is the implementor's responsibility to ensure there is no /// conflicting access across all `SystemParam`'s. pub unsafe trait SystemParam: Sized { From 8325859594608773f8adbce406319e099b3d7a44 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Mon, 12 Dec 2022 13:36:05 -0500 Subject: [PATCH 27/49] add docs to `SystemParam::State` --- crates/bevy_ecs/src/system/system_param.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 4e97ba325133b..1241ab661cc6a 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -130,6 +130,7 @@ use std::{ /// Additionally, it is the implementor's responsibility to ensure there is no /// conflicting access across all `SystemParam`'s. pub unsafe trait SystemParam: Sized { + /// Used to store data which persists across invocations of a system. type State: Send + Sync + 'static; /// The item type returned when constructing this system param. From db60b72290224008d6001ba3be3f4173b4bc4d11 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Mon, 12 Dec 2022 13:53:17 -0500 Subject: [PATCH 28/49] fix meaningless safety invariants --- crates/bevy_ecs/src/system/system_param.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 1241ab661cc6a..8dd138b38e418 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -126,9 +126,6 @@ use std::{ /// /// The implementor must ensure that [`SystemParam::init`] correctly registers all /// [`World`] accesses used by this [`SystemParam`] with the provided [`system_meta`](SystemMeta). -/// -/// Additionally, it is the implementor's responsibility to ensure there is no -/// conflicting access across all `SystemParam`'s. pub unsafe trait SystemParam: Sized { /// Used to store data which persists across invocations of a system. type State: Send + Sync + 'static; @@ -155,8 +152,8 @@ pub unsafe trait SystemParam: Sized { /// # 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. + /// This call might use any of the [`World`] accesses that were registered in [`Self::init`]. + /// You must ensure that none of those accesses conflict with any other [`SystemParam`]s running in parallel with this one. unsafe fn get_param<'world, 'state>( state: &'state mut Self::State, system_meta: &SystemMeta, From 17372f6a0d0a4de84ec7b163cb33e4044cdad9b1 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Mon, 12 Dec 2022 14:00:03 -0500 Subject: [PATCH 29/49] document `SystemParam::apply` --- crates/bevy_ecs/src/system/system_param.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 8dd138b38e418..cb668f030d692 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -146,6 +146,8 @@ pub unsafe trait SystemParam: Sized { ) { } + /// Applies any deferred mutations stored in this [`SystemParam`]'s state. + /// This is used to apply [`Commands`] at the end of a stage. #[inline] #[allow(unused_variables)] fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {} From fe01fb13203f3d0fa9daedd5981a020a63332f8d Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Mon, 12 Dec 2022 14:06:07 -0500 Subject: [PATCH 30/49] add docs to `new_archetype` --- crates/bevy_ecs/src/system/system_param.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index cb668f030d692..7248c49e15e45 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -138,6 +138,7 @@ pub unsafe trait SystemParam: Sized { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State; + /// For the specified [`Archetype`], registers the components accessed by this [`SystemParam`] (if applicable). #[inline] fn new_archetype( _state: &mut Self::State, From 5d0c3b4f03bbf4316f90b6704de21ef291c66b8b Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Mon, 12 Dec 2022 14:07:52 -0500 Subject: [PATCH 31/49] add docs to `init` --- crates/bevy_ecs/src/system/system_param.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 7248c49e15e45..986cd7d9c5bd5 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -136,6 +136,8 @@ pub unsafe trait SystemParam: Sized { /// You could think of `SystemParam::Item<'w, 's>` as being an *operation* that changes the lifetimes bound to `Self`. type Item<'world, 'state>: SystemParam; + /// Registers any [`World`] access used by this [`SystemParam`] + /// and creates a new instance of this param's [`State`](Self::State). fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State; /// For the specified [`Archetype`], registers the components accessed by this [`SystemParam`] (if applicable). From ab256a5b856049844e9d23494b3b6f24e06b93b1 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Tue, 13 Dec 2022 22:04:52 -0500 Subject: [PATCH 32/49] add docs to `SystemParamItem` --- crates/bevy_ecs/src/system/system_param.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 986cd7d9c5bd5..defe614bfb451 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -173,6 +173,7 @@ pub unsafe trait SystemParam: Sized { /// This must only be implemented for [`SystemParam`] impls that exclusively read the World passed in to [`SystemParam::get_param`] pub unsafe trait ReadOnlySystemParam: SystemParam {} +/// Shorthand way of accessing the associated type [`SystemParam::Item`] for a given [`SystemParam`]. pub type SystemParamItem<'w, 's, P> =

::Item<'w, 's>; // SAFETY: QueryState is constrained to read-only fetches, so it only reads World. From 23204dca953f2f444e07579c3831988ab614d436 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Tue, 13 Dec 2022 22:10:26 -0500 Subject: [PATCH 33/49] remove another trivial state type --- crates/bevy_ecs/src/system/system_param.rs | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index defe614bfb451..2c497ba01b25e 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -814,36 +814,26 @@ impl<'a, T: Component> IntoIterator for &'a RemovedComponents<'a, T> { // SAFETY: Only reads World components unsafe impl<'a, T: Component> ReadOnlySystemParam for RemovedComponents<'a, T> {} -/// The [`SystemParam`] state of [`RemovedComponents`]. -#[doc(hidden)] -pub struct RemovedComponentsState { - component_id: ComponentId, - marker: PhantomData, -} - // SAFETY: no component access. removed component entity collections can be read in parallel and are // never mutably borrowed during system execution unsafe impl<'a, T: Component> SystemParam for RemovedComponents<'a, T> { - type State = RemovedComponentsState; + type State = ComponentId; type Item<'w, 's> = RemovedComponents<'w, T>; fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { - RemovedComponentsState { - component_id: world.init_component::(), - marker: PhantomData, - } + world.init_component::() } #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self::State, + &mut component_id: &'s mut Self::State, _system_meta: &SystemMeta, world: &'w World, _change_tick: u32, ) -> Self::Item<'w, 's> { RemovedComponents { world, - component_id: state.component_id, + component_id, marker: PhantomData, } } From be4b98b3d7a76c82dc0ab92fe3239fd4688a51ec Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Tue, 13 Dec 2022 22:12:38 -0500 Subject: [PATCH 34/49] move docs above an attribute --- crates/bevy_ecs/src/system/commands/parallel_scope.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/system/commands/parallel_scope.rs b/crates/bevy_ecs/src/system/commands/parallel_scope.rs index 34fef0d0b5c73..ee942572d3517 100644 --- a/crates/bevy_ecs/src/system/commands/parallel_scope.rs +++ b/crates/bevy_ecs/src/system/commands/parallel_scope.rs @@ -10,9 +10,9 @@ use crate::{ use super::{CommandQueue, Commands}; +/// The internal [`SystemParam`] state of the [`ParallelCommands`] type #[doc(hidden)] #[derive(Default)] -/// The internal [`SystemParam`] state of the [`ParallelCommands`] type pub struct ParallelCommandsState { thread_local_storage: ThreadLocal>, } From 7edd6dcf0629fd1b1c0961364f6e799fbdf56e9d Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Tue, 13 Dec 2022 22:34:33 -0500 Subject: [PATCH 35/49] yeet `SystemNameState` --- crates/bevy_ecs/src/system/system_param.rs | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 2c497ba01b25e..0867910e7b368 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -1262,37 +1262,27 @@ impl<'s> std::fmt::Display for SystemName<'s> { // SAFETY: no component value access unsafe impl SystemParam for SystemName<'_> { - type State = SystemNameState; + type State = Cow<'static, str>; type Item<'w, 's> = SystemName<'s>; fn init(_world: &mut World, system_meta: &mut SystemMeta) -> Self::State { - SystemNameState { - name: system_meta.name.clone(), - } + system_meta.name.clone() } #[inline] unsafe fn get_param<'w, 's>( - state: &'s mut Self::State, + name: &'s mut Self::State, _system_meta: &SystemMeta, _world: &'w World, _change_tick: u32, ) -> Self::Item<'w, 's> { - SystemName { - name: state.name.as_ref(), - } + SystemName { name } } } // SAFETY: Only reads internal system state unsafe impl<'s> ReadOnlySystemParam for SystemName<'s> {} -/// The [`SystemParam`] state of [`SystemName`]. -#[doc(hidden)] -pub struct SystemNameState { - name: Cow<'static, str>, -} - macro_rules! impl_system_param_tuple { ($($param: ident),*) => { From fbd94f18eadf1d5f664e7d52665881529b4c4ed7 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Thu, 15 Dec 2022 19:39:47 -0500 Subject: [PATCH 36/49] remove unnecessary fully-qualified type syntax --- crates/bevy_ecs/src/system/function_system.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/crates/bevy_ecs/src/system/function_system.rs b/crates/bevy_ecs/src/system/function_system.rs index 85a0024638798..41b37d8801ca3 100644 --- a/crates/bevy_ecs/src/system/function_system.rs +++ b/crates/bevy_ecs/src/system/function_system.rs @@ -147,7 +147,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 = Param::init(world, &mut meta); Self { meta, param_state, @@ -221,12 +221,7 @@ impl SystemState { world: &'w World, ) -> SystemParamItem<'w, 's, Param> { let change_tick = world.increment_change_tick(); - let param = ::get_param( - &mut self.param_state, - &self.meta, - world, - change_tick, - ); + let param = Param::get_param(&mut self.param_state, &self.meta, world, change_tick); self.meta.last_change_tick = change_tick; param } @@ -398,7 +393,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 = ::get_param( + let params = Param::get_param( self.param_state.as_mut().expect(Self::PARAM_MESSAGE), &self.system_meta, world, @@ -427,7 +422,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(world, &mut self.system_meta)); + self.param_state = Some(Param::init(world, &mut self.system_meta)); } fn update_archetype_component_access(&mut self, world: &World) { From fa56c5e8d8c177ffc3c4528f10715c93bf71d4c6 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Fri, 16 Dec 2022 12:48:36 -0500 Subject: [PATCH 37/49] `init` -> `init_state` --- crates/bevy_ecs/macros/src/lib.rs | 10 ++-- .../src/system/commands/parallel_scope.rs | 2 +- crates/bevy_ecs/src/system/function_system.rs | 4 +- crates/bevy_ecs/src/system/system_param.rs | 56 +++++++++---------- crates/bevy_render/src/extract_param.rs | 4 +- 5 files changed, 38 insertions(+), 38 deletions(-) diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index 98648b124ac40..aecd2afa4177c 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -250,14 +250,14 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream { type State = (#(#param::State,)*); type Item<'w, 's> = ParamSet<'w, 's, (#(#param,)*)>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { #( // 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::init(world, &mut #meta); - let #param = #param::init(world, &mut system_meta.clone()); + #param::init_state(world, &mut #meta); + let #param = #param::init_state(world, &mut system_meta.clone()); )* #( system_meta @@ -431,8 +431,8 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { type State = <(#(#field_types,)*) as #path::system::SystemParam>::State; type Item<'_w, '_s> = #struct_name <#(#shadowed_lifetimes,)* #punctuated_generic_idents>; - fn init(world: &mut #path::world::World, system_meta: &mut #path::system::SystemMeta) -> Self::State { - <(#(#field_types,)*) as #path::system::SystemParam>::init(world, system_meta) + fn init_state(world: &mut #path::world::World, system_meta: &mut #path::system::SystemMeta) -> Self::State { + <(#(#field_types,)*) as #path::system::SystemParam>::init_state(world, system_meta) } fn new_archetype(state: &mut Self::State, archetype: &#path::archetype::Archetype, system_meta: &mut #path::system::SystemMeta) { diff --git a/crates/bevy_ecs/src/system/commands/parallel_scope.rs b/crates/bevy_ecs/src/system/commands/parallel_scope.rs index ee942572d3517..5975e9d668d68 100644 --- a/crates/bevy_ecs/src/system/commands/parallel_scope.rs +++ b/crates/bevy_ecs/src/system/commands/parallel_scope.rs @@ -53,7 +53,7 @@ unsafe impl SystemParam for ParallelCommands<'_, '_> { type State = ParallelCommandsState; type Item<'w, 's> = ParallelCommands<'w, 's>; - fn init(_: &mut World, _: &mut crate::system::SystemMeta) -> Self::State { + fn init_state(_: &mut World, _: &mut crate::system::SystemMeta) -> Self::State { ParallelCommandsState::default() } diff --git a/crates/bevy_ecs/src/system/function_system.rs b/crates/bevy_ecs/src/system/function_system.rs index 41b37d8801ca3..6a78ab3d95e05 100644 --- a/crates/bevy_ecs/src/system/function_system.rs +++ b/crates/bevy_ecs/src/system/function_system.rs @@ -147,7 +147,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 = Param::init(world, &mut meta); + let param_state = Param::init_state(world, &mut meta); Self { meta, param_state, @@ -422,7 +422,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(Param::init(world, &mut self.system_meta)); + self.param_state = Some(Param::init_state(world, &mut self.system_meta)); } fn update_archetype_component_access(&mut self, world: &World) { diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 0867910e7b368..627b197feb9c0 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -138,7 +138,7 @@ pub unsafe trait SystemParam: Sized { /// Registers any [`World`] access used by this [`SystemParam`] /// and creates a new instance of this param's [`State`](Self::State). - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State; + fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State; /// For the specified [`Archetype`], registers the components accessed by this [`SystemParam`] (if applicable). #[inline] @@ -190,7 +190,7 @@ unsafe impl SystemPara type State = QueryState; type Item<'w, 's> = Query<'w, 's, Q, F>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { let state = QueryState::new(world); assert_component_access_compatibility( &system_meta.name, @@ -396,7 +396,7 @@ unsafe impl<'a, T: Resource> SystemParam for Res<'a, T> { type State = ComponentId; type Item<'w, 's> = Res<'w, T>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { let component_id = world.initialize_resource::(); let combined_access = system_meta.component_access_set.combined_access(); assert!( @@ -453,8 +453,8 @@ unsafe impl<'a, T: Resource> SystemParam for Option> { type State = ComponentId; type Item<'w, 's> = Option>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { - Res::::init(world, system_meta) + fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + Res::::init_state(world, system_meta) } #[inline] @@ -482,7 +482,7 @@ unsafe impl<'a, T: Resource> SystemParam for ResMut<'a, T> { type State = ComponentId; type Item<'w, 's> = ResMut<'w, T>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { let component_id = world.initialize_resource::(); let combined_access = system_meta.component_access_set.combined_access(); if combined_access.has_write(component_id) { @@ -541,8 +541,8 @@ unsafe impl<'a, T: Resource> SystemParam for Option> { type State = ComponentId; type Item<'w, 's> = Option>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { - ResMut::::init(world, system_meta) + fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + ResMut::::init_state(world, system_meta) } #[inline] @@ -574,7 +574,7 @@ unsafe impl SystemParam for Commands<'_, '_> { type State = CommandQueue; type Item<'w, 's> = Commands<'w, 's>; - fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { + fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { Default::default() } @@ -605,7 +605,7 @@ unsafe impl SystemParam for &'_ World { type State = (); type Item<'w, 's> = &'w World; - fn init(_world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + fn init_state(_world: &mut World, system_meta: &mut SystemMeta) -> Self::State { let mut access = Access::default(); access.read_all(); if !system_meta @@ -741,7 +741,7 @@ unsafe impl<'a, T: FromWorld + Send + 'static> SystemParam for Local<'a, T> { type State = SyncCell; type Item<'w, 's> = Local<'s, T>; - fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { + fn init_state(world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { SyncCell::new(T::from_world(world)) } @@ -820,7 +820,7 @@ unsafe impl<'a, T: Component> SystemParam for RemovedComponents<'a, T> { type State = ComponentId; type Item<'w, 's> = RemovedComponents<'w, T>; - fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { + fn init_state(world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { world.init_component::() } @@ -910,7 +910,7 @@ unsafe impl<'a, T: 'static> SystemParam for NonSend<'a, T> { type State = ComponentId; type Item<'w, 's> = NonSend<'w, T>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { system_meta.set_non_send(); let component_id = world.initialize_non_send_resource::(); @@ -967,8 +967,8 @@ unsafe impl SystemParam for Option> { type State = ComponentId; type Item<'w, 's> = Option>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { - NonSend::::init(world, system_meta) + fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + NonSend::::init_state(world, system_meta) } #[inline] @@ -999,7 +999,7 @@ unsafe impl<'a, T: 'static> SystemParam for NonSendMut<'a, T> { type State = ComponentId; type Item<'w, 's> = NonSendMut<'w, T>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { system_meta.set_non_send(); let component_id = world.initialize_non_send_resource::(); @@ -1056,8 +1056,8 @@ unsafe impl<'a, T: 'static> SystemParam for Option> { type State = ComponentId; type Item<'w, 's> = Option>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { - NonSendMut::::init(world, system_meta) + fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + NonSendMut::::init_state(world, system_meta) } #[inline] @@ -1085,7 +1085,7 @@ unsafe impl<'a> SystemParam for &'a Archetypes { type State = (); type Item<'w, 's> = &'w Archetypes; - fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} + fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} #[inline] unsafe fn get_param<'w, 's>( @@ -1106,7 +1106,7 @@ unsafe impl<'a> SystemParam for &'a Components { type State = (); type Item<'w, 's> = &'w Components; - fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} + fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} #[inline] unsafe fn get_param<'w, 's>( @@ -1127,7 +1127,7 @@ unsafe impl<'a> SystemParam for &'a Entities { type State = (); type Item<'w, 's> = &'w Entities; - fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} + fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} #[inline] unsafe fn get_param<'w, 's>( @@ -1148,7 +1148,7 @@ unsafe impl<'a> SystemParam for &'a Bundles { type State = (); type Item<'w, 's> = &'w Bundles; - fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} + fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} #[inline] unsafe fn get_param<'w, 's>( @@ -1198,7 +1198,7 @@ unsafe impl SystemParam for SystemChangeTick { type State = (); type Item<'w, 's> = SystemChangeTick; - fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} + fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {} unsafe fn get_param<'w, 's>( _state: &'s mut Self::State, @@ -1265,7 +1265,7 @@ unsafe impl SystemParam for SystemName<'_> { type State = Cow<'static, str>; type Item<'w, 's> = SystemName<'s>; - fn init(_world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + fn init_state(_world: &mut World, system_meta: &mut SystemMeta) -> Self::State { system_meta.name.clone() } @@ -1297,8 +1297,8 @@ macro_rules! impl_system_param_tuple { type Item<'w, 's> = ($($param::Item::<'w, 's>,)*); #[inline] - fn init(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { - (($($param::init(_world, _system_meta),)*)) + fn init_state(_world: &mut World, _system_meta: &mut SystemMeta) -> Self::State { + (($($param::init_state(_world, _system_meta),)*)) } #[inline] @@ -1429,8 +1429,8 @@ unsafe impl SystemParam for StaticSystemParam<'_, '_, type State = P::State; type Item<'world, 'state> = StaticSystemParam<'world, 'state, P>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { - P::init(world, system_meta) + fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + P::init_state(world, system_meta) } fn new_archetype(state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta) { diff --git a/crates/bevy_render/src/extract_param.rs b/crates/bevy_render/src/extract_param.rs index ebdb7976b9973..a90ba4fd56281 100644 --- a/crates/bevy_render/src/extract_param.rs +++ b/crates/bevy_render/src/extract_param.rs @@ -55,11 +55,11 @@ where type State = ExtractState

; type Item<'w, 's> = Extract<'w, 's, P>; - fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { + fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { let mut main_world = world.resource_mut::(); ExtractState { state: SystemState::new(&mut main_world), - main_world_state: Res::::init(world, system_meta), + main_world_state: Res::::init_state(world, system_meta), } } From 7682ae2929511485bc9408a7ea183d81d2c35aed Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Fri, 16 Dec 2022 13:05:07 -0500 Subject: [PATCH 38/49] fix doc links --- crates/bevy_ecs/src/system/system_param.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 627b197feb9c0..ef231ef900489 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -124,7 +124,7 @@ use std::{ /// /// # Safety /// -/// The implementor must ensure that [`SystemParam::init`] correctly registers all +/// The implementor must ensure that [`SystemParam::init_state`] correctly registers all /// [`World`] accesses used by this [`SystemParam`] with the provided [`system_meta`](SystemMeta). pub unsafe trait SystemParam: Sized { /// Used to store data which persists across invocations of a system. @@ -157,7 +157,7 @@ pub unsafe trait SystemParam: Sized { /// # Safety /// - /// This call might use any of the [`World`] accesses that were registered in [`Self::init`]. + /// This call might use any of the [`World`] accesses that were registered in [`Self::init_init`]. /// You must ensure that none of those accesses conflict with any other [`SystemParam`]s running in parallel with this one. unsafe fn get_param<'world, 'state>( state: &'state mut Self::State, From 5f59bf31d7078738cbc7be320df4b8b7b4c80932 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Fri, 16 Dec 2022 13:05:43 -0500 Subject: [PATCH 39/49] .. --- crates/bevy_ecs/src/system/system_param.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index ef231ef900489..fc4bcc32bf89c 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -157,7 +157,7 @@ pub unsafe trait SystemParam: Sized { /// # Safety /// - /// This call might use any of the [`World`] accesses that were registered in [`Self::init_init`]. + /// This call might use any of the [`World`] accesses that were registered in [`Self::init_state`]. /// You must ensure that none of those accesses conflict with any other [`SystemParam`]s running in parallel with this one. unsafe fn get_param<'world, 'state>( state: &'state mut Self::State, From 566f7f398ad30d8afff60178e3d531fa348bd773 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Tue, 20 Dec 2022 23:49:25 -0500 Subject: [PATCH 40/49] cargo fmt --- crates/bevy_ecs/src/system/system_param.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 1e08b1a40c951..a7985e99d63dd 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -1517,10 +1517,10 @@ mod tests { #[system_param(ignore)] marker: PhantomData, } - + #[derive(SystemParam)] pub struct UnitParam; - + #[derive(SystemParam)] pub struct TupleParam<'w, 's, R: Resource, L: FromWorld + Send + 'static>( Res<'w, R>, From 58623ee4ee32465dc19948d452be78ee639fd973 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Tue, 20 Dec 2022 23:51:13 -0500 Subject: [PATCH 41/49] fix merge errors --- crates/bevy_ecs/macros/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index 927fbc340c617..1a99e29506723 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -453,15 +453,15 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { type Item<'_w, '_s> = #struct_name <#(#shadowed_lifetimes,)* #punctuated_generic_idents>; fn init_state(world: &mut #path::world::World, system_meta: &mut #path::system::SystemMeta) -> Self::State { - <(#(#field_types,)*) as #path::system::SystemParam>::init_state(world, system_meta) + <(#(#tuple_types,)*) as #path::system::SystemParam>::init_state(world, system_meta) } fn new_archetype(state: &mut Self::State, archetype: &#path::archetype::Archetype, system_meta: &mut #path::system::SystemMeta) { - <(#(#field_types,)*) as #path::system::SystemParam>::new_archetype(state, archetype, system_meta) + <(#(#tuple_types,)*) as #path::system::SystemParam>::new_archetype(state, archetype, system_meta) } fn apply(state: &mut Self::State, system_meta: &#path::system::SystemMeta, world: &mut #path::world::World) { - <(#(#field_types,)*) as #path::system::SystemParam>::apply(state, system_meta, world); + <(#(#tuple_types,)*) as #path::system::SystemParam>::apply(state, system_meta, world); } unsafe fn get_param<'w2, 's2>( @@ -472,7 +472,7 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { ) -> Self::Item<'w2, 's2> { let (#(#tuple_patterns,)*) = < (#(#tuple_types,)*) as #path::system::SystemParam - >::get_param(&mut state.state, system_meta, world, change_tick); + >::get_param(state, system_meta, world, change_tick); #struct_name { #(#fields: #field_locals,)* #(#ignored_fields: <#ignored_field_types>::default(),)* From b3149d0201959e9ef850e6d8358ddb9fd8ba7bd5 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Tue, 20 Dec 2022 23:59:28 -0500 Subject: [PATCH 42/49] remove more unnecessary fully qualified types --- crates/bevy_ecs/macros/src/lib.rs | 4 ++-- crates/bevy_ecs/src/system/exclusive_system_param.rs | 2 +- crates/bevy_ecs/src/system/function_system.rs | 2 +- crates/bevy_ecs/src/system/system_param.rs | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index 1a99e29506723..bb97784ced652 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -227,7 +227,7 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream { // Conflicting params in ParamSet are not accessible at the same time // ParamSets are guaranteed to not conflict with other SystemParams unsafe { - <#param as SystemParam>::get_param(&mut self.param_states.#index, &self.system_meta, self.world, self.change_tick) + #param::get_param(&mut self.param_states.#index, &self.system_meta, self.world, self.change_tick) } } }); @@ -273,7 +273,7 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream { fn new_archetype(state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta) { let (#(#param,)*) = state; #( - <#param as SystemParam>::new_archetype(#param, archetype, system_meta); + #param::new_archetype(#param, archetype, 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 c5863afb9b620..e0c0f5678265f 100644 --- a/crates/bevy_ecs/src/system/exclusive_system_param.rs +++ b/crates/bevy_ecs/src/system/exclusive_system_param.rs @@ -78,7 +78,7 @@ macro_rules! impl_exclusive_system_param_tuple { fn apply(state: &mut Self::State, _world: &mut World) { let ($($param,)*) = state; $( - <$param as ExclusiveSystemParam>::apply($param, _world); + $param::apply($param, _world); )* } diff --git a/crates/bevy_ecs/src/system/function_system.rs b/crates/bevy_ecs/src/system/function_system.rs index 6a78ab3d95e05..f99ae67b15a4a 100644 --- a/crates/bevy_ecs/src/system/function_system.rs +++ b/crates/bevy_ecs/src/system/function_system.rs @@ -138,7 +138,7 @@ impl SystemMeta { /// ``` pub struct SystemState { meta: SystemMeta, - param_state: ::State, + param_state: Param::State, world_id: WorldId, archetype_generation: ArchetypeGeneration, } diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index a7985e99d63dd..14e9f656bc159 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -1304,14 +1304,14 @@ macro_rules! impl_system_param_tuple { #[inline] fn new_archetype(($($param,)*): &mut Self::State, _archetype: &Archetype, _system_meta: &mut SystemMeta) { $( - <$param as SystemParam>::new_archetype($param, _archetype, _system_meta); + $param::new_archetype($param, _archetype, _system_meta); )* } #[inline] fn apply(($($param,)*): &mut Self::State, _system_meta: &SystemMeta, _world: &mut World) { $( - <$param as SystemParam>::apply($param, _system_meta, _world); + $param::apply($param, _system_meta, _world); )* } From 5df68aeff8f19edf220246e29fd41536d73bd81c Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 21 Dec 2022 00:03:07 -0500 Subject: [PATCH 43/49] simplify repetion --- crates/bevy_ecs/src/system/system_param.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 14e9f656bc159..c63816db0b3b6 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -1303,16 +1303,12 @@ macro_rules! impl_system_param_tuple { #[inline] fn new_archetype(($($param,)*): &mut Self::State, _archetype: &Archetype, _system_meta: &mut SystemMeta) { - $( - $param::new_archetype($param, _archetype, _system_meta); - )* + $($param::new_archetype($param, _archetype, _system_meta);)* } #[inline] fn apply(($($param,)*): &mut Self::State, _system_meta: &SystemMeta, _world: &mut World) { - $( - $param::apply($param, _system_meta, _world); - )* + $($param::apply($param, _system_meta, _world);)* } #[inline] From 69804773245a9929e8b1b666434092945bc4ff5b Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Sat, 24 Dec 2022 20:38:04 -0500 Subject: [PATCH 44/49] removed unused punctuated generics --- crates/bevy_ecs/macros/src/lib.rs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index 10f5986875660..053562bfa1451 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -429,21 +429,6 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { _ => unreachable!(), })); - let mut punctuated_generics_no_bounds = punctuated_generics.clone(); - for g in &mut punctuated_generics_no_bounds { - match g { - GenericParam::Type(g) => g.bounds.clear(), - GenericParam::Lifetime(g) => g.bounds.clear(), - GenericParam::Const(_) => {} - } - } - - let mut punctuated_type_generic_idents = Punctuated::<_, Token![,]>::new(); - punctuated_type_generic_idents.extend(lifetimeless_generics.iter().filter_map(|g| match g { - GenericParam::Type(g) => Some(&g.ident), - _ => None, - })); - let mut punctuated_generic_idents = Punctuated::<_, Token![,]>::new(); punctuated_generic_idents.extend(lifetimeless_generics.iter().map(|g| match g { GenericParam::Type(g) => &g.ident, From 76dea874745ded254b9240d0dd695d35e02d9f1b Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Tue, 27 Dec 2022 13:38:47 -0500 Subject: [PATCH 45/49] simplify `ParamSet::new_archetype` --- crates/bevy_ecs/macros/src/lib.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index 053562bfa1451..f88020e8a236e 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -281,10 +281,7 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream { } fn new_archetype(state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta) { - let (#(#param,)*) = state; - #( - #param::new_archetype(#param, archetype, system_meta); - )* + <(#(#param,)*) as SystemParam>::new_archetype(state, archetype, system_meta); } fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) { From a06129a8cc4fdf3c19462571c8aadeb610dc3b09 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Tue, 27 Dec 2022 13:44:46 -0500 Subject: [PATCH 46/49] simplify more repetition --- crates/bevy_ecs/src/system/exclusive_system_param.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/bevy_ecs/src/system/exclusive_system_param.rs b/crates/bevy_ecs/src/system/exclusive_system_param.rs index e0c0f5678265f..4b6342660439e 100644 --- a/crates/bevy_ecs/src/system/exclusive_system_param.rs +++ b/crates/bevy_ecs/src/system/exclusive_system_param.rs @@ -77,9 +77,7 @@ macro_rules! impl_exclusive_system_param_tuple { #[inline] fn apply(state: &mut Self::State, _world: &mut World) { let ($($param,)*) = state; - $( - $param::apply($param, _world); - )* + $($param::apply($param, _world);)* } #[inline] From 02a70092746b1089f7f17db977b1017708f59e39 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 4 Jan 2023 23:02:47 -0500 Subject: [PATCH 47/49] remove an unused variable --- crates/bevy_ecs/macros/src/lib.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index 3bdc0759ffb6a..5951a5668c068 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -426,15 +426,6 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { _ => unreachable!(), })); - let mut punctuated_generics_no_bounds = punctuated_generics.clone(); - for g in &mut punctuated_generics_no_bounds { - match g { - GenericParam::Type(g) => g.bounds.clear(), - GenericParam::Lifetime(g) => g.bounds.clear(), - GenericParam::Const(_) => {} - } - } - let mut punctuated_generic_idents = Punctuated::<_, Token![,]>::new(); punctuated_generic_idents.extend(lifetimeless_generics.iter().map(|g| match g { GenericParam::Type(g) => &g.ident, From 5e1625df898b18693394ad57a683769393e9595e Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Wed, 4 Jan 2023 23:04:02 -0500 Subject: [PATCH 48/49] re-add a comment --- crates/bevy_ecs/macros/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/bevy_ecs/macros/src/lib.rs b/crates/bevy_ecs/macros/src/lib.rs index 5951a5668c068..1990f89107774 100644 --- a/crates/bevy_ecs/macros/src/lib.rs +++ b/crates/bevy_ecs/macros/src/lib.rs @@ -460,6 +460,9 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream { 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::State, e.g. EventReaderState can be accessed via + // as SystemParam>::State const _: () = { #[doc(hidden)] #state_struct_visibility struct FetchState <'w, 's, #(#lifetimeless_generics,)*> { From 550edd5e438450496c683cfac5004a705fc5fd71 Mon Sep 17 00:00:00 2001 From: JoJoJet <21144246+JoJoJet@users.noreply.github.com> Date: Sat, 7 Jan 2023 17:58:35 -0500 Subject: [PATCH 49/49] reduce extract_param churn --- crates/bevy_render/src/extract_param.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/bevy_render/src/extract_param.rs b/crates/bevy_render/src/extract_param.rs index a90ba4fd56281..4038a71aa6a50 100644 --- a/crates/bevy_render/src/extract_param.rs +++ b/crates/bevy_render/src/extract_param.rs @@ -46,6 +46,12 @@ where item: SystemParamItem<'w, 's, P>, } +#[doc(hidden)] +pub struct ExtractState { + state: SystemState

, + main_world_state: as SystemParam>::State, +} + // SAFETY: only accesses MainWorld resource with read only system params using Res, // which is initialized in init() unsafe impl

SystemParam for Extract<'_, '_, P> @@ -80,12 +86,6 @@ where } } -#[doc(hidden)] -pub struct ExtractState { - state: SystemState

, - main_world_state: as SystemParam>::State, -} - impl<'w, 's, P> Deref for Extract<'w, 's, P> where P: ReadOnlySystemParam,