Skip to content

Commit 1efdbb7

Browse files
committed
Remove the SystemParamState trait and remove types like ResState (#6919)
Spiritual successor to #5205. Actual successor to #6865. # Objective Currently, system params are defined using three traits: `SystemParam`, `ReadOnlySystemParam`, `SystemParamState`. The behavior for each param is specified by the `SystemParamState` trait, while `SystemParam` simply defers to the state. Splitting the traits in this way makes it easier to implement within macros, but it increases the cognitive load. Worst of all, this approach requires each `MySystemParam` to have a public `MySystemParamState` type associated with it. ## Solution * Merge the trait `SystemParamState` into `SystemParam`. * Remove all trivial `SystemParam` state types. * `OptionNonSendMutState<T>`: you will not be missed. --- - [x] Fix/resolve the remaining test failure. ## Changelog * Removed the trait `SystemParamState`, merging its functionality into `SystemParam`. ## Migration Guide **Note**: this should replace the migration guide for #6865. This is relative to Bevy 0.9, not main. The traits `SystemParamState` and `SystemParamFetch` have been removed, and their functionality has been transferred to `SystemParam`. ```rust // Before (0.9) impl SystemParam for MyParam<'_, '_> { type State = MyParamState; } unsafe impl SystemParamState for MyParamState { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { ... } } unsafe impl<'w, 's> SystemParamFetch<'w, 's> for MyParamState { type Item = MyParam<'w, 's>; fn get_param(&mut self, ...) -> Self::Item; } unsafe impl ReadOnlySystemParamFetch for MyParamState { } // After (0.10) unsafe impl SystemParam for MyParam<'_, '_> { type State = MyParamState; type Item<'w, 's> = MyParam<'w, 's>; fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State { ... } fn get_param<'w, 's>(state: &mut Self::State, ...) -> Self::Item<'w, 's>; } unsafe impl ReadOnlySystemParam for MyParam<'_, '_> { } ``` The trait `ReadOnlySystemParamFetch` has been replaced with `ReadOnlySystemParam`. ```rust // Before unsafe impl ReadOnlySystemParamFetch for MyParamState {} // After unsafe impl ReadOnlySystemParam for MyParam<'_, '_> {} ```
1 parent 076e6f7 commit 1efdbb7

File tree

7 files changed

+288
-527
lines changed

7 files changed

+288
-527
lines changed

crates/bevy_ecs/macros/src/lib.rs

Lines changed: 37 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,6 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream {
216216
let mut tokens = TokenStream::new();
217217
let max_params = 8;
218218
let params = get_idents(|i| format!("P{i}"), max_params);
219-
let params_state = get_idents(|i| format!("PF{i}"), max_params);
220219
let metas = get_idents(|i| format!("m{i}"), max_params);
221220
let mut param_fn_muts = Vec::new();
222221
for (i, param) in params.iter().enumerate() {
@@ -238,44 +237,37 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream {
238237
// Conflicting params in ParamSet are not accessible at the same time
239238
// ParamSets are guaranteed to not conflict with other SystemParams
240239
unsafe {
241-
<#param::State as SystemParamState>::get_param(&mut self.param_states.#index, &self.system_meta, self.world, self.change_tick)
240+
#param::get_param(&mut self.param_states.#index, &self.system_meta, self.world, self.change_tick)
242241
}
243242
}
244243
});
245244
}
246245

247246
for param_count in 1..=max_params {
248247
let param = &params[0..param_count];
249-
let param_state = &params_state[0..param_count];
250248
let meta = &metas[0..param_count];
251249
let param_fn_mut = &param_fn_muts[0..param_count];
252250
tokens.extend(TokenStream::from(quote! {
253-
impl<'w, 's, #(#param: SystemParam,)*> SystemParam for ParamSet<'w, 's, (#(#param,)*)>
254-
{
255-
type State = ParamSetState<(#(#param::State,)*)>;
256-
}
257-
258-
// SAFETY: All parameters are constrained to ReadOnlyState, so World is only read
259-
251+
// SAFETY: All parameters are constrained to ReadOnlySystemParam, so World is only read
260252
unsafe impl<'w, 's, #(#param,)*> ReadOnlySystemParam for ParamSet<'w, 's, (#(#param,)*)>
261253
where #(#param: ReadOnlySystemParam,)*
262254
{ }
263255

264256
// SAFETY: Relevant parameter ComponentId and ArchetypeComponentId access is applied to SystemMeta. If any ParamState conflicts
265257
// with any prior access, a panic will occur.
266-
267-
unsafe impl<#(#param_state: SystemParamState,)*> SystemParamState for ParamSetState<(#(#param_state,)*)>
258+
unsafe impl<'_w, '_s, #(#param: SystemParam,)*> SystemParam for ParamSet<'_w, '_s, (#(#param,)*)>
268259
{
269-
type Item<'w, 's> = ParamSet<'w, 's, (#(<#param_state as SystemParamState>::Item::<'w, 's>,)*)>;
260+
type State = (#(#param::State,)*);
261+
type Item<'w, 's> = ParamSet<'w, 's, (#(#param,)*)>;
270262

271-
fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
263+
fn init_state(world: &mut World, system_meta: &mut SystemMeta) -> Self::State {
272264
#(
273265
// Pretend to add each param to the system alone, see if it conflicts
274266
let mut #meta = system_meta.clone();
275267
#meta.component_access_set.clear();
276268
#meta.archetype_component_access.clear();
277-
#param_state::init(world, &mut #meta);
278-
let #param = #param_state::init(world, &mut system_meta.clone());
269+
#param::init_state(world, &mut #meta);
270+
let #param = #param::init_state(world, &mut system_meta.clone());
279271
)*
280272
#(
281273
system_meta
@@ -285,29 +277,26 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream {
285277
.archetype_component_access
286278
.extend(&#meta.archetype_component_access);
287279
)*
288-
ParamSetState((#(#param,)*))
280+
(#(#param,)*)
289281
}
290282

291-
fn new_archetype(&mut self, archetype: &Archetype, system_meta: &mut SystemMeta) {
292-
let (#(#param,)*) = &mut self.0;
293-
#(
294-
#param.new_archetype(archetype, system_meta);
295-
)*
283+
fn new_archetype(state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta) {
284+
<(#(#param,)*) as SystemParam>::new_archetype(state, archetype, system_meta);
296285
}
297286

298-
fn apply(&mut self, system_meta: &SystemMeta, world: &mut World) {
299-
self.0.apply(system_meta, world)
287+
fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World) {
288+
<(#(#param,)*) as SystemParam>::apply(state, system_meta, world);
300289
}
301290

302291
#[inline]
303292
unsafe fn get_param<'w, 's>(
304-
state: &'s mut Self,
293+
state: &'s mut Self::State,
305294
system_meta: &SystemMeta,
306295
world: &'w World,
307296
change_tick: u32,
308297
) -> Self::Item<'w, 's> {
309298
ParamSet {
310-
param_states: &mut state.0,
299+
param_states: state,
311300
system_meta: system_meta.clone(),
312301
world,
313302
change_tick,
@@ -317,7 +306,6 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream {
317306

318307
impl<'w, 's, #(#param: SystemParam,)*> ParamSet<'w, 's, (#(#param,)*)>
319308
{
320-
321309
#(#param_fn_mut)*
322310
}
323311
}));
@@ -411,14 +399,20 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
411399
}
412400
}
413401

414-
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
402+
let (_impl_generics, ty_generics, where_clause) = generics.split_for_impl();
415403

416404
let lifetimeless_generics: Vec<_> = generics
417405
.params
418406
.iter()
419407
.filter(|g| !matches!(g, GenericParam::Lifetime(_)))
420408
.collect();
421409

410+
let mut shadowed_lifetimes: Vec<_> = generics.lifetimes().map(|x| x.lifetime.clone()).collect();
411+
for lifetime in &mut shadowed_lifetimes {
412+
let shadowed_ident = format_ident!("_{}", lifetime.ident);
413+
lifetime.ident = shadowed_ident;
414+
}
415+
422416
let mut punctuated_generics = Punctuated::<_, Token![,]>::new();
423417
punctuated_generics.extend(lifetimeless_generics.iter().map(|g| match g {
424418
GenericParam::Type(g) => GenericParam::Type(TypeParam {
@@ -432,15 +426,6 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
432426
_ => unreachable!(),
433427
}));
434428

435-
let mut punctuated_generics_no_bounds = punctuated_generics.clone();
436-
for g in &mut punctuated_generics_no_bounds {
437-
match g {
438-
GenericParam::Type(g) => g.bounds.clear(),
439-
GenericParam::Lifetime(g) => g.bounds.clear(),
440-
GenericParam::Const(_) => {}
441-
}
442-
}
443-
444429
let mut punctuated_generic_idents = Punctuated::<_, Token![,]>::new();
445430
punctuated_generic_idents.extend(lifetimeless_generics.iter().map(|g| match g {
446431
GenericParam::Type(g) => &g.ident,
@@ -479,10 +464,6 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
479464
// The struct can still be accessed via SystemParam::State, e.g. EventReaderState can be accessed via
480465
// <EventReader<'static, 'static, T> as SystemParam>::State
481466
const _: () = {
482-
impl #impl_generics #path::system::SystemParam for #struct_name #ty_generics #where_clause {
483-
type State = FetchState<'static, 'static, #punctuated_generic_idents>;
484-
}
485-
486467
#[doc(hidden)]
487468
#state_struct_visibility struct FetchState <'w, 's, #(#lifetimeless_generics,)*> {
488469
state: (#(<#tuple_types as #path::system::SystemParam>::State,)*),
@@ -492,34 +473,33 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
492473
)>,
493474
}
494475

495-
unsafe impl<#punctuated_generics> #path::system::SystemParamState for
496-
FetchState<'static, 'static, #punctuated_generic_idents>
497-
#where_clause {
498-
type Item<'w, 's> = #struct_name #ty_generics;
476+
unsafe impl<'w, 's, #punctuated_generics> #path::system::SystemParam for #struct_name #ty_generics #where_clause {
477+
type State = FetchState<'static, 'static, #punctuated_generic_idents>;
478+
type Item<'_w, '_s> = #struct_name <#(#shadowed_lifetimes,)* #punctuated_generic_idents>;
499479

500-
fn init(world: &mut #path::world::World, system_meta: &mut #path::system::SystemMeta) -> Self {
501-
Self {
502-
state: #path::system::SystemParamState::init(world, system_meta),
480+
fn init_state(world: &mut #path::world::World, system_meta: &mut #path::system::SystemMeta) -> Self::State {
481+
FetchState {
482+
state: <(#(#tuple_types,)*) as #path::system::SystemParam>::init_state(world, system_meta),
503483
marker: std::marker::PhantomData,
504484
}
505485
}
506486

507-
fn new_archetype(&mut self, archetype: &#path::archetype::Archetype, system_meta: &mut #path::system::SystemMeta) {
508-
self.state.new_archetype(archetype, system_meta)
487+
fn new_archetype(state: &mut Self::State, archetype: &#path::archetype::Archetype, system_meta: &mut #path::system::SystemMeta) {
488+
<(#(#tuple_types,)*) as #path::system::SystemParam>::new_archetype(&mut state.state, archetype, system_meta)
509489
}
510490

511-
fn apply(&mut self, system_meta: &#path::system::SystemMeta, world: &mut #path::world::World) {
512-
self.state.apply(system_meta, world)
491+
fn apply(state: &mut Self::State, system_meta: &#path::system::SystemMeta, world: &mut #path::world::World) {
492+
<(#(#tuple_types,)*) as #path::system::SystemParam>::apply(&mut state.state, system_meta, world);
513493
}
514494

515-
unsafe fn get_param<'w, 's>(
516-
state: &'s mut Self,
495+
unsafe fn get_param<'w2, 's2>(
496+
state: &'s2 mut Self::State,
517497
system_meta: &#path::system::SystemMeta,
518-
world: &'w #path::world::World,
498+
world: &'w2 #path::world::World,
519499
change_tick: u32,
520-
) -> Self::Item<'w, 's> {
500+
) -> Self::Item<'w2, 's2> {
521501
let (#(#tuple_patterns,)*) = <
522-
<(#(#tuple_types,)*) as #path::system::SystemParam>::State as #path::system::SystemParamState
502+
(#(#tuple_types,)*) as #path::system::SystemParam
523503
>::get_param(&mut state.state, system_meta, world, change_tick);
524504
#struct_name {
525505
#(#fields: #field_locals,)*

crates/bevy_ecs/src/system/commands/parallel_scope.rs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ use thread_local::ThreadLocal;
55
use crate::{
66
entity::Entities,
77
prelude::World,
8-
system::{SystemMeta, SystemParam, SystemParamState},
8+
system::{SystemMeta, SystemParam},
99
};
1010

1111
use super::{CommandQueue, Commands};
1212

13+
/// The internal [`SystemParam`] state of the [`ParallelCommands`] type
1314
#[doc(hidden)]
1415
#[derive(Default)]
15-
/// The internal [`SystemParamState`] of the [`ParallelCommands`] type
1616
pub struct ParallelCommandsState {
1717
thread_local_storage: ThreadLocal<Cell<CommandQueue>>,
1818
}
@@ -48,30 +48,27 @@ pub struct ParallelCommands<'w, 's> {
4848
entities: &'w Entities,
4949
}
5050

51-
impl SystemParam for ParallelCommands<'_, '_> {
52-
type State = ParallelCommandsState;
53-
}
54-
5551
// SAFETY: no component or resource access to report
56-
unsafe impl SystemParamState for ParallelCommandsState {
52+
unsafe impl SystemParam for ParallelCommands<'_, '_> {
53+
type State = ParallelCommandsState;
5754
type Item<'w, 's> = ParallelCommands<'w, 's>;
5855

59-
fn init(_: &mut World, _: &mut crate::system::SystemMeta) -> Self {
60-
Self::default()
56+
fn init_state(_: &mut World, _: &mut crate::system::SystemMeta) -> Self::State {
57+
ParallelCommandsState::default()
6158
}
6259

63-
fn apply(&mut self, _system_meta: &SystemMeta, world: &mut World) {
60+
fn apply(state: &mut Self::State, _system_meta: &SystemMeta, world: &mut World) {
6461
#[cfg(feature = "trace")]
6562
let _system_span =
6663
bevy_utils::tracing::info_span!("system_commands", name = _system_meta.name())
6764
.entered();
68-
for cq in &mut self.thread_local_storage {
65+
for cq in &mut state.thread_local_storage {
6966
cq.get_mut().apply(world);
7067
}
7168
}
7269

7370
unsafe fn get_param<'w, 's>(
74-
state: &'s mut Self,
71+
state: &'s mut Self::State,
7572
_: &crate::system::SystemMeta,
7673
world: &'w World,
7774
_: u32,

crates/bevy_ecs/src/system/exclusive_function_system.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::{
66
schedule::{SystemLabel, SystemLabelId},
77
system::{
88
check_system_change_tick, AsSystemLabel, ExclusiveSystemParam, ExclusiveSystemParamItem,
9-
ExclusiveSystemParamState, IntoSystem, System, SystemMeta, SystemTypeIdLabel,
9+
IntoSystem, System, SystemMeta, SystemTypeIdLabel,
1010
},
1111
world::{World, WorldId},
1212
};
@@ -94,7 +94,7 @@ where
9494
let saved_last_tick = world.last_change_tick;
9595
world.last_change_tick = self.system_meta.last_change_tick;
9696

97-
let params = <Param as ExclusiveSystemParam>::State::get_param(
97+
let params = Param::get_param(
9898
self.param_state.as_mut().expect(PARAM_MESSAGE),
9999
&self.system_meta,
100100
);
@@ -122,17 +122,14 @@ where
122122
#[inline]
123123
fn apply_buffers(&mut self, world: &mut World) {
124124
let param_state = self.param_state.as_mut().expect(PARAM_MESSAGE);
125-
param_state.apply(world);
125+
Param::apply(param_state, world);
126126
}
127127

128128
#[inline]
129129
fn initialize(&mut self, world: &mut World) {
130130
self.world_id = Some(world.id());
131131
self.system_meta.last_change_tick = world.change_tick().wrapping_sub(MAX_CHANGE_AGE);
132-
self.param_state = Some(<Param::State as ExclusiveSystemParamState>::init(
133-
world,
134-
&mut self.system_meta,
135-
));
132+
self.param_state = Some(Param::init(world, &mut self.system_meta));
136133
}
137134

138135
fn update_archetype_component_access(&mut self, _world: &World) {}

0 commit comments

Comments
 (0)