Closure inference fail

Given this

struct Closure<F> 
where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8 + 'static,
{
    data: (u8, u16),
    func: F,
}

fn do_it<'a>(data: &'a (u8, u16)) -> &'a u8 { &data.0 }

Function pointer to a lifetime annotated function works fine

    let data = (0, 1);
    let func: do_it;
    let clo = Closure { data, func };

Annotated boxed closure also works

    let func: Box<dyn for<'a> Fn(&'a (u8, u16)) -> &'a u8 + 'static> = Box::new(|data: &(u8, u16)| -> &u8 { &data.0 });

But an unannotated naked closure does not work

    let func = |data: &(u8, u16)| -> &u8 { &data.0 };
error: lifetime may not live long enough
  --> src/main.rs:83:44
   |
83 |     let func = |data: &(u8, u16)| -> &u8 { &data.0 };
   |                       -              -     ^^^^^^^ returning this value requires that `'1` must outlive `'2`
   |                       |              |
   |                       |              let's call the lifetime of this reference `'2`
   |                       let's call the lifetime of this reference `'1`

It expected the return type of the closure to be &'a u8 to be moved into Closure but it instead found &u8, so some other anonymous references &'_ u8. I suspect I need to figure out how to type annotate let func in the case of an unboxed closure to specify the same lifetimes that I made in the boxed version?

[EDIT] I think I need this Allow using `for<'a>` syntax when declaring closures by Aaron1011 · Pull Request #3216 · rust-lang/rfcs · GitHub

I have tried to annotate a function that is used on the closure to see if that activates inference but does not work.

    let func = |data: &(u8, u16)| -> &u8 { &data.0 };
    let clo = Closure { data, func };
    clo.call();

    fn call<'a>(&'a self) -> &'a u8 where F: Fn(&'a (u8, u16)) -> &'a u8 {
        (self.func)(&self.data)
    }

Only works with explicitly typed variable. I only know how to make a boxed closure explicitly typed on a variable, not an unboxed one. Inference just isn't working for the let binding case. I have to bind it to a struct field or a function call param directly.

    let clo = Closure { data, func: |data: &(u8, u16)| -> &u8 { &data.0 } };
    struct Closure<F> 
    where 
       for<'a> F: Fn(&'a (u8, u16)) -> &'a u8 + 'static,
{
    data: (u8, u16),
    func: F,
}

Is there no way to annotate an unboxed closure on a variable?

    #![feature(closure_lifetime_binder)]

    let func = for<'a> |data: &'a (u8, u16)| -> &'a u8 { &data.0 };

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.