How to set a appropriate life time?


#1

I’m struggling with a lifetime problem recently. There goes the problem:

I have a struct A and struct B in some library, and an A object contains a reference to a B object like this:

#[derive(Debug)]
struct B {}

#[derive(Debug)]
struct A<'a> {
    b: &'a B
}

And the library provides a function that receives a lambda invoked with a reference to some A object constructed within the function scope:


fn lib_func<F: 'static + Sized + Fn(&A)>(f: F) {
    let b = B {};
    let a = A { b: &b };
    f(&a);
}

Based on that function, I make a new function which receives a user-provided lambda which returns a new A object referring the same B object with the input A reference, like Fn(&A<'a>) -> A<'a>. My function looks like:

fn test<'a, F>(f: F)
  where F: 'static + Fn(&A<'a>) -> A<'a>
{
    lib_func(|a| {
        let x = f(a);    
        println!("lib_func give a ref, user func produce: {:?}", x);
    });
}

fn main() {
    test(|a| A {b: a.b});
}

But I got E0308 when compiling saying that the lifetime defined in lambda of test's body doesn’t outlive lifetime 'a.

Execution
Share
Close
Standard Error
   Compiling playground v0.0.1 (file:///playground)
error[E0308]: mismatched types
  --> src/main.rs:19:19
   |
19 |         let x = f(a);    
   |                   ^ lifetime mismatch
   |
   = note: expected type `&A<'a>`
              found type `&A<'_>`
note: the anonymous lifetime #3 defined on the body at 18:14...
  --> src/main.rs:18:14
   |
18 |       lib_func(|a| {
   |  ______________^
19 | |         let x = f(a);    
20 | |         println!("Get result: {:?}", x);
21 | |     });
   | |_____^
note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 15:1
  --> src/main.rs:15:1
   |
15 | / fn test<'a, F>(f: F)
16 | |   where F: 'static + Fn(&A<'a>) -> A<'a>,
17 | | {
18 | |     lib_func(|a| {
...  |
21 | |     });
22 | | }
   | |_^

I’m confused about this. I specify the lifetime 'a to input and output of the user-provided lambda is just to limit them to reference the same B object. And expecting the returned A object only live within the lambda scope, why does the compiler required the lambda lifetime scope outlive 'a ??

Full code can be found here: https://play.rust-lang.org/?gist=8c322b9969b0535c5a1872099f7591d4&version=stable&mode=debug

Thanks in advance.


#3

You need an HRTB bound on F in test(): play