Explicit annotation

The borrow checker uses explicit lifetime annotations to determine
how long references should be valid. In cases where lifetimes are not
elided[^1], Rust requires explicit annotations to determine what the
lifetime of a reference should be. The syntax for explicitly annotating
a lifetime uses an apostrophe character as follows:

  1. foo<'a>
  2. // `foo` has a lifetime parameter `'a`

Similar to closures, using lifetimes requires generics.
Additionally, this lifetime syntax indicates that the lifetime of foo
may not exceed that of 'a. Explicit annotation of a type has the form
&'a T where 'a has already been introduced.

In cases with multiple lifetimes, the syntax is similar:

  1. foo<'a, 'b>
  2. // `foo` has lifetime parameters `'a` and `'b`

In this case, the lifetime of foo cannot exceed that of either 'a or 'b.

See the following example for explicit lifetime annotation in use:

  1. // `print_refs` takes two references to `i32` which have different
  2. // lifetimes `'a` and `'b`. These two lifetimes must both be at
  3. // least as long as the function `print_refs`.
  4. fn print_refs<'a, 'b>(x: &'a i32, y: &'b i32) {
  5. println!("x is {} and y is {}", x, y);
  6. }
  7. // A function which takes no arguments, but has a lifetime parameter `'a`.
  8. fn failed_borrow<'a>() {
  9. let _x = 12;
  10. // ERROR: `_x` does not live long enough
  11. //let y: &'a i32 = &_x;
  12. // Attempting to use the lifetime `'a` as an explicit type annotation
  13. // inside the function will fail because the lifetime of `&_x` is shorter
  14. // than that of `y`. A short lifetime cannot be coerced into a longer one.
  15. }
  16. fn main() {
  17. // Create variables to be borrowed below.
  18. let (four, nine) = (4, 9);
  19. // Borrows (`&`) of both variables are passed into the function.
  20. print_refs(&four, &nine);
  21. // Any input which is borrowed must outlive the borrower.
  22. // In other words, the lifetime of `four` and `nine` must
  23. // be longer than that of `print_refs`.
  24. failed_borrow();
  25. // `failed_borrow` contains no references to force `'a` to be
  26. // longer than the lifetime of the function, but `'a` is longer.
  27. // Because the lifetime is never constrained, it defaults to `'static`.
  28. }

[^1]: elision implicitly annotates lifetimes and so is different.

See also:

generics and closures