error[E0562]: `impl Trait` is not allowed in the return type of `Fn` trait bounds
I want to express the fact the returned value of f depends on the lifetime 'a but I don't know who to write this with where close.
Something like this :
fn foo<N, FN, IN>(f: FN)
where
FN: for<'a> Fn(&'a N, &'a [u32]) -> (IN + 'a),
IN: Iterator<Item = N>,
{/* ... */}
Also, there should be a &self parameter for get_iter. Silly that I forgot that part.
I remember that AsyncFn acts somewhat different from Fn in regards to this exact sort of lifetime bound on its return type. There may be a way to abuse that trait to get roughly what you want.
There is no direct way to have such a "generic type constructor" or such...
// (How I think of your hypothetical snippet)
// vvvvv imaginary "generic type constructor" feature
fn foo<N, F, I<..>>(f: F)
where
F: for<'a> Fn(&'a N, &'a [u32]) -> I<'a, N, ..>,
for<'a> I<'a, N, ..>: Iterator<Item = N>,
// ("Normal" type generics like `N` or `IN` cannot contain any generic introduced
// later, such as the `'a` from the`for<'a>` binder.)
...where the return type varies based on the input lifetime to the function.
Building up your own effective trait alias is possible, but as the link shows, it tends to wreck inference,[1] and as it turns out that inference is critical for the "closure takes any lifetime in the inputs and returns something with that lifetime in the output" case.
If your return types are not nameable, like they involve closures or compiler generated futures, you may have to resort to type erasure (Box<dyn Iterator<Item = N> + 'a>), which is a constant thorn in the Rust async world.
If there's a limited number of patterns you have to support (a limited number of return type constructors), there may be other alternatives to make the ergonomic situation slightly better. Or perhaps taking another tact that doesn't involve closures and the Fn traits directly.
The closest thing I'm aware of to an actual solution on the horizon are TAIT and related features.TAIT (type Iter<'a> = impl ...) allows you to give a name to type constructors that may not otherwise be nameable. And impl Trait in bindings (as currently implemented) provides an alternative to the funnel trick.
Incidentally,
you probably meant + use<'a, N> not + 'a. Probably you don't care about the actual outlives bound of the iterator, which is what + 'a is about. (That said it may not make a big difference for this particular use case.)
more accurately it interferes with how closure bounds can override inference ↩︎