Skip to content

Commit

Permalink
Fix Option<NonSend<T>> and Option<NonSendMut<T>> (#2757)
Browse files Browse the repository at this point in the history
# Objective
Fix `Option<NonSend<T>>` to work when T isn't `Send`
Fix `Option<NonSendMut<T>>` 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<NonSendMut<T>>`
also added a rudimentary test


Co-authored-by: Ïvar Källström <ivar.kallstrom@gmail.com>
  • Loading branch information
bilsen and bilsen committed Aug 31, 2021
1 parent c563dd0 commit 3597992
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 4 deletions.
46 changes: 44 additions & 2 deletions crates/bevy_ecs/src/system/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
};
Expand Down Expand Up @@ -331,6 +331,48 @@ mod tests {
assert!(*world.get_resource::<bool>().unwrap());
}

#[test]
fn non_send_option_system() {
let mut world = World::default();

world.insert_resource(false);
struct NotSend1(std::rc::Rc<i32>);
struct NotSend2(std::rc::Rc<i32>);
world.insert_non_send(NotSend1(std::rc::Rc::new(0)));

fn sys(
op: Option<NonSend<NotSend1>>,
mut _op2: Option<NonSendMut<NotSend2>>,
mut run: ResMut<bool>,
) {
op.expect("NonSend should exist");
*run = true;
}

run_system(&mut world, sys);
// ensure the system actually ran
assert!(*world.get_resource::<bool>().unwrap());
}

#[test]
fn non_send_system() {
let mut world = World::default();

world.insert_resource(false);
struct NotSend1(std::rc::Rc<i32>);
struct NotSend2(std::rc::Rc<i32>);

world.insert_non_send(NotSend1(std::rc::Rc::new(1)));
world.insert_non_send(NotSend2(std::rc::Rc::new(2)));

fn sys(_op: NonSend<NotSend1>, mut _op2: NonSendMut<NotSend2>, mut run: ResMut<bool>) {
*run = true;
}

run_system(&mut world, sys);
assert!(*world.get_resource::<bool>().unwrap());
}

#[test]
fn remove_tracking() {
let mut world = World::new();
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_ecs/src/system/system_param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -820,7 +820,7 @@ impl<'w, 's, T: 'static> SystemParamFetch<'w, 's> for NonSendState<T> {
/// See: [`NonSend<T>`]
pub struct OptionNonSendState<T>(NonSendState<T>);

impl<'w, T: Component> SystemParam for Option<NonSend<'w, T>> {
impl<'w, T: 'static> SystemParam for Option<NonSend<'w, T>> {
type Fetch = OptionNonSendState<T>;
}

Expand Down Expand Up @@ -877,7 +877,7 @@ unsafe impl<T: 'static> SystemParamState for NonSendMutState<T> {
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::<T>();
let component_id = world.initialize_non_send_resource::<T>();
let combined_access = system_meta.component_access_set.combined_access_mut();
if combined_access.has_write(component_id) {
panic!(
Expand Down

0 comments on commit 3597992

Please sign in to comment.