I currently try to implement a IOC-Container, where I try to build scopes entirely on the stack. To do so, a trait resolves dependencies by calling a lambda on service-request. Here is some sample code which works:
pub trait Resolvable{
type Result;
fn resolve(container: &Container, callback: &dyn Fn(&Self::Result));
}
impl Resolvable for () {
type Result = ();
fn resolve(_: &Container, callback: &dyn Fn(&Self::Result)) {
let a = ();
callback(&a);
}
}
Unfortunately, I run into problems when the type-Parameter requires a lifetime. I got inspired by Lukas Kalbertodt to use Type-Constructors. My implementation looks as follows:
trait FamilyLt<'a> {
type Out;
}
struct SingleStructFamily<T: ?Sized>(PhantomData<T>);
impl<'a, T: 'a + ?Sized> FamilyLt<'a> for SingleStructFamily<T> {
type Out = (&'a T,);
}
When i try to use it, it doesn't compile, but I can't see what I'm doing wrong:
trait Thing {
type Result: for<'a> FamilyLt<'a>;
fn resolve<TFn>(&self, c: TFn) where for<'a> TFn: Fn(<Self::Result as FamilyLt<'a>>::Out);
}
struct Foo();
impl Thing for Foo {
type Result = SingleStructFamily<i32>;
fn resolve<TFn>(&self, c: TFn) where for<'a> TFn: Fn(<Self::Result as FamilyLt<'a>>::Out) {
let cant_be_static = 42;
//(c)((&42,); // Doesnt compile !
}
}
When I change the signature from as FamilyLt<'a>
to as FamilyLt<'static>
it at least compiles with the static reference to 42
. Any suggestions how I can do someting like that (Prefferaby even without complicated "Family-Types". The generic trait-parameters/lifetimes can be changed. I'd even use unsafe code to fake a lifetime, because I know, that the reference must be valid just during the callback-invocation.