Expected lifetime parameter

This is a followup / attempted simplification of How do I get this to compile? - #2 by krdln

How do I get the following to compile ?

I feel that I am moving the vec passed by value into the Closure, and thus expect all to work.


pub fn vec_to_func<T>(
    v: Vec<T>)
    -> Box< Fn(usize) -> &T >
{
    let g = move |i: usize| -> &T {
        v[i]
    };

    Box::new(g)
}

gives error:

error[E0106]: missing lifetime specifier
  --> crates/z_zutil/src/dag/vec2_to_func.rs:11:26
   |
11 |     -> Box< Fn(usize) -> &T >
   |                          ^ expected lifetime parameter
   |
   = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
   = help: consider giving it an explicit bounded or 'static lifetime

This is an interesting case! The only lifetime that could make sense is that of the &self, since you would be borrowing from the closure.

pub trait Fn<Args>: FnMut<Args> {
    extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}

But note here that the associated type Self::Output can't be tied to &self at all. This is somewhat like the restriction that Iterator::Item can't be tied to the lifetime of the next(&mut self) call. Maybe someday generic associated types will help with this general problem, although I don't think Fn would change.

If we tried to allow this, one thing that would break is that Fn implements FnOnce too, as they are defined Fn: FnMut and FnMut: FnOnce. So if someone called your closure in an FnOnce setting, the returned reference would be dangling!

2 Likes