Why does it work `ref1: &'a (&'b i32,)? Implicit lifetime annotation?

Why does it works?

struct X<'a, 'b> {
    ref1: &'a (&'b i32,),
}

My understanding it should have explicit promise that 'b lives at least as long as 'a:
'b : 'a.
Why compiler does not require it?

Playground

1 Like

This struct will actually get an implicit 'b: 'a bound. So the struct definition is equivalent to if you were to explicitly add that bound as in struct X<'a, 'b: 'a> {.

Those implicit bounds are unfortunately still very much undocumented in the generated rustdoc (even though IMO, it would be a good thing if they were shown there); so it's an implicit property of the struct, perhaps comparable to how implicit/undocumented the variance of a struct is.

6 Likes

You can observe the implications of this implicit lifetime bound e. g. in code like

fn f<'a, 'b>() {
    let _: &X<'a, 'b>;
}

which will fail to compile until you change it to

fn f<'a, 'b: 'a>() {
    let _: &X<'a, 'b>;
}
3 Likes

By the way, it has not always been this way, see

2093-infer-outlives - The Rust RFC Book

4 Likes

Remove the need for explicit T: 'x annotations on structs. We will infer their presence based on the fields of the struct. In short, if the struct contains a reference, directly or indirectly, to T with lifetime 'x, then we will infer that T: 'x is a requirement:

struct Foo<'x, T> {
  // inferred: `T: 'x`
  field: &'x T
}  

That from the RFC and your examples explains a lot. Thank you!

Do you know where exactly?

I meant that the generated Rustdoc should IMO probably present the thing as struct X<'a, 'b: 'a> again, even if the 'b: 'a was just inferred.

2 Likes

I see. So do i think.

Here