Hi there Rustaceans!
Ive been attempting to implement a basic async ECS using Rust as a toy project to help me understand the subject better.
My idea is that i want to accept both simple (async) functions and complex structs as systems.
I thought this wouldnt be a problem, since i run the systems using trait objects (dynamic dispatch) anyway.
These are the basic trait definitions i have so far:
#[async_trait]
pub trait System: Send + Sync {
type Data: SystemData;
async fn run(&mut self, data: Self::Data);
}
#[async_trait]
impl<D: SystemData, O> System for fn(D) -> O
where O: Future<Output = ()> + Send
{
type Data = D;
async fn run(&mut self, data: Self::Data) {
self(data).await
}
}
pub trait IntoDynSystem {
fn into_dyn_system(self) -> Box<dyn DynSystem>;
}
impl<D: SystemData + 'static, O: Future<Output = ()> + Send + 'static> IntoDynSystem for fn(D) -> O {
fn into_dyn_system(self) -> Box<dyn DynSystem> {
Box::new(self)
}
}
#[async_trait]
pub trait DynSystem {
async fn dyn_run(&mut self, world: &World);
}
#[async_trait]
impl<S: System> DynSystem for S {
async fn dyn_run(&mut self, world: &World) {
self.run(S::Data::fetch(world).await).await
}
}
System
itself is intended for defining the systems, while a trait object of DynSystem
will be used to actually run them. However, during this basic test:
async fn run_basic_system<S: IntoDynSystem>(sys: S) {
let system_box: Box<dyn DynSystem> = sys.into_dyn_system();
}
async fn basic_system(_args: ()) {
println!("Basic system!");
}
#[async_std::test]
async fn test_basic_system() {
run_basic_system(basic_system).await
}
I get a type mismatch error like this:
the trait bound `fn(()) -> impl std::future::Future<Output = ()> {basic_system}: messy_ecs::system::IntoDynSystem` is not satisfied
the following implementations were found:
<fn(D) -> O as messy_ecs::system::IntoDynSystem>
What am i missing and/or fundamentally misunderstanding in my approach here?
Any help would be greatly appreciated. I would assume impl Future<Output = ()>
would be caught by the trait constraints.