I have this function which is having some lifetime trouble:
fn provide_importable_func<Params, Returns, F>(&mut self, name : &str, f : F) -> Result<&mut Self, VxConfigError>
where
Params : WasmToVxList,
Params::Wasm : 'static,
Returns : VxToWasmList,
for<'l, 'k> F
: Clone + Send + Sync + 'static
+ AsyncFn<PrependTuple<&'k SharedState, Params::Vx<'l>>, Output = Returns::Vx<'static>>,
for<'l, 'k> (&'k SharedState, Params::Vx<'l>,) : TuplePrepend<&'k SharedState, Params::Vx<'l>>,
for<'l, 'k> <(&'k SharedState, Params::Vx<'l>,) as TuplePrepend<&'k SharedState, Params::Vx<'l>>>::Type : Tuple,
This won't compile beacuse
future cannot be sent between threads safely
the trait `Send` is not implemented for `<F as AsyncFnMut<<(&SharedState, Params::Vx<'_>) as TuplePrepend<&SharedState, Params::Vx<'_>>>::Type>>::CallRefFuture<'_>`
which makes perfect sense. Calling f
returns a Future
that isn't send, so the async
block around it isn't Send
because it await
s said Future
.
So I added this where
clause to the function:
where for<'a, 'b, 'e> <F as AsyncFnMut<<(&'a SharedState, Params::Vx<'b>) as TuplePrepend<&'a SharedState, Params::Vx<'b>>>::Type>>::CallRefFuture<'e> : Send
...but the Box::new(async move { /* ... */ })
inside the function errors saying
implementation of `Send` is not general enough
`Send` would have to be implemented for the type `<F as AsyncFnMut<<(&SharedState, Params::Vx<'_>) as TuplePrepend<&SharedState, Params::Vx<'_>>>::Type>>::CallRefFuture<'_>`
...but `Send` is actually implemented for the type `<F as AsyncFnMut<<(&'0 SharedState, Params::Vx<'_>) as TuplePrepend<&'0 SharedState, Params::Vx<'_>>>::Type>>::CallRefFuture<'_>`, for some specific lifetime `'0`
Adding a few more lifetimes to the where
clause fixes that:
where for<'a, 'b, 'c, 'd, 'e> <F as AsyncFnMut<<(&'a SharedState, Params::Vx<'b>) as TuplePrepend<&'c SharedState, Params::Vx<'d>>>::Type>>::CallRefFuture<'e> : Send
...but causes calls of this function to error with
implementation of `TuplePrepend` is not general enough
`(&'a (), (&'b str,))` must implement `TuplePrepend<&'c (), (&'d str,)>`
...but it actually implements `TuplePrepend<&'a (), (&'b str,)>`
So it seems like both clauses are needed:
where
for<'a, 'b, 'e> <F as AsyncFnMut<<(&'a SharedState, Params::Vx<'b>) as TuplePrepend<&'a SharedState, Params::Vx<'b>>>::Type>>::CallRefFuture<'e> : Send,
for<'a, 'b, 'c, 'd, 'e> <F as AsyncFnMut<<(&'a SharedState, Params::Vx<'b>) as TuplePrepend<&'c SharedState, Params::Vx<'d>>>::Type>>::CallRefFuture<'e> : Send
Now the Box
in Box::new(async move { /* ... */ })
errors with
type annotations needed: cannot satisfy `<F as AsyncFnMut<<(&SharedState, Params::Vx<'b>) as TuplePrepend<&SharedState, ...>>::CallRefFuture<'e> : Send`
...multiple `impl`s or `where` clauses satisfying`for<'a, 'b, 'e> <F as AsyncFnMut<<(&'a SharedState, Params::Vx<'b>) as TuplePrepend<&'a SharedState, Params::Vx<'b>>>::Type>>::CallRefFuture<'e> : Send` found
I'm not sure how to get around this, or if I am overthinking it.
Any help would be appreciated. Thank you.