Lifetimes in Rust explained

Francesco Ciulla - Jul 23 - - Dev Community

I want to discuss a fundamental concept you must grasp to master the Rust programming language: “Lifetimes.”

Usually, when we learn about a programming language, we reference other languages, like “it works like in JavaScript,” “it’s similar to Python,” and so on.

We can’t make this analogy in this case because “Lifetimes” are peculiar to the Rust programming language.

Lifetimes in Rust ensure that references are valid as long as they are used, preventing common bugs like dangling pointers and use-after-free errors.

This article explores lifetimes, their significance, and how to work with them through examples.

If you prefer a video version

So what are lifetimes?

In short, Lifetimes are a form of generic parameter that describes the scope for which a reference is valid. The Rust compiler uses lifetimes to check that references do not outlive the data they point to, ensuring memory safety.

In Rust, every reference has a lifetime (even though you don't always see it in the code). The compiler infers lifetimes in many cases, but sometimes you need to specify them explicitly, especially in function signatures and struct definitions.

Basic Example:

Let’s see a basic example

Lifetimes in Rust

In this example, x is created inside an inner scope and is destroyed at the end of that scope.

The reference r points to x, but r is used outside the scope where x was valid. Rust's borrow checker will produce a compile-time error to prevent this situation.

Explicit Lifetimes in Function Signatures

Sometimes, you need to write functions that accept references and return references. To ensure the references are valid, you must specify the lifetimes explicitly.

Consider this function that returns the longer of two string slice:

Lifetimes in Rust

In the function longest, we declare a lifetime parameter 'a and use it to indicate that the references s1 and s2 must be valid for at least as long as the returned reference.

This ensures the returned reference does not outlive the data it points to.

Lifetimes in Structs

Lifetimes are also used in structs to ensure that references held by the struct do not outlive the struct itself.

Let’s see an example:

Lifetimes in Rust

In this example, the ImportantExcerpt struct references a part of a string. The lifetime 'a ensures that the reference part cannot outlive the ImportantExcerpt instance, thereby preventing invalid references.

Conclusion

Lifetimes in Rust are a powerful feature that guarantees memory safety by ensuring references are valid for as long as they are used.

While the compiler often infers lifetimes, understanding and specifying them explicitly when needed is important for writing robust Rust programs.

With these examples and explanations, you should have a good foundation to explore more complex scenarios involving lifetimes in Rust.

If you prefer a video version

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .