# 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);
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://learning-rust.gitbook.io/book/the-tough-part/lifetimes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
