Fix Option<NonSend<T>> and Option<NonSendMut<T>> (#2757)

# 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>
This commit is contained in:
bilsen 2021-08-31 20:52:21 +00:00
parent c563dd094f
commit 35979922df
2 changed files with 46 additions and 4 deletions

View File

@ -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::<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();

View File

@ -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>;
}
@ -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!(