I have the following type
struct Test<Args> {
// ...
phantom: PhantomData<Args>,
}
that needs to store, alongside it's contents, a type parameter for determining arguments to a function to be passed on later.
I use it as follows:
#![feature(unboxed_closures, fn_traits)]
impl<Args> Test<Args> {
fn update<F>(&mut self, args: Args, f: F)
where
F: FnOnce<Args>
{
//...
let value = f.call_once(args);
// ...
}
}
Unfortunately I cannot use it for borrowed values. I would need to be able to do something like
type MyTest = Test<for<'a> (&'a u32, &'a u32)>;
let mut t: MyTest = ...;
t.update((&5, &8), |lhs, rhs| lhs + rhs);
But Test<for<'a> (&'a u32, &'a u32)> is not valid syntax.
My workaround currently is to modify Test to instead take in an fn type and then restrict it alongside another type at the call site as follows:
#![feature(unboxed_closures, fn_traits)]
struct Test<F> {
// ...
phantom: PhantomData<F>,
}
impl<F> Test<F> {
fn update<Args, F2>(&mut self, args: Args, f: F2)
where
F: FnOnce<Args>,
F2: FnOnce<Args>,
{
//...
let value = f.call_once(args);
// ...
}
}
type MyTest = Test<for<'a> fn(&'a u32, &'a u32)>;
let mut t: MyTest = ...;
t.update((&5, &8), |lhs, rhs| lhs + rhs);
But this is relatively ugly and requires changing the public interface. I'm also not sure if there's any issues with fn being contra-variant in it's arguments.
Is there any better way to achieve this while keeping the original signature (or close to it)?
I don't want to use the call-site F itself in the type generics, as I need it to be generic in the method and not the type, as it can be a closure with borrowed values while the type may be static.