178

I've encountered a number of types in Rust denoted with a single apostrophe:

'static
'r
'a

What is the significance of that apostrophe (')? Maybe it's a modifier of references (&)? Generic typing specific to references? I've no idea where the documentation for this is hiding.

A. K.
  • 34,395
  • 15
  • 52
  • 89
Greg Malcolm
  • 3,238
  • 4
  • 23
  • 24

2 Answers2

138

These are Rust's named lifetimes.

Quoting from The Rust Programming Language:

Every reference in Rust has a lifetime, which is the scope for which that reference is valid. Most of the time lifetimes are implicit and inferred, just like most of the time types are inferred. Similarly to when we have to annotate types because multiple types are possible, there are cases where the lifetimes of references could be related in a few different ways, so Rust needs us to annotate the relationships using generic lifetime parameters so that it can make sure the actual references used at runtime will definitely be valid.

Lifetime annotations don’t change how long any of the references involved live. In the same way that functions can accept any type when the signature specifies a generic type parameter, functions can accept references with any lifetime when the signature specifies a generic lifetime parameter. What lifetime annotations do is relate the lifetimes of multiple references to each other.

Lifetime annotations have a slightly unusual syntax: the names of lifetime parameters must start with an apostrophe '. The names of lifetime parameters are usually all lowercase, and like generic types, their names are usually very short. 'a is the name most people use as a default. Lifetime parameter annotations go after the & of a reference, and a space separates the lifetime annotation from the reference’s type.

Said another way, a lifetime approximates the span of execution during which the data a reference points to is valid. The Rust compiler will conservatively infer the shortest lifetime possible to be safe. If you want to tell the compiler that a reference lives longer than the shortest estimate, you can name it, saying that the output reference, for example, has the same lifetime as a given input reference.

The 'static lifetime is a special lifetime, the longest lived of all lifetimes - for the duration of the program. A typical example are string "literals" that will always be available during the lifetime of the program/module.

You can get more information from this slide deck, starting around slide 29.

Lifetimes in Rust also discusses lifetimes in some depth.

LuxuryMode
  • 33,401
  • 34
  • 117
  • 188
quux00
  • 13,679
  • 10
  • 57
  • 69
55

To add to quux00's excellent answer, named lifetimes are also used to indicate the origin of a returned borrowed variable to the rust compiler.

This function

pub fn f(a: &str, b: &str) -> &str {
  b
}

won't compile because it returns a borrowed value but does not specify whether it borrowed it from a or b.

To fix that, you'd declare a named lifetime and use the same lifetime for b and the return type:

pub fn f<'r>(a: &str, b: &'r str) -> &'r str {
//      ----              ---         ---
  b
}

and use it as expected

f("a", "b")
Nino Filiu
  • 16,660
  • 11
  • 54
  • 84
  • 10
    "If you want to tell the compiler that a reference lives longer than the shortest estimate, you can name it, saying that the output reference, for example, has the same lifetime as a given input reference." For someone very new to Rust, I did need both answers to understand this. Theirs did not click without a code example, and I was stuck on why the compiler would have a problem with the code without their description. – Kevin Jan 25 '22 at 13:41
  • 3
    I think I understand everything in this example except `f<'r>`. Why does the function have a lifetime specification? The whole example would make sense to me without the `<'r>` after the function name; what does it add? – lmat - Reinstate Monica Feb 01 '22 at 14:22
  • If I understand it right, in rust you have to specify where your borrowed value comes from. In this example it passes the borrowing from b, but a is free when f ends, it's different from a being still borrowed. – Nino Filiu Feb 01 '22 at 17:06
  • 2
    Why can't the compiler infer that the variable b is to live longer automatically as it is b that is being returned? – Ren Nov 30 '22 at 13:52
  • 2
    @Ren it can infer that, but that would allowing for unspecified side effects with unforseen consequences and you would have to work through the code to figure out where you've allowed that side effect to happen. Example: you have an array of 100 on heap. You access 501st element. Array is nice so it grows to accomodate that. Now you have a side effect and the reason is hidden in code or data. – nurettin Dec 22 '22 at 10:54
  • Compiler cannot understand what to return by variable/parameter name? What's wrong with this language? – flm Jan 04 '23 at 15:15
  • @lmat-ReinstateMonica I was also confused by this, but I think I've figured it out (while reading a [proposal for C# lifetimes](https://github.com/dotnet/csharplang/blob/54d783292eb51f37ba5b70bade2239a46f7e2869/proposals/ref-lifetimes.md)). I don't think the resemblance to regular generic/template functions is a coincidence. I think lifetimes can't be the same across all call sites for a function, so multiple versions of the function are generated. Or something. I really haven't fully wrapped my head around lifetimes yet. It'll take a lot more time to properly sink in. – Clonkex Mar 15 '23 at 11:11
  • @Clonkex I do not think functions with lifetime specifiers are templates for which new functions are "instantiated". It's only to help the compiler enforce lifetimes at compiletime. – lmat - Reinstate Monica Mar 16 '23 at 12:57
  • @lmat-ReinstateMonica I think I'm right, though. I think they are actually generic parameters. As in, because the function can be called in many places, and the lifetimes could be different at each call site, the functions have to be generic/templated. Check out this question: https://stackoverflow.com/q/65349833/2288578 – Clonkex Mar 17 '23 at 20:51