liveBook · Manning

Lifetime

As explained in Rust in Action: Systems programming concepts and techniques

A lifetime is the statically determined span during which a Rust value or reference remains valid.

A lifetime is the period during which accessing a value is valid. A local value may live until its function returns; a value passed to another function may stop being available to the caller sooner. Rust checks these limits at compile time. section 4.0 section 4.1.1

Scope and lifetime are not the same. A variable name can remain in scope after its value has moved elsewhere. In the satellite-status example, passing a CubeSat to check_status moves it into that function. A second attempt to pass the same value fails: the first call has already consumed it. section 4.1.1

error[E0382]: use of moved value: `sat_a`
  --> code/ch4-check-sats-2.rs:26:31
   |
 |   let a_status = check_status(sat_a);
   |                               ----- value moved here
...
 |   let a_status = check_status(sat_a);
   |                               ^^^^^ value used here after move
   |
   = note: move occurs because `sat_a` has type `CubeSat`,
   = which does not implement the `Copy` trait
 
...      #1
 
error: aborting due to 3 previous errors

The compiler points to both the call that moved sat_a and the later call that tries to use it again. section 4.1.1

References have lifetimes too. Rust usually infers them, so ordinary calls need no lifetime annotations. When a function takes multiple references or returns one, the compiler may need an explicit statement of how those lifetimes relate. An annotation expresses that relationship; it does not keep a value alive. section 2.8.1

Listing 2.13 A function signature with explicit lifetime annotations
 fn add_with_lifetimes<'a, 'b>(i: &'a i32, j: &'b i32) -> i32 {
   *i + *j
 }

The two parameters have separate lifetime names, 'a and 'b. The function reads both referenced integers and returns an integer, not a reference. section 2.8.1

If a lifetime-related error blocks a program, check whether a value was moved or is still borrowed. Shorter-lived values or a different ownership design may resolve the conflict. section 4.1.1 section 4.6

How Rust in Action: Systems programming concepts and techniques covers it

How deep it goes
Explains lifetime annotations and a worked move error, without detailing the compiler’s lifetime-inference rules.
Examples
Uses an annotated two-reference addition function and a satellite-status program that fails on reuse of a moved value.
What it assumes
Assumes familiarity with basic Rust function signatures while introducing lifetime-variable syntax for references.
What you can do after
Diagnose/debug with it by distinguishing a variable’s scope from the valid lifetime of its moved value.
How it connects
Connects lifetimes to ownership, borrowing, scope, references, and the borrow checker.

Also explained in

Compare how 8 books explain lifetime →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Rust in Action: Systems programming concepts and techniques. The section links point to the parts of the book it draws on.