Lifetimes

In Rust, lifetimes are the mechanism by which the Rust compiler can reason about the logic of the scope of variables in your program. Lifetimes are denoted by a single quote followed by an identifier, which is typically one letter - for example. Lifetimes behave similarly to types, but come with a few important differences:


 * Lifetimes are always anonymous. This means that they can be referred to only from generic lifetime parameters - there's no such thing as a concrete lifetime.
 * Lifetimes can often be elided - most of the time  can be replaced with   or even just  . Type parameters on the other hand must always be specified.
 * Lifetimes do not have any direct correspondance with a the resulting binary of the program like types do - they exist only in the compiler. As a result, lifetime parameters do not cause functions to be monomorphized, and they can be used in trait objects.

The static lifetime
The is one special lifetime in Rust that is different from all the rest - the  lifetime. While other lifetimes represent short-lived values on the stack, the  lifetime represents a value that exists for the entirety of the duration of the program.

All lifetimed static and const varibles use the static lifetime - in fact, you can omit  since it is inferred anyway.

Lifetime Elision
Writing out lifetimes is a pain. In the example above, we had to manually specify the lifetime of the references - this just adds boilerplate and is annoying to have to type out. Luckily, in a few specific cases the compiler can help us. If there is one elided lifetime in the parameters of a function or there is a  parameter with an elided lifetime (such as   or , then all elided lifetimes in the return type of that function will be that lifetime.

There are two levels of lifetime elision: anonymous lifetimes and implicit lifetimes. Anonymous lifetimes look like this:  and can be used in the place of regular lifetimes:. Sometimes, you can omit the lifetime entirely, and then it is implicit:.

The automatic lifetime elision resolver covers 99% of cases. If you are writing something so complex that it doesn't get accepted, it is probably better to be explicit about the lifetimes anyway.


 * See the Lifetime elision RFC for more details on lifetime elision.
 * Read Validating References with Lifetimes in "The Rust Programming Language" for more information on lifetimes.

Higher Ranked Trait Bounds
In very specific scenarios, a concrete lifetime will not be known to a function until runtime. In which case, a function must work for every possible lifetime without regard to whether it is short or long. This might be caused by running a closure in multiple places, or writing a function that takes a reference to an object that hasn't been created yet. Consider the example code:

is created at the beginning of  and dropped at the end. That means that  is not allowed to return a reference to , otherwise there would be a reference to a dropped struct. Another way of thinking about this would be to say that  has to be valid for every lifetime, even for lifetimes that are too short to be in scope yet. Luckily, Rust catches that the second example is not allowed, and gives a lifetime error. However, the waters can be muddied by the addition of other references. In the following example, lifetime annotations are required:

Rust needs help to know that the arguments to  have different lifetimes: a short lifetime called   and a long lifetime called. It's okay to return  because that references , and   is dropped at the end of. However it's not okay to return  because that references   and   is dropped at the end of.

The  in the code above tells rust that   is valid for any lifetime wherever   is used. The  tells Rust that   is only valid for an existing lifetime   that is still valid after   returns.