Lifetime of references captured by a struct

struct MyStruct<'a, 'b> {
    vec_a: &'a Vec<usize>,
    vec_b: &'b Vec<usize>,
}

Is there any reason to have two separate lifetimes, or should I do

struct MyStruct<'this> {
    vec_a: &'this Vec<usize>,
    vec_b: &'this Vec<usize>,
}

This compiles:

struct MyStruct<'a, 'b> {
    vec_a: &'a Vec<usize>,
    vec_b: &'b Vec<usize>,
}

fn main() {
    let vec_a = vec![1, 2, 3];
    let vec_ref;
    
    {
        let vec_b = vec![4, 5, 6];
        
        let my_struct = MyStruct {
            vec_a: &vec_a,
            vec_b: &vec_b,
        };
        
        vec_ref = my_struct.vec_a;
        
        // vec_b goes out of scope here
    }
    
    println!("{:?}", vec_ref);
}

playground

but if you change it to use the same lifetime, the vec_a reference's lifetime is shortened to be as short as the vec_b reference's lifetime, giving you this error:

error[E0597]: `vec_b` does not live long enough
  --> src/main.rs:15:20
   |
15 |             vec_b: &vec_b,
   |                    ^^^^^^ borrowed value does not live long enough
...
21 |     }
   |     - `vec_b` dropped here while still borrowed
22 |     
23 |     println!("{:?}", vec_ref);
   |                      ------- borrow later used here

If both vec_a and vec_b are private, and no reference will be taken to them in this module, then having separate lifetimes doesn't have any advantages, right?

Indeed, it's simpler to use one lifetime if you don't need to take the references back out of the struct later. Privacy isn't that important to the distinction though, because methods can also return such references.

Privacy isn't that important to the distinction though, because methods can also return such references.

Right

I guess that there is no way to elide the lifetime, like (this doesn't compiles)

struct MyStruct<'_> {
    vec_a: &Vec<usize>,
    vec_b: &Vec<usize>,
}

hence the various discussions around adding 'self, I guess!

You can never elide lifetimes in structs.

1 Like

I'd prefer '_ as you've written it to 'self, should elision within struct definitions become a thing. I feel 'self would deepen the already common misconceptions that the lifetime is a property carried around with the struct, and that self-referencial structs should trivially work.

2 Likes