Understanding rust lifetimes in structures

I ran the following example (which is expected not to compile):

struct S<'a> {
   x : &'a i32,
   y: &'a i32
}

fn main() {
   let x = 10;
   let r;
   {
      let y = 20;
      {
          let s = S { x: &x, y: &y};
          r = s.x;
       }
   }
   println!("{}",r);
}

The error message from rust playground doesn't make sense to me.

   Compiling playground v0.0.1 (/playground)
error[E0597]: `y` does not live long enough
  --> src/main.rs:12:34
   |
12 |            let s = S { x: &x, y: &y};
   |                                  ^^ borrowed value does not live long enough
...
15 |    }
   |    - `y` dropped here while still borrowed
16 |    println!("{}",r);
   |                  - borrow later used here

error: aborting due to previous error

For more information about this error, try `rustc --explain E0597`.
error: could not compile `playground`.

To learn more, run the command again with --verbose.

Am confused why it's complaining about "y".

Since the struct S<'a> have single lifetime parameter, both of its fields have same lifetime. It means that every places the s.x is usable, the s.y should also be usable too.

@Hyeonu Got it. Thank you!

Why doesn’t it complain about s not living long enough? It’s declared in the innermost scope, but the value of r is printed in the outermost scope.

The use of r in the println requires the 'a lifetime on s to extend at least that far. This puts a requirement that both x and y are alive at that println, hence the error.

On the other hand, the requirement it puts on s is different: it says that s must not exist outside the lifetime, but this is not violated as s is destroyed in the innermost scope, which is before the println and thus s is contained in the lifetime.

Lifetime parameters on a struct are not the lifetime of the struct. They are upper bounds on the struct.

1 Like

If the println! is removed this code compiles with no errors.
Does the compiler figures out that 'r' is not used, so the lifetime 'a doesn't have to cover 'r' ?

This is a feature of the new borrow checker, sometimes called Non-Lexical Lifetimes. Without the println! at the end, NLL will drop r after its last use, which is the assignment in the inner-most scope.

Yes, only actual uses of a variable are relevant for lifetime analysis.

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.