Skip to content

Commit

Permalink
Alternative resource fetching implementation, goes around the ICE;
Browse files Browse the repository at this point in the history
keep monitoring rust-lang/rust#62529.
  • Loading branch information
Ratysz committed Dec 17, 2019
1 parent 361a938 commit fda50c4
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 61 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ license = "MIT OR Apache-2.0"
fixedbitset = "0.2.0"
fxhash = "0.2.1"
hecs = { path = "../hecs" }#"0.1.4"
paste = "0.1.6"
resources = "0.2.1"
45 changes: 38 additions & 7 deletions src/impls_for_tuple.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,43 @@
use crate::{
query_bundle::{QueryBundle, QueryEffector},
resource_bundle::{Fetch, ResourceBundle},
resource_bundle::{FetchEffector, Mutability, ResourceBundle},
system::TypeSet,
world::ArchetypeSet,
Query, World,
Fetch, Query, Resource, World,
};

macro_rules! impls_for_tuple {
($($letter:ident),*) => {
impl<'a, $($letter: ResourceBundle),*> ResourceBundle for ($($letter,)*)
impl<$($letter),*> ResourceBundle for ($($letter,)*)
where
$($letter: Resource + ResourceBundle,)*
{
type Effectors = ($($letter::Effectors,)*);

fn effectors() -> Self::Effectors {
($($letter::effectors(),)*)
}
}

paste::item! {
impl<'a, $([<M $letter>]),*, $([<R $letter>]),*> Fetch<'a>
for ($(FetchEffector<[<M $letter>], [<R $letter>]>,)*)
where
$([<M $letter>]: Mutability,)*
$([<R $letter>]: Resource,)*
$(FetchEffector<[<M $letter>], [<R $letter>]>: Fetch<'a>,)*
{
type Refs = ($(<FetchEffector<[<M $letter>], [<R $letter>]> as Fetch<'a>>::Refs,)*);

fn fetch(&self, world: &'a World) -> Self::Refs {
($(FetchEffector::<[<M $letter>], [<R $letter>]>::new().fetch(world),)*)
}
}
}

// FIXME this should be used instead of the above after
// https://github.com/rust-lang/rust/issues/62529 is fixed
/*impl<'a, $($letter: ResourceBundle),*> ResourceBundle for ($($letter,)*)
{
type Refs = ($($letter::Refs,)*);
}
Expand All @@ -20,14 +49,16 @@ macro_rules! impls_for_tuple {
fn fetch(world: &'a World) -> Self::Item {
($($letter::fetch(world),)*)
}
}
}*/

impl<$($letter: Query + QueryBundle),*> QueryBundle for ($($letter,)*)
impl<$($letter),*> QueryBundle for ($($letter,)*)
where
$($letter: Query + QueryBundle,)*
{
type Effectors = ($(QueryEffector<$letter>,)*);
type Effectors = ($($letter::Effectors,)*);

fn effectors() -> Self::Effectors {
($(QueryEffector::<$letter>::new(),)*)
($($letter::effectors(),)*)
}

fn borrowed_components() -> TypeSet {
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ mod resource_bundle;
mod system;
mod world;

pub use resource_bundle::Fetch;
pub use system::{DynamicSystemBuilder, StaticSystem, StaticSystemBuilder};
pub use world::World;
40 changes: 20 additions & 20 deletions src/query_bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,25 @@ pub trait QueryBundle: Send + Sync {
fn touched_archetypes(world: &World) -> ArchetypeSet;
}

impl<'a, C> QueryBundle for &'a C
impl QueryBundle for () {
type Effectors = ();

fn effectors() -> Self::Effectors {}

fn borrowed_components() -> TypeSet {
TypeSet::default()
}

fn borrowed_mut_components() -> TypeSet {
TypeSet::default()
}

fn touched_archetypes(_: &World) -> ArchetypeSet {
ArchetypeSet::default()
}
}

impl<C> QueryBundle for &'_ C
where
C: Component,
{
Expand All @@ -63,7 +81,7 @@ where
}
}

impl<'a, C> QueryBundle for &'a mut C
impl<C> QueryBundle for &'_ mut C
where
C: Component,
{
Expand Down Expand Up @@ -110,21 +128,3 @@ where
Q::touched_archetypes(world)
}
}

impl QueryBundle for () {
type Effectors = ();

fn effectors() -> Self::Effectors {}

fn borrowed_components() -> TypeSet {
TypeSet::default()
}

fn borrowed_mut_components() -> TypeSet {
TypeSet::default()
}

fn touched_archetypes(_: &World) -> ArchetypeSet {
ArchetypeSet::default()
}
}
126 changes: 110 additions & 16 deletions src/resource_bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,107 @@ use std::{any::type_name, marker::PhantomData};

use crate::{Resource, ResourceRef, ResourceRefMut, World};

pub struct Immutable;

pub struct Mutable;

pub trait Mutability: Send + Sync {}

impl Mutability for Immutable {}

impl Mutability for Mutable {}

pub struct FetchEffector<M, R>
where
M: Mutability,
R: Resource + Send + Sync,
{
phantom_data: PhantomData<(M, R)>,
}

impl<M, R> FetchEffector<M, R>
where
M: Mutability,
R: Resource + Send + Sync,
{
pub(crate) fn new() -> Self {
Self {
phantom_data: PhantomData,
}
}
}

pub trait ResourceBundle: Send + Sync {
type Effectors;

fn effectors() -> Self::Effectors;
}

pub trait Fetch<'a> {
type Refs;

fn fetch(&self, world: &'a World) -> Self::Refs;
}

impl ResourceBundle for () {
type Effectors = ();

fn effectors() -> Self::Effectors {}
}

impl<'a> Fetch<'a> for () {
type Refs = ();

fn fetch(&self, world: &'a World) -> Self::Refs {}
}

impl<R: Resource> ResourceBundle for &'_ R {
type Effectors = FetchEffector<Immutable, R>;

fn effectors() -> Self::Effectors {
FetchEffector::new()
}
}

impl<'a, R: Resource> Fetch<'a> for FetchEffector<Immutable, R> {
type Refs = ResourceRef<'a, R>;

fn fetch(&self, world: &'a World) -> Self::Refs {
world
.resource()
.unwrap_or_else(|error| panic!("cannot fetch {}: {}", type_name::<R>(), error))
}
}

impl<R: Resource> ResourceBundle for &'_ mut R {
type Effectors = FetchEffector<Mutable, R>;

fn effectors() -> Self::Effectors {
FetchEffector::new()
}
}

impl<'a, R: Resource> Fetch<'a> for FetchEffector<Mutable, R> {
type Refs = ResourceRefMut<'a, R>;

fn fetch(&self, world: &'a World) -> Self::Refs {
world
.resource_mut()
.unwrap_or_else(|error| panic!("cannot fetch {}: {}", type_name::<R>(), error))
}
}

// FIXME this should be used instead of the above after
// https://github.com/rust-lang/rust/issues/62529 is fixed
/*
pub struct ElidedRef<R: Resource> {
phantom_data: PhantomData<R>,
}
pub struct ElidedRefMut<R: Resource> {
phantom_data: PhantomData<R>,
}
pub trait ResourceBundle: Send + Sync {
type Refs: for<'a> Fetch<'a>;
Expand All @@ -16,15 +117,17 @@ pub trait Fetch<'a> {
fn fetch(world: &'a World) -> Self::Item;
}
pub struct ElidedRef<R: Resource> {
phantom_data: PhantomData<R>,
impl ResourceBundle for () {
type Refs = ();
}
pub struct ElidedRefMut<R: Resource> {
phantom_data: PhantomData<R>,
impl<'a> Fetch<'a> for () {
type Item = ();
fn fetch(_: &'a World) -> Self::Item {}
}
impl<'a, R> ResourceBundle for &'a R
impl<R> ResourceBundle for &'_ R
where
R: Resource,
{
Expand All @@ -44,7 +147,7 @@ where
}
}
impl<'a, R: Resource> ResourceBundle for &'a mut R {
impl<R: Resource> ResourceBundle for &'_ mut R {
type Refs = ElidedRefMut<R>;
}
Expand All @@ -60,13 +163,4 @@ where
.unwrap_or_else(|error| panic!("cannot fetch {}: {}", type_name::<R>(), error))
}
}

impl ResourceBundle for () {
type Refs = ();
}

impl<'a> Fetch<'a> for () {
type Item = ();

fn fetch(_: &'a World) -> Self::Item {}
}
*/
31 changes: 19 additions & 12 deletions src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ impl<'a, R, Q, F> StaticSystem<'a, R, Q> for F
where
R: ResourceBundle,
Q: QueryBundle,
F: FnMut(&'a World, <R::Refs as Fetch<'a>>::Item, Q::Effectors),
F: FnMut(&'a World, R::Effectors, Q::Effectors),
{
fn run(&mut self, world: &'a World) {
self(world, R::fetch(world), Q::effectors())
self(world, R::effectors(), Q::effectors())
}
}

Expand All @@ -58,7 +58,7 @@ where
Q: QueryBundle,
{
pub fn build(
system: impl FnMut(&'a World, <R::Refs as Fetch<'a>>::Item, Q::Effectors),
system: impl FnMut(&'a World, R::Effectors, Q::Effectors),
) -> impl StaticSystem<'a, R, Q> {
system
}
Expand All @@ -68,7 +68,7 @@ struct SystemBox<R, Q, F>
where
R: ResourceBundle,
Q: QueryBundle,
F: FnMut(&World, <R::Refs as Fetch>::Item, Q::Effectors),
F: FnMut(&World, R::Effectors, Q::Effectors),
{
phantom_data: PhantomData<(R, Q)>,
system: F,
Expand All @@ -78,7 +78,7 @@ impl<R, Q, F> From<F> for SystemBox<R, Q, F>
where
R: ResourceBundle,
Q: QueryBundle,
F: FnMut(&World, <R::Refs as Fetch>::Item, Q::Effectors),
F: FnMut(&World, R::Effectors, Q::Effectors),
{
fn from(system: F) -> Self {
Self {
Expand All @@ -102,10 +102,10 @@ impl<R, Q, F> DynamicSystem for SystemBox<R, Q, F>
where
R: ResourceBundle,
Q: QueryBundle,
F: FnMut(&World, <R::Refs as Fetch>::Item, Q::Effectors),
F: FnMut(&World, R::Effectors, Q::Effectors),
{
fn run(&mut self, world: &World) {
(self.system)(world, R::fetch(world), Q::effectors())
(self.system)(world, R::effectors(), Q::effectors())
}

fn borrowed_components(&self) -> TypeSet {
Expand Down Expand Up @@ -135,7 +135,7 @@ where
Q: QueryBundle + 'static,
{
pub fn build(
system: impl FnMut(&World, <R::Refs as Fetch>::Item, Q::Effectors) + 'static,
system: impl FnMut(&World, R::Effectors, Q::Effectors) + 'static,
) -> Box<dyn DynamicSystem> {
Box::new(SystemBox::<R, Q, _>::from(Box::new(system)))
}
Expand All @@ -145,10 +145,17 @@ where
fn test() {
let mut world = World::new();
world.add_resource::<usize>(1);
let mut system =
StaticSystemBuilder::<(), (&usize, Option<&usize>)>::build(|world, _, component| {});
world.add_resource::<f32>(1.0);
let mut system = StaticSystemBuilder::<(&usize, &mut f32), (&usize, Option<&usize>)>::build(
|world, fetch, query| {
let (res1, mut res2) = fetch.fetch(world);
},
);
system.run(&world);
let mut system =
DynamicSystemBuilder::<(), (&usize, Option<&usize>)>::build(|world, _, component| {});
let mut system = DynamicSystemBuilder::<(&usize, &mut f32), (&usize, Option<&usize>)>::build(
|world, fetch, query| {
let (res1, mut res2) = fetch.fetch(world);
},
);
system.run(&world);
}
Loading

0 comments on commit fda50c4

Please sign in to comment.