From 35979922df9de488e67dfdf5d8a7c857527cb2a7 Mon Sep 17 00:00:00 2001 From: bilsen <40690317+bilsen@users.noreply.github.com> Date: Tue, 31 Aug 2021 20:52:21 +0000 Subject: [PATCH] Fix Option> and Option> (#2757) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Objective Fix `Option>` to work when T isn't `Send` Fix `Option>` to work when T isnt in the world. ## Solution Simple two row fix, properly initialize T in `OptionNonSendState` and remove `T: Component` bound for `Option>` also added a rudimentary test Co-authored-by: Ïvar Källström --- crates/bevy_ecs/src/system/mod.rs | 46 +++++++++++++++++++++- crates/bevy_ecs/src/system/system_param.rs | 4 +- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/crates/bevy_ecs/src/system/mod.rs b/crates/bevy_ecs/src/system/mod.rs index 8f0172af97a59..d4fd0ad79909c 100644 --- a/crates/bevy_ecs/src/system/mod.rs +++ b/crates/bevy_ecs/src/system/mod.rs @@ -27,8 +27,8 @@ mod tests { query::{Added, Changed, Or, QueryState, With, Without}, schedule::{Schedule, Stage, SystemStage}, system::{ - ConfigurableSystem, IntoExclusiveSystem, IntoSystem, Local, Query, QuerySet, - RemovedComponents, Res, ResMut, System, SystemState, + ConfigurableSystem, IntoExclusiveSystem, IntoSystem, Local, NonSend, NonSendMut, Query, + QuerySet, RemovedComponents, Res, ResMut, System, SystemState, }, world::{FromWorld, World}, }; @@ -331,6 +331,48 @@ mod tests { assert!(*world.get_resource::().unwrap()); } + #[test] + fn non_send_option_system() { + let mut world = World::default(); + + world.insert_resource(false); + struct NotSend1(std::rc::Rc); + struct NotSend2(std::rc::Rc); + world.insert_non_send(NotSend1(std::rc::Rc::new(0))); + + fn sys( + op: Option>, + mut _op2: Option>, + mut run: ResMut, + ) { + op.expect("NonSend should exist"); + *run = true; + } + + run_system(&mut world, sys); + // ensure the system actually ran + assert!(*world.get_resource::().unwrap()); + } + + #[test] + fn non_send_system() { + let mut world = World::default(); + + world.insert_resource(false); + struct NotSend1(std::rc::Rc); + struct NotSend2(std::rc::Rc); + + world.insert_non_send(NotSend1(std::rc::Rc::new(1))); + world.insert_non_send(NotSend2(std::rc::Rc::new(2))); + + fn sys(_op: NonSend, mut _op2: NonSendMut, mut run: ResMut) { + *run = true; + } + + run_system(&mut world, sys); + assert!(*world.get_resource::().unwrap()); + } + #[test] fn remove_tracking() { let mut world = World::new(); diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 2e350c05f3eb1..6f3e731ad3f22 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -820,7 +820,7 @@ impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for NonSendState { /// See: [`NonSend`] pub struct OptionNonSendState(NonSendState); -impl<'w, T: Component> SystemParam for Option> { +impl<'w, T: 'static> SystemParam for Option> { type Fetch = OptionNonSendState; } @@ -877,7 +877,7 @@ unsafe impl SystemParamState for NonSendMutState { fn init(world: &mut World, system_meta: &mut SystemMeta, _config: Self::Config) -> Self { system_meta.set_non_send(); - let component_id = world.components.get_or_insert_non_send_resource_id::(); + let component_id = world.initialize_non_send_resource::(); let combined_access = system_meta.component_access_set.combined_access_mut(); if combined_access.has_write(component_id) { panic!(