> For the complete documentation index, see [llms.txt](https://learning-rust.gitbook.io/book/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://learning-rust.gitbook.io/book/the-tough-part/lifetimes.md).

# Lifetimes

When we are dealing with references, we have to make sure that the referencing data stay alive until we are stop using the references.

Think,

* We have a variable binding, “**a**”.
* We are referencing the value of “a”, from another variable binding “**x**”.

  We have to make sure that “a” **lives** until we stop using “x”

> 🔎 **Memory management** is a form of resource management applied to computer memory. Up until the mid-1990s, the majority of programming languages used **Manual Memory Management** which **requires the programmer to give manual instructions** to identify and deallocate unused objects/ garbage. Around 1959 John McCarthy invented **Garbage collection**(GC), a form of **Automatic Memory Management**(AMM). It determines what memory is no longer used and frees it automatically instead of relying on the programmer. However **Objective-C and Swift** provide similar functionality through **Automatic Reference Counting**(ARC).

## What is Lifetimes?

In Rust,

* A resource can only have **one owner** at a time. When it goes **out of the scope**, Rust removes it from the Memory.
* When we want to reuse the same resource, we are **referencing** it/ **borrowing** its content.
* When dealing with **references**, we have to specify **lifetime annotations** to provide instructions for the **compiler** to set **how long** those referenced resources **should be alive**.
* ⭐ ️But because of lifetime annotations make **code more verbose**, in order to make **common patterns** more ergonomic, Rust allows lifetimes to be **elided/omitted** in `fn` definitions. In this case, the compiler assigns lifetime annotations **implicitly**.

Lifetime annotations are **checked at compile-time**. Compiler checks when a data is used for the first and the last times. According to that, Rust manages memory in **run time**. This is the major reason of having **slower compilation times** in Rust.

> * Unlike C and C++, **usually** Rust doesn’t explicitly drop values at all.
> * Unlike GC, Rust doesn’t place deallocation calls where the data is no longer referenced.
> * Rust places deallocation calls where the data is about to go out of the scope and then enforces that no references to that resource exist after that point.

## Usage

Lifetimes are denoted with an apostrophe. By convention, a lowercase letter is used for naming. Usually **starts with** `'a` and **follows alphabetic order** when we need to add **multiple lifetime** annotations.

When using references,

### 01. On Function Declaration

* Input and output parameters with references should attach lifetimes after `&` sign. ex `..(x: &'a str)` , `..(x: &'a mut str)`
* After the function name, we should mention that the given lifetimes are generic types. ex `fn foo<'a>(..)` , `fn foo<'a, 'b>(..)`

```rust
// no inputs, return a reference
fn function<'a>() -> &'a str {}

// single input
fn function<'a>(x: &'a str) {}

// single input and output, both has same lifetime
// output should live at least as long as input exists
fn function<'a>(x: &'a str) -> &'a str {}

// multiple inputs, only one input and the output share same lifetime
// output should live at least as long as y exists
fn function<'a>(x: i32, y: &'a str) -> &'a str {}

// multiple inputs. both inputs and the output share same lifetime
// output should live at least as long as x and y exist
fn function<'a>(x: &'a str, y: &'a str) -> &'a str {}

// multiple inputs. inputs can have diffent lifetimes 🔎
// output should live at least as long as x exists
fn function<'a, 'b>(x: &'a str, y: &'b str) -> &'a str {}
```

### 02. On Struct or Enum Declaration

* Elements with references should attach lifetimes after `&` sign.
* After the name of the struct or enum, we should mention that the given lifetimes are generic types.

```rust
// single element
// data of x should live at least as long as Struct exists
struct Struct<'a> {
    x: &'a str
}

// multiple elements
// data of x and y should live at least as long as Struct exists
struct Struct<'a> {
    x: &'a str,
    y: &'a str
}


// variant with single element
// data of the variant should live at least as long as Enum exists
enum Enum<'a> {
    Variant(&'a Type)
}
```

### 03. With Impls and Traits

```rust
struct Struct<'a> {
    x: &'a str
}
    impl<'a> Struct<'a> {
        fn function<'a>(&self) -> &'a str {
            self.x
        }
    }


struct Struct<'a> {
    x: &'a str,
    y: &'a str
}
    impl<'a> Struct<'a> {
        fn new(x: &'a str, y: &'a str) -> Struct<'a> { //no need to specify <'a> after new; impl already has it
          Struct {
              x : x,
              y : y
          }
        }
    }


// 🔎
impl<'a> Trait<'a> for Type
impl<'a> Trait for Type<'a>
```

### 04. With Generic Types

```rust
// 🔎
fn function<F>(f: F) where for<'a> F: FnOnce(&'a Type)
struct Struct<F> where for<'a> F: FnOnce(&'a Type) { x: F }
enum Enum<F> where for<'a> F: FnOnce(&'a Type) { Variant(F) }
impl<F> Struct<F> where for<'a> F: FnOnce(&'a Type) { fn x(&self) -> &F { &self.x } }
```

## Lifetime Elision

As I mentioned earlier, in order to make **common patterns** more ergonomic, Rust allows lifetimes to be **elided/omitted**. This process is called **Lifetime Elision**.

💡 For the moment Rust supports Lifetime Elisions only on `fn` definitions. But in the future it will support for `impl` headers as well.

Lifetime annotations of `fn` definitions can be elided\
if its **parameter list** has either,

* **only one input parameter passes by reference**.
* a parameter with **either** `&self` **or** **\&mut self** reference.

```rust
fn triple(x: &u64) -> u64 { //only one input parameter passes by reference
    x * 3
}


fn filter(x: u8, y: &str) -> &str { // only one input parameter passes by reference
    if x > 5 { y } else { "invalid inputs" }
}


struct Player<'a> {
    id: u8,
    name: &'a str
}
    impl<'a> Player<'a> { //so far Lifetime Elisions are allowed only on fn definitions; but in the future they might support on impl headers as well.
        fn new(id: u8, name: &str) -> Player { //only one input parameter passes by reference
            Player {
                id : id,
                name : name
            }
        }

        fn heading_text(&self) -> String { // a fn definition with &self (or &mut self) reference
            format!("{}: {}", self.id, self.name)
        }
    }

fn main() {
    let player1 = Player::new(1, "Serena Williams");
    let player1_heading_text = player1.heading_text()
    println!("{}", player1_heading_text);
}
```

> 💡 In the Lifetime Elision process of fn definitions,
>
> * Each parameter passes by reference is got a distinct lifetime annotation.
>
>   &#x20; ex. `..(x: &str, y: &str)` → `..<'a, 'b>(x: &'a str, y: &'b str)`
> * If the parameter list has only one parameter passes by reference, that lifetime is assigned to all elided lifetimes in the return values of that function.
>
>   &#x20; ex. `..(x: i32, y: &str) -> &str` → `..<'a>(x: i32, y: &'a str) -> &'a str`
> * Even it has multiple parameters pass by reference, if one of them has \&self or \&mut self, the lifetime of self is assigned to all elided output lifetimes.
>
>   &#x20; ex. `impl Impl{ fn function(&self, x: &str) -> &str {} }` →
>
>   &#x20; `impl<'a> Impl<'a>{ fn function(&'a self, x: &'b str) -> &'a str {} }`
> * For all other cases, we have to write lifetime annotations manually.

## `'static` Annotations

`'static` lifetime annotation is a **reserved** lifetime annotation. These **references are valid for the entire program**. They are saved in the data segment of the binary and the data referred to will never go out of scope.

```rust
static N: i32 = 5; //A constant with 'static lifetime

let a = "Hello, world."; //a: &'static str


fn index() -> &'static str { //No need to mention <'static> ; fn index ̶<̶'̶s̶t̶a̶t̶i̶c̶>̶ 
    "Hello, world!"
}
```

## Few more examples about usage of Rust lifetimes.

```rust
fn greeting<'a>() -> &'a str {
  "Hi!"
}


fn fullname<'a>(fname: &'a str, lname: &'a str) -> String {
  format!("{} {}", fname, lname)
}


struct Person<'a> {
    fname: &'a str,
    lname: &'a str
}
  impl<'a> Person<'a> {
      fn new(fname: &'a str, lname: &'a str) -> Person<'a> { //no need to specify <'a> after new; impl already has it
          Person {
              fname : fname,
              lname : lname
          }
      }

      fn fullname(&self) -> String {
          format!("{} {}", self.fname , self.lname)
      }
  }

fn main() {
    let player = Person::new("Serena", "Williams");
    let player_fullname = player.fullname();

    println!("Player: {}", player_fullname);
}
```
