Skip to content

Commit d1c6fbe

Browse files
authored
Support fallible one-shot systems (#19678)
Closes #19677. I don't think that the output type needs to be `Send`. I've done some test at it seems to work fine without it, which in IMO makes sense, but please correct me if that is not the case.
1 parent 2915a3b commit d1c6fbe

File tree

3 files changed

+69
-14
lines changed

3 files changed

+69
-14
lines changed

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,11 @@ where
144144

145145
/// A [`Command`] that runs the given system,
146146
/// caching its [`SystemId`] in a [`CachedSystemId`](crate::system::CachedSystemId) resource.
147-
pub fn run_system_cached<M, S>(system: S) -> impl Command<Result>
147+
pub fn run_system_cached<O, M, S>(system: S) -> impl Command<Result>
148148
where
149+
O: 'static,
149150
M: 'static,
150-
S: IntoSystem<(), (), M> + Send + 'static,
151+
S: IntoSystem<(), O, M> + Send + 'static,
151152
{
152153
move |world: &mut World| -> Result {
153154
world.run_system_cached(system)?;
@@ -157,11 +158,15 @@ where
157158

158159
/// A [`Command`] that runs the given system with the given input value,
159160
/// caching its [`SystemId`] in a [`CachedSystemId`](crate::system::CachedSystemId) resource.
160-
pub fn run_system_cached_with<I, M, S>(system: S, input: I::Inner<'static>) -> impl Command<Result>
161+
pub fn run_system_cached_with<I, O, M, S>(
162+
system: S,
163+
input: I::Inner<'static>,
164+
) -> impl Command<Result>
161165
where
162166
I: SystemInput<Inner<'static>: Send> + Send + 'static,
167+
O: 'static,
163168
M: 'static,
164-
S: IntoSystem<I, (), M> + Send + 'static,
169+
S: IntoSystem<I, O, M> + Send + 'static,
165170
{
166171
move |world: &mut World| -> Result {
167172
world.run_system_cached_with(system, input)?;
@@ -175,7 +180,7 @@ where
175180
pub fn unregister_system<I, O>(system_id: SystemId<I, O>) -> impl Command<Result>
176181
where
177182
I: SystemInput + Send + 'static,
178-
O: Send + 'static,
183+
O: 'static,
179184
{
180185
move |world: &mut World| -> Result {
181186
world.unregister_system(system_id)?;

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -872,7 +872,7 @@ impl<'w, 's> Commands<'w, 's> {
872872
///
873873
/// It will internally return a [`RegisteredSystemError`](crate::system::system_registry::RegisteredSystemError),
874874
/// which will be handled by [logging the error at the `warn` level](warn).
875-
pub fn run_system(&mut self, id: SystemId) {
875+
pub fn run_system<O: 'static>(&mut self, id: SystemId<(), O>) {
876876
self.queue(command::run_system(id).handle_error_with(warn));
877877
}
878878

@@ -965,7 +965,7 @@ impl<'w, 's> Commands<'w, 's> {
965965
) -> SystemId<I, O>
966966
where
967967
I: SystemInput + Send + 'static,
968-
O: Send + 'static,
968+
O: 'static,
969969
{
970970
let entity = self.spawn_empty().id();
971971
let system = RegisteredSystem::<I, O>::new(Box::new(IntoSystem::into_system(system)));
@@ -990,7 +990,7 @@ impl<'w, 's> Commands<'w, 's> {
990990
pub fn unregister_system<I, O>(&mut self, system_id: SystemId<I, O>)
991991
where
992992
I: SystemInput + Send + 'static,
993-
O: Send + 'static,
993+
O: 'static,
994994
{
995995
self.queue(command::unregister_system(system_id).handle_error_with(warn));
996996
}
@@ -1039,10 +1039,11 @@ impl<'w, 's> Commands<'w, 's> {
10391039
/// consider passing them in as inputs via [`Commands::run_system_cached_with`].
10401040
///
10411041
/// If that's not an option, consider [`Commands::register_system`] instead.
1042-
pub fn run_system_cached<M, S>(&mut self, system: S)
1042+
pub fn run_system_cached<O, M, S>(&mut self, system: S)
10431043
where
1044+
O: 'static,
10441045
M: 'static,
1045-
S: IntoSystem<(), (), M> + Send + 'static,
1046+
S: IntoSystem<(), O, M> + Send + 'static,
10461047
{
10471048
self.queue(command::run_system_cached(system).handle_error_with(warn));
10481049
}
@@ -1069,11 +1070,12 @@ impl<'w, 's> Commands<'w, 's> {
10691070
/// consider passing them in as inputs.
10701071
///
10711072
/// If that's not an option, consider [`Commands::register_system`] instead.
1072-
pub fn run_system_cached_with<I, M, S>(&mut self, system: S, input: I::Inner<'static>)
1073+
pub fn run_system_cached_with<I, O, M, S>(&mut self, system: S, input: I::Inner<'static>)
10731074
where
10741075
I: SystemInput<Inner<'static>: Send> + Send + 'static,
1076+
O: 'static,
10751077
M: 'static,
1076-
S: IntoSystem<I, (), M> + Send + 'static,
1078+
S: IntoSystem<I, O, M> + Send + 'static,
10771079
{
10781080
self.queue(command::run_system_cached_with(system, input).handle_error_with(warn));
10791081
}

crates/bevy_ecs/src/system/system_registry.rs

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,19 @@ mod tests {
651651
assert_eq!(output, NonCopy(3));
652652
}
653653

654+
#[test]
655+
fn fallible_system() {
656+
fn sys() -> Result<()> {
657+
Err("error")?;
658+
Ok(())
659+
}
660+
661+
let mut world = World::new();
662+
let fallible_system_id = world.register_system(sys);
663+
let output = world.run_system(fallible_system_id);
664+
assert!(matches!(output, Ok(Err(_))));
665+
}
666+
654667
#[test]
655668
fn exclusive_system() {
656669
let mut world = World::new();
@@ -751,19 +764,54 @@ mod tests {
751764
assert!(matches!(output, Ok(x) if x == four()));
752765
}
753766

767+
#[test]
768+
fn cached_fallible_system() {
769+
fn sys() -> Result<()> {
770+
Err("error")?;
771+
Ok(())
772+
}
773+
774+
let mut world = World::new();
775+
let fallible_system_id = world.register_system_cached(sys);
776+
let output = world.run_system(fallible_system_id);
777+
assert!(matches!(output, Ok(Err(_))));
778+
let output = world.run_system_cached(sys);
779+
assert!(matches!(output, Ok(Err(_))));
780+
let output = world.run_system_cached_with(sys, ());
781+
assert!(matches!(output, Ok(Err(_))));
782+
}
783+
754784
#[test]
755785
fn cached_system_commands() {
756786
fn sys(mut counter: ResMut<Counter>) {
757-
counter.0 = 1;
787+
counter.0 += 1;
758788
}
759789

760790
let mut world = World::new();
761791
world.insert_resource(Counter(0));
762-
763792
world.commands().run_system_cached(sys);
764793
world.flush_commands();
794+
assert_eq!(world.resource::<Counter>().0, 1);
795+
world.commands().run_system_cached_with(sys, ());
796+
world.flush_commands();
797+
assert_eq!(world.resource::<Counter>().0, 2);
798+
}
765799

800+
#[test]
801+
fn cached_fallible_system_commands() {
802+
fn sys(mut counter: ResMut<Counter>) -> Result {
803+
counter.0 += 1;
804+
Ok(())
805+
}
806+
807+
let mut world = World::new();
808+
world.insert_resource(Counter(0));
809+
world.commands().run_system_cached(sys);
810+
world.flush_commands();
766811
assert_eq!(world.resource::<Counter>().0, 1);
812+
world.commands().run_system_cached_with(sys, ());
813+
world.flush_commands();
814+
assert_eq!(world.resource::<Counter>().0, 2);
767815
}
768816

769817
#[test]

0 commit comments

Comments
 (0)