> For the complete documentation index, see [llms.txt](https://thomasbui.gitbook.io/blog/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://thomasbui.gitbook.io/blog/software-engineering/rust-101/smart-pointer/deref-coercion.md).

# Deref Coercion

## What is **`Deref`** Coercion?

{% hint style="success" %}
💡 The `Deref` trait enables "**`Deref` coercion**," which allows the compiler to automatically perform implicit dereferencing when calling functions or methods by converting the references of custom types to references of their inner types.
{% endhint %}

This is how `Deref` coercion works behind the scenes:

1. The compiler will check if the argument type implements `Deref` .
2. If it does, and the dereferenced type matches the expected type in the function signature, the compiler will automatically inserts calls to the `deref` method as needed.

## When the `Deref` Coercion is applied?

Rust performs **`Deref` coercion** in **three** specific cases:

<table><thead><tr><th width="265">Cases</th><th>How it works?</th></tr></thead><tbody><tr><td><strong>From <code>&#x26;T</code> to <code>&#x26;U</code> when <code>T</code>: <code>Deref&#x3C;Target=U></code></strong></td><td><p></p><ul><li>This happens when you pass a reference to a type <code>T</code> (e.g., <code>&#x26;String</code>) to a function or method that expects a reference to a different type <code>U</code> (e.g., <code>&#x26;str</code>).</li><li>As long as <code>T</code> implements <code>Deref&#x3C;Target=U></code>, the compiler will automatically dereference the <code>&#x26;T</code> reference to get a reference to the underlying <code>U</code> value.</li><li>This allows you to use types like <code>String</code> interchangeably with <code>&#x26;str</code> in many situations because <code>String</code> implements <code>Deref&#x3C;Target=str></code>.</li></ul></td></tr><tr><td><strong>From <code>&#x26;mut T</code> to <code>&#x26;mut U</code> when <code>T</code>: <code>DerefMut&#x3C;Target=U></code></strong></td><td><p></p><ul><li>This case is similar to the first one, but it applies to mutable references (<code>&#x26;mut T</code>).</li><li><strong><code>Deref</code></strong> <strong>coercion</strong> occurs when you pass a mutable reference to a type <code>T</code> to a function or method that expects a mutable reference to a different type <code>U</code>.</li><li>As long as <code>T</code> implements <code>DerefMut&#x3C;Target=U></code>, the compiler will dereference the <code>&#x26;mut T</code> to provide a mutable reference to the underlying <code>U</code> value.</li><li>This allows you to use types like <code>Box&#x3C;T></code> (heap-allocated box) interchangeably with <code>&#x26;mut T</code> in some contexts when necessary (assuming <code>Box&#x3C;T></code> implements <code>DerefMut&#x3C;Target=T></code>).</li></ul></td></tr><tr><td><strong>From <code>&#x26;mut T</code> to <code>&#x26;U</code> when <code>T</code>: <code>Deref&#x3C;Target=U></code></strong></td><td><p></p><ul><li>This case is less common, but it's still valid.</li><li>It allows dereferencing a mutable reference to a type <code>T</code> to get an immutable reference to a type <code>U</code>.</li><li>Similar to the first case, the condition is that <code>T</code> implements <code>Deref&#x3C;Target=U></code>. This can be useful in specific scenarios where you might need a temporary immutable reference from a mutable reference.</li></ul></td></tr></tbody></table>

## `Deref` with Function & Method Calls

Using the [previous example of our custom smart pointer](/blog/software-engineering/rust-101/smart-pointer/deref-trait.md#using-deref-with-custom-smart-pointer). To demonstrate how the **`Deref` coercion** works, we add a new function `say_hi` which receives a `&str` reference.

```rust
use std::ops::Deref;

#[derive(Debug)]
struct MySmartPointer<T>(T);

impl<T> MySmartPointer<T> {
    fn new(x: T) -> MySmartPointer<T> {
        MySmartPointer(x)
    }
}

impl<T> Deref for MySmartPointer<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

fn say_hi(name: &str) {
    println!("Hi, {name}!")
}

fn main() {
    let name = MySmartPointer::new(String::from("Thomas"));

    println!("name = {:?}", name); // Outputs: name = MySmartPointer(5)
    println!("name = {}", *name); // Outputs: name = 5

    say_hi(&name); // Outputs: Hi, Thomas!
}

```

In this code, the **`Deref` coercion** happens in the `say_hi` function.

The `say_hi` function expects a `&str` reference. But we passed `&name`, which is a reference to a `MySmartPointer<String>`.

**`Deref` coercion** comes into play again:

* The compiler sees the argument type `&MySmartPointer<String>` and the expected type `&str`.
* `MySmartPointer<String>` implements `Deref<Target=String>`, but `say_hi` needs `&str`
* Behind the scenes, the compiler performs a double dereference.
* First, it dereferences `&name` to get a reference `&String` from inner `&MySmartPointer<String>`.
* Then, because `String` implements `Deref<Target=str>`, it automatically dereferences again to the `&String` to get the underlying string slice (`&str`) that `say_hi` can use.
* Finally, the `say_hi` function will get the correct string format and print `Hi, Thomas!`.

## `DerefMut` for Mutable Dereferencing

Rust also provides the `DerefMut` trait for mutable dereferencing.

Let’s dive a bit inside the `Deref` implementation

```rust
pub trait DerefMut: Deref<Target = Self::Target> {
  fn deref_mut(&mut self) -> &mut Self::Target;
}
```

`DerefMut` trait inherits from the `Deref` trait, it means it requires everything from `Deref` and adds its own method.

The different here is the `DerefMut` has a required method which is called `deref_mut`. This method takes `&mut self` (a mutable reference to the implementing type) as an argument and returns a mutable reference (`&mut`) to the associated type `Target`.

As the [previous example](/blog/software-engineering/rust-101/smart-pointer/deref-coercion.md#deref-with-function-and-method-calls), we have the `MySmartPointer` smart pointer with implemented `Deref` trait. In this updates, we will implement the `DerefMut` trait for `MySmartPointer` to demonstrate how we can dereference a mutable reference and mutate the data.

```rust
use std::ops::{Deref, DerefMut};

#[derive(Debug)]
struct MySmartPointer<T>(T);

impl<T> MySmartPointer<T> {
    fn new(x: T) -> MySmartPointer<T> {
        MySmartPointer(x)
    }
}

impl<T> Deref for MySmartPointer<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

impl<T> DerefMut for MySmartPointer<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

fn say_hi(name: &str) {
    println!("Hi, {name}!")
}

fn main() {
    let mut name = MySmartPointer::new(String::from("Thomas"));
    *name = String::from("Ashley"); // DerefMut happens here

    say_hi(&name); // Outputs: Hi, Ashley!
}
```

To allow dereference mutable reference for our smart pointer, we’re going to implement `DerefMut` trait for `MySmartPointer`. The `deref_mut` method returns a mutable reference (`&mut`) to the inner value (`&self.0` - the `.0` accesses the first value in a tuple struct). This allows dereferencing and mutating to the underlying data.

In the main function, we created a new mutable `MySmartPointer` with the string “**Thomas**”.

The **`DerefMut` coercion** happens in the **`name = String::from("Ashley")`** line.

* We’re assigning a new `String` ("**Ashley**") to the dereferenced value of `name`.
* **`Deref` coercion** happens because `MySmartPointer` implements `DerefMut<Target=String>`.
* The compiler automatically dereferences `name` (which is a `&mut MySmartPointer<String>`) using `deref_mut` to get a mutable reference (`&mut String`) to the inner value, and then modifies the inner string through assignment `*name`.
* Finally, the `say_hi` function will print `Hi, Ashley!`.
