I want to gather a set of different functions as handlers, and was inspired by the implementation of bevy
's ECS system. So I write something like this(playground):
trait Handler<'a>: Send + Sync {
type Output: Send + 'a;
fn handle(&self, x: &'a mut u32, y: &'a mut u32) -> Self::Output;
}
trait HandlerFunc<'a, Marker>: Send + Sync {
type Output: Send + 'a;
fn handle(&self, x: &'a mut u32, y: &'a mut u32) -> Self::Output;
}
impl<'a, G, T, A> HandlerFunc<'a, for<'any> fn(&'any mut u32, Ref<'any, u32, A>)> for G
where
G: Fn(&'a mut u32, Ref<'a, u32, A>) -> T + Send + Sync,
T: Send + 'a,
{
type Output = T;
fn handle(&self, x: &'a mut u32, y: &'a mut u32) -> Self::Output {
(self)(x, Ref(y, PhantomData))
}
}
pub struct FunctionHandler<F, Marker> {
func: F,
marker: PhantomData<fn(Marker)>,
}
impl<'a, G, Marker> Handler<'a> for FunctionHandler<G, Marker>
where
G: HandlerFunc<'a, Marker>,
{
type Output = G::Output;
fn handle(&self, x: &'a mut u32, y: &'a mut u32) -> Self::Output {
self.func.handle(x, y)
}
}
trait IntoHandler<'a, O, Marker> {
type Hf: Handler<'a, Output = O>;
fn into_handler(self) -> Self::Hf;
}
impl<'a, H: Handler<'a>> IntoHandler<'a, H::Output, ()> for H {
type Hf = Self;
fn into_handler(self) -> Self::Hf {
self
}
}
pub enum AsHandlerFunc {}
impl<'a, G, Marker> IntoHandler<'a, G::Output, (AsHandlerFunc, Marker)> for G
where
G: HandlerFunc<'a, Marker>,
{
type Hf = FunctionHandler<G, Marker>;
fn into_handler(self) -> Self::Hf {
FunctionHandler {
func: self,
marker: PhantomData,
}
}
}
The code above works well. However, when I write a generic function that push a handler to a collection:
type AnyHandler = dyn for<'any> Handler<'any, Output = u32>;
fn push<'a, Marker, H>(handlers: &mut Vec<Box<AnyHandler>>, handler: H)
where
Marker: 'static,
H: for<'any> IntoHandler<'any, u32, Marker> + 'static,
{
handlers.push(Box::new(handler.into_handler()));
}
It gives errors like this:
error: implementation of `Handler` is not general enough
--> str-match/src/main.rs:119:19
|
119 | handlers.push(Box::new(handler.into_handler()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Handler` is not general enough
|
= note: `<H as IntoHandler<'2, u32, Marker>>::Hf` must implement `Handler<'1>`, for any lifetime `'1`...
= note: ...but it actually implements `Handler<'2>`, for some specific lifetime `'2`
error[E0308]: mismatched types
--> str-match/src/main.rs:119:19
|
119 | handlers.push(Box::new(handler.into_handler()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected associated type `<<H as IntoHandler<'_, u32, Marker>>::Hf as Handler<'_>>::Output`
found associated type `<<H as IntoHandler<'_, u32, Marker>>::Hf as Handler<'any>>::Output`
How should I fix the code above?