Lifetimes in Rust
Tags: rust, coding, programming
Published: 2018-01-28 15:31:44

---
title: Lifetimes in Rust
published: true
description: In this post we'll briefly go over lifetimes, a concept in rust
tags: #rust #coding #programming
---
# Introduction
Rust is a system programming language which guarantees memory safety and prevents problems associated with it like data races between threads, memory leaks and dangling pointers by taking radically new approach to memory management. In this article I'd like to discuss about one such approach which they call Lifetimes.

## Brief intro to borrowing and ownership
Borrowing, ownership and lifetimes, all three of them are concepts in Rust which complement each other and provide memory guarantees at runtime. To keep our focus on Lifetimes we'll briefly see what others are.
#### Borrowing
Example: `let x = &y`
Here `x` references `y` and is "almost" similar in functionality to C/C++ references. 
#### Ownership
Rust doesn't have a garbage collector, so it follows a simple rule to clear out allocated memory.
```rust
fn foo() {
    let v = [1, 2, 3];
}
```
When `v` goes out of scope it's memory will be cleared, even if it is dynamically allocated.

# So what is Lifetime ?
In layman terms lifetime of a thing is "the length of time that thing is usable" and it means almost the same in Rust, the "thing" here being "variables".

Take a look at this code, and errors generated by compiler in the comments:
```rust
fn main() {
    let r;              
    {
        let i = 1;      
        r = &i;         // borrow occurs here
    }                   // `i` dropped here while still borrowed

    println!("{}", r);
}    // borrowed value needs to live until here

```
What happens here is:
1. We declare a variable `r`
2. We go inside a scope <br/>
    2.1. We initialize a variable `i` <br/><br/>
    2.2. Assign a reference of `i` to `r`
3. Go out of scope
4. Use `r`

At step 3, what happened was that memory for `i` was freed and `r` referred to a junk memory location.

The compiler gave us a sweet error message after step 4 saving us from a runtime disaster which C/C++ would have given us.


# Okay, but why care ?
Let's see another example:
```rust
struct Car {
    model: &str
}
```
You create a struct, and happily click that compile button, but...
```
error[E0106]: missing lifetime specifier

model: &str
        ^ expected lifetime parameter
```
you get this message. You're scratching your head and thinking, "I didn't do anything wrong".

Well, by compiler logic the reference `model` will be destroyed as soon as the struct scope finishes. So how do you fix it:

```rust
struct Car<'a> {
    model: &'a str
}
```
Notice the `'a`, we have explicitly assigned a name to variable's lifetime, then in the statement `model: &'a str` we tell the compiler to keep the reference around for as long as we have the variable of type `Car`.

Point to take note is that, lifetimes are always there but most of the times they are implied automatically by the compiler so you don't have to explicitly assign them each time you borrow a reference.

# Leveling up
We'll look at another code:
```rust
struct Person<'a> {
    name: &'a str,
    do_task: &'a Fn(&str)
}
```
Here `do_task` is a reference to a function and it borrows a string reference, "but... we didn't define `&'a str`". `&str` means it is tied to the scope of function, hence the string reference will be cleared when the function completes.

While `do_task` and `name` are tied to the scope of variable which is of `Person` type.

Lifetimes is a new and interesting concept, but can be hard to understand the first time. Other resources you can look at are:
* [Rust by example: Lifetimes](https://rustbyexample.com/scope/lifetime.html)
* [Rust Documentation: Lifetimes](https://doc.rust-lang.org/1.9.0/book/lifetimes.html)

Happy coding!!