Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fallible System Parameters #6923

Closed
18 changes: 9 additions & 9 deletions crates/bevy_ecs/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,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::State as SystemParamState<Infallible>>::get_param(&mut self.param_states.#index, &self.system_meta, self.world, self.change_tick)
}
}
});
Expand All @@ -240,7 +240,7 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream {
let meta = &metas[0..param_count];
let param_fn_mut = &param_fn_muts[0..param_count];
tokens.extend(TokenStream::from(quote! {
impl<'w, 's, #(#param: SystemParam,)*> SystemParam for ParamSet<'w, 's, (#(#param,)*)>
impl<'w, 's, #(#param: SystemParam<Infallible>,)*> SystemParam<Infallible> for ParamSet<'w, 's, (#(#param,)*)>
{
type State = ParamSetState<(#(#param::State,)*)>;
}
Expand All @@ -254,9 +254,9 @@ 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<#(#param_state: SystemParamState,)*> SystemParamState for ParamSetState<(#(#param_state,)*)>
unsafe impl<#(#param_state: SystemParamState<Infallible>,)*> SystemParamState<Infallible> 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_state as SystemParamState<Infallible>>::Item::<'w, 's>,)*)>;

fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self {
#(
Expand Down Expand Up @@ -305,7 +305,7 @@ pub fn impl_param_set(_input: TokenStream) -> TokenStream {
}
}

impl<'w, 's, #(#param: SystemParam,)*> ParamSet<'w, 's, (#(#param,)*)>
impl<'w, 's, #(#param: SystemParam<Infallible>,)*> ParamSet<'w, 's, (#(#param,)*)>
{

#(#param_fn_mut)*
Expand Down Expand Up @@ -434,13 +434,13 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
// The struct can still be accessed via SystemParam::State, e.g. EventReaderState can be accessed via
// <EventReader<'static, 'static, T> as SystemParam>::State
const _: () = {
impl<'w, 's, #punctuated_generics> #path::system::SystemParam for #struct_name #ty_generics #where_clause {
impl<'w, 's, #punctuated_generics> #path::system::SystemParam<#path::system::Infallible> 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,)*),
(#(<#field_types as #path::system::SystemParam<#path::system::Infallible>>::State,)*),
#punctuated_generic_idents
>;

Expand All @@ -450,7 +450,7 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
marker: std::marker::PhantomData<fn()->(#punctuated_generic_idents)>
}

unsafe impl<'__w, '__s, #punctuated_generics> #path::system::SystemParamState for
unsafe impl<'__w, '__s, #punctuated_generics> #path::system::SystemParamState<#path::system::Infallible> for
State<'__w, '__s, #punctuated_generic_idents>
#where_clause {
type Item<'w, 's> = #struct_name #ty_generics;
Expand All @@ -477,7 +477,7 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
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<#path::system::Infallible>>::State as #path::system::SystemParamState<#path::system::Infallible>>::get_param(&mut state.state.#field_indices, system_meta, world, change_tick),)*
#(#ignored_fields: <#ignored_field_types>::default(),)*
}
}
Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_ecs/src/system/commands/parallel_scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use thread_local::ThreadLocal;
use crate::{
entity::Entities,
prelude::World,
system::{SystemMeta, SystemParam, SystemParamState},
system::{Infallible, SystemMeta, SystemParam, SystemParamState},
};

use super::{CommandQueue, Commands};
Expand Down Expand Up @@ -48,12 +48,12 @@ pub struct ParallelCommands<'w, 's> {
entities: &'w Entities,
}

impl SystemParam for ParallelCommands<'_, '_> {
impl SystemParam<Infallible> for ParallelCommands<'_, '_> {
type State = ParallelCommandsState;
}

// SAFETY: no component or resource access to report
unsafe impl SystemParamState for ParallelCommandsState {
unsafe impl SystemParamState<Infallible> for ParallelCommandsState {
type Item<'w, 's> = ParallelCommands<'w, 's>;

fn init(_: &mut World, _: &mut crate::system::SystemMeta) -> Self {
Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_ecs/src/system/exclusive_system_param.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
prelude::{FromWorld, QueryState},
query::{ReadOnlyWorldQuery, WorldQuery},
system::{Local, LocalState, SystemMeta, SystemParam, SystemState},
system::{Infallible, Local, LocalState, SystemMeta, SystemParam, SystemState},
world::World,
};
use bevy_ecs_macros::all_tuples;
Expand Down Expand Up @@ -45,11 +45,11 @@ impl<Q: WorldQuery + 'static, F: ReadOnlyWorldQuery + 'static> ExclusiveSystemPa
}
}

impl<'a, P: SystemParam + 'static> ExclusiveSystemParam for &'a mut SystemState<P> {
impl<'a, P: SystemParam<Infallible> + 'static> ExclusiveSystemParam for &'a mut SystemState<P> {
type State = SystemState<P>;
}

impl<P: SystemParam> ExclusiveSystemParamState for SystemState<P> {
impl<P: SystemParam<Infallible>> ExclusiveSystemParamState for SystemState<P> {
type Item<'s> = &'s mut SystemState<P>;

fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self {
Expand Down
51 changes: 29 additions & 22 deletions crates/bevy_ecs/src/system/function_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use crate::{
query::{Access, FilteredAccessSet},
schedule::{SystemLabel, SystemLabelId},
system::{
check_system_change_tick, ReadOnlySystemParam, System, SystemParam, SystemParamItem,
SystemParamState,
check_system_change_tick, Infallible, ReadOnlySystemParam, System, SystemParam,
SystemParamItem, SystemParamState,
},
world::{World, WorldId},
};
Expand Down Expand Up @@ -139,18 +139,18 @@ impl SystemMeta {
/// };
/// });
/// ```
pub struct SystemState<Param: SystemParam + 'static> {
pub struct SystemState<Param: SystemParam<Infallible> + 'static> {
meta: SystemMeta,
param_state: <Param as SystemParam>::State,
param_state: <Param as SystemParam<Infallible>>::State,
world_id: WorldId,
archetype_generation: ArchetypeGeneration,
}

impl<Param: SystemParam> SystemState<Param> {
impl<Param: SystemParam<Infallible>> SystemState<Param> {
pub fn new(world: &mut World) -> Self {
let mut meta = SystemMeta::new::<Param>();
meta.last_change_tick = world.change_tick().wrapping_sub(MAX_CHANGE_AGE);
let param_state = <Param::State as SystemParamState>::init(world, &mut meta);
let param_state = <Param::State as SystemParamState<Infallible>>::init(world, &mut meta);
Self {
meta,
param_state,
Expand Down Expand Up @@ -223,7 +223,7 @@ impl<Param: SystemParam> SystemState<Param> {
world: &'w World,
) -> SystemParamItem<'w, 's, Param> {
let change_tick = world.increment_change_tick();
let param = <Param::State as SystemParamState>::get_param(
let param = <Param::State as SystemParamState<Infallible>>::get_param(
&mut self.param_state,
&self.meta,
world,
Expand All @@ -234,7 +234,7 @@ impl<Param: SystemParam> SystemState<Param> {
}
}

impl<Param: SystemParam> FromWorld for SystemState<Param> {
impl<Param: SystemParam<Infallible>> FromWorld for SystemState<Param> {
fn from_world(world: &mut World) -> Self {
Self::new(world)
}
Expand Down Expand Up @@ -312,7 +312,7 @@ pub struct InputMarker;
/// [`FunctionSystem`] must be `.initialized` before they can be run.
pub struct FunctionSystem<In, Out, Param, Marker, F>
where
Param: SystemParam,
Param: SystemParam<Infallible>,
{
func: F,
param_state: Option<Param::State>,
Expand All @@ -329,7 +329,7 @@ impl<In, Out, Param, Marker, F> IntoSystem<In, Out, (IsFunctionSystem, Param, Ma
where
In: 'static,
Out: 'static,
Param: SystemParam + 'static,
Param: SystemParam<Infallible> + 'static,
Marker: 'static,
F: SystemParamFunction<In, Out, Param, Marker> + Send + Sync + 'static,
{
Expand All @@ -348,7 +348,7 @@ where

impl<In, Out, Param, Marker, F> FunctionSystem<In, Out, Param, Marker, F>
where
Param: SystemParam,
Param: SystemParam<Infallible>,
{
/// Message shown when a system isn't initialised
// When lines get too long, rustfmt can sometimes refuse to format them.
Expand All @@ -360,7 +360,7 @@ impl<In, Out, Param, Marker, F> System for FunctionSystem<In, Out, Param, Marker
where
In: 'static,
Out: 'static,
Param: SystemParam + 'static,
Param: SystemParam<Infallible> + 'static,
Marker: 'static,
F: SystemParamFunction<In, Out, Param, Marker> + Send + Sync + 'static,
{
Expand Down Expand Up @@ -400,7 +400,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 = <Param as SystemParam>::State::get_param(
let params = <Param as SystemParam<Infallible>>::State::get_param(
self.param_state.as_mut().expect(Self::PARAM_MESSAGE),
&self.system_meta,
world,
Expand Down Expand Up @@ -429,7 +429,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::State as SystemParamState>::init(
self.param_state = Some(<Param::State as SystemParamState<Infallible>>::init(
world,
&mut self.system_meta,
));
Expand Down Expand Up @@ -505,7 +505,7 @@ impl<T> Copy for SystemTypeIdLabel<T> {}
/// use std::num::ParseIntError;
///
/// use bevy_ecs::prelude::*;
/// use bevy_ecs::system::{SystemParam, SystemParamItem};
/// use bevy_ecs::system::{Infallible, SystemParam, SystemParamItem};
///
/// // Unfortunately, we need all of these generics. `A` is the first system, with its
/// // parameters and marker type required for coherence. `B` is the second system, and
Expand All @@ -519,8 +519,8 @@ impl<T> Copy for SystemTypeIdLabel<T> {}
/// // We need A and B to be systems, add those bounds
/// A: SystemParamFunction<AIn, Shared, AParam, AMarker>,
/// B: SystemParamFunction<Shared, BOut, BParam, BMarker>,
/// AParam: SystemParam,
/// BParam: SystemParam,
/// AParam: SystemParam<Infallible>,
/// BParam: SystemParam<Infallible>,
/// {
/// // The type of `params` is inferred based on the return of this function above
/// move |In(a_in), mut params| {
Expand Down Expand Up @@ -553,14 +553,16 @@ impl<T> Copy for SystemTypeIdLabel<T> {}
/// ```
/// [`PipeSystem`]: crate::system::PipeSystem
/// [`ParamSet`]: crate::system::ParamSet
pub trait SystemParamFunction<In, Out, Param: SystemParam, Marker>: Send + Sync + 'static {
pub trait SystemParamFunction<In, Out, Param: SystemParam<Infallible>, Marker>:
Send + Sync + 'static
{
fn run(&mut self, input: In, param_value: SystemParamItem<Param>) -> Out;
}

macro_rules! impl_system_function {
($($param: ident),*) => {
#[allow(non_snake_case)]
impl<Out, Func: Send + Sync + 'static, $($param: SystemParam),*> SystemParamFunction<(), Out, ($($param,)*), ()> for Func
impl<Out, Func: Send + Sync + 'static, $($param: SystemParam<Infallible>),*> SystemParamFunction<(), Out, ($($param,)*), ()> for Func
where
for <'a> &'a mut Func:
FnMut($($param),*) -> Out +
Expand All @@ -584,7 +586,7 @@ macro_rules! impl_system_function {
}

#[allow(non_snake_case)]
impl<Input, Out, Func: Send + Sync + 'static, $($param: SystemParam),*> SystemParamFunction<Input, Out, ($($param,)*), InputMarker> for Func
impl<Input, Out, Func: Send + Sync + 'static, $($param: SystemParam<Infallible>),*> SystemParamFunction<Input, Out, ($($param,)*), InputMarker> for Func
where
for <'a> &'a mut Func:
FnMut(In<Input>, $($param),*) -> Out +
Expand Down Expand Up @@ -617,8 +619,13 @@ pub trait AsSystemLabel<Marker> {
fn as_system_label(&self) -> SystemLabelId;
}

impl<In, Out, Param: SystemParam, Marker, T: SystemParamFunction<In, Out, Param, Marker>>
AsSystemLabel<(In, Out, Param, Marker)> for T
impl<
In,
Out,
Param: SystemParam<Infallible>,
Marker,
T: SystemParamFunction<In, Out, Param, Marker>,
> AsSystemLabel<(In, Out, Param, Marker)> for T
{
#[inline]
fn as_system_label(&self) -> SystemLabelId {
Expand Down
Loading