I have a specific problem I'm facing currently,
I'm designing a component system for an engine that I'm writing myself and I'd like to do something like this:
trait BaseComponent {
fn dimensions(&self) -> Dimensions;
fn topleftmost_point(&self) -> Point;
// other methods etc...
}
I want all components to implement this trait, but also one or more of these subtraits:
trait Component: BaseComponent {
type State;
fn draw(&mut self, ctx: &mut RenderContext<Self::State>) -> crate::Result<()>;
}
trait DynamicComponent: Component {
fn update(&mut self, ctx: &mut RenderContext<<Self as Component>::State>) -> crate::Result<()>;
}
trait AsyncComponent: BaseComponent {
type State;
fn poll_draw(self: Pin<&mut Self>, ctx: &mut AsyncRenderContext<'_, Self::State>) -> Poll<crate::Result<()>;
}
I also have planned for a async and blocking version of a stateless component, which is similar without the extra ctx
parameter.
My question is, would there be a way to automatically require any object that implements the BaseComponent
trait also implement one or more of these subtraits? It's not entirely necessary, but I feel like it could for sure eliminate some dumb errors I could potentially make.
UPDATE:
after about a day of trying different solutions, I found a system that at least partially works (it works for marker traits)
#![feature(marker_trait_attr)]
use core::marker::{PhantomData};
trait A
where
Comp<Self>: Coerce<dyn A>
{}
trait B: A {}
trait C: A {}
#[marker] trait Coerce<T: ?Sized> {}
impl<T: ?Sized + B> Coerce<dyn A> for Comp<T> {}
impl<T: ?Sized + C> Coerce<dyn A> for Comp<T> {}
struct Comp<T: ?Sized>(PhantomData<T>);
struct D;
struct E;
impl A for D {}
impl B for D {}
impl A for E {}
impl C for E {}
fn main() {}
the main issue of this, however, is that it is based off of unstable features, due to the marker trait attribute.