From 87ec70a4343e11d774d8721f1ab6b43c6e059608 Mon Sep 17 00:00:00 2001 From: james7132 Date: Fri, 6 May 2022 12:44:58 -0700 Subject: [PATCH 01/16] Bare minimum: Get it to compile --- crates/bevy_ecs/src/bundle.rs | 2 +- crates/bevy_ecs/src/component.rs | 4 ++-- crates/bevy_ecs/src/query/fetch.rs | 22 +++++++++++++++++----- crates/bevy_ecs/src/query/filter.rs | 12 ++++++++++++ crates/bevy_ecs/src/system/commands/mod.rs | 8 ++++---- crates/bevy_ecs/src/system/system_param.rs | 4 ++++ crates/bevy_render/src/camera/camera.rs | 14 +++++++------- crates/bevy_render/src/render_component.rs | 12 ++++++------ 8 files changed, 53 insertions(+), 25 deletions(-) diff --git a/crates/bevy_ecs/src/bundle.rs b/crates/bevy_ecs/src/bundle.rs index 1ff332ec62ca6..5ad3fe1b8e237 100644 --- a/crates/bevy_ecs/src/bundle.rs +++ b/crates/bevy_ecs/src/bundle.rs @@ -76,7 +76,7 @@ use std::{any::TypeId, collections::HashMap}; /// bundle, in the _exact_ order that [`Bundle::get_components`] is called. /// - [`Bundle::from_components`] must call `func` exactly once for each [`ComponentId`] returned by /// [`Bundle::component_ids`]. -pub unsafe trait Bundle: Send + Sync + 'static { +pub unsafe trait Bundle: Send + 'static { /// Gets this [`Bundle`]'s component ids, in the order of this bundle's [`Component`]s fn component_ids(components: &mut Components, storages: &mut Storages) -> Vec; diff --git a/crates/bevy_ecs/src/component.rs b/crates/bevy_ecs/src/component.rs index 92767386742c7..e88f6505c1f12 100644 --- a/crates/bevy_ecs/src/component.rs +++ b/crates/bevy_ecs/src/component.rs @@ -14,7 +14,7 @@ use std::{ /// A component is data associated with an [`Entity`](crate::entity::Entity). Each entity can have /// multiple different types of components, but only one of them per type. /// -/// Any type that is `Send + Sync + 'static` can implement `Component` using `#[derive(Component)]`. +/// Any type that is `Send + 'static` can implement `Component` using `#[derive(Component)]`. /// /// In order to use foreign types as components, wrap them using a newtype pattern. /// ``` @@ -31,7 +31,7 @@ use std::{ /// as one of the arguments. /// /// Components can be grouped together into a [`Bundle`](crate::bundle::Bundle). -pub trait Component: Send + Sync + 'static { +pub trait Component: Send + 'static { type Storage: ComponentStorage; } diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 5a89bc5280f63..b47550f3ae02d 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -541,7 +541,7 @@ impl<'w> Fetch<'w> for EntityFetch<'w> { } } -impl WorldQuery for &T { +impl WorldQuery for &T { type State = ReadState; fn shrink<'wlong: 'wshort, 'wshort>(item: QueryItem<'wlong, Self>) -> QueryItem<'wshort, Self> { @@ -556,9 +556,13 @@ pub struct ReadState { marker: PhantomData, } +// SAFETY: ReadState only contains a ComponentId, should be safe to read +// from multiple threads concurrently +unsafe impl Sync for ReadState {} + // SAFETY: component access and archetype component access are properly updated to reflect that T is // read -unsafe impl FetchState for ReadState { +unsafe impl FetchState for ReadState { fn init(world: &mut World) -> Self { let component_id = world.init_component::(); ReadState { @@ -620,15 +624,15 @@ impl Clone for ReadFetch<'_, T> { } /// SAFETY: access is read only -unsafe impl<'w, T: Component> ReadOnlyFetch for ReadFetch<'w, T> {} +unsafe impl<'w, T: Component + Sync> ReadOnlyFetch for ReadFetch<'w, T> {} -impl<'w, T: Component> WorldQueryGats<'w> for &T { +impl<'w, T: Component + Sync> WorldQueryGats<'w> for &T { type Fetch = ReadFetch<'w, T>; type ReadOnlyFetch = ReadFetch<'w, T>; type _State = ReadState; } -impl<'w, T: Component> Fetch<'w> for ReadFetch<'w, T> { +impl<'w, T: Component + Sync> Fetch<'w> for ReadFetch<'w, T> { type Item = &'w T; type State = ReadState; @@ -793,6 +797,10 @@ pub struct WriteState { marker: PhantomData, } +// SAFETY: WriteState only contains a ComponentId, should be safe to read +// from multiple threads concurrently +unsafe impl Sync for WriteState {} + // SAFETY: component access and archetype component access are properly updated to reflect that T is // written unsafe impl FetchState for WriteState { @@ -1259,6 +1267,10 @@ pub struct ChangeTrackersState { marker: PhantomData, } +// SAFETY: WriteState only contains a ComponentId, should be safe to read +// from multiple threads concurrently +unsafe impl Sync for ChangeTrackersState {} + // SAFETY: component access and archetype component access are properly updated to reflect that T is // read unsafe impl FetchState for ChangeTrackersState { diff --git a/crates/bevy_ecs/src/query/filter.rs b/crates/bevy_ecs/src/query/filter.rs index 276b43459e64d..1f30259cd4b44 100644 --- a/crates/bevy_ecs/src/query/filter.rs +++ b/crates/bevy_ecs/src/query/filter.rs @@ -67,6 +67,10 @@ pub struct WithState { marker: PhantomData, } +// SAFETY: WithState only contains a ComponentId, should be safe to read +// from multiple threads concurrently +unsafe impl Sync for WithState {} + // SAFETY: no component access or archetype component access unsafe impl FetchState for WithState { fn init(world: &mut World) -> Self { @@ -210,6 +214,10 @@ pub struct WithoutState { marker: PhantomData, } +// SAFETY: WithoutState only contains a ComponentId, should be safe to read +// from multiple threads concurrently +unsafe impl Sync for WithoutState {} + // SAFETY: no component access or archetype component access unsafe impl FetchState for WithoutState { fn init(world: &mut World) -> Self { @@ -508,6 +516,10 @@ macro_rules! impl_tick_filter { } } + // SAFETY: The state only contains a ComponentId, should be safe to read + // from multiple threads concurrently + unsafe impl Sync for $state_name {} + // SAFETY: this reads the T component. archetype component access and component access are updated to reflect that unsafe impl FetchState for $state_name { fn init(world: &mut World) -> Self { diff --git a/crates/bevy_ecs/src/system/commands/mod.rs b/crates/bevy_ecs/src/system/commands/mod.rs index d9495f80c48d1..c70fa47430a70 100644 --- a/crates/bevy_ecs/src/system/commands/mod.rs +++ b/crates/bevy_ecs/src/system/commands/mod.rs @@ -13,7 +13,7 @@ use std::marker::PhantomData; use super::Resource; /// A [`World`] mutation. -pub trait Command: Send + Sync + 'static { +pub trait Command: Send + 'static { fn write(self, world: &mut World); } @@ -261,7 +261,7 @@ impl<'w, 's> Commands<'w, 's> { /// worked out to share an ID space (which doesn't happen by default). pub fn insert_or_spawn_batch(&mut self, bundles_iter: I) where - I: IntoIterator + Send + Sync + 'static, + I: IntoIterator + Send + 'static, I::IntoIter: Iterator, B: Bundle, { @@ -640,7 +640,7 @@ where pub struct InsertOrSpawnBatch where - I: IntoIterator + Send + Sync + 'static, + I: IntoIterator + Send + 'static, B: Bundle, I::IntoIter: Iterator, { @@ -649,7 +649,7 @@ where impl Command for InsertOrSpawnBatch where - I: IntoIterator + Send + Sync + 'static, + I: IntoIterator + Send + 'static, B: Bundle, I::IntoIter: Iterator, { diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 55cb02176a5ab..6d6d2ae1ce502 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -714,6 +714,10 @@ pub struct RemovedComponentsState { marker: PhantomData, } +// SAFETY: RemovedComponentState only contains a ComponentId, should be safe to read +// from multiple threads concurrently +unsafe impl Sync for RemovedComponentsState {} + impl<'a, T: Component> SystemParam for RemovedComponents<'a, T> { type Fetch = RemovedComponentsState; } diff --git a/crates/bevy_render/src/camera/camera.rs b/crates/bevy_render/src/camera/camera.rs index 2cbec6a0e0a79..768516db7c035 100644 --- a/crates/bevy_render/src/camera/camera.rs +++ b/crates/bevy_render/src/camera/camera.rs @@ -238,7 +238,7 @@ impl Default for CameraTypePlugin { } } -impl Plugin for CameraTypePlugin { +impl Plugin for CameraTypePlugin { fn build(&self, app: &mut App) { app.init_resource::>() .add_startup_system_to_stage(StartupStage::PostStartup, set_active_camera::) @@ -251,12 +251,12 @@ impl Plugin for CameraTypePlugin { /// The canonical source of the "active camera" of the given camera type `T`. #[derive(Debug)] -pub struct ActiveCamera { +pub struct ActiveCamera { camera: Option, marker: PhantomData, } -impl Default for ActiveCamera { +impl Default for ActiveCamera { fn default() -> Self { Self { camera: Default::default(), @@ -265,7 +265,7 @@ impl Default for ActiveCamera { } } -impl Clone for ActiveCamera { +impl Clone for ActiveCamera { fn clone(&self) -> Self { Self { camera: self.camera, @@ -274,7 +274,7 @@ impl Clone for ActiveCamera { } } -impl ActiveCamera { +impl ActiveCamera { /// Sets the active camera to the given `camera` entity. pub fn set(&mut self, camera: Entity) { self.camera = Some(camera); @@ -286,7 +286,7 @@ impl ActiveCamera { } } -pub fn set_active_camera( +pub fn set_active_camera( mut active_camera: ResMut>, cameras: Query, With)>, ) { @@ -313,7 +313,7 @@ pub struct ExtractedCamera { pub physical_size: Option, } -pub fn extract_cameras( +pub fn extract_cameras( mut commands: Commands, windows: Res, images: Res>, diff --git a/crates/bevy_render/src/render_component.rs b/crates/bevy_render/src/render_component.rs index 7cd3158cb94d7..b6601f20e0445 100644 --- a/crates/bevy_render/src/render_component.rs +++ b/crates/bevy_render/src/render_component.rs @@ -58,7 +58,7 @@ impl Default for UniformComponentPlugin { } } -impl Plugin for UniformComponentPlugin { +impl Plugin for UniformComponentPlugin { fn build(&self, app: &mut App) { if let Ok(render_app) = app.get_sub_app_mut(RenderApp) { render_app @@ -69,11 +69,11 @@ impl Plugin for UniformComponentPlugin { } /// Stores all uniforms of the component type. -pub struct ComponentUniforms { +pub struct ComponentUniforms { uniforms: DynamicUniformVec, } -impl Deref for ComponentUniforms { +impl Deref for ComponentUniforms { type Target = DynamicUniformVec; #[inline] @@ -82,14 +82,14 @@ impl Deref for ComponentUniforms { } } -impl ComponentUniforms { +impl ComponentUniforms { #[inline] pub fn uniforms(&self) -> &DynamicUniformVec { &self.uniforms } } -impl Default for ComponentUniforms { +impl Default for ComponentUniforms { fn default() -> Self { Self { uniforms: Default::default(), @@ -99,7 +99,7 @@ impl Default for ComponentUniforms { /// This system prepares all components of the corresponding component type. /// They are transformed into uniforms and stored in the [`ComponentUniforms`] resource. -fn prepare_uniform_components( +fn prepare_uniform_components( mut commands: Commands, render_device: Res, render_queue: Res, From 16e86aca8a598eb38c76100139cf4c7481bbd8be Mon Sep 17 00:00:00 2001 From: james7132 Date: Fri, 6 May 2022 12:52:53 -0700 Subject: [PATCH 02/16] Update bounds on Query/World/Entity{Ref/Mut} --- crates/bevy_ecs/src/system/query.rs | 2 +- crates/bevy_ecs/src/world/entity_ref.rs | 4 ++-- crates/bevy_ecs/src/world/mod.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index 1598c95388af3..b01f6de3d58c3 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -827,7 +827,7 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// # bevy_ecs::system::assert_is_system(print_selected_character_name_system); /// ``` #[inline] - pub fn get_component(&self, entity: Entity) -> Result<&T, QueryComponentError> { + pub fn get_component(&self, entity: Entity) -> Result<&T, QueryComponentError> { let world = self.world; let entity_ref = world .get_entity(entity) diff --git a/crates/bevy_ecs/src/world/entity_ref.rs b/crates/bevy_ecs/src/world/entity_ref.rs index c9b6006381a7d..45d2648f98c71 100644 --- a/crates/bevy_ecs/src/world/entity_ref.rs +++ b/crates/bevy_ecs/src/world/entity_ref.rs @@ -64,7 +64,7 @@ impl<'w> EntityRef<'w> { } #[inline] - pub fn get(&self) -> Option<&'w T> { + pub fn get(&self) -> Option<&'w T> { // SAFE: entity location is valid and returned component is of type T unsafe { get_component_with_type(self.world, TypeId::of::(), self.entity, self.location) @@ -166,7 +166,7 @@ impl<'w> EntityMut<'w> { } #[inline] - pub fn get(&self) -> Option<&'_ T> { + pub fn get(&self) -> Option<&'_ T> { // SAFE: lifetimes enforce correct usage of returned borrow unsafe { get_component_with_type(self.world, TypeId::of::(), self.entity, self.location) diff --git a/crates/bevy_ecs/src/world/mod.rs b/crates/bevy_ecs/src/world/mod.rs index bdcd809bd9e23..f83c906623009 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -413,7 +413,7 @@ impl World { /// assert_eq!(position.x, 0.0); /// ``` #[inline] - pub fn get(&self, entity: Entity) -> Option<&T> { + pub fn get(&self, entity: Entity) -> Option<&T> { self.get_entity(entity)?.get() } From 998b4bff2742d1a297f51f4ce79409051fa6dcb2 Mon Sep 17 00:00:00 2001 From: james7132 Date: Fri, 6 May 2022 13:07:37 -0700 Subject: [PATCH 03/16] Add compile_fail_test and update Component derive macro --- crates/bevy_ecs/macros/src/component.rs | 2 +- .../tests/ui/non_sync_ref.rs | 26 ++++++ .../tests/ui/non_sync_ref.stderr | 81 +++++++++++++++++++ 3 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 crates/bevy_ecs_compile_fail_tests/tests/ui/non_sync_ref.rs create mode 100644 crates/bevy_ecs_compile_fail_tests/tests/ui/non_sync_ref.stderr diff --git a/crates/bevy_ecs/macros/src/component.rs b/crates/bevy_ecs/macros/src/component.rs index 440fe31468df7..d96bc958d66a6 100644 --- a/crates/bevy_ecs/macros/src/component.rs +++ b/crates/bevy_ecs/macros/src/component.rs @@ -18,7 +18,7 @@ pub fn derive_component(input: TokenStream) -> TokenStream { ast.generics .make_where_clause() .predicates - .push(parse_quote! { Self: Send + Sync + 'static }); + .push(parse_quote! { Self: Send + 'static }); let struct_name = &ast.ident; let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl(); diff --git a/crates/bevy_ecs_compile_fail_tests/tests/ui/non_sync_ref.rs b/crates/bevy_ecs_compile_fail_tests/tests/ui/non_sync_ref.rs new file mode 100644 index 0000000000000..6438838ed8bde --- /dev/null +++ b/crates/bevy_ecs_compile_fail_tests/tests/ui/non_sync_ref.rs @@ -0,0 +1,26 @@ +use bevy_ecs::prelude::*; +use std::cell::Cell; + +#[derive(Component, Eq, PartialEq, Debug)] +struct A(Cell); + +fn main() { + let mut world = World::default(); + let e = world.spawn().insert(A(Cell::new(10_usize))).id(); + + { + let query = QueryState::<&A>::new(&mut world); + } + + { + let value = world.get::(e); + } + + { + let value = world.entity(e).get::(); + } + + { + let value = world.entity_mut(e).get::(); + } +} diff --git a/crates/bevy_ecs_compile_fail_tests/tests/ui/non_sync_ref.stderr b/crates/bevy_ecs_compile_fail_tests/tests/ui/non_sync_ref.stderr new file mode 100644 index 0000000000000..a9c209dec16df --- /dev/null +++ b/crates/bevy_ecs_compile_fail_tests/tests/ui/non_sync_ref.stderr @@ -0,0 +1,81 @@ +error[E0599]: the function or associated item `new` exists for struct `bevy_ecs::query::QueryState<&A>`, but its trait bounds were not satisfied + --> tests/ui/non_sync_ref.rs:12:39 + | +12 | let query = QueryState::<&A>::new(&mut world); + | ^^^ function or associated item cannot be called on `bevy_ecs::query::QueryState<&A>` due to unsatisfied trait bounds + | + = note: the following trait bounds were not satisfied: + `&A: WorldQuery` + +error[E0277]: `Cell` cannot be shared between threads safely + --> tests/ui/non_sync_ref.rs:12:21 + | +12 | let query = QueryState::<&A>::new(&mut world); + | ^^^^^^^^^^^^^^^^ `Cell` cannot be shared between threads safely + | + = help: within `A`, the trait `Sync` is not implemented for `Cell` +note: required because it appears within the type `A` + --> tests/ui/non_sync_ref.rs:5:8 + | +5 | struct A(Cell); + | ^ + = note: required because of the requirements on the impl of `WorldQuery` for `&A` +note: required by a bound in `bevy_ecs::query::QueryState` + --> C:/Users/James/Git/bevy/crates/bevy_ecs/src/query/state.rs:20:26 + | +20 | pub struct QueryState { + | ^^^^^^^^^^ required by this bound in `bevy_ecs::query::QueryState` + +error[E0277]: `Cell` cannot be shared between threads safely + --> tests/ui/non_sync_ref.rs:16:27 + | +16 | let value = world.get::(e); + | ^^^ `Cell` cannot be shared between threads safely + | + = help: within `A`, the trait `Sync` is not implemented for `Cell` +note: required because it appears within the type `A` + --> tests/ui/non_sync_ref.rs:5:8 + | +5 | struct A(Cell); + | ^ +note: required by a bound in `bevy_ecs::world::World::get` + --> C:/Users/James/Git/bevy/crates/bevy_ecs/src/world/mod.rs:416:31 + | +416 | pub fn get(&self, entity: Entity) -> Option<&T> { + | ^^^^ required by this bound in `bevy_ecs::world::World::get` + +error[E0277]: `Cell` cannot be shared between threads safely + --> tests/ui/non_sync_ref.rs:20:37 + | +20 | let value = world.entity(e).get::(); + | ^^^ `Cell` cannot be shared between threads safely + | + = help: within `A`, the trait `Sync` is not implemented for `Cell` +note: required because it appears within the type `A` + --> tests/ui/non_sync_ref.rs:5:8 + | +5 | struct A(Cell); + | ^ +note: required by a bound in `EntityRef::<'w>::get` + --> C:/Users/James/Git/bevy/crates/bevy_ecs/src/world/entity_ref.rs:67:31 + | +67 | pub fn get(&self) -> Option<&'w T> { + | ^^^^ required by this bound in `EntityRef::<'w>::get` + +error[E0277]: `Cell` cannot be shared between threads safely + --> tests/ui/non_sync_ref.rs:24:41 + | +24 | let value = world.entity_mut(e).get::(); + | ^^^ `Cell` cannot be shared between threads safely + | + = help: within `A`, the trait `Sync` is not implemented for `Cell` +note: required because it appears within the type `A` + --> tests/ui/non_sync_ref.rs:5:8 + | +5 | struct A(Cell); + | ^ +note: required by a bound in `EntityMut::<'w>::get` + --> C:/Users/James/Git/bevy/crates/bevy_ecs/src/world/entity_ref.rs:169:31 + | +169 | pub fn get(&self) -> Option<&'_ T> { + | ^^^^ required by this bound in `EntityMut::<'w>::get` From dd6fcd3bcdfb02584e863a37f5e9a7486cf9f1af Mon Sep 17 00:00:00 2001 From: james7132 Date: Fri, 6 May 2022 13:26:42 -0700 Subject: [PATCH 04/16] Formatting --- crates/bevy_ecs/src/system/query.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index b01f6de3d58c3..1b707259e3858 100644 --- a/crates/bevy_ecs/src/system/query.rs +++ b/crates/bevy_ecs/src/system/query.rs @@ -827,7 +827,10 @@ impl<'w, 's, Q: WorldQuery, F: WorldQuery> Query<'w, 's, Q, F> { /// # bevy_ecs::system::assert_is_system(print_selected_character_name_system); /// ``` #[inline] - pub fn get_component(&self, entity: Entity) -> Result<&T, QueryComponentError> { + pub fn get_component( + &self, + entity: Entity, + ) -> Result<&T, QueryComponentError> { let world = self.world; let entity_ref = world .get_entity(entity) From f101e847ce61567cc36a722b74b663a0e7792f62 Mon Sep 17 00:00:00 2001 From: james7132 Date: Fri, 6 May 2022 14:18:54 -0700 Subject: [PATCH 05/16] unsafe impl -> PhantomData T> --- crates/bevy_ecs/src/query/fetch.rs | 18 +++--------------- crates/bevy_ecs/src/query/filter.rs | 18 +++--------------- crates/bevy_ecs/src/system/system_param.rs | 6 +----- 3 files changed, 7 insertions(+), 35 deletions(-) diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index b47550f3ae02d..bd73783cdd802 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -553,13 +553,9 @@ impl WorldQuery for &T { #[doc(hidden)] pub struct ReadState { component_id: ComponentId, - marker: PhantomData, + marker: PhantomData T>, } -// SAFETY: ReadState only contains a ComponentId, should be safe to read -// from multiple threads concurrently -unsafe impl Sync for ReadState {} - // SAFETY: component access and archetype component access are properly updated to reflect that T is // read unsafe impl FetchState for ReadState { @@ -794,13 +790,9 @@ impl Clone for ReadOnlyWriteFetch<'_, T> { #[doc(hidden)] pub struct WriteState { component_id: ComponentId, - marker: PhantomData, + marker: PhantomData T>, } -// SAFETY: WriteState only contains a ComponentId, should be safe to read -// from multiple threads concurrently -unsafe impl Sync for WriteState {} - // SAFETY: component access and archetype component access are properly updated to reflect that T is // written unsafe impl FetchState for WriteState { @@ -1264,13 +1256,9 @@ impl WorldQuery for ChangeTrackers { #[doc(hidden)] pub struct ChangeTrackersState { component_id: ComponentId, - marker: PhantomData, + marker: PhantomData T>, } -// SAFETY: WriteState only contains a ComponentId, should be safe to read -// from multiple threads concurrently -unsafe impl Sync for ChangeTrackersState {} - // SAFETY: component access and archetype component access are properly updated to reflect that T is // read unsafe impl FetchState for ChangeTrackersState { diff --git a/crates/bevy_ecs/src/query/filter.rs b/crates/bevy_ecs/src/query/filter.rs index 1f30259cd4b44..ff525f703b961 100644 --- a/crates/bevy_ecs/src/query/filter.rs +++ b/crates/bevy_ecs/src/query/filter.rs @@ -64,13 +64,9 @@ pub struct WithFetch { #[doc(hidden)] pub struct WithState { component_id: ComponentId, - marker: PhantomData, + marker: PhantomData T>, } -// SAFETY: WithState only contains a ComponentId, should be safe to read -// from multiple threads concurrently -unsafe impl Sync for WithState {} - // SAFETY: no component access or archetype component access unsafe impl FetchState for WithState { fn init(world: &mut World) -> Self { @@ -211,13 +207,9 @@ pub struct WithoutFetch { #[doc(hidden)] pub struct WithoutState { component_id: ComponentId, - marker: PhantomData, + marker: PhantomData T>, } -// SAFETY: WithoutState only contains a ComponentId, should be safe to read -// from multiple threads concurrently -unsafe impl Sync for WithoutState {} - // SAFETY: no component access or archetype component access unsafe impl FetchState for WithoutState { fn init(world: &mut World) -> Self { @@ -505,7 +497,7 @@ macro_rules! impl_tick_filter { $(#[$state_meta])* pub struct $state_name { component_id: ComponentId, - marker: PhantomData, + marker: PhantomData T>, } impl WorldQuery for $name { @@ -516,10 +508,6 @@ macro_rules! impl_tick_filter { } } - // SAFETY: The state only contains a ComponentId, should be safe to read - // from multiple threads concurrently - unsafe impl Sync for $state_name {} - // SAFETY: this reads the T component. archetype component access and component access are updated to reflect that unsafe impl FetchState for $state_name { fn init(world: &mut World) -> Self { diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 6d6d2ae1ce502..fa67dfde5ccfe 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -711,13 +711,9 @@ unsafe impl ReadOnlySystemParamFetch for RemovedComponentsState #[doc(hidden)] pub struct RemovedComponentsState { component_id: ComponentId, - marker: PhantomData, + marker: PhantomData T>, } -// SAFETY: RemovedComponentState only contains a ComponentId, should be safe to read -// from multiple threads concurrently -unsafe impl Sync for RemovedComponentsState {} - impl<'a, T: Component> SystemParam for RemovedComponents<'a, T> { type Fetch = RemovedComponentsState; } From 61f4d7c3ee6d81c3c10bcfd64e669a3ba7f09c50 Mon Sep 17 00:00:00 2001 From: james7132 Date: Fri, 6 May 2022 14:25:54 -0700 Subject: [PATCH 06/16] Fix examples --- examples/games/game_menu.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/games/game_menu.rs b/examples/games/game_menu.rs index 78167cb33a7d0..387f0af45f961 100644 --- a/examples/games/game_menu.rs +++ b/examples/games/game_menu.rs @@ -370,7 +370,7 @@ mod menu { // This system updates the settings when a new value for a setting is selected, and marks // the button as the one currently selected - fn setting_button( + fn setting_button( interaction_query: Query<(&Interaction, &T, Entity), (Changed, With