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/src/bundle.rs b/crates/bevy_ecs/src/bundle.rs index 6b81435fc8b4b..50a2641150de7 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 97adb2f5beb3e..066c5e6c6a531 100644 --- a/crates/bevy_ecs/src/component.rs +++ b/crates/bevy_ecs/src/component.rs @@ -15,7 +15,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. /// ``` @@ -32,7 +32,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; } @@ -121,8 +121,8 @@ impl ComponentInfo { } #[inline] - pub fn is_send_and_sync(&self) -> bool { - self.descriptor.is_send_and_sync + pub fn is_send(&self) -> bool { + self.descriptor.is_send } fn new(id: ComponentId, descriptor: ComponentDescriptor) -> Self { @@ -162,8 +162,9 @@ pub struct ComponentDescriptor { // associated rust component type if one exists. storage_type: StorageType, // SAFETY: This must remain private. It must only be set to "true" if this component is - // actually Send + Sync - is_send_and_sync: bool, + // actually Send + // TODO: Add is_sync to this when applicable. + is_send: bool, type_id: Option, layout: Layout, // SAFETY: this function must be safe to call with pointers pointing to items of the type @@ -177,7 +178,7 @@ impl std::fmt::Debug for ComponentDescriptor { f.debug_struct("ComponentDescriptor") .field("name", &self.name) .field("storage_type", &self.storage_type) - .field("is_send_and_sync", &self.is_send_and_sync) + .field("is_send", &self.is_send) .field("type_id", &self.type_id) .field("layout", &self.layout) .finish() @@ -194,7 +195,7 @@ impl ComponentDescriptor { Self { name: std::any::type_name::().to_string(), storage_type: T::Storage::STORAGE_TYPE, - is_send_and_sync: true, + is_send: true, type_id: Some(TypeId::of::()), layout: Layout::new::(), drop: Self::drop_ptr::, @@ -210,7 +211,7 @@ impl ComponentDescriptor { // PERF: `SparseStorage` may actually be a more // reasonable choice as `storage_type` for resources. storage_type: StorageType::Table, - is_send_and_sync: true, + is_send: true, type_id: Some(TypeId::of::()), layout: Layout::new::(), drop: Self::drop_ptr::, @@ -221,7 +222,7 @@ impl ComponentDescriptor { Self { name: std::any::type_name::().to_string(), storage_type, - is_send_and_sync: false, + is_send: false, type_id: Some(TypeId::of::()), layout: Layout::new::(), drop: Self::drop_ptr::, diff --git a/crates/bevy_ecs/src/query/fetch.rs b/crates/bevy_ecs/src/query/fetch.rs index 5a89bc5280f63..76e04a214dace 100644 --- a/crates/bevy_ecs/src/query/fetch.rs +++ b/crates/bevy_ecs/src/query/fetch.rs @@ -292,6 +292,31 @@ use std::{cell::UnsafeCell, marker::PhantomData}; /// /// # bevy_ecs::system::assert_is_system(my_system); /// ``` +/// +/// ## Non-Sync Queries +/// +/// Non-`Sync` components are supported, but cannot be accessed as `&T`, +/// as the type cannot be safely read from multiple threads at the same +/// time. These components must be accessed via a `&mut T` to guarentee +/// that the system has exclusive access to the components. +/// +/// ```compile_fail,E0277 +/// # use bevy_ecs::prelude::*; +/// # use std::cell::Cell; +/// +/// #[derive(Component)] +/// struct NotSync(Cell); +/// +/// // This will not compile! +/// fn my_system(query: Query<&NotSync>) { +/// for _ in query.iter() {} +/// } +/// +/// // This will compile! +/// fn my_system_mut(query: Query<&mut NotSync>) { +/// for _ in query.iter() {} +/// } +/// ``` pub trait WorldQuery: for<'w> WorldQueryGats<'w, _State = Self::State> { type State: FetchState; @@ -541,7 +566,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> { @@ -553,12 +578,12 @@ impl WorldQuery for &T { #[doc(hidden)] pub struct ReadState { component_id: ComponentId, - marker: PhantomData, + marker: PhantomData T>, } // 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 +645,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; @@ -790,7 +815,7 @@ impl Clone for ReadOnlyWriteFetch<'_, T> { #[doc(hidden)] pub struct WriteState { component_id: ComponentId, - marker: PhantomData, + marker: PhantomData T>, } // SAFETY: component access and archetype component access are properly updated to reflect that T is @@ -1256,7 +1281,7 @@ impl WorldQuery for ChangeTrackers { #[doc(hidden)] pub struct ChangeTrackersState { component_id: ComponentId, - marker: PhantomData, + marker: PhantomData T>, } // SAFETY: component access and archetype component access are properly updated to reflect that T is diff --git a/crates/bevy_ecs/src/query/filter.rs b/crates/bevy_ecs/src/query/filter.rs index 63c83f6350b1a..3a1ca71ae6466 100644 --- a/crates/bevy_ecs/src/query/filter.rs +++ b/crates/bevy_ecs/src/query/filter.rs @@ -64,7 +64,7 @@ pub struct WithFetch { #[doc(hidden)] pub struct WithState { component_id: ComponentId, - marker: PhantomData, + marker: PhantomData T>, } // SAFETY: no component access or archetype component access @@ -207,7 +207,7 @@ pub struct WithoutFetch { #[doc(hidden)] pub struct WithoutState { component_id: ComponentId, - marker: PhantomData, + marker: PhantomData T>, } // SAFETY: no component access or archetype component access @@ -497,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 { diff --git a/crates/bevy_ecs/src/schedule/stage.rs b/crates/bevy_ecs/src/schedule/stage.rs index 2cf14f0d0097b..73b615a6adc4b 100644 --- a/crates/bevy_ecs/src/schedule/stage.rs +++ b/crates/bevy_ecs/src/schedule/stage.rs @@ -20,7 +20,7 @@ use std::fmt::Debug; use super::IntoSystemDescriptor; /// A type that can run as a step of a [`Schedule`](super::Schedule). -pub trait Stage: Downcast + Send + Sync { +pub trait Stage: Downcast + Send { /// Runs the stage; this happens once per update. /// Implementors must initialize all of their state and systems before running the first time. fn run(&mut self, world: &mut World); 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/exclusive_system.rs b/crates/bevy_ecs/src/system/exclusive_system.rs index 46d2e9eb8c091..931035d0353da 100644 --- a/crates/bevy_ecs/src/system/exclusive_system.rs +++ b/crates/bevy_ecs/src/system/exclusive_system.rs @@ -5,7 +5,7 @@ use crate::{ }; use std::borrow::Cow; -pub trait ExclusiveSystem: Send + Sync + 'static { +pub trait ExclusiveSystem: Send + 'static { fn name(&self) -> Cow<'static, str>; fn run(&mut self, world: &mut World); diff --git a/crates/bevy_ecs/src/system/query.rs b/crates/bevy_ecs/src/system/query.rs index c65c85b487433..5ba8b4d0d653b 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) diff --git a/crates/bevy_ecs/src/system/system.rs b/crates/bevy_ecs/src/system/system.rs index 44b719e52617f..fdde247edbe13 100644 --- a/crates/bevy_ecs/src/system/system.rs +++ b/crates/bevy_ecs/src/system/system.rs @@ -17,7 +17,7 @@ use std::borrow::Cow; /// Systems are executed in parallel, in opportunistic order; data access is managed automatically. /// It's possible to specify explicit execution order between specific systems, /// see [`SystemDescriptor`](crate::schedule::SystemDescriptor). -pub trait System: Send + Sync + 'static { +pub trait System: Send + 'static { /// The system's input. See [`In`](crate::system::In) for /// [`FunctionSystem`](crate::system::FunctionSystem)s. type In; diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index b56a2e3461d70..d46e7f74ef60e 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -60,7 +60,7 @@ pub type SystemParamItem<'w, 's, P> = <

::Fetch as SystemParamF /// [`World`] access used by the [`SystemParamState`] (and associated [`SystemParamFetch`]). /// Additionally, it is the implementor's responsibility to ensure there is no /// conflicting access across all [`SystemParam`]'s. -pub unsafe trait SystemParamState: Send + Sync + 'static { +pub unsafe trait SystemParamState: Send + 'static { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self; #[inline] fn new_archetype(&mut self, _archetype: &Archetype, _system_meta: &mut SystemMeta) {} @@ -178,9 +178,9 @@ pub struct ParamSetState SystemParamFetch<'w, 's>>(T); impl_param_set!(); -pub trait Resource: Send + Sync + 'static {} +pub trait Resource: Send + 'static {} -impl Resource for T where T: Send + Sync + 'static {} +impl Resource for T where T: Send + 'static {} /// Shared borrow of a resource. /// @@ -193,7 +193,7 @@ impl Resource for T where T: Send + Sync + 'static {} /// Panics when used as a [`SystemParameter`](SystemParam) if the resource does not exist. /// /// Use `Option>` instead if the resource might not always exist. -pub struct Res<'w, T: Resource> { +pub struct Res<'w, T: Resource + Sync> { value: &'w T, ticks: &'w ComponentTicks, last_change_tick: u32, @@ -201,9 +201,9 @@ pub struct Res<'w, T: Resource> { } // SAFE: Res only reads a single World resource -unsafe impl ReadOnlySystemParamFetch for ResState {} +unsafe impl ReadOnlySystemParamFetch for ResState {} -impl<'w, T: Resource> Debug for Res<'w, T> +impl<'w, T: Resource + Sync> Debug for Res<'w, T> where T: Debug, { @@ -212,8 +212,9 @@ where } } -impl<'w, T: Resource> Res<'w, T> { - /// Returns `true` if the resource was added after the system last ran. +impl<'w, T: Resource + Sync> Res<'w, T> { + /// Returns true if (and only if) this resource been added since the last execution of this + /// system. pub fn is_added(&self) -> bool { self.ticks.is_added(self.last_change_tick, self.change_tick) } @@ -229,7 +230,7 @@ impl<'w, T: Resource> Res<'w, T> { } } -impl<'w, T: Resource> Deref for Res<'w, T> { +impl<'w, T: Resource + Sync> Deref for Res<'w, T> { type Target = T; fn deref(&self) -> &Self::Target { @@ -237,14 +238,14 @@ impl<'w, T: Resource> Deref for Res<'w, T> { } } -impl<'w, T: Resource> AsRef for Res<'w, T> { +impl<'w, T: Resource + Sync> AsRef for Res<'w, T> { #[inline] fn as_ref(&self) -> &T { self.deref() } } -impl<'w, T: Resource> From> for Res<'w, T> { +impl<'w, T: Resource + Sync> From> for Res<'w, T> { fn from(res: ResMut<'w, T>) -> Self { Self { value: res.value, @@ -262,13 +263,13 @@ pub struct ResState { marker: PhantomData, } -impl<'a, T: Resource> SystemParam for Res<'a, T> { +impl<'a, T: Resource + Sync> SystemParam for Res<'a, T> { type Fetch = ResState; } // SAFE: Res ComponentId and ArchetypeComponentId access is applied to SystemMeta. If this Res // conflicts with any prior access, a panic will occur. -unsafe impl SystemParamState for ResState { +unsafe impl SystemParamState for ResState { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { let component_id = world.initialize_resource::(); let combined_access = system_meta.component_access_set.combined_access_mut(); @@ -294,7 +295,7 @@ unsafe impl SystemParamState for ResState { } } -impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for ResState { +impl<'w, 's, T: Resource + Sync> SystemParamFetch<'w, 's> for ResState { type Item = Res<'w, T>; #[inline] @@ -327,20 +328,20 @@ impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for ResState { #[doc(hidden)] pub struct OptionResState(ResState); -impl<'a, T: Resource> SystemParam for Option> { +impl<'a, T: Resource + Sync> SystemParam for Option> { type Fetch = OptionResState; } // SAFE: Only reads a single World resource -unsafe impl ReadOnlySystemParamFetch for OptionResState {} +unsafe impl ReadOnlySystemParamFetch for OptionResState {} -unsafe impl SystemParamState for OptionResState { +unsafe impl SystemParamState for OptionResState { fn init(world: &mut World, system_meta: &mut SystemMeta) -> Self { Self(ResState::init(world, system_meta)) } } -impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for OptionResState { +impl<'w, 's, T: Resource + Sync> SystemParamFetch<'w, 's> for OptionResState { type Item = Option>; #[inline] @@ -365,7 +366,7 @@ impl<'w, 's, T: Resource> SystemParamFetch<'w, 's> for OptionResState { #[doc(hidden)] pub struct ResMutState { component_id: ComponentId, - marker: PhantomData, + marker: PhantomData T>, } impl<'a, T: Resource> SystemParam for ResMut<'a, T> { @@ -709,7 +710,7 @@ unsafe impl ReadOnlySystemParamFetch for RemovedComponentsState #[doc(hidden)] pub struct RemovedComponentsState { component_id: ComponentId, - marker: PhantomData, + marker: PhantomData T>, } impl<'a, T: Component> SystemParam for RemovedComponents<'a, T> { diff --git a/crates/bevy_ecs/src/world/entity_ref.rs b/crates/bevy_ecs/src/world/entity_ref.rs index c9b6006381a7d..37449897affcf 100644 --- a/crates/bevy_ecs/src/world/entity_ref.rs +++ b/crates/bevy_ecs/src/world/entity_ref.rs @@ -63,8 +63,30 @@ impl<'w> EntityRef<'w> { contains_component_with_type(self.world, type_id, self.location) } + /// Gets the [`Component`] of a given type for the referenced entity, if available. + /// Returns `None` if not present. + /// + /// This component type must be [`Sync`]. Attempting to use a non-`Sync` type will + /// fail to compile. To safely access a non-`Sync` component, use [`EntityMut::get_mut`] + /// instead. + /// + /// ```compile_fail,E0277 + /// # use bevy_ecs::{component::Component, world::World}; + /// # use std::cell::Cell; + /// + /// #[derive(Component)] + /// struct NotSync(Cell); + /// + /// # fn main() { + /// # let world = World::new(); + /// # let entity = todo!(); + /// let entity_ref = world.entity(entity); + /// // Will fail to compile! + /// entity_ref.get::(); + /// # } + /// ``` #[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) @@ -165,8 +187,30 @@ impl<'w> EntityMut<'w> { contains_component_with_type(self.world, type_id, self.location) } + /// Gets the [`Component`] of a given type for the referenced entity, if available. + /// Returns `None` if not present. + /// + /// This component type must be [`Sync`]. Attempting to use a non-`Sync` type will + /// fail to compile. To safely access a non-`Sync` component, use [`get_mut`](Self::get_mut) + /// instead. + /// + /// ```compile_fail,E0277 + /// # use bevy_ecs::{component::Component, world::World}; + /// # use std::cell::Cell; + /// + /// #[derive(Component)] + /// struct NotSync(Cell); + /// + /// # fn main() { + /// # let world = World::new(); + /// # let entity = todo!(); + /// let entity_mut = world.entity_mut(entity); + /// // Will fail to compile! + /// entity_mut.get::(); + /// # } + /// ``` #[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..89f08513aeb2e 100644 --- a/crates/bevy_ecs/src/world/mod.rs +++ b/crates/bevy_ecs/src/world/mod.rs @@ -412,8 +412,25 @@ impl World { /// let position = world.get::(entity).unwrap(); /// assert_eq!(position.x, 0.0); /// ``` + /// + /// Attempting to use this on a component that is not [`Sync`] will fail to compile. + /// + /// ```compile_fail,E0277 + /// # use bevy_ecs::{component::Component, world::World}; + /// # use std::cell::Cell; + /// + /// #[derive(Component)] + /// struct NotSync(Cell); + /// + /// # fn main() { + /// # let world = World::new(); + /// # let entity = todo!(); + /// // Will fail to compile! + /// world.get::(entity); + /// # } + /// ``` #[inline] - pub fn get(&self, entity: Entity) -> Option<&T> { + pub fn get(&self, entity: Entity) -> Option<&T> { self.get_entity(entity)?.get() } diff --git a/crates/bevy_render/src/camera/camera.rs b/crates/bevy_render/src/camera/camera.rs index 2cbec6a0e0a79..bdc29f1085c9d 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::) @@ -253,7 +253,7 @@ impl Plugin for CameraTypePlugin { #[derive(Debug)] pub struct ActiveCamera { camera: Option, - marker: PhantomData, + marker: PhantomData T>, } impl Default for ActiveCamera { @@ -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, diff --git a/crates/bevy_render/src/render_phase/draw.rs b/crates/bevy_render/src/render_phase/draw.rs index 5ffca0ea25886..5f035ce070dfa 100644 --- a/crates/bevy_render/src/render_phase/draw.rs +++ b/crates/bevy_render/src/render_phase/draw.rs @@ -285,6 +285,7 @@ impl> RenderCommandState { impl + Send + Sync + 'static> Draw

for RenderCommandState where ::Fetch: ReadOnlySystemParamFetch, + SystemState: Sync, { /// Prepares the ECS parameters for the wrapped [`RenderCommand`] and then renders it. fn draw<'w>( @@ -307,7 +308,8 @@ pub trait AddRenderCommand { &mut self, ) -> &mut Self where - ::Fetch: ReadOnlySystemParamFetch; + ::Fetch: ReadOnlySystemParamFetch, + <>::Param as SystemParam>::Fetch: Sync; } impl AddRenderCommand for App { @@ -316,6 +318,7 @@ impl AddRenderCommand for App { ) -> &mut Self where ::Fetch: ReadOnlySystemParamFetch, + <>::Param as SystemParam>::Fetch: Sync, { let draw_function = RenderCommandState::::new(&mut self.world); let draw_functions = self diff --git a/examples/ecs/custom_query_param.rs b/examples/ecs/custom_query_param.rs index b18275794d429..b899879fc91e9 100644 --- a/examples/ecs/custom_query_param.rs +++ b/examples/ecs/custom_query_param.rs @@ -40,7 +40,7 @@ struct ComponentZ; #[derive(WorldQuery)] #[world_query(derive(Debug))] -struct ReadOnlyCustomQuery { +struct ReadOnlyCustomQuery { entity: Entity, a: &'static ComponentA, b: Option<&'static ComponentB>, @@ -74,7 +74,7 @@ fn print_components_read_only( // using the `derive` attribute. #[derive(WorldQuery)] #[world_query(mutable, derive(Debug))] -struct CustomQuery { +struct CustomQuery { entity: Entity, a: &'static mut ComponentA, b: Option<&'static mut ComponentB>, @@ -101,7 +101,7 @@ struct NestedQuery { #[derive(WorldQuery)] #[world_query(derive(Debug))] -struct GenericQuery { +struct GenericQuery { generic: (&'static T, &'static P), } 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