From 35bf9596f12b764f9046f663a9d37bf402f35a11 Mon Sep 17 00:00:00 2001 From: Anders429 Date: Mon, 24 Apr 2023 22:36:03 -0700 Subject: [PATCH 01/16] Decouple the filter from the archetype claims iterator. --- src/query/result/archetype_claims.rs | 39 +++++++++++++++------------- src/registry/contains/mod.rs | 3 +-- src/registry/mod.rs | 1 + src/system/schedule/stage.rs | 16 +++++++----- src/system/schedule/stager.rs | 9 +++++-- src/world/mod.rs | 28 ++++++++++++++------ 6 files changed, 60 insertions(+), 36 deletions(-) diff --git a/src/query/result/archetype_claims.rs b/src/query/result/archetype_claims.rs index 3d182946..93809abd 100644 --- a/src/query/result/archetype_claims.rs +++ b/src/query/result/archetype_claims.rs @@ -3,13 +3,11 @@ use crate::{ archetype, archetypes, - query::{ - filter::And, - view, - }, - registry, + query::view, registry::{ + self, contains::filter::Sealed as ContainsFilterSealed, + ContainsFilter, ContainsQuery, }, }; @@ -19,18 +17,21 @@ use core::marker::PhantomData; /// /// This iterator returns key-value pairs of archetype identifiers and the list of claimed /// components for the given query on that archetype. -pub struct ArchetypeClaims<'a, Registry, Filter, Views, Indices> +pub struct ArchetypeClaims<'a, Registry, Views, QueryFilter, Filter, QueryIndices, FilterIndices> where Registry: registry::Registry, { archetypes_iter: archetypes::IterMut<'a, Registry>, + views: PhantomData, + query_filter: PhantomData, filter: PhantomData, - view: PhantomData, - indices: PhantomData, + query_indices: PhantomData, + filter_indices: PhantomData, } -impl<'a, Registry, Filter, Views, Indices> ArchetypeClaims<'a, Registry, Filter, Views, Indices> +impl<'a, Registry, Views, QueryFilter, Filter, QueryIndices, FilterIndices> + ArchetypeClaims<'a, Registry, Views, QueryFilter, Filter, QueryIndices, FilterIndices> where Registry: registry::Registry, { @@ -43,18 +44,21 @@ where Self { archetypes_iter, + views: PhantomData, + query_filter: PhantomData, filter: PhantomData, - view: PhantomData, - indices: PhantomData, + query_indices: PhantomData, + filter_indices: PhantomData, } } } -impl<'a, Registry, Filter, Views, Indices> Iterator - for ArchetypeClaims<'a, Registry, Filter, Views, Indices> +impl<'a, Registry, Views, QueryFilter, Filter, QueryIndices, FilterIndices> Iterator + for ArchetypeClaims<'a, Registry, Views, QueryFilter, Filter, QueryIndices, FilterIndices> where Views: view::Views<'a>, - Registry: ContainsQuery<'a, Filter, Views, Indices>, + Registry: + ContainsFilter + ContainsQuery<'a, QueryFilter, Views, QueryIndices>, { type Item = (archetype::IdentifierRef, Registry::Claims); @@ -65,10 +69,9 @@ where // identifier is generic over. Additionally, the identifier reference created here // will not outlive `archetype`. unsafe { - , - And, - >>::filter(archetype.identifier()) + >::filter( + archetype.identifier(), + ) } }) .map(|archetype| { diff --git a/src/registry/contains/mod.rs b/src/registry/contains/mod.rs index 5ff6e7cf..69f140d1 100644 --- a/src/registry/contains/mod.rs +++ b/src/registry/contains/mod.rs @@ -29,11 +29,10 @@ pub use par_query::ContainsParQuery; pub use query::ContainsQuery; pub use views::ContainsViews; +pub(crate) use filter::ContainsFilter; #[cfg(feature = "rayon")] pub(crate) use par_views::ContainsParViews; -use filter::ContainsFilter; - /// Type marker for a component contained in an entity. pub enum Contained {} diff --git a/src/registry/mod.rs b/src/registry/mod.rs index 82e58186..ddaef933 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -57,6 +57,7 @@ pub use eq::{ PartialEq, }; +pub(crate) use contains::ContainsFilter; #[cfg(feature = "rayon")] pub(crate) use contains::ContainsParViews; #[cfg(feature = "rayon")] diff --git a/src/system/schedule/stage.rs b/src/system/schedule/stage.rs index 29550d83..ae0ea857 100644 --- a/src/system/schedule/stage.rs +++ b/src/system/schedule/stage.rs @@ -2,10 +2,11 @@ use crate::{ archetype, hlist::define_null, query::{ + filter::And, view::Claims, - Query, }, registry::{ + ContainsFilter, ContainsQuery, Registry, }, @@ -162,7 +163,8 @@ fn query_archetype_identifiers< borrowed_archetypes: &mut HashMap, R::Claims, FnvBuildHasher>, ) -> bool where - R: ContainsQuery<'a, T::Filter, T::Views, QueryIndices>, + R: ContainsFilter, And> + + ContainsQuery<'a, T::Filter, T::Views, QueryIndices>, Resources: 'a, T: Task<'a, R, Resources, QueryIndices, ResourceViewsIndices, DisjointIndices, EntryIndices>, { @@ -172,7 +174,7 @@ where // SAFETY: The access to the world's archetype identifiers follows Rust's borrowing // rules. unsafe { - (*world.get()).query_archetype_claims(Query::::new()) + (*world.get()).query_archetype_claims::, QueryIndices, And>() } { match merged_borrowed_archetypes.entry(identifier) { @@ -206,7 +208,8 @@ fn query_archetype_identifiers_unchecked< world: SendableWorld, borrowed_archetypes: &mut HashMap, R::Claims, FnvBuildHasher>, ) where - R: ContainsQuery<'a, T::Filter, T::Views, QueryIndices>, + R: ContainsFilter, And> + + ContainsQuery<'a, T::Filter, T::Views, QueryIndices>, Resources: 'a, T: Task<'a, R, Resources, QueryIndices, ResourceViewsIndices, DisjointIndices, EntryIndices>, { @@ -214,7 +217,7 @@ fn query_archetype_identifiers_unchecked< // SAFETY: The access to the world's archetype identifiers follows Rust's borrowing // rules. unsafe { - (*world.get()).query_archetype_claims(Query::::new()) + (*world.get()).query_archetype_claims::, QueryIndices, And>() } { borrowed_archetypes.insert_unique_unchecked(identifier, claims); @@ -246,7 +249,8 @@ impl< (EntryIndices, EntryIndicesList), > for (&mut T, U) where - R: ContainsQuery<'a, T::Filter, T::Views, QueryIndices>, + R: ContainsFilter, And> + + ContainsQuery<'a, T::Filter, T::Views, QueryIndices>, Resources: 'a, T: Task<'a, R, Resources, QueryIndices, ResourceViewsIndices, DisjointIndices, EntryIndices> + Send, diff --git a/src/system/schedule/stager.rs b/src/system/schedule/stager.rs index 53b09884..4fa135b8 100644 --- a/src/system/schedule/stager.rs +++ b/src/system/schedule/stager.rs @@ -1,11 +1,15 @@ use crate::{ hlist::define_null, - query::view, + query::{ + filter::And, + view, + }, registry::{ contains::views::{ ContainsViewsOuter, Sealed as ContainsViewsSealed, }, + ContainsFilter, ContainsQuery, Registry, }, @@ -720,7 +724,8 @@ impl< (EntryIndices, EntryIndicesList), > for (T, U) where - R: ContainsQuery<'a, T::Filter, T::Views, QueryIndices>, + R: ContainsFilter, And> + + ContainsQuery<'a, T::Filter, T::Views, QueryIndices>, Resources: 'a, T: Task<'a, R, Resources, QueryIndices, ResourceViewsIndices, DisjointIndices, EntryIndices> + Send diff --git a/src/world/mod.rs b/src/world/mod.rs index a1740060..968039b0 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -44,10 +44,7 @@ use crate::{ }; #[cfg(feature = "rayon")] use crate::{ - query::{ - filter::And, - view::ParViews, - }, + query::view::ParViews, registry::{ contains::filter::ContainsFilter, ContainsParQuery, @@ -460,13 +457,28 @@ where /// `Archetypes` to which they belong. #[cfg(feature = "rayon")] #[cfg_attr(doc_cfg, doc(cfg(feature = "rayon")))] - pub(crate) unsafe fn query_archetype_claims<'a, Views, Filter, FilterIndices, Indices>( + pub(crate) unsafe fn query_archetype_claims< + 'a, + Views, + QueryFilter, + Filter, + QueryIndices, + FilterIndices, + >( &'a mut self, - #[allow(unused_variables)] query: Query, - ) -> result::ArchetypeClaims<'a, Registry, Filter, Views, Indices> + ) -> result::ArchetypeClaims< + 'a, + Registry, + Views, + QueryFilter, + Filter, + QueryIndices, + FilterIndices, + > where Views: view::Views<'a>, - Registry: ContainsFilter, FilterIndices>, + Registry: ContainsFilter + + ContainsQuery<'a, QueryFilter, Views, QueryIndices>, { // SAFETY: The safety contract here is upheld by the safety contract of this method. unsafe { result::ArchetypeClaims::new(self.archetypes.iter_mut()) } From b3d86cc71e29cf7ff0f3807d3d8e4d3fea593768 Mon Sep 17 00:00:00 2001 From: Anders429 Date: Wed, 26 Apr 2023 23:45:26 -0700 Subject: [PATCH 02/16] Respect EntryViews in dynamic scheduling optimizations. --- src/query/result/archetype_claims.rs | 101 ++++++++++++++-- src/query/view/claim.rs | 114 +++++++++++++++++- src/query/view/sealed.rs | 10 ++ src/registry/mod.rs | 6 +- src/system/schedule/scheduler.rs | 13 ++ src/system/schedule/sealed.rs | 7 ++ src/system/schedule/stage.rs | 48 ++++++-- src/system/schedule/stager.rs | 35 +++++- src/system/schedule/stages.rs | 8 +- src/system/schedule/task/sealed.rs | 13 +- src/world/mod.rs | 102 +++++++++++++++- .../schedule/non_send_entry_views.stderr | 8 +- .../schedule/non_send_resource_views.stderr | 8 +- tests/trybuild/schedule/non_send_views.stderr | 8 +- 14 files changed, 438 insertions(+), 43 deletions(-) diff --git a/src/query/result/archetype_claims.rs b/src/query/result/archetype_claims.rs index 93809abd..1cded5d4 100644 --- a/src/query/result/archetype_claims.rs +++ b/src/query/result/archetype_claims.rs @@ -3,12 +3,19 @@ use crate::{ archetype, archetypes, - query::view, + query::{ + view, + view::Claims, + }, + registry, registry::{ - self, - contains::filter::Sealed as ContainsFilterSealed, + contains::{ + filter::Sealed as ContainsFilterSealed, + views::Sealed as ContainsViewsSealed, + }, ContainsFilter, ContainsQuery, + ContainsViews, }, }; use core::marker::PhantomData; @@ -17,8 +24,17 @@ use core::marker::PhantomData; /// /// This iterator returns key-value pairs of archetype identifiers and the list of claimed /// components for the given query on that archetype. -pub struct ArchetypeClaims<'a, Registry, Views, QueryFilter, Filter, QueryIndices, FilterIndices> -where +pub struct ArchetypeClaims< + 'a, + Registry, + Views, + QueryFilter, + Filter, + EntryViews, + QueryIndices, + FilterIndices, + EntryViewsIndices, +> where Registry: registry::Registry, { archetypes_iter: archetypes::IterMut<'a, Registry>, @@ -26,12 +42,34 @@ where views: PhantomData, query_filter: PhantomData, filter: PhantomData, + entry_views: PhantomData, query_indices: PhantomData, filter_indices: PhantomData, + entry_views_indices: PhantomData, } -impl<'a, Registry, Views, QueryFilter, Filter, QueryIndices, FilterIndices> - ArchetypeClaims<'a, Registry, Views, QueryFilter, Filter, QueryIndices, FilterIndices> +impl< + 'a, + Registry, + Views, + QueryFilter, + Filter, + EntryViews, + QueryIndices, + FilterIndices, + EntryViewsIndices, + > + ArchetypeClaims< + 'a, + Registry, + Views, + QueryFilter, + Filter, + EntryViews, + QueryIndices, + FilterIndices, + EntryViewsIndices, + > where Registry: registry::Registry, { @@ -47,18 +85,42 @@ where views: PhantomData, query_filter: PhantomData, filter: PhantomData, + entry_views: PhantomData, query_indices: PhantomData, filter_indices: PhantomData, + entry_views_indices: PhantomData, } } } -impl<'a, Registry, Views, QueryFilter, Filter, QueryIndices, FilterIndices> Iterator - for ArchetypeClaims<'a, Registry, Views, QueryFilter, Filter, QueryIndices, FilterIndices> +impl< + 'a, + Registry, + Views, + QueryFilter, + Filter, + EntryViews, + QueryIndices, + FilterIndices, + EntryViewsIndices, + > Iterator + for ArchetypeClaims< + 'a, + Registry, + Views, + QueryFilter, + Filter, + EntryViews, + QueryIndices, + FilterIndices, + EntryViewsIndices, + > where Views: view::Views<'a>, - Registry: - ContainsFilter + ContainsQuery<'a, QueryFilter, Views, QueryIndices>, + EntryViews: view::Views<'a>, + Registry: ContainsFilter + + ContainsQuery<'a, QueryFilter, Views, QueryIndices> + + ContainsViews<'a, EntryViews, EntryViewsIndices>, { type Item = (archetype::IdentifierRef, Registry::Claims); @@ -79,7 +141,22 @@ where // SAFETY: The `IdentifierRef` created here is guaranteed to outlive // `archetype`, so long as the safety contract at construction is upheld. unsafe { archetype.identifier() }, - Registry::claims(), + unsafe { + >::claims() + .merge_unchecked(&>::claims()) + }, ) }) } diff --git a/src/query/view/claim.rs b/src/query/view/claim.rs index ddce2dfc..3316564f 100644 --- a/src/query/view/claim.rs +++ b/src/query/view/claim.rs @@ -25,7 +25,7 @@ impl Claim { /// /// If the claims are compatible, meaning they can both exist at the same time, they are merged /// together into a single claim. If they are incompatible, `None` is returned. - pub(crate) fn try_merge(self, other: Self) -> Option { + fn try_merge(self, other: Self) -> Option { match self { Self::None => Some(other), Self::Immutable => { @@ -44,6 +44,16 @@ impl Claim { } } } + + /// Merge two claims on a single component column without checking that they are compatible. + /// + /// # Safety + /// The two claims must be compatible, meaning they can both exist at the same time. Otherwise, + /// this function will cause undefined behavior. + unsafe fn merge_unchecked(self, other: Self) -> Self { + // SAFETY: The claims are compatible, so this value will always be `Some`. + unsafe { self.try_merge(other).unwrap_unchecked() } + } } /// A list of claims on the components contained in a heterogeneous list. @@ -55,12 +65,23 @@ pub trait Claims: Sized { /// If the claims are compatible, meaning they can both exist at the same time, they are merged /// together into a single list. If they are incompatible, `None` is returned. fn try_merge(self, other: &Self) -> Option; + + /// Merge two lists of claims without checking that they are compatible. + /// + /// # Safety + /// The two lists of claims must be compatible, meaning they can both exist at the same time. + /// Otherwise, this function will cause undefined behavior. + unsafe fn merge_unchecked(self, other: &Self) -> Self; } impl Claims for Null { fn try_merge(self, _other: &Self) -> Option { Some(self) } + + unsafe fn merge_unchecked(self, _other: &Self) -> Self { + self + } } impl Claims for (Claim, C) @@ -70,6 +91,16 @@ where fn try_merge(self, other: &Self) -> Option { Some((self.0.try_merge(other.0)?, self.1.try_merge(&other.1)?)) } + + unsafe fn merge_unchecked(self, other: &Self) -> Self { + // SAFETY: The lists of claims are compatible. + unsafe { + ( + self.0.merge_unchecked(other.0), + self.1.merge_unchecked(&other.1), + ) + } + } } #[cfg(test)] @@ -179,4 +210,85 @@ mod tests { (Claim::Mutable, (Claim::Immutable, (Claim::None, Null))) ))); } + + #[test] + fn claim_merge_unchecked_none_none() { + assert_eq!( + unsafe { Claim::None.merge_unchecked(Claim::None) }, + Claim::None + ); + } + + #[test] + fn claim_merge_unchecked_none_immutable() { + assert_eq!( + unsafe { Claim::None.merge_unchecked(Claim::Immutable) }, + Claim::Immutable + ); + } + + #[test] + fn claim_merge_unchecked_none_mutable() { + assert_eq!( + unsafe { Claim::None.merge_unchecked(Claim::Mutable) }, + Claim::Mutable + ); + } + + #[test] + fn claim_merge_unchecked_immutable_none() { + assert_eq!( + unsafe { Claim::Immutable.merge_unchecked(Claim::None) }, + Claim::Immutable + ); + } + + #[test] + fn claim_merge_unchecked_immutable_immutable() { + assert_eq!( + unsafe { Claim::Immutable.merge_unchecked(Claim::Immutable) }, + Claim::Immutable + ); + } + + #[test] + fn claim_merge_unchecked_mutable_none() { + assert_eq!( + unsafe { Claim::Mutable.merge_unchecked(Claim::None) }, + Claim::Mutable + ); + } + + #[test] + fn claims_merge_unchecked_null() { + assert_eq!(unsafe { Null.merge_unchecked(&Null) }, Null); + } + + #[test] + fn claims_merge_unchecked_single_element() { + assert_eq!( + unsafe { (Claim::None, Null).merge_unchecked(&(Claim::Mutable, Null)) }, + (Claim::Mutable, Null) + ); + } + + #[test] + fn claims_merge_unchecked_multiple_elements() { + assert_eq!( + unsafe { + ( + Claim::None, + (Claim::Immutable, (Claim::Immutable, (Claim::Mutable, Null))), + ) + .merge_unchecked(&( + Claim::Mutable, + (Claim::None, (Claim::Immutable, (Claim::None, Null))), + )) + }, + ( + Claim::Mutable, + (Claim::Immutable, (Claim::Immutable, (Claim::Mutable, Null))) + ) + ); + } } diff --git a/src/query/view/sealed.rs b/src/query/view/sealed.rs index 8775b33d..0c62ac32 100644 --- a/src/query/view/sealed.rs +++ b/src/query/view/sealed.rs @@ -2,6 +2,7 @@ use crate::{ component::Component, entity, query::{ + filter, result::Results, view::Null, }, @@ -17,6 +18,7 @@ pub trait ViewSealed<'a> { type Result: Iterator; type Index; type MaybeUninit; + type EntryFilter; } impl<'a, C> ViewSealed<'a> for &'a C @@ -26,6 +28,7 @@ where type Result = slice::Iter<'a, C>; type Index = usize; type MaybeUninit = MaybeUninit; + type EntryFilter = filter::Has; } impl<'a, C> ViewSealed<'a> for &'a mut C @@ -35,6 +38,7 @@ where type Result = slice::IterMut<'a, C>; type Index = usize; type MaybeUninit = MaybeUninit; + type EntryFilter = filter::Has; } impl<'a, C> ViewSealed<'a> for Option<&'a C> @@ -47,6 +51,7 @@ where >; type Index = usize; type MaybeUninit = Self; + type EntryFilter = filter::Has; } impl<'a, C> ViewSealed<'a> for Option<&'a mut C> @@ -59,24 +64,28 @@ where >; type Index = usize; type MaybeUninit = Self; + type EntryFilter = filter::Has; } impl<'a> ViewSealed<'a> for entity::Identifier { type Result = iter::Copied>; type Index = Null; type MaybeUninit = Self; + type EntryFilter = filter::Not; } pub trait ViewsSealed<'a> { type Results: Results; type Indices; type MaybeUninit; + type EntryFilter; } impl<'a> ViewsSealed<'a> for Null { type Results = iter::Take>; type Indices = Null; type MaybeUninit = Null; + type EntryFilter = filter::Not; } impl<'a, V, W> ViewsSealed<'a> for (V, W) @@ -87,4 +96,5 @@ where type Results = (V::Result, W::Results); type Indices = (V::Index, W::Indices); type MaybeUninit = (V::MaybeUninit, W::MaybeUninit); + type EntryFilter = filter::Or; } diff --git a/src/registry/mod.rs b/src/registry/mod.rs index ddaef933..acbff4ac 100644 --- a/src/registry/mod.rs +++ b/src/registry/mod.rs @@ -57,9 +57,11 @@ pub use eq::{ PartialEq, }; -pub(crate) use contains::ContainsFilter; #[cfg(feature = "rayon")] -pub(crate) use contains::ContainsParViews; +pub(crate) use contains::{ + ContainsFilter, + ContainsParViews, +}; #[cfg(feature = "rayon")] pub(crate) use sealed::CanonicalParViews; pub(crate) use sealed::{ diff --git a/src/system/schedule/scheduler.rs b/src/system/schedule/scheduler.rs index cde547da..d93d4f26 100644 --- a/src/system/schedule/scheduler.rs +++ b/src/system/schedule/scheduler.rs @@ -27,6 +27,7 @@ pub trait Scheduler< ResourceViewsIndicesLists, DisjointIndicesLists, EntryIndicesLists, + EntryViewsFilterIndicesLists, > where R: Registry, { @@ -38,6 +39,7 @@ pub trait Scheduler< ResourceViewsIndicesLists, DisjointIndicesLists, EntryIndicesLists, + EntryViewsFilterIndicesLists, >; fn as_stages(&'a mut self) -> Self::Stages; @@ -59,6 +61,7 @@ impl<'a, R, Resources> stages::Null, stages::Null, stages::Null, + stages::Null, > for task::Null where R: Registry, @@ -99,6 +102,8 @@ impl< DisjointIndicesLists, EntryIndicesList, EntryIndicesLists, + EntryViewsFilterIndicesList, + EntryViewsFilterIndicesLists, > Scheduler< 'a, @@ -115,6 +120,7 @@ impl< (ResourceViewsIndicesList, ResourceViewsIndicesLists), (DisjointIndicesList, DisjointIndicesLists), (EntryIndicesList, EntryIndicesLists), + (EntryViewsFilterIndicesList, EntryViewsFilterIndicesLists), > for (T, U) where (T, U): Stager< @@ -134,6 +140,7 @@ where ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, >, <(T, U) as Stager< 'a, @@ -152,6 +159,7 @@ where ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, >>::Remainder: Scheduler< 'a, R, @@ -167,6 +175,7 @@ where ResourceViewsIndicesLists, DisjointIndicesLists, EntryIndicesLists, + EntryViewsFilterIndicesLists, >, R: Registry + 'a, Resources: 'a, @@ -181,6 +190,7 @@ where ResourceViewsIndicesList: 'a, DisjointIndicesList: 'a, EntryIndicesList: 'a, + EntryViewsFilterIndicesList: 'a, { type Stages = ( <(T, U) as Stager< @@ -200,6 +210,7 @@ where ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, >>::Stage, <<(T, U) as Stager< 'a, @@ -218,6 +229,7 @@ where ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, >>::Remainder as Scheduler< 'a, R, @@ -233,6 +245,7 @@ where ResourceViewsIndicesLists, DisjointIndicesLists, EntryIndicesLists, + EntryViewsFilterIndicesLists, >>::Stages, ); diff --git a/src/system/schedule/sealed.rs b/src/system/schedule/sealed.rs index bb958ce0..89576fc6 100644 --- a/src/system/schedule/sealed.rs +++ b/src/system/schedule/sealed.rs @@ -14,6 +14,7 @@ where type ResourceViewsIndicesLists; type DisjointIndicesLists; type EntryIndicesLists; + type EntryViewsFilterIndicesLists; type Stages: Stages< 'a, R, @@ -22,6 +23,7 @@ where Self::ResourceViewsIndicesLists, Self::DisjointIndicesLists, Self::EntryIndicesLists, + Self::EntryViewsFilterIndicesLists, >; fn as_stages(&'a mut self) -> Self::Stages; @@ -43,6 +45,7 @@ impl< ResourceViewsIndicesLists, DisjointIndicesLists, EntryIndicesLists, + EntryViewsFilterIndicesLists, > Sealed< 'a, @@ -60,6 +63,7 @@ impl< ResourceViewsIndicesLists, DisjointIndicesLists, EntryIndicesLists, + EntryViewsFilterIndicesLists, ), > for T where @@ -79,12 +83,14 @@ where ResourceViewsIndicesLists, DisjointIndicesLists, EntryIndicesLists, + EntryViewsFilterIndicesLists, >, { type QueryIndicesLists = QueryIndicesLists; type ResourceViewsIndicesLists = ResourceViewsIndicesLists; type DisjointIndicesLists = DisjointIndicesLists; type EntryIndicesLists = EntryIndicesLists; + type EntryViewsFilterIndicesLists = EntryViewsFilterIndicesLists; type Stages = >::Stages; #[inline] diff --git a/src/system/schedule/stage.rs b/src/system/schedule/stage.rs index ae0ea857..ae00d68b 100644 --- a/src/system/schedule/stage.rs +++ b/src/system/schedule/stage.rs @@ -2,12 +2,16 @@ use crate::{ archetype, hlist::define_null, query::{ - filter::And, + filter::{ + And, + Or, + }, view::Claims, }, registry::{ ContainsFilter, ContainsQuery, + ContainsViews, Registry, }, system::schedule::{ @@ -36,6 +40,7 @@ pub trait Stage< ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, >: Send where R: Registry, { @@ -54,6 +59,7 @@ pub trait Stage< NextResourceViewsIndicesLists, NextDisjointIndicesList, NextEntryIndicesList, + NextEntryViewsFilterIndicesList, >( &mut self, world: SendableWorld, @@ -70,6 +76,7 @@ pub trait Stage< NextResourceViewsIndicesLists, NextDisjointIndicesList, NextEntryIndicesList, + NextEntryViewsFilterIndicesList, >; /// Attempt to run as many tasks within this stage as possible as add-ons to the previous @@ -93,7 +100,7 @@ pub trait Stage< fn new_has_run() -> Self::HasRun; } -impl Stage<'_, R, Resources, Null, Null, Null, Null> for Null +impl Stage<'_, R, Resources, Null, Null, Null, Null, Null> for Null where R: Registry, { @@ -106,6 +113,7 @@ where NextResourceViewsIndicesLists, NextDisjointIndicesList, NextEntryIndicesList, + NextEntryViewsFilterIndicesList, >( &mut self, world: SendableWorld, @@ -122,6 +130,7 @@ where NextResourceViewsIndicesLists, NextDisjointIndicesList, NextEntryIndicesList, + NextEntryViewsFilterIndicesList, >, { // Check if borrowed_archetypes is empty. @@ -158,13 +167,17 @@ fn query_archetype_identifiers< ResourceViewsIndices, DisjointIndices, EntryIndices, + EntryViewsFilterIndices, >( world: SendableWorld, borrowed_archetypes: &mut HashMap, R::Claims, FnvBuildHasher>, ) -> bool where - R: ContainsFilter, And> - + ContainsQuery<'a, T::Filter, T::Views, QueryIndices>, + R: ContainsFilter< + Or, T::EntryViewsFilter>, + Or, EntryViewsFilterIndices>, + > + ContainsQuery<'a, T::Filter, T::Views, QueryIndices> + + ContainsViews<'a, T::EntryViews, EntryIndices>, Resources: 'a, T: Task<'a, R, Resources, QueryIndices, ResourceViewsIndices, DisjointIndices, EntryIndices>, { @@ -174,7 +187,7 @@ where // SAFETY: The access to the world's archetype identifiers follows Rust's borrowing // rules. unsafe { - (*world.get()).query_archetype_claims::, QueryIndices, And>() + (*world.get()).query_archetype_claims::, T::EntryViewsFilter>, T::EntryViews, QueryIndices, Or, EntryViewsFilterIndices>, EntryIndices>() } { match merged_borrowed_archetypes.entry(identifier) { @@ -204,12 +217,16 @@ fn query_archetype_identifiers_unchecked< ResourceViewsIndices, DisjointIndices, EntryIndices, + EntryViewsFilterIndices, >( world: SendableWorld, borrowed_archetypes: &mut HashMap, R::Claims, FnvBuildHasher>, ) where - R: ContainsFilter, And> - + ContainsQuery<'a, T::Filter, T::Views, QueryIndices>, + R: ContainsFilter< + Or, T::EntryViewsFilter>, + Or, EntryViewsFilterIndices>, + > + ContainsQuery<'a, T::Filter, T::Views, QueryIndices> + + ContainsViews<'a, T::EntryViews, EntryIndices>, Resources: 'a, T: Task<'a, R, Resources, QueryIndices, ResourceViewsIndices, DisjointIndices, EntryIndices>, { @@ -217,7 +234,7 @@ fn query_archetype_identifiers_unchecked< // SAFETY: The access to the world's archetype identifiers follows Rust's borrowing // rules. unsafe { - (*world.get()).query_archetype_claims::, QueryIndices, And>() + (*world.get()).query_archetype_claims::, T::EntryViewsFilter>, T::EntryViews, QueryIndices, Or, EntryViewsFilterIndices>, EntryIndices>() } { borrowed_archetypes.insert_unique_unchecked(identifier, claims); @@ -238,6 +255,8 @@ impl< DisjointIndicesList, EntryIndices, EntryIndicesList, + EntryViewsFilterIndices, + EntryViewsFilterIndicesList, > Stage< 'a, @@ -247,10 +266,14 @@ impl< (ResourceViewsIndices, ResourceViewsIndicesList), (DisjointIndices, DisjointIndicesList), (EntryIndices, EntryIndicesList), + (EntryViewsFilterIndices, EntryViewsFilterIndicesList), > for (&mut T, U) where - R: ContainsFilter, And> - + ContainsQuery<'a, T::Filter, T::Views, QueryIndices>, + R: ContainsFilter< + Or, T::EntryViewsFilter>, + Or, EntryViewsFilterIndices>, + > + ContainsQuery<'a, T::Filter, T::Views, QueryIndices> + + ContainsViews<'a, T::EntryViews, EntryIndices>, Resources: 'a, T: Task<'a, R, Resources, QueryIndices, ResourceViewsIndices, DisjointIndices, EntryIndices> + Send, @@ -262,6 +285,7 @@ where ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, >, { type HasRun = (bool, U::HasRun); @@ -273,6 +297,7 @@ where NextResourceViewsIndicesLists, NextDisjointIndicesList, NextEntryIndices, + NextEntryViewsFilterIndicesList, >( &mut self, world: SendableWorld, @@ -289,6 +314,7 @@ where NextResourceViewsIndicesLists, NextDisjointIndicesList, NextEntryIndices, + NextEntryViewsFilterIndicesList, >, { // Determine whether this task still needs to run, or if it has been run as part of a @@ -310,6 +336,7 @@ where ResourceViewsIndices, DisjointIndices, EntryIndices, + EntryViewsFilterIndices, >(world, &mut borrowed_archetypes); self.1 @@ -335,6 +362,7 @@ where ResourceViewsIndices, DisjointIndices, EntryIndices, + EntryViewsFilterIndices, >(world, &mut borrowed_archetypes) { rayon::join( diff --git a/src/system/schedule/stager.rs b/src/system/schedule/stager.rs index 4fa135b8..92544b5d 100644 --- a/src/system/schedule/stager.rs +++ b/src/system/schedule/stager.rs @@ -1,7 +1,10 @@ use crate::{ hlist::define_null, query::{ - filter::And, + filter::{ + And, + Or, + }, view, }, registry::{ @@ -11,6 +14,7 @@ use crate::{ }, ContainsFilter, ContainsQuery, + ContainsViews, Registry, }, system::{ @@ -49,6 +53,7 @@ pub trait Stager< ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, > where R: Registry, { @@ -60,6 +65,7 @@ pub trait Stager< ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, >; type Remainder; @@ -84,6 +90,7 @@ impl<'a, R, Resources, C, ResourcesClaims> stage::Null, stage::Null, stage::Null, + stage::Null, > for task::Null where R: Registry, @@ -122,6 +129,7 @@ impl< ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, > Stager< 'a, @@ -140,6 +148,7 @@ impl< ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, > for (task::System, U) where T::EntryViews<'a>: view::Views<'a>, @@ -295,6 +304,7 @@ where ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, >, { type Stage = <(task::System, U) as Cutoff< @@ -337,6 +347,7 @@ where ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, >>::Stage; type Remainder = <(task::System, U) as Cutoff< 'a, @@ -378,6 +389,7 @@ where ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, >>::Remainder; #[inline] @@ -411,6 +423,7 @@ impl< ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, > Stager< 'a, @@ -429,6 +442,7 @@ impl< ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, > for (task::ParSystem, U) where T::EntryViews<'a>: view::Views<'a>, @@ -521,6 +535,7 @@ where ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, >, { type Stage = <(task::ParSystem, U) as Cutoff< @@ -563,6 +578,7 @@ where ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, >>::Stage; type Remainder = <(task::ParSystem, U) as Cutoff< 'a, @@ -604,6 +620,7 @@ where ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, >>::Remainder; #[inline] @@ -630,6 +647,7 @@ pub trait Cutoff< ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, > where R: Registry, { @@ -641,6 +659,7 @@ pub trait Cutoff< ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, >; type Remainder; @@ -666,6 +685,7 @@ impl<'a, R, Resources, T, C, ResourcesClaims> stage::Null, stage::Null, stage::Null, + stage::Null, > for T where R: Registry, @@ -703,6 +723,8 @@ impl< DisjointIndicesList, EntryIndices, EntryIndicesList, + EntryViewsFilterIndices, + EntryViewsFilterIndicesList, > Cutoff< 'a, @@ -722,10 +744,14 @@ impl< (ResourceViewsIndices, ResourceViewsIndicesList), (DisjointIndices, DisjointIndicesList), (EntryIndices, EntryIndicesList), + (EntryViewsFilterIndices, EntryViewsFilterIndicesList), > for (T, U) where - R: ContainsFilter, And> - + ContainsQuery<'a, T::Filter, T::Views, QueryIndices>, + R: ContainsFilter< + Or, T::EntryViewsFilter>, + Or, EntryViewsFilterIndices>, + > + ContainsQuery<'a, T::Filter, T::Views, QueryIndices> + + ContainsViews<'a, T::EntryViews, EntryIndices>, Resources: 'a, T: Task<'a, R, Resources, QueryIndices, ResourceViewsIndices, DisjointIndices, EntryIndices> + Send @@ -747,6 +773,7 @@ where ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, >, { type Stage = ( @@ -768,6 +795,7 @@ where ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, >>::Stage, ); type Remainder = >::Remainder; #[inline] diff --git a/src/system/schedule/stages.rs b/src/system/schedule/stages.rs index 92ab1d8f..69d1604d 100644 --- a/src/system/schedule/stages.rs +++ b/src/system/schedule/stages.rs @@ -22,6 +22,7 @@ pub trait Stages< ResourceViewsIndicesLists, DisjointIndicesLists, EntryIndicesLists, + EntryViewsFilterIndicesLists, >: Send where R: Registry, { @@ -61,7 +62,7 @@ pub trait Stages< fn new_has_run() -> Self::HasRun; } -impl Stages<'_, R, Resources, Null, Null, Null, Null> for Null +impl Stages<'_, R, Resources, Null, Null, Null, Null, Null> for Null where R: Registry, { @@ -96,6 +97,8 @@ impl< DisjointIndicesLists, EntryIndicesList, EntryIndicesLists, + EntryViewsFilterIndicesList, + EntryViewsFilterIndicesLists, > Stages< 'a, @@ -105,6 +108,7 @@ impl< (ResourceViewsIndicesList, ResourceViewsIndicesLists), (DisjointIndicesList, DisjointIndicesLists), (EntryIndicesList, EntryIndicesLists), + (EntryViewsFilterIndicesList, EntryViewsFilterIndicesLists), > for (T, U) where R: Registry, @@ -116,6 +120,7 @@ where ResourceViewsIndicesList, DisjointIndicesList, EntryIndicesList, + EntryViewsFilterIndicesList, >, U: Stages< 'a, @@ -125,6 +130,7 @@ where ResourceViewsIndicesLists, DisjointIndicesLists, EntryIndicesLists, + EntryViewsFilterIndicesLists, >, { type HasRun = T::HasRun; diff --git a/src/system/schedule/task/sealed.rs b/src/system/schedule/task/sealed.rs index c0e355f1..78684016 100644 --- a/src/system/schedule/task/sealed.rs +++ b/src/system/schedule/task/sealed.rs @@ -7,7 +7,10 @@ use super::{ use crate::{ query::{ view, - view::Views, + view::{ + Views, + ViewsSealed, + }, Query, }, registry, @@ -30,6 +33,10 @@ where type Views: Views<'a> + Send; /// A filter applied to the components viewed by this task. type Filter; + /// The entry views on components for this task. + type EntryViews: Views<'a>; + /// The entry views filter on components for this task. + type EntryViewsFilter; /// Executes the task over the given world. fn run(&mut self, world: SendableWorld); @@ -50,6 +57,8 @@ where { type Views = S::Views<'a>; type Filter = S::Filter; + type EntryViews = S::EntryViews<'a>; + type EntryViewsFilter = as ViewsSealed<'a>>::EntryFilter; fn run(&mut self, world: SendableWorld) { // Query world using system. @@ -76,6 +85,8 @@ where { type Views = P::Views<'a>; type Filter = P::Filter; + type EntryViews = P::EntryViews<'a>; + type EntryViewsFilter = as ViewsSealed<'a>>::EntryFilter; fn run(&mut self, world: SendableWorld) { // Query world using system. diff --git a/src/world/mod.rs b/src/world/mod.rs index 968039b0..f1f22ac6 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -462,8 +462,10 @@ where Views, QueryFilter, Filter, + EntryViews, QueryIndices, FilterIndices, + EntryViewsIndices, >( &'a mut self, ) -> result::ArchetypeClaims< @@ -472,13 +474,17 @@ where Views, QueryFilter, Filter, + EntryViews, QueryIndices, FilterIndices, + EntryViewsIndices, > where Views: view::Views<'a>, + EntryViews: view::Views<'a>, Registry: ContainsFilter - + ContainsQuery<'a, QueryFilter, Views, QueryIndices>, + + ContainsQuery<'a, QueryFilter, Views, QueryIndices> + + registry::ContainsViews<'a, EntryViews, EntryViewsIndices>, { // SAFETY: The safety contract here is upheld by the safety contract of this method. unsafe { result::ArchetypeClaims::new(self.archetypes.iter_mut()) } @@ -2552,6 +2558,100 @@ mod tests { world.run_schedule(&mut schedule); } + #[cfg(feature = "rayon")] + #[test] + fn schedule_dynamic_optimization_entry_views() { + #[derive(Clone)] + struct A(u32); + #[derive(Clone)] + struct B(u32); + #[derive(Clone)] + struct C(u32); + + type Registry = Registry!(A, B, C); + + struct Foo; + + impl System for Foo { + type Views<'a> = Views!(entity::Identifier); + type Filter = filter::None; + type ResourceViews<'a> = Views!(); + type EntryViews<'a> = Views!(&'a mut A, &'a mut B); + + fn run<'a, R, S, I, E>( + &mut self, + mut query_results: Result< + 'a, + R, + S, + I, + Self::ResourceViews<'a>, + Self::EntryViews<'a>, + E, + >, + ) where + R: registry::ContainsViews<'a, Self::EntryViews<'a>, E>, + I: Iterator>, + { + for result!(identifier) in query_results.iter { + if let Some(result!(b)) = query_results + .entries + .entry(identifier) + .map(|mut entry| entry.query(Query::::new())) + .flatten() + { + b.0 += 1; + } + } + } + } + + struct Bar; + + impl System for Bar { + type Views<'a> = Views!(entity::Identifier); + type Filter = filter::None; + type ResourceViews<'a> = Views!(); + type EntryViews<'a> = Views!(&'a mut A, &'a mut C); + + fn run<'a, R, S, I, E>( + &mut self, + mut query_results: Result< + 'a, + R, + S, + I, + Self::ResourceViews<'a>, + Self::EntryViews<'a>, + E, + >, + ) where + R: registry::ContainsViews<'a, Self::EntryViews<'a>, E>, + I: Iterator>, + { + for result!(identifier) in query_results.iter { + if let Some(result!(c)) = query_results + .entries + .entry(identifier) + .map(|mut entry| entry.query(Query::::new())) + .flatten() + { + c.0 += 1; + } + } + } + } + + let mut world = World::::new(); + + world.extend(entities!((B(0)); 1000)); + world.extend(entities!((C(0)); 1000)); + + let mut schedule = schedule!(task::System(Foo), task::System(Bar)); + + world.run_schedule(&mut schedule); + } + #[test] fn contains() { let mut world = World::::new(); diff --git a/tests/trybuild/schedule/non_send_entry_views.stderr b/tests/trybuild/schedule/non_send_entry_views.stderr index 04e6954d..96498973 100644 --- a/tests/trybuild/schedule/non_send_entry_views.stderr +++ b/tests/trybuild/schedule/non_send_entry_views.stderr @@ -10,10 +10,10 @@ error[E0277]: `Rc` cannot be shared between threads safely = note: required for `&Rc` to implement `Send` = note: required because it appears within the type `(&Rc, Null)` = note: required for `brood::system::schedule::task::System` to implement `brood::system::schedule::task::sealed::Task<'_, (Rc, brood::registry::Null), brood::resource::Null, (registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), (resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), (((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null, ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null))>` - = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::stager::Cutoff<'_, (Rc, brood::registry::Null), brood::resource::Null, schedule::claim::decision::Append, ((&Rc, brood::query::view::Null), schedule::claim::Null), schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, (brood::query::view::Null, schedule::claim::Null), schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, ((registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), ((resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), schedule::stage::Null), ((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null, ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), schedule::stage::Null), (((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), schedule::stage::Null)>` - = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::scheduler::Scheduler<'_, (Rc, brood::registry::Null), brood::resource::Null, ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), (view::merge::Neither, (view::merge::Right, view::merge::Null))), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), (((resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null, ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), schedule::stage::Null), schedule::stages::Null)>` - = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::sealed::Sealed<'_, (Rc, brood::registry::Null), brood::resource::Null, (((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), (view::merge::Neither, (view::merge::Right, view::merge::Null))), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), (((resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null, ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), schedule::stage::Null), schedule::stages::Null))>` - = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `Schedule<'_, (Rc, brood::registry::Null), brood::resource::Null, (((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), (view::merge::Neither, (view::merge::Right, view::merge::Null))), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), (((resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null, ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), schedule::stage::Null), schedule::stages::Null))>` + = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::stager::Cutoff<'_, (Rc, brood::registry::Null), brood::resource::Null, schedule::claim::decision::Append, ((&Rc, brood::query::view::Null), schedule::claim::Null), schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, (brood::query::view::Null, schedule::claim::Null), schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, ((registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), ((resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), schedule::stage::Null), ((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null, ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), schedule::stage::Null), (((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), schedule::stage::Null), (Or, registry::contains::Contained>, schedule::stage::Null)>` + = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::scheduler::Scheduler<'_, (Rc, brood::registry::Null), brood::resource::Null, ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), (view::merge::Neither, (view::merge::Right, view::merge::Null))), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), (((resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null, ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), schedule::stage::Null), schedule::stages::Null), ((Or, registry::contains::Contained>, schedule::stage::Null), schedule::stages::Null)>` + = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::sealed::Sealed<'_, (Rc, brood::registry::Null), brood::resource::Null, (((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), (view::merge::Neither, (view::merge::Right, view::merge::Null))), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), (((resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null, ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), schedule::stage::Null), schedule::stages::Null), ((Or, registry::contains::Contained>, schedule::stage::Null), schedule::stages::Null))>` + = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `Schedule<'_, (Rc, brood::registry::Null), brood::resource::Null, (((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), (view::merge::Neither, (view::merge::Right, view::merge::Null))), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), (((resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null, ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), schedule::stage::Null), schedule::stages::Null), ((Or, registry::contains::Contained>, schedule::stage::Null), schedule::stages::Null))>` note: required by a bound in `World::::run_schedule` --> src/world/mod.rs | diff --git a/tests/trybuild/schedule/non_send_resource_views.stderr b/tests/trybuild/schedule/non_send_resource_views.stderr index 4d803af2..60635287 100644 --- a/tests/trybuild/schedule/non_send_resource_views.stderr +++ b/tests/trybuild/schedule/non_send_resource_views.stderr @@ -10,10 +10,10 @@ error[E0277]: `Rc` cannot be shared between threads safely = note: required for `&Rc` to implement `Send` = note: required because it appears within the type `(&Rc, Null)` = note: required for `brood::system::schedule::task::System` to implement `brood::system::schedule::task::sealed::Task<'_, brood::registry::Null, (Rc, brood::resource::Null), (registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), ((resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null), (resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null)), (((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null)>` - = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::stager::Cutoff<'_, brood::registry::Null, (Rc, brood::resource::Null), schedule::claim::decision::Append, (brood::query::view::Null, schedule::claim::Null), schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, ((&Rc, brood::query::view::Null), schedule::claim::Null), schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, ((registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), (((resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null), (resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null)), schedule::stage::Null), ((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), schedule::stage::Null), (((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), schedule::stage::Null)>` - = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::scheduler::Scheduler<'_, brood::registry::Null, (Rc, brood::resource::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), (view::merge::Neither, view::merge::Null)), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), ((((resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null), (resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null)), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null)>` - = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::sealed::Sealed<'_, brood::registry::Null, (Rc, brood::resource::Null), (((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), (view::merge::Neither, view::merge::Null)), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), ((((resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null), (resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null)), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null))>` - = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `Schedule<'_, brood::registry::Null, (Rc, brood::resource::Null), (((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), (view::merge::Neither, view::merge::Null)), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), ((((resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null), (resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null)), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null))>` + = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::stager::Cutoff<'_, brood::registry::Null, (Rc, brood::resource::Null), schedule::claim::decision::Append, (brood::query::view::Null, schedule::claim::Null), schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, ((&Rc, brood::query::view::Null), schedule::claim::Null), schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, ((registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), (((resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null), (resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null)), schedule::stage::Null), ((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), schedule::stage::Null), (((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), (brood::query::filter::Not, schedule::stage::Null)>` + = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::scheduler::Scheduler<'_, brood::registry::Null, (Rc, brood::resource::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), (view::merge::Neither, view::merge::Null)), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), ((((resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null), (resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null)), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), ((brood::query::filter::Not, schedule::stage::Null), schedule::stages::Null)>` + = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::sealed::Sealed<'_, brood::registry::Null, (Rc, brood::resource::Null), (((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), (view::merge::Neither, view::merge::Null)), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), ((((resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null), (resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null)), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), ((brood::query::filter::Not, schedule::stage::Null), schedule::stages::Null))>` + = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `Schedule<'_, brood::registry::Null, (Rc, brood::resource::Null), (((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), (view::merge::Neither, view::merge::Null)), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), ((((resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null), (resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null)), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), ((brood::query::filter::Not, schedule::stage::Null), schedule::stages::Null))>` note: required by a bound in `World::::run_schedule` --> src/world/mod.rs | diff --git a/tests/trybuild/schedule/non_send_views.stderr b/tests/trybuild/schedule/non_send_views.stderr index d2809d47..081397f0 100644 --- a/tests/trybuild/schedule/non_send_views.stderr +++ b/tests/trybuild/schedule/non_send_views.stderr @@ -10,10 +10,10 @@ error[E0277]: `Rc` cannot be shared between threads safely = note: required for `&Rc` to implement `Send` = note: required because it appears within the type `(&Rc, Null)` = note: required for `brood::system::schedule::task::System` to implement `brood::system::schedule::task::sealed::Task<'_, (Rc, brood::registry::Null), brood::resource::Null, (registry::contains::Null, (registry::contains::Contained, registry::contains::Null), (registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), (resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), (((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null), ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null)>` - = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::stager::Cutoff<'_, (Rc, brood::registry::Null), brood::resource::Null, schedule::claim::decision::Append, ((&Rc, brood::query::view::Null), schedule::claim::Null), schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, (brood::query::view::Null, schedule::claim::Null), schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, ((registry::contains::Null, (registry::contains::Contained, registry::contains::Null), (registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), schedule::stage::Null), ((resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), schedule::stage::Null), ((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null), schedule::stage::Null), (((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), schedule::stage::Null)>` - = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::scheduler::Scheduler<'_, (Rc, brood::registry::Null), brood::resource::Null, ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), (view::merge::Neither, (view::merge::Left, view::merge::Null))), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, (registry::contains::Contained, registry::contains::Null), (registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), schedule::stage::Null), schedule::stages::Null), (((resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null)>` - = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::sealed::Sealed<'_, (Rc, brood::registry::Null), brood::resource::Null, (((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), (view::merge::Neither, (view::merge::Left, view::merge::Null))), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, (registry::contains::Contained, registry::contains::Null), (registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), schedule::stage::Null), schedule::stages::Null), (((resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null))>` - = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `Schedule<'_, (Rc, brood::registry::Null), brood::resource::Null, (((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), (view::merge::Neither, (view::merge::Left, view::merge::Null))), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, (registry::contains::Contained, registry::contains::Null), (registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), schedule::stage::Null), schedule::stages::Null), (((resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null))>` + = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::stager::Cutoff<'_, (Rc, brood::registry::Null), brood::resource::Null, schedule::claim::decision::Append, ((&Rc, brood::query::view::Null), schedule::claim::Null), schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, (brood::query::view::Null, schedule::claim::Null), schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, ((registry::contains::Null, (registry::contains::Contained, registry::contains::Null), (registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), schedule::stage::Null), ((resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), schedule::stage::Null), ((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null), schedule::stage::Null), (((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), (brood::query::filter::Not, schedule::stage::Null)>` + = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::scheduler::Scheduler<'_, (Rc, brood::registry::Null), brood::resource::Null, ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), (view::merge::Neither, (view::merge::Left, view::merge::Null))), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, (registry::contains::Contained, registry::contains::Null), (registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), schedule::stage::Null), schedule::stages::Null), (((resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), ((brood::query::filter::Not, schedule::stage::Null), schedule::stages::Null)>` + = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::sealed::Sealed<'_, (Rc, brood::registry::Null), brood::resource::Null, (((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), (view::merge::Neither, (view::merge::Left, view::merge::Null))), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, (registry::contains::Contained, registry::contains::Null), (registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), schedule::stage::Null), schedule::stages::Null), (((resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), ((brood::query::filter::Not, schedule::stage::Null), schedule::stages::Null))>` + = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `Schedule<'_, (Rc, brood::registry::Null), brood::resource::Null, (((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), (view::merge::Neither, (view::merge::Left, view::merge::Null))), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, (registry::contains::Contained, registry::contains::Null), (registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), schedule::stage::Null), schedule::stages::Null), (((resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), ((brood::query::filter::Not, schedule::stage::Null), schedule::stages::Null))>` note: required by a bound in `World::::run_schedule` --> src/world/mod.rs | From 78168fc40052324215db4662c8f8e803a1a09851 Mon Sep 17 00:00:00 2001 From: Anders429 Date: Fri, 28 Apr 2023 12:38:29 -0700 Subject: [PATCH 03/16] Respect resource claims when dynamically scheduling. --- src/query/view/claim.rs | 6 ++ src/resource/claim.rs | 29 ++++++++ src/resource/contains/views.rs | 48 +++++++++++-- src/resource/mod.rs | 9 +++ src/resource/view.rs | 36 +++++++++- src/system/schedule/mod.rs | 3 + src/system/schedule/scheduler.rs | 4 ++ src/system/schedule/sealed.rs | 3 + src/system/schedule/stage.rs | 104 ++++++++++++++++++++--------- src/system/schedule/stager.rs | 9 +++ src/system/schedule/stages.rs | 13 +++- src/system/schedule/task/sealed.rs | 4 ++ src/world/mod.rs | 1 + 13 files changed, 233 insertions(+), 36 deletions(-) create mode 100644 src/resource/claim.rs diff --git a/src/query/view/claim.rs b/src/query/view/claim.rs index 3316564f..bf8a6d9d 100644 --- a/src/query/view/claim.rs +++ b/src/query/view/claim.rs @@ -56,6 +56,12 @@ impl Claim { } } +impl Default for Claim { + fn default() -> Self { + Self::None + } +} + /// A list of claims on the components contained in a heterogeneous list. /// /// This is most commonly a list of claims for the components of a `Registry`. diff --git a/src/resource/claim.rs b/src/resource/claim.rs new file mode 100644 index 00000000..71cda9f1 --- /dev/null +++ b/src/resource/claim.rs @@ -0,0 +1,29 @@ +use crate::{ + query::{ + view, + view::{ + claim, + Claim, + }, + }, + resource::Null, +}; +use core::{ + fmt::Debug, + hash::Hash, +}; + +pub trait Claims { + type Claims: view::Claims + Clone + Debug + Eq + Hash + Send + Default; +} + +impl Claims for Null { + type Claims = claim::Null; +} + +impl Claims for (Resource, Resources) +where + Resources: Claims, +{ + type Claims = (Claim, Resources::Claims); +} diff --git a/src/resource/contains/views.rs b/src/resource/contains/views.rs index 00c4aa75..bd470ff7 100644 --- a/src/resource/contains/views.rs +++ b/src/resource/contains/views.rs @@ -1,5 +1,10 @@ -/// Given a list of resource views, and a list of resources (not guaranteed to be in the same -/// order), we return the borrowed resources as specified by the views. +//! Given a list of resource views, and a list of resources (not guaranteed to be in the same +//! order), we return the borrowed resources as specified by the views. +#[cfg(feature = "rayon")] +use crate::query::view::{ + claim, + claim::Claim, +}; use crate::{ query::{ view, @@ -24,8 +29,12 @@ impl<'a, Resources, Views, Indices> ContainsViews<'a, Views, Indices> for Resour { } -pub trait Sealed<'a, Views, Indices> { +pub trait Sealed<'a, Views, Indices>: resource::Resources { fn view(&'a mut self) -> Views; + + #[cfg(feature = "rayon")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "rayon")))] + fn claims() -> Self::Claims; } impl<'a, Resources, Views, Containments, Indices, CanonicalContainments, ReshapeIndices> @@ -36,13 +45,24 @@ where fn view(&'a mut self) -> Views { self.view() } + + #[cfg(feature = "rayon")] + fn claims() -> Self::Claims { + Self::claims() + } } -pub trait Expanded<'a, Views, Containments, Indices, CanonicalContainments, ReshapeIndices> { +pub trait Expanded<'a, Views, Containments, Indices, CanonicalContainments, ReshapeIndices>: + resource::Resources +{ /// The canonical form of the `Views` with respect to the resources. type Canonical: Reshape; fn view(&'a mut self) -> Views; + + #[cfg(feature = "rayon")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "rayon")))] + fn claims() -> Self::Claims; } impl<'a, ReshapeIndices> Expanded<'a, view::Null, Null, Null, Null, ReshapeIndices> @@ -55,6 +75,11 @@ where fn view(&'a mut self) -> view::Null { view::Null } + + #[cfg(feature = "rayon")] + fn claims() -> Self::Claims { + claim::Null + } } impl< @@ -76,6 +101,7 @@ impl< ReshapeIndices, > for (Resource, Resources) where + Resource: resource::Resource, Resources: Expanded<'a, Views, Containments, Indices, CanonicalContainments, ReshapeIndices>, { type Canonical = Resources::Canonical; @@ -83,6 +109,11 @@ where fn view(&'a mut self) -> Views { self.1.view() } + + #[cfg(feature = "rayon")] + fn claims() -> Self::Claims { + (Claim::None, Resources::claims()) + } } impl< @@ -128,4 +159,13 @@ where fn view(&'a mut self) -> Views { CanonicalViews::view(self).reshape() } + + #[cfg(feature = "rayon")] + fn claims() -> Self::Claims { + >::claims() + } } diff --git a/src/resource/mod.rs b/src/resource/mod.rs index b9026b33..df1feba3 100644 --- a/src/resource/mod.rs +++ b/src/resource/mod.rs @@ -37,6 +37,8 @@ //! [`System`]: crate::system::System //! [`World`]: crate::World +#[cfg(feature = "rayon")] +mod claim; #[cfg(feature = "serde")] mod de; mod debug; @@ -57,6 +59,8 @@ pub use debug::Debug; #[cfg(feature = "serde")] pub use ser::Serialize; +#[cfg(feature = "rayon")] +pub(crate) use claim::Claims; #[cfg(feature = "serde")] pub(crate) use de::Deserializer; pub(crate) use debug::Debugger; @@ -137,11 +141,16 @@ mod impl_resources { } mod sealed { + #[cfg(feature = "rayon")] + use super::Claims; use super::{ Length, Null, }; + #[cfg(feature = "rayon")] + pub trait Sealed: Length + Claims {} + #[cfg(not(feature = "rayon"))] pub trait Sealed: Length {} impl Sealed for Null {} diff --git a/src/resource/view.rs b/src/resource/view.rs index 51d075ae..0931bc92 100644 --- a/src/resource/view.rs +++ b/src/resource/view.rs @@ -1,5 +1,11 @@ +#[cfg(feature = "rayon")] +use crate::query::view::{ + claim, + claim::Claim, +}; use crate::{ query::view, + resource, resource::{ contains, contains::{ @@ -10,43 +16,71 @@ use crate::{ }, }; -pub trait CanonicalViews<'a, Views, Containments> { +pub trait CanonicalViews<'a, Views, Containments>: resource::Resources { fn view(&'a mut self) -> Views; + + /// Return the dynamic claims over the resources borrowed by the `Views`. + #[cfg(feature = "rayon")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "rayon")))] + fn claims() -> Self::Claims; } impl<'a> CanonicalViews<'a, view::Null, contains::Null> for Null { fn view(&'a mut self) -> view::Null { view::Null } + + #[cfg(feature = "rayon")] + fn claims() -> Self::Claims { + claim::Null + } } impl<'a, Resource, Resources, Views, Containments> CanonicalViews<'a, (&'a Resource, Views), (Contained, Containments)> for (Resource, Resources) where + Resource: resource::Resource, Resources: CanonicalViews<'a, Views, Containments>, { fn view(&'a mut self) -> (&'a Resource, Views) { (&self.0, self.1.view()) } + + #[cfg(feature = "rayon")] + fn claims() -> Self::Claims { + (Claim::Immutable, Resources::claims()) + } } impl<'a, Resource, Resources, Views, Containments> CanonicalViews<'a, (&'a mut Resource, Views), (Contained, Containments)> for (Resource, Resources) where + Resource: resource::Resource, Resources: CanonicalViews<'a, Views, Containments>, { fn view(&'a mut self) -> (&'a mut Resource, Views) { (&mut self.0, self.1.view()) } + + #[cfg(feature = "rayon")] + fn claims() -> Self::Claims { + (Claim::Mutable, Resources::claims()) + } } impl<'a, Resource, Resources, Views, Containments> CanonicalViews<'a, Views, (NotContained, Containments)> for (Resource, Resources) where + Resource: resource::Resource, Resources: CanonicalViews<'a, Views, Containments>, { fn view(&'a mut self) -> Views { self.1.view() } + + #[cfg(feature = "rayon")] + fn claims() -> Self::Claims { + (Claim::None, Resources::claims()) + } } diff --git a/src/system/schedule/mod.rs b/src/system/schedule/mod.rs index cbb47566..f9808dea 100644 --- a/src/system/schedule/mod.rs +++ b/src/system/schedule/mod.rs @@ -95,6 +95,7 @@ pub(crate) use stages::Stages; use crate::{ doc, registry, + resource, }; use scheduler::Scheduler; use sealed::Sealed; @@ -118,12 +119,14 @@ pub trait Schedule<'a, Registry, Resources, Indices>: Sealed<'a, Registry, Resources, Indices> where Registry: registry::Registry, + Resources: resource::Resources, { } impl<'a, T, Registry, Resources, Indices> Schedule<'a, Registry, Resources, Indices> for T where Registry: registry::Registry, + Resources: resource::Resources, T: Sealed<'a, Registry, Resources, Indices>, { } diff --git a/src/system/schedule/scheduler.rs b/src/system/schedule/scheduler.rs index d93d4f26..2773fc47 100644 --- a/src/system/schedule/scheduler.rs +++ b/src/system/schedule/scheduler.rs @@ -1,6 +1,7 @@ use crate::{ hlist::define_null, registry::Registry, + resource, system::schedule::{ claim, stages, @@ -30,6 +31,7 @@ pub trait Scheduler< EntryViewsFilterIndicesLists, > where R: Registry, + Resources: resource::Resources, { type Stages: Stages< 'a, @@ -65,6 +67,7 @@ impl<'a, R, Resources> > for task::Null where R: Registry, + Resources: resource::Resources, { type Stages = stages::Null; @@ -178,6 +181,7 @@ where EntryViewsFilterIndicesLists, >, R: Registry + 'a, + Resources: resource::Resources, Resources: 'a, I: 'a, P: 'a, diff --git a/src/system/schedule/sealed.rs b/src/system/schedule/sealed.rs index 89576fc6..d97b1efa 100644 --- a/src/system/schedule/sealed.rs +++ b/src/system/schedule/sealed.rs @@ -1,5 +1,6 @@ use crate::{ registry::Registry, + resource, system::schedule::{ Scheduler, Stages, @@ -9,6 +10,7 @@ use crate::{ pub trait Sealed<'a, R, Resources, Indices> where R: Registry, + Resources: resource::Resources, { type QueryIndicesLists; type ResourceViewsIndicesLists; @@ -68,6 +70,7 @@ impl< > for T where R: Registry, + Resources: resource::Resources, T: Scheduler< 'a, R, diff --git a/src/system/schedule/stage.rs b/src/system/schedule/stage.rs index ae00d68b..b33b1e85 100644 --- a/src/system/schedule/stage.rs +++ b/src/system/schedule/stage.rs @@ -14,6 +14,7 @@ use crate::{ ContainsViews, Registry, }, + resource, system::schedule::{ sendable::SendableWorld, Task, @@ -43,6 +44,7 @@ pub trait Stage< EntryViewsFilterIndicesList, >: Send where R: Registry, + Resources: resource::Resources, { /// A list of booleans indicating whether each task within the stage has already been run. type HasRun: Send; @@ -64,6 +66,7 @@ pub trait Stage< &mut self, world: SendableWorld, borrowed_archetypes: HashMap, R::Claims, FnvBuildHasher>, + resource_claims: Resources::Claims, has_run: Self::HasRun, next_stage: &mut N, ) -> N::HasRun @@ -93,6 +96,7 @@ pub trait Stage< &mut self, world: SendableWorld, borrowed_archetypes: HashMap, R::Claims, FnvBuildHasher>, + resource_claims: Resources::Claims, ) -> Self::HasRun; /// Creates a new default set of booleans to indicate that each task within the stage has not @@ -103,6 +107,7 @@ pub trait Stage< impl Stage<'_, R, Resources, Null, Null, Null, Null, Null> for Null where R: Registry, + Resources: resource::Resources, { type HasRun = Null; @@ -118,6 +123,7 @@ where &mut self, world: SendableWorld, borrowed_archetypes: HashMap, R::Claims, FnvBuildHasher>, + resource_claims: Resources::Claims, _has_run: Self::HasRun, next_stage: &mut N, ) -> N::HasRun @@ -141,7 +147,7 @@ where // Run tasks from next stage that can be parallelized dynamically. // SAFETY: The safety contract of this method call is upheld by the safety contract of // this method. - unsafe { next_stage.run_add_ons(world, borrowed_archetypes) } + unsafe { next_stage.run_add_ons(world, borrowed_archetypes, resource_claims) } } } @@ -149,6 +155,7 @@ where &mut self, _world: SendableWorld, _borrowed_archetypes: HashMap, R::Claims, FnvBuildHasher>, + _resource_claims: Resources::Claims, ) -> Self::HasRun { Null } @@ -274,7 +281,9 @@ where Or, EntryViewsFilterIndices>, > + ContainsQuery<'a, T::Filter, T::Views, QueryIndices> + ContainsViews<'a, T::EntryViews, EntryIndices>, - Resources: 'a, + Resources: resource::Resources + + resource::ContainsViews<'a, T::ResourceViews, ResourceViewsIndices> + + 'a, T: Task<'a, R, Resources, QueryIndices, ResourceViewsIndices, DisjointIndices, EntryIndices> + Send, U: Stage< @@ -302,6 +311,7 @@ where &mut self, world: SendableWorld, mut borrowed_archetypes: HashMap, R::Claims, FnvBuildHasher>, + resource_claims: Resources::Claims, has_run: Self::HasRun, next_stage: &mut N, ) -> N::HasRun @@ -320,8 +330,13 @@ where // Determine whether this task still needs to run, or if it has been run as part of a // previous stage. if has_run.0 { - self.1 - .run(world, borrowed_archetypes, has_run.1, next_stage) + self.1.run( + world, + borrowed_archetypes, + resource_claims, + has_run.1, + next_stage, + ) } else { rayon::join( // Continue scheduling tasks. Note that the first task is executed on the @@ -339,8 +354,18 @@ where EntryViewsFilterIndices, >(world, &mut borrowed_archetypes); - self.1 - .run(world, borrowed_archetypes, has_run.1, next_stage) + // SAFETY: The resource claims are compatible because they are in the same + // stage. + let resource_claims = + unsafe { resource_claims.merge_unchecked(&Resources::claims()) }; + + self.1.run( + world, + borrowed_archetypes, + resource_claims, + has_run.1, + next_stage, + ) }, // Execute the current task. || self.0.run(world), @@ -353,36 +378,55 @@ where &mut self, world: SendableWorld, mut borrowed_archetypes: HashMap, R::Claims, FnvBuildHasher>, + resource_claims: Resources::Claims, ) -> Self::HasRun { - if query_archetype_identifiers::< - R, - Resources, - T, - QueryIndices, - ResourceViewsIndices, - DisjointIndices, - EntryIndices, - EntryViewsFilterIndices, - >(world, &mut borrowed_archetypes) - { - rayon::join( - || { - ( - true, - // SAFETY: The safety contract of this method call is upheld by the safety - // contract of this method. - unsafe { self.1.run_add_ons(world, borrowed_archetypes) }, - ) - }, - || self.0.run(world), - ) - .0 + if let Some(resource_claims) = Resources::claims().try_merge(&resource_claims) { + if query_archetype_identifiers::< + R, + Resources, + T, + QueryIndices, + ResourceViewsIndices, + DisjointIndices, + EntryIndices, + EntryViewsFilterIndices, + >(world, &mut borrowed_archetypes) + { + rayon::join( + || { + ( + true, + // SAFETY: The safety contract of this method call is upheld by the + // safety contract of this method. + unsafe { + self.1 + .run_add_ons(world, borrowed_archetypes, resource_claims) + }, + ) + }, + || self.0.run(world), + ) + .0 + } else { + ( + false, + // SAFETY: The safety contract of this method call is upheld by the safety + // contract of this method. + unsafe { + self.1 + .run_add_ons(world, borrowed_archetypes, resource_claims) + }, + ) + } } else { ( false, // SAFETY: The safety contract of this method call is upheld by the safety contract // of this method. - unsafe { self.1.run_add_ons(world, borrowed_archetypes) }, + unsafe { + self.1 + .run_add_ons(world, borrowed_archetypes, resource_claims) + }, ) } } diff --git a/src/system/schedule/stager.rs b/src/system/schedule/stager.rs index 92544b5d..d7a4ddbf 100644 --- a/src/system/schedule/stager.rs +++ b/src/system/schedule/stager.rs @@ -17,6 +17,7 @@ use crate::{ ContainsViews, Registry, }, + resource, system::{ schedule::{ claim::{ @@ -56,6 +57,7 @@ pub trait Stager< EntryViewsFilterIndicesList, > where R: Registry, + Resources: resource::Resources, { type Stage: Stage< 'a, @@ -94,6 +96,7 @@ impl<'a, R, Resources, C, ResourcesClaims> > for task::Null where R: Registry, + Resources: resource::Resources, { type Stage = stage::Null; type Remainder = task::Null; @@ -161,6 +164,7 @@ where T::EntryViews<'a>, RightMergeIndices >, + Resources: resource::Resources, , LeftMergeIndices>>::Viewable: view::Merge< <: view::Views<'a>, R: ContainsViewsSealed<'a, T::Views<'a>, LeftMergeIndices> + ContainsViewsSealed<'a, T::EntryViews<'a>, RightMergeIndices>, + Resources: resource::Resources, , LeftMergeIndices>>::Viewable: view::Merge<<, LeftMergeIndices>>::Viewable as ContainsViewsOuter<'a, T::Views<'a>, , LeftMergeIndices>>::Containments, , LeftMergeIndices>>::Indices, @@ -650,6 +655,7 @@ pub trait Cutoff< EntryViewsFilterIndicesList, > where R: Registry, + Resources: resource::Resources, { type Stage: Stage< 'a, @@ -689,6 +695,7 @@ impl<'a, R, Resources, T, C, ResourcesClaims> > for T where R: Registry, + Resources: resource::Resources, T: 'a, { type Stage = stage::Null; @@ -753,6 +760,8 @@ where > + ContainsQuery<'a, T::Filter, T::Views, QueryIndices> + ContainsViews<'a, T::EntryViews, EntryIndices>, Resources: 'a, + Resources: + resource::Resources + resource::ContainsViews<'a, T::ResourceViews, ResourceViewsIndices>, T: Task<'a, R, Resources, QueryIndices, ResourceViewsIndices, DisjointIndices, EntryIndices> + Send + 'a, diff --git a/src/system/schedule/stages.rs b/src/system/schedule/stages.rs index 69d1604d..98f38f22 100644 --- a/src/system/schedule/stages.rs +++ b/src/system/schedule/stages.rs @@ -2,6 +2,7 @@ use crate::{ archetype, hlist::define_null, registry::Registry, + resource, system::schedule::{ sendable::SendableWorld, Stage, @@ -25,6 +26,7 @@ pub trait Stages< EntryViewsFilterIndicesLists, >: Send where R: Registry, + Resources: resource::Resources, { /// A list of booleans indicating whether each task within the first stage has already been run. type HasRun: Send; @@ -55,6 +57,7 @@ pub trait Stages< &mut self, world: SendableWorld, borrowed_archetypes: HashMap, R::Claims, FnvBuildHasher>, + resource_claims: Resources::Claims, ) -> Self::HasRun; /// Creates a new default set of booleans to indicate that each task within the first stage has @@ -65,6 +68,7 @@ pub trait Stages< impl Stages<'_, R, Resources, Null, Null, Null, Null, Null> for Null where R: Registry, + Resources: resource::Resources, { type HasRun = Null; @@ -74,6 +78,7 @@ where &mut self, _world: SendableWorld, _borrowed_archetypes: HashMap, R::Claims, FnvBuildHasher>, + _resource_claims: Resources::Claims, ) -> Self::HasRun { Null } @@ -112,6 +117,7 @@ impl< > for (T, U) where R: Registry, + Resources: resource::Resources, T: Stage< 'a, R, @@ -141,6 +147,7 @@ where // SAFETY: The pointer provided here is unique, being created from a mutable reference. unsafe { SendableWorld::new(world) }, HashMap::default(), + Resources::Claims::default(), has_run, &mut self.1, ); @@ -151,10 +158,14 @@ where &mut self, world: SendableWorld, borrowed_archetypes: HashMap, R::Claims, FnvBuildHasher>, + resource_claims: Resources::Claims, ) -> Self::HasRun { // SAFETY: The safety contract of this method call is upheld by the safety contract of this // method. - unsafe { self.0.run_add_ons(world, borrowed_archetypes) } + unsafe { + self.0 + .run_add_ons(world, borrowed_archetypes, resource_claims) + } } fn new_has_run() -> Self::HasRun { diff --git a/src/system/schedule/task/sealed.rs b/src/system/schedule/task/sealed.rs index 78684016..dfef8c31 100644 --- a/src/system/schedule/task/sealed.rs +++ b/src/system/schedule/task/sealed.rs @@ -33,6 +33,8 @@ where type Views: Views<'a> + Send; /// A filter applied to the components viewed by this task. type Filter; + /// The views on resources for this task. + type ResourceViews; /// The entry views on components for this task. type EntryViews: Views<'a>; /// The entry views filter on components for this task. @@ -57,6 +59,7 @@ where { type Views = S::Views<'a>; type Filter = S::Filter; + type ResourceViews = S::ResourceViews<'a>; type EntryViews = S::EntryViews<'a>; type EntryViewsFilter = as ViewsSealed<'a>>::EntryFilter; @@ -85,6 +88,7 @@ where { type Views = P::Views<'a>; type Filter = P::Filter; + type ResourceViews = P::ResourceViews<'a>; type EntryViews = P::EntryViews<'a>; type EntryViewsFilter = as ViewsSealed<'a>>::EntryFilter; diff --git a/src/world/mod.rs b/src/world/mod.rs index f1f22ac6..ec2844e3 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -742,6 +742,7 @@ where #[cfg_attr(doc_cfg, doc(cfg(feature = "rayon")))] pub fn run_schedule<'a, Schedule, Indices>(&mut self, schedule: &'a mut Schedule) where + Resources: resource::Resources, Schedule: schedule::Schedule<'a, Registry, Resources, Indices>, { schedule From d735bbfc925f58d2e106543f2e7425bde50c0ed1 Mon Sep 17 00:00:00 2001 From: Anders429 Date: Fri, 28 Apr 2023 12:41:29 -0700 Subject: [PATCH 04/16] Document dynamic scheduling fix. --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10552da5..9f38f1db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Changelog ## Unreleased +### Fixed +- Dynamic scheduling now respects both `EntryViews` and `ResourceViews`. ## 0.9.0 - 2023-04-22 ### Changed From 2922dcc4d2180e94990eb87646bf7ad56d412b30 Mon Sep 17 00:00:00 2001 From: Anders429 Date: Sun, 30 Apr 2023 21:19:47 -0700 Subject: [PATCH 05/16] Add tests for dynamic scheduling with resources. --- src/world/mod.rs | 144 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) diff --git a/src/world/mod.rs b/src/world/mod.rs index ec2844e3..928fb079 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -2653,6 +2653,150 @@ mod tests { world.run_schedule(&mut schedule); } + #[cfg(feature = "rayon")] + #[test] + fn schedule_dynamic_optimization_compatible_resource_views() { + #[derive(Clone)] + struct A(u32); + #[derive(Clone)] + struct B(u32); + #[derive(Clone)] + struct C(u32); + + type Registry = Registry!(A, B, C); + + struct Foo; + + impl System for Foo { + type Views<'a> = Views!(&'a mut A, &'a mut B); + type Filter = filter::None; + type ResourceViews<'a> = Views!(&'a A); + type EntryViews<'a> = Views!(); + + fn run<'a, R, S, I, E>( + &mut self, + _query_results: Result< + 'a, + R, + S, + I, + Self::ResourceViews<'a>, + Self::EntryViews<'a>, + E, + >, + ) where + R: registry::ContainsViews<'a, Self::EntryViews<'a>, E>, + I: Iterator>, + { + } + } + + struct Bar; + + impl System for Bar { + type Views<'a> = Views!(&'a mut A, &'a mut C); + type Filter = filter::None; + type ResourceViews<'a> = Views!(&'a A); + type EntryViews<'a> = Views!(); + + fn run<'a, R, S, I, E>( + &mut self, + _query_results: Result< + 'a, + R, + S, + I, + Self::ResourceViews<'a>, + Self::EntryViews<'a>, + E, + >, + ) where + R: registry::ContainsViews<'a, Self::EntryViews<'a>, E>, + I: Iterator>, + { + } + } + + let mut world = World::::with_resources(resources!(A(0))); + + let mut schedule = schedule!(task::System(Foo), task::System(Bar)); + + world.run_schedule(&mut schedule); + } + + #[cfg(feature = "rayon")] + #[test] + fn schedule_dynamic_optimization_incompatible_resource_views() { + #[derive(Clone)] + struct A(u32); + #[derive(Clone)] + struct B(u32); + #[derive(Clone)] + struct C(u32); + + struct Foo; + + impl System for Foo { + type Views<'a> = Views!(); + type Filter = filter::None; + type ResourceViews<'a> = Views!(&'a mut A, &'a mut B); + type EntryViews<'a> = Views!(); + + fn run<'a, R, S, I, E>( + &mut self, + query_results: Result< + 'a, + R, + S, + I, + Self::ResourceViews<'a>, + Self::EntryViews<'a>, + E, + >, + ) where + R: registry::ContainsViews<'a, Self::EntryViews<'a>, E>, + I: Iterator>, + { + let result!(a, b) = query_results.resources; + core::mem::swap(&mut a.0, &mut b.0); + } + } + + struct Bar; + + impl System for Bar { + type Views<'a> = Views!(); + type Filter = filter::None; + type ResourceViews<'a> = Views!(&'a mut A, &'a mut C); + type EntryViews<'a> = Views!(); + + fn run<'a, R, S, I, E>( + &mut self, + query_results: Result< + 'a, + R, + S, + I, + Self::ResourceViews<'a>, + Self::EntryViews<'a>, + E, + >, + ) where + R: registry::ContainsViews<'a, Self::EntryViews<'a>, E>, + I: Iterator>, + { + let result!(a, c) = query_results.resources; + core::mem::swap(&mut a.0, &mut c.0); + } + } + + let mut world = World::::with_resources(resources!(A(0), B(0), C(0))); + + let mut schedule = schedule!(task::System(Foo), task::System(Bar)); + + world.run_schedule(&mut schedule); + } + #[test] fn contains() { let mut world = World::::new(); From df35aac30ef2cab363b7e951043cf7cd4fd9c9eb Mon Sep 17 00:00:00 2001 From: Anders429 Date: Sun, 30 Apr 2023 21:28:49 -0700 Subject: [PATCH 06/16] Test dynamic scheduling where resource view is not the first resource. --- src/world/mod.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/src/world/mod.rs b/src/world/mod.rs index 928fb079..cbc2c8ee 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -2724,6 +2724,77 @@ mod tests { world.run_schedule(&mut schedule); } + #[cfg(feature = "rayon")] + #[test] + fn schedule_dynamic_optimization_compatible_resource_views_with_multiple_resource_views() { + #[derive(Clone)] + struct A(u32); + #[derive(Clone)] + struct B(u32); + #[derive(Clone)] + struct C(u32); + + type Registry = Registry!(A, B, C); + + struct Foo; + + impl System for Foo { + type Views<'a> = Views!(&'a mut A, &'a mut B); + type Filter = filter::None; + type ResourceViews<'a> = Views!(&'a B); + type EntryViews<'a> = Views!(); + + fn run<'a, R, S, I, E>( + &mut self, + _query_results: Result< + 'a, + R, + S, + I, + Self::ResourceViews<'a>, + Self::EntryViews<'a>, + E, + >, + ) where + R: registry::ContainsViews<'a, Self::EntryViews<'a>, E>, + I: Iterator>, + { + } + } + + struct Bar; + + impl System for Bar { + type Views<'a> = Views!(&'a mut A, &'a mut C); + type Filter = filter::None; + type ResourceViews<'a> = Views!(&'a B); + type EntryViews<'a> = Views!(); + + fn run<'a, R, S, I, E>( + &mut self, + _query_results: Result< + 'a, + R, + S, + I, + Self::ResourceViews<'a>, + Self::EntryViews<'a>, + E, + >, + ) where + R: registry::ContainsViews<'a, Self::EntryViews<'a>, E>, + I: Iterator>, + { + } + } + + let mut world = World::::with_resources(resources!(A(0), B(0), C(0))); + + let mut schedule = schedule!(task::System(Foo), task::System(Bar)); + + world.run_schedule(&mut schedule); + } + #[cfg(feature = "rayon")] #[test] fn schedule_dynamic_optimization_incompatible_resource_views() { From 966f721c29ea8ada06e02d5d1ef1338a88235e29 Mon Sep 17 00:00:00 2001 From: Anders429 Date: Sun, 30 Apr 2023 21:35:51 -0700 Subject: [PATCH 07/16] Document memory safety reasoning. --- src/query/result/archetype_claims.rs | 4 ++++ src/system/schedule/stage.rs | 10 ++++++---- src/world/mod.rs | 2 ++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/query/result/archetype_claims.rs b/src/query/result/archetype_claims.rs index 1cded5d4..c055cbcc 100644 --- a/src/query/result/archetype_claims.rs +++ b/src/query/result/archetype_claims.rs @@ -78,6 +78,8 @@ where /// # Safety /// The `archetype::IdentifierRef`s over which this iterator iterates must not outlive the /// `Archetypes` to which they belong. + /// + /// The views and entry views must be compatible with each other. pub(crate) unsafe fn new(archetypes_iter: archetypes::IterMut<'a, Registry>) -> Self { Self { archetypes_iter, @@ -141,6 +143,8 @@ where // SAFETY: The `IdentifierRef` created here is guaranteed to outlive // `archetype`, so long as the safety contract at construction is upheld. unsafe { archetype.identifier() }, + // SAFETY: The views and entry views are compatible, meaning merging them is + // always defined. unsafe { , T::EntryViewsFilter>, T::EntryViews, QueryIndices, Or, EntryViewsFilterIndices>, EntryIndices>() } @@ -239,7 +240,8 @@ fn query_archetype_identifiers_unchecked< { for (identifier, claims) in // SAFETY: The access to the world's archetype identifiers follows Rust's borrowing - // rules. + // rules. Additionally, the views within the task are guaranteed to be valid and + // compatible. unsafe { (*world.get()).query_archetype_claims::, T::EntryViewsFilter>, T::EntryViews, QueryIndices, Or, EntryViewsFilterIndices>, EntryIndices>() } @@ -354,9 +356,9 @@ where EntryViewsFilterIndices, >(world, &mut borrowed_archetypes); - // SAFETY: The resource claims are compatible because they are in the same - // stage. let resource_claims = + // SAFETY: The resource claims are compatible because they are in the same + // stage. unsafe { resource_claims.merge_unchecked(&Resources::claims()) }; self.1.run( diff --git a/src/world/mod.rs b/src/world/mod.rs index cbc2c8ee..37c04227 100644 --- a/src/world/mod.rs +++ b/src/world/mod.rs @@ -455,6 +455,8 @@ where /// # Safety /// The `archetype::IdentifierRef`s over which this iterator iterates must not outlive the /// `Archetypes` to which they belong. + /// + /// The views and entry views must be compatible with each other. #[cfg(feature = "rayon")] #[cfg_attr(doc_cfg, doc(cfg(feature = "rayon")))] pub(crate) unsafe fn query_archetype_claims< From 2a384d9a739183a54ad88bc15f265fdc311b8400 Mon Sep 17 00:00:00 2001 From: Anders429 Date: Wed, 31 May 2023 14:51:28 -0700 Subject: [PATCH 08/16] Switch to stable MSRV channel for trybuild tests. --- tests/trybuild.rs | 10 +++++++++- tests/trybuild/entities/comma_alone.stderr | 6 ------ tests/trybuild/entities/component_order.stderr | 4 ++-- tests/trybuild/entities/double_comma.stderr | 6 ------ tests/trybuild/entities/same_components.stderr | 2 +- tests/trybuild/entities/semicolon_separated.stderr | 6 ------ tests/trybuild/entities/unexpected_token.stderr | 6 ------ tests/trybuild/entity/comma_alone.stderr | 6 ------ tests/trybuild/entity/type_comma_alone.stderr | 6 ------ tests/trybuild/entity/type_unexpected_token.stderr | 6 ------ tests/trybuild/entity/unexpected_token.stderr | 6 ------ tests/trybuild/registry/comma_alone.stderr | 6 ------ tests/trybuild/registry/unexpected_token.stderr | 6 ------ tests/trybuild/resources/comma_alone.stderr | 6 ------ tests/trybuild/resources/type_comma_alone.stderr | 6 ------ tests/trybuild/resources/type_unexpected_token.stderr | 6 ------ tests/trybuild/resources/unexpected_token.stderr | 6 ------ tests/trybuild/result/comma_alone.stderr | 2 -- tests/trybuild/result/unexpected_token.stderr | 6 ------ tests/trybuild/schedule/comma_alone.stderr | 6 ------ tests/trybuild/schedule/non_send_entry_views.stderr | 2 +- tests/trybuild/schedule/non_send_resource_views.stderr | 2 +- tests/trybuild/schedule/non_send_views.stderr | 2 +- tests/trybuild/schedule/type_comma_alone.stderr | 6 ------ tests/trybuild/schedule/type_unexpected_token.stderr | 6 ------ tests/trybuild/schedule/unexpected_token.stderr | 6 ------ tests/trybuild/views/comma_alone.stderr | 6 ------ tests/trybuild/views/unexpected_token.stderr | 6 ------ 28 files changed, 15 insertions(+), 135 deletions(-) diff --git a/tests/trybuild.rs b/tests/trybuild.rs index d7d0e5ff..7f57e9c2 100644 --- a/tests/trybuild.rs +++ b/tests/trybuild.rs @@ -1,8 +1,16 @@ #![cfg(not(skip_trybuild))] +#[test] +fn check_msrv() { + // If this test fails, the MSRV needs to be updated both here and in the `trybuild_test!` macro + // definition. This ensures that the trybuild tests are run on the MSRV even when the MSRV is + // updated. + assert_eq!(env!("CARGO_PKG_RUST_VERSION"), "1.65.0") +} + macro_rules! trybuild_test { ($test_name:ident) => { - #[rustversion::attr(not(nightly), ignore)] + #[rustversion::attr(not(stable(1.65)), ignore)] #[test] fn $test_name() { trybuild::TestCases::new().compile_fail(concat!( diff --git a/tests/trybuild/entities/comma_alone.stderr b/tests/trybuild/entities/comma_alone.stderr index 4dfefbc3..741603f1 100644 --- a/tests/trybuild/entities/comma_alone.stderr +++ b/tests/trybuild/entities/comma_alone.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `,` | 4 | let entities = entities!(,); | ^ no rules expected this token in macro call - | -note: while trying to match `(` - --> src/entities/mod.rs - | - | (($component:expr $(,$components:expr)* $(,)?); $n:expr) => { - | ^ diff --git a/tests/trybuild/entities/component_order.stderr b/tests/trybuild/entities/component_order.stderr index 7f375497..aa1531e2 100644 --- a/tests/trybuild/entities/component_order.stderr +++ b/tests/trybuild/entities/component_order.stderr @@ -2,10 +2,10 @@ error[E0308]: mismatched types --> tests/trybuild/entities/component_order.rs:8:39 | 8 | let entities = entities!((A, B), (B, A)); - | ^ expected `A`, found `B` + | ^ expected struct `A`, found struct `B` error[E0308]: mismatched types --> tests/trybuild/entities/component_order.rs:8:42 | 8 | let entities = entities!((A, B), (B, A)); - | ^ expected `B`, found `A` + | ^ expected struct `B`, found struct `A` diff --git a/tests/trybuild/entities/double_comma.stderr b/tests/trybuild/entities/double_comma.stderr index 246c95c9..8bb8ef30 100644 --- a/tests/trybuild/entities/double_comma.stderr +++ b/tests/trybuild/entities/double_comma.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `,` | 8 | let entities = entities!((A, B),, (A, B)); | ^ no rules expected this token in macro call - | -note: while trying to match `(` - --> src/entities/mod.rs - | - | ($(($($components:expr),*)),+ $(,)?) => { - | ^ diff --git a/tests/trybuild/entities/same_components.stderr b/tests/trybuild/entities/same_components.stderr index 949beab9..7b3223db 100644 --- a/tests/trybuild/entities/same_components.stderr +++ b/tests/trybuild/entities/same_components.stderr @@ -2,4 +2,4 @@ error[E0308]: mismatched types --> tests/trybuild/entities/same_components.rs:9:42 | 9 | let entities = entities!((A, B), (A, C)); - | ^ expected `B`, found `C` + | ^ expected struct `B`, found struct `C` diff --git a/tests/trybuild/entities/semicolon_separated.stderr b/tests/trybuild/entities/semicolon_separated.stderr index a34e5f1c..b94f8808 100644 --- a/tests/trybuild/entities/semicolon_separated.stderr +++ b/tests/trybuild/entities/semicolon_separated.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `;` | 10 | let entities = entities!((A, B); (A, B); (A, B)); | ^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$n:expr` - --> src/entities/mod.rs - | - | (($component:expr $(,$components:expr)* $(,)?); $n:expr) => { - | ^^^^^^^ diff --git a/tests/trybuild/entities/unexpected_token.stderr b/tests/trybuild/entities/unexpected_token.stderr index a2d1d0d3..5bfc1166 100644 --- a/tests/trybuild/entities/unexpected_token.stderr +++ b/tests/trybuild/entities/unexpected_token.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `+` | 8 | let entities = entities!((A, B), (A, B), + (A, B)); | ^ no rules expected this token in macro call - | -note: while trying to match `(` - --> src/entities/mod.rs - | - | ($(($($components:expr),*)),+ $(,)?) => { - | ^ diff --git a/tests/trybuild/entity/comma_alone.stderr b/tests/trybuild/entity/comma_alone.stderr index 66e12d72..4d0a639c 100644 --- a/tests/trybuild/entity/comma_alone.stderr +++ b/tests/trybuild/entity/comma_alone.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `,` | 4 | let entity = entity!(,); | ^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$component:expr` - --> src/entity/mod.rs - | - | ($component:expr $(,$components:expr)* $(,)?) => { - | ^^^^^^^^^^^^^^^ diff --git a/tests/trybuild/entity/type_comma_alone.stderr b/tests/trybuild/entity/type_comma_alone.stderr index baf56d31..6517f0c3 100644 --- a/tests/trybuild/entity/type_comma_alone.stderr +++ b/tests/trybuild/entity/type_comma_alone.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `,` | 3 | type Entity = Entity!(,); | ^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$component:ty` - --> src/entity/mod.rs - | - | ($component:ty $(,$components:ty)* $(,)?) => { - | ^^^^^^^^^^^^^ diff --git a/tests/trybuild/entity/type_unexpected_token.stderr b/tests/trybuild/entity/type_unexpected_token.stderr index b0877741..989bebb1 100644 --- a/tests/trybuild/entity/type_unexpected_token.stderr +++ b/tests/trybuild/entity/type_unexpected_token.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `+` | 6 | type Entity = Entity!(A, + B,); | ^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$components:ty` - --> src/entity/mod.rs - | - | ($component:ty $(,$components:ty)* $(,)?) => { - | ^^^^^^^^^^^^^^ diff --git a/tests/trybuild/entity/unexpected_token.stderr b/tests/trybuild/entity/unexpected_token.stderr index 2693bbc6..39a9f218 100644 --- a/tests/trybuild/entity/unexpected_token.stderr +++ b/tests/trybuild/entity/unexpected_token.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `+` | 8 | let entity = entity!(A, + B,); | ^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$components:expr` - --> src/entity/mod.rs - | - | ($component:expr $(,$components:expr)* $(,)?) => { - | ^^^^^^^^^^^^^^^^ diff --git a/tests/trybuild/registry/comma_alone.stderr b/tests/trybuild/registry/comma_alone.stderr index d9d81cb9..1c0acf09 100644 --- a/tests/trybuild/registry/comma_alone.stderr +++ b/tests/trybuild/registry/comma_alone.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `,` | 3 | type Registry = Registry!(,); | ^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$component:ty` - --> src/registry/mod.rs - | - | ($component:ty $(,$components:ty)* $(,)?) => { - | ^^^^^^^^^^^^^ diff --git a/tests/trybuild/registry/unexpected_token.stderr b/tests/trybuild/registry/unexpected_token.stderr index 5373706f..05cf79d3 100644 --- a/tests/trybuild/registry/unexpected_token.stderr +++ b/tests/trybuild/registry/unexpected_token.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `+` | 7 | type Registry = Registry!(A, + B,); | ^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$components:ty` - --> src/registry/mod.rs - | - | ($component:ty $(,$components:ty)* $(,)?) => { - | ^^^^^^^^^^^^^^ diff --git a/tests/trybuild/resources/comma_alone.stderr b/tests/trybuild/resources/comma_alone.stderr index 1edca815..ce8a71a5 100644 --- a/tests/trybuild/resources/comma_alone.stderr +++ b/tests/trybuild/resources/comma_alone.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `,` | 4 | let resources = resources!(,); | ^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$resource:expr` - --> src/resource/mod.rs - | - | ($resource:expr $(,$resources:expr)* $(,)?) => { - | ^^^^^^^^^^^^^^ diff --git a/tests/trybuild/resources/type_comma_alone.stderr b/tests/trybuild/resources/type_comma_alone.stderr index beb0a9f5..ebc52038 100644 --- a/tests/trybuild/resources/type_comma_alone.stderr +++ b/tests/trybuild/resources/type_comma_alone.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `,` | 3 | type Resources = Resources!(,); | ^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$resource:ty` - --> src/resource/mod.rs - | - | ($resource:ty $(,$resources:ty)* $(,)?) => { - | ^^^^^^^^^^^^ diff --git a/tests/trybuild/resources/type_unexpected_token.stderr b/tests/trybuild/resources/type_unexpected_token.stderr index cacb8ffa..783e5041 100644 --- a/tests/trybuild/resources/type_unexpected_token.stderr +++ b/tests/trybuild/resources/type_unexpected_token.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `+` | 7 | type Resources = Resources!(A, + B); | ^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$resources:ty` - --> src/resource/mod.rs - | - | ($resource:ty $(,$resources:ty)* $(,)?) => { - | ^^^^^^^^^^^^^ diff --git a/tests/trybuild/resources/unexpected_token.stderr b/tests/trybuild/resources/unexpected_token.stderr index 203395a0..723e816f 100644 --- a/tests/trybuild/resources/unexpected_token.stderr +++ b/tests/trybuild/resources/unexpected_token.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `+` | 8 | let resources = resources!(A, + B); | ^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$resources:expr` - --> src/resource/mod.rs - | - | ($resource:expr $(,$resources:expr)* $(,)?) => { - | ^^^^^^^^^^^^^^^ diff --git a/tests/trybuild/result/comma_alone.stderr b/tests/trybuild/result/comma_alone.stderr index 9752a6ca..75ed8fe1 100644 --- a/tests/trybuild/result/comma_alone.stderr +++ b/tests/trybuild/result/comma_alone.stderr @@ -3,5 +3,3 @@ error: no rules expected the token `,` | 4 | let result!(,) = view::Null; | ^ no rules expected this token in macro call - | - = note: while trying to match end of macro diff --git a/tests/trybuild/result/unexpected_token.stderr b/tests/trybuild/result/unexpected_token.stderr index 2c51a419..6026b945 100644 --- a/tests/trybuild/result/unexpected_token.stderr +++ b/tests/trybuild/result/unexpected_token.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `+` | 8 | let result!(a, + b) = (A, (A, view::Null)); | ^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$components:ident` - --> src/query/result/mod.rs - | - | ($component:ident $(,$components:ident)* $(,)?) => ( - | ^^^^^^^^^^^^^^^^^ diff --git a/tests/trybuild/schedule/comma_alone.stderr b/tests/trybuild/schedule/comma_alone.stderr index 67d4d7b2..7753dd47 100644 --- a/tests/trybuild/schedule/comma_alone.stderr +++ b/tests/trybuild/schedule/comma_alone.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `,` | 4 | let schedule = schedule!(,); | ^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$task:expr` - --> src/system/schedule/mod.rs - | - | ($task:expr $(,$tasks:expr)* $(,)?) => ( - | ^^^^^^^^^^ diff --git a/tests/trybuild/schedule/non_send_entry_views.stderr b/tests/trybuild/schedule/non_send_entry_views.stderr index 96498973..116f6401 100644 --- a/tests/trybuild/schedule/non_send_entry_views.stderr +++ b/tests/trybuild/schedule/non_send_entry_views.stderr @@ -8,7 +8,7 @@ error[E0277]: `Rc` cannot be shared between threads safely | = help: the trait `Sync` is not implemented for `Rc` = note: required for `&Rc` to implement `Send` - = note: required because it appears within the type `(&Rc, Null)` + = note: required because it appears within the type `(&Rc, brood::query::view::Null)` = note: required for `brood::system::schedule::task::System` to implement `brood::system::schedule::task::sealed::Task<'_, (Rc, brood::registry::Null), brood::resource::Null, (registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), (resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), (((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null, ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null))>` = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::stager::Cutoff<'_, (Rc, brood::registry::Null), brood::resource::Null, schedule::claim::decision::Append, ((&Rc, brood::query::view::Null), schedule::claim::Null), schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, (brood::query::view::Null, schedule::claim::Null), schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, ((registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), ((resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), schedule::stage::Null), ((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null, ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), schedule::stage::Null), (((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), schedule::stage::Null), (Or, registry::contains::Contained>, schedule::stage::Null)>` = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::scheduler::Scheduler<'_, (Rc, brood::registry::Null), brood::resource::Null, ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), (view::merge::Neither, (view::merge::Right, view::merge::Null))), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), (((resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null, ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), schedule::stage::Null), schedule::stages::Null), ((Or, registry::contains::Contained>, schedule::stage::Null), schedule::stages::Null)>` diff --git a/tests/trybuild/schedule/non_send_resource_views.stderr b/tests/trybuild/schedule/non_send_resource_views.stderr index 60635287..2e280050 100644 --- a/tests/trybuild/schedule/non_send_resource_views.stderr +++ b/tests/trybuild/schedule/non_send_resource_views.stderr @@ -8,7 +8,7 @@ error[E0277]: `Rc` cannot be shared between threads safely | = help: the trait `Sync` is not implemented for `Rc` = note: required for `&Rc` to implement `Send` - = note: required because it appears within the type `(&Rc, Null)` + = note: required because it appears within the type `(&Rc, brood::query::view::Null)` = note: required for `brood::system::schedule::task::System` to implement `brood::system::schedule::task::sealed::Task<'_, brood::registry::Null, (Rc, brood::resource::Null), (registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), ((resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null), (resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null)), (((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null)>` = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::stager::Cutoff<'_, brood::registry::Null, (Rc, brood::resource::Null), schedule::claim::decision::Append, (brood::query::view::Null, schedule::claim::Null), schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, ((&Rc, brood::query::view::Null), schedule::claim::Null), schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, ((registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), (((resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null), (resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null)), schedule::stage::Null), ((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), schedule::stage::Null), (((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), (brood::query::filter::Not, schedule::stage::Null)>` = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::scheduler::Scheduler<'_, brood::registry::Null, (Rc, brood::resource::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), (view::merge::Neither, view::merge::Null)), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, registry::contains::Null, (registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), ((((resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null), (resource::contains::Contained, resource::contains::Null), (view::resource::get::index::Index, resource::contains::Null)), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, registry::contains::Null), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), ((brood::query::filter::Not, schedule::stage::Null), schedule::stages::Null)>` diff --git a/tests/trybuild/schedule/non_send_views.stderr b/tests/trybuild/schedule/non_send_views.stderr index 081397f0..1c5273bc 100644 --- a/tests/trybuild/schedule/non_send_views.stderr +++ b/tests/trybuild/schedule/non_send_views.stderr @@ -8,7 +8,7 @@ error[E0277]: `Rc` cannot be shared between threads safely | = help: the trait `Sync` is not implemented for `Rc` = note: required for `&Rc` to implement `Send` - = note: required because it appears within the type `(&Rc, Null)` + = note: required because it appears within the type `(&Rc, brood::query::view::Null)` = note: required for `brood::system::schedule::task::System` to implement `brood::system::schedule::task::sealed::Task<'_, (Rc, brood::registry::Null), brood::resource::Null, (registry::contains::Null, (registry::contains::Contained, registry::contains::Null), (registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), (resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), (((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null), ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null)>` = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::stager::Cutoff<'_, (Rc, brood::registry::Null), brood::resource::Null, schedule::claim::decision::Append, ((&Rc, brood::query::view::Null), schedule::claim::Null), schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, (brood::query::view::Null, schedule::claim::Null), schedule::stager::Null, schedule::stager::Null, schedule::stager::Null, ((registry::contains::Null, (registry::contains::Contained, registry::contains::Null), (registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), schedule::stage::Null), ((resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), schedule::stage::Null), ((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null), schedule::stage::Null), (((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), (brood::query::filter::Not, schedule::stage::Null)>` = note: required for `(brood::system::schedule::task::System, brood::system::schedule::task::Null)` to implement `schedule::scheduler::Scheduler<'_, (Rc, brood::registry::Null), brood::resource::Null, ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::scheduler::Null), (((((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), ((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), (view::merge::Neither, (view::merge::Left, view::merge::Null))), schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), ((schedule::claim::Null, schedule::stager::Null), schedule::stages::Null), (((registry::contains::Null, (registry::contains::Contained, registry::contains::Null), (registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), schedule::stage::Null), schedule::stages::Null), (((resource::contains::Null, resource::contains::Null, resource::contains::Null, resource::contains::Null), schedule::stage::Null), schedule::stages::Null), (((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), view::disjoint::Null, ((registry::contains::NotContained, (®istry::contains::Contained, registry::contains::Null)), (brood::hlist::get::Index, registry::contains::Null), (brood::hlist::get::Index, brood::hlist::Null)), view::disjoint::Null), schedule::stage::Null), schedule::stages::Null), ((((registry::contains::NotContained, (registry::contains::NotContained, registry::contains::Null)), registry::contains::Null, brood::hlist::Null), schedule::stage::Null), schedule::stages::Null), ((brood::query::filter::Not, schedule::stage::Null), schedule::stages::Null)>` diff --git a/tests/trybuild/schedule/type_comma_alone.stderr b/tests/trybuild/schedule/type_comma_alone.stderr index 2d1fb70e..7bd11d0a 100644 --- a/tests/trybuild/schedule/type_comma_alone.stderr +++ b/tests/trybuild/schedule/type_comma_alone.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `,` | 3 | type Schedule = Schedule!(,); | ^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$task:ty` - --> src/system/schedule/mod.rs - | - | ($task:ty $(,$tasks:ty)* $(,)?) => ( - | ^^^^^^^^ diff --git a/tests/trybuild/schedule/type_unexpected_token.stderr b/tests/trybuild/schedule/type_unexpected_token.stderr index 80c2cc37..aaacedb0 100644 --- a/tests/trybuild/schedule/type_unexpected_token.stderr +++ b/tests/trybuild/schedule/type_unexpected_token.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `+` | 39 | type Schedule = Schedule!(task::System, + task::System,); | ^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$tasks:ty` - --> src/system/schedule/mod.rs - | - | ($task:ty $(,$tasks:ty)* $(,)?) => ( - | ^^^^^^^^^ diff --git a/tests/trybuild/schedule/unexpected_token.stderr b/tests/trybuild/schedule/unexpected_token.stderr index ef766295..d02d2b66 100644 --- a/tests/trybuild/schedule/unexpected_token.stderr +++ b/tests/trybuild/schedule/unexpected_token.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `+` | 40 | let schedule = schedule!(task::System(A), + task::System(B),); | ^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$tasks:expr` - --> src/system/schedule/mod.rs - | - | ($task:expr $(,$tasks:expr)* $(,)?) => ( - | ^^^^^^^^^^^ diff --git a/tests/trybuild/views/comma_alone.stderr b/tests/trybuild/views/comma_alone.stderr index 8f6a05b5..3e6757ba 100644 --- a/tests/trybuild/views/comma_alone.stderr +++ b/tests/trybuild/views/comma_alone.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `,` | 3 | type Views = Views!(,); | ^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$view:ty` - --> src/query/view/mod.rs - | - | ($view:ty $(,$views:ty)* $(,)?) => ( - | ^^^^^^^^ diff --git a/tests/trybuild/views/unexpected_token.stderr b/tests/trybuild/views/unexpected_token.stderr index 0b2e1fa5..593d1488 100644 --- a/tests/trybuild/views/unexpected_token.stderr +++ b/tests/trybuild/views/unexpected_token.stderr @@ -3,9 +3,3 @@ error: no rules expected the token `+` | 7 | type Views = Views!(&A, + &B,); | ^ no rules expected this token in macro call - | -note: while trying to match meta-variable `$views:ty` - --> src/query/view/mod.rs - | - | ($view:ty $(,$views:ty)* $(,)?) => ( - | ^^^^^^^^^ From d77d140e00f171f8bb8ed59f1dc205f6d40614e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 31 May 2023 22:06:29 +0000 Subject: [PATCH 09/16] Update serde_assert requirement from 0.4.0 to 0.5.0 Updates the requirements on [serde_assert](https://github.com/Anders429/serde_assert) to permit the latest version. - [Release notes](https://github.com/Anders429/serde_assert/releases) - [Changelog](https://github.com/Anders429/serde_assert/blob/master/CHANGELOG.md) - [Commits](https://github.com/Anders429/serde_assert/compare/v0.4.0...v0.5.0) --- updated-dependencies: - dependency-name: serde_assert dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 129db147..e4058c11 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ serde = {version = "1.0.148", default-features = false, features = ["alloc"], op [dev-dependencies] claims = "0.7.1" rustversion = "1.0.9" -serde_assert = "0.4.0" +serde_assert = "0.5.0" serde_derive = "1.0.148" trybuild = "1.0.72" From cce9f41c39b44d11a06ba765652e1b4fd0a3cc28 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Jun 2023 19:58:59 +0000 Subject: [PATCH 10/16] Update hashbrown requirement from 0.13.1 to 0.14.0 Updates the requirements on [hashbrown](https://github.com/rust-lang/hashbrown) to permit the latest version. - [Changelog](https://github.com/rust-lang/hashbrown/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/hashbrown/compare/v0.13.1...v0.14.0) --- updated-dependencies: - dependency-name: hashbrown dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e4058c11..66e48a36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ rustdoc-args = ["--cfg", "doc_cfg"] [dependencies] either = {version = "1.8.0", default-features = false} fnv = {version = "1.0.7", default-features = false} -hashbrown = {version = "0.13.1", default-features = false, features = ["inline-more", "raw"]} +hashbrown = {version = "0.14.0", default-features = false, features = ["inline-more", "raw"]} rayon = {version = "1.6.0", optional = true} serde = {version = "1.0.148", default-features = false, features = ["alloc"], optional = true} From 0bb175ed75e78578fcee64508c32c5ca8147a03a Mon Sep 17 00:00:00 2001 From: Anders429 Date: Wed, 9 Aug 2023 16:31:22 -0700 Subject: [PATCH 11/16] Check foreign_identifier_lookup when inserting with an entity type. --- src/archetypes/mod.rs | 70 ++++++++++++++++++++--------------------- src/world/impl_serde.rs | 20 ++++++++++++ 2 files changed, 55 insertions(+), 35 deletions(-) diff --git a/src/archetypes/mod.rs b/src/archetypes/mod.rs index 8ed6bea9..ce33530b 100644 --- a/src/archetypes/mod.rs +++ b/src/archetypes/mod.rs @@ -186,9 +186,6 @@ where } } - /// # Safety - /// `component_map` must contain an entry for each component in the entity `E`. Each entry must - /// correspond to its component's location in the registry `R`. pub(crate) unsafe fn get_mut_or_insert_new_for_entity(&mut self) -> &mut Archetype where E: Entity, @@ -209,48 +206,51 @@ where None => unsafe { unreachable_unchecked() }, } } else { - let identifier = R::create_archetype_identifier(); - - let hash = Self::make_hash( - // SAFETY: The `IdentifierRef` obtained here does not live longer than the - // `identifier_buffer`. - unsafe { identifier.as_ref() }, - &self.hash_builder, - ); + // Although type id lookup failed, that doesn't mean the archetype does not exist. We + // instead look up by the raw slice using `foreign_identifier_lookup`. + let identifier_buffer = R::create_archetype_identifier(); - if let Some(archetype_bucket) = self.raw_archetypes.find( - hash, - Self::equivalent_identifier( - // SAFETY: The `IdentifierRef` obtained here does not live longer than the - // `identifier_buffer`. - unsafe { identifier.as_ref() }, - ), + let archetype = if let Some(&identifier) = self.foreign_identifier_lookup.get( + // SAFETY: The slice created here does not outlive the `identifier_buffer`. + unsafe { identifier_buffer.as_slice() }, ) { - // SAFETY: This reference to the archetype contained in this bucket is unique. - unsafe { archetype_bucket.as_mut() } + if let Some(archetype) = self.raw_archetypes.get_mut( + Self::make_hash(identifier, &self.hash_builder), + Self::equivalent_identifier(identifier), + ) { + archetype + } else { + // SAFETY: Since the identifier was present in `foreign_identifier_lookup`, it + // is guaranteed to have an associated `archetype`. + unsafe { unreachable_unchecked() } + } } else { - self.type_id_lookup.insert( - TypeId::of::(), - // SAFETY: The `IdentifierRef` obtained here does not live longer than the - // `identifier_buffer`. - unsafe { identifier.as_ref() }, - ); - // SAFETY: Since the archetype is not contained anywhere in this container, it is - // invariantly guaranteed that the identifier is not contained in - // `foreign_identifier_lookup` either. Additionally, both the slice and - // `IdentifierRef` created here do not outlive `identifier`. + // SAFETY: This identifier has already been verified to not be contained in + // `foreign_identifier_lookup`. Additionally, the slice and `IdentifierRef` created + // here will not outlive the `identifier_buffer`. unsafe { self.foreign_identifier_lookup.insert_unique_unchecked( - &*(identifier.as_slice() as *const [u8]), - identifier.as_ref(), + &*(identifier_buffer.as_slice() as *const [u8]), + identifier_buffer.as_ref(), ); } self.raw_archetypes.insert_entry( - hash, - Archetype::new(identifier), + // SAFETY: The `IdentifierRef` created here does not outlive the + // `identifier_buffer`. + Self::make_hash(unsafe { identifier_buffer.as_ref() }, &self.hash_builder), + Archetype::new(identifier_buffer), Self::make_hasher(&self.hash_builder), ) - } + }; + + self.type_id_lookup.insert( + TypeId::of::(), + // SAFETY: The `IdentifierRef` obtained here does not live longer than the + // `identifier_buffer`. + unsafe { archetype.identifier() }, + ); + + archetype } } diff --git a/src/world/impl_serde.rs b/src/world/impl_serde.rs index 1965712e..9b0ead32 100644 --- a/src/world/impl_serde.rs +++ b/src/world/impl_serde.rs @@ -112,6 +112,7 @@ mod tests { use alloc::vec; use claims::{ assert_err_eq, + assert_ok, assert_ok_eq, }; use serde::{ @@ -493,4 +494,23 @@ mod tests { Error::invalid_length(2, &"serialized World") ); } + + #[test] + fn deserialize_then_mutate() { + let mut world = World::::new(); + world.insert(entity!(A(0))); + + let serializer = Serializer::builder().build(); + let tokens = assert_ok!(world.serialize(&serializer)); + + let mut deserializer = Deserializer::builder().tokens(tokens).build(); + let mut deserialized_world = assert_ok!(World::::deserialize( + &mut deserializer + )); + + world.insert(entity!(A(1))); + deserialized_world.insert(entity!(A(1))); + + assert_eq!(world, deserialized_world); + } } From 5ad96c2db68697f0557cd5ca7c0cdf335e8495bc Mon Sep 17 00:00:00 2001 From: Anders429 Date: Wed, 9 Aug 2023 16:40:16 -0700 Subject: [PATCH 12/16] Fix incorrect clone implementations. --- src/archetype/identifier/mod.rs | 6 +----- src/entity/allocator/location.rs | 5 +---- src/query/mod.rs | 2 +- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/archetype/identifier/mod.rs b/src/archetype/identifier/mod.rs index 2f57492f..e8805f60 100644 --- a/src/archetype/identifier/mod.rs +++ b/src/archetype/identifier/mod.rs @@ -318,11 +318,7 @@ where R: Registry, { fn clone(&self) -> Self { - Self { - registry: PhantomData, - - pointer: self.pointer, - } + *self } } diff --git a/src/entity/allocator/location.rs b/src/entity/allocator/location.rs index e310137c..23aea8db 100644 --- a/src/entity/allocator/location.rs +++ b/src/entity/allocator/location.rs @@ -59,10 +59,7 @@ where R: Registry, { fn clone(&self) -> Self { - Self { - identifier: self.identifier, - index: self.index, - } + *self } } diff --git a/src/query/mod.rs b/src/query/mod.rs index 96241d66..9b330a8f 100644 --- a/src/query/mod.rs +++ b/src/query/mod.rs @@ -145,7 +145,7 @@ impl Clone for Query { fn clone(&self) -> Self { - Self::new() + *self } } From d82e2f51fdfd94712ec87fedfa354e0466a1e81e Mon Sep 17 00:00:00 2001 From: Anders429 Date: Wed, 9 Aug 2023 16:41:26 -0700 Subject: [PATCH 13/16] Look over reference to type id lookup container. --- src/archetypes/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/archetypes/mod.rs b/src/archetypes/mod.rs index ce33530b..14ce7899 100644 --- a/src/archetypes/mod.rs +++ b/src/archetypes/mod.rs @@ -439,7 +439,7 @@ where } } - for (&type_id, identifier) in self.type_id_lookup.iter() { + for (&type_id, identifier) in &self.type_id_lookup { cloned_archetypes.type_id_lookup.insert( type_id, // SAFETY: Each identifier in `self.type_id_lookup` is guaranteed to be found in @@ -515,7 +515,7 @@ where // // Note that no type id entries are removed here. New ones are just added, since the old // archetypes were just cleared, not removed entirely. - for (&type_id, identifier) in source.type_id_lookup.iter() { + for (&type_id, identifier) in &source.type_id_lookup { self.type_id_lookup.insert( type_id, // SAFETY: Each identifier in `source.type_id_lookup` is guaranteed to be found in From 1297cc2374bfd696a1eeaeb5a1c456abbcca3ce3 Mon Sep 17 00:00:00 2001 From: Anders429 Date: Wed, 9 Aug 2023 16:42:43 -0700 Subject: [PATCH 14/16] Update changelog. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f38f1db..d1cb2582 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased ### Fixed - Dynamic scheduling now respects both `EntryViews` and `ResourceViews`. +- Mutating a deserialized `World` no longer creates duplicate `Archetype`s, instead correctly looking up the existing deserialized `Archetype`. ## 0.9.0 - 2023-04-22 ### Changed From 208618b4860f06d2db8cfea4dd96db217e9963e8 Mon Sep 17 00:00:00 2001 From: Anders429 Date: Wed, 9 Aug 2023 17:21:32 -0700 Subject: [PATCH 15/16] Fix stray lint. --- src/system/schedule/sendable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/system/schedule/sendable.rs b/src/system/schedule/sendable.rs index d12ff83d..b7c1c1a1 100644 --- a/src/system/schedule/sendable.rs +++ b/src/system/schedule/sendable.rs @@ -30,7 +30,7 @@ where R: Registry, { fn clone(&self) -> Self { - Self(self.0) + *self } } From 4659c502ccaaec5e1ba65ab93aaddceddd5db448 Mon Sep 17 00:00:00 2001 From: Anders429 Date: Wed, 9 Aug 2023 17:41:28 -0700 Subject: [PATCH 16/16] Cut version 0.9.1. --- CHANGELOG.md | 2 ++ Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1cb2582..2e097940 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Changelog ## Unreleased + +## 0.9.1 - 2023-08-09 ### Fixed - Dynamic scheduling now respects both `EntryViews` and `ResourceViews`. - Mutating a deserialized `World` no longer creates duplicate `Archetype`s, instead correctly looking up the existing deserialized `Archetype`. diff --git a/Cargo.toml b/Cargo.toml index 66e48a36..a4b46ce5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "brood" -version = "0.9.0" +version = "0.9.1" authors = ["Anders Evensen"] edition = "2021" rust-version = "1.65.0"