# Understanding &mut &mut Reference

&mut? &mut &mut?? &mut &mut &mut??? &mut &mut &mut &mut...

## Problem Statement

I followed a Solana tutorial and had some trouble understanding the following code:

``greeting_account.serialize(&mut &mut account.data.borrow_mut()[..])?;``

where `greeting_account` is a struct and `.serialize()` is a method derived from BorshSerialize.

One other thing to note is that `account` is an AccountInfo struct from the solana_program crate and `data` has to type: `Rc<RefCell<&'a mut [u8]>>`

The magic with double `&mut` and `[..]` make me, a Rust newbie, really feel scared.

This problem has troubled me for a long time, making me care neither for food nor drink, and now I want to beat fear and try to understand this sentence.

## Resolution

First of all, let me google it, and fortunately, I found the most relevant answer just on the top of the result: Trouble understanding &mut &mut reference.

Let me split the problem into the following:

1. Why should we add `[..]`?

2. Why double `&mut`?

The code in the tutorial is very long and deep, if you don't want to clone the code, the following code (which has the same effect as the code in the tutorial I think...) is simplified for you to understand:

``````use borsh::maybestd::io::Write; // Simply add 'borsh = "0.9.1"' to Cargo.toml
use std::cell::RefCell;
use std::rc::Rc;

struct Node<'a> {
value: Rc<RefCell<&'a mut [u8]>>,
}

fn ref_mut<T: Write>(x: &mut T) -> &mut T {
x
}

fn main() {
let mut v: [u8; 3] = [1, 2, 3];
let node = Node {
value: Rc::new(RefCell::new(&mut v)),
};
println!("{:?}", ref_mut(&mut &mut node.value.borrow_mut()[..]));
}``````

where `value` in the struct `Node` has the same type as the `data` in `account`, and the function `ref_mut` has the same receiver as the function `serialize`.

### Why should we add `[..]`?

Most of this part is referenced from the top answer in Trouble understanding &mut &mut reference.

If we want to know the secret of the double `&mut`, we may go through the `[..]` first.

When we look at the documentation about certain cases of indexing, we see, that

``node.value.borrow_mut()[..]``

is sugar for

``*(node.value.borrow_mut().index_mut(..))``

Why is that a valid expression?

`..` is a shorthand for `RangeFull`.

`RangeFull` has an implementation for `SliceIndex<[u8]>`.

With this blanket implementation, we get a `IndexMut<RangeFull> for [u8]`, which provides

``fn index_mut(&mut [u8], index: RangeFull) -> &mut [u8]``

### Why double `&mut`?

The double `&mut` really bothered me for a while, since the common case may only have one in it.

After I made it clear, I found it is actually a simple problem of type. Let's go back to the code above again, and locate the line of code which we have a problem with:

``println!("{:?}", ref_mut(&mut &mut node.value.borrow_mut()[..]));``

In this line, we pass `&mut &mut node.value.borrow_mut()[..]` as a parameter into the function named `ref_mut`:

``````fn ref_mut<T: Write>(x: &mut T) -> &mut T {
x
}``````

As Trait Bound Syntax says:

The `impl Trait` syntax works for straightforward cases but is actually syntax sugar for a longer form, which is called a trait bound; it looks like this:

``````pub fn notify<T: Summary>(item: &T) {
println!("Breaking news! {}", item.summarize());
}``````

This longer form is equivalent to the example in the previous section but is more verbose. We place trait bounds with the declaration of the generic type parameter after a colon and inside angle brackets.

so the type `T` we input to `ref_mut` should implement `Write`, which is the same as the `Write` in the problem, since the definition of the trait Write is very long, so let's go to the definition of the main method (`write` for a writer) in it:

``````#[stable(feature = "rust1", since = "1.0.0")]
#[doc(notable_trait)]
#[cfg_attr(not(test), rustc_diagnostic_item = "IoWrite")]
pub trait Write {
// -- snip --
#[stable(feature = "rust1", since = "1.0.0")]
fn write(&mut self, buf: &[u8]) -> Result<usize>;
// -- snip --
}``````

According to the method, the instance of `Write` should be a mutable reference of an array with `u8` type.

Now let's push it backwords, in order to satisfy the bound `Write`, the generic type in `ref_mut` has to be `&mut [u8]`, and we remove the generic type in `ref_mut` temporarily, which simply replaces T with `&mut [u8]`, besides, add some suitable lifetime parameters:

``````fn ref_mut<'a>(x: &'a mut &'a mut [u8]) -> &'a mut &'a mut [u8] {
x
}``````

From now on, the problem is simple for everyone, we have a function that receives one parameter with the type: `&mut &mut [u8]`.

Here are the types of every part of `&mut &mut node.value.borrow_mut()[..]`:

• `node.value.borrow_mut()` has `RefMut<&mut [u8]>`

• `node.value.borrow_mut()[..]` has `[u8]`

• `&mut node.value.borrow_mut()[..]` has `&mut [u8]`

• `&mut &mut node.value.borrow_mut()[..]` has `&mut &mut [u8]`

To keep track of the actual writing position, we need a mutable reference to the mutable reference, and the input should have double `&mut` now.

Now the auto dereferencing kicks in.

``node.value.borrow_mut().index_mut(..)``

And `RefMut<&mut [u8]>` implements `DerefMut` which have `Deref<Target = &mut [u8]>` as a super trait.

And `&mut [u8]` implements `DerefMut` with `Deref<Target = [u8]>` as a super trait.

As mentioned in the reference, the compiler will now take the receiver expression and dereference it repeatedly, so it gets a list of candidate types. It also adds for each type resulting from a dereference of the reference type and the mutable reference type to the list of candidate types. From these candidate types, it selects one providing the method to call.

1. `RefMut<&mut [u8]>` using `node.value.borrow_mut()`

2. `&RefMut<&mut [u8]>`

3. `&mut RefMut<&mut [u8]>`

4. `&mut [u8]` using `*node.value.borrow_mut().deref_mut()` (means dereferenced from `RefMut<&mut [u8]>`)

5. `&&mut [u8]`

6. `&mut &mut [u8]`

7. `[u8]` using `*(*node.value.borrow_mut().deref_mut())` (now dereferenced from `&mut [u8]`)

8. `&[u8]`

9. `&mut [u8]`

(In 7. we are dereferencing a pointer type `&mut [u8]` so no `DerefMut` the Trait is used.)

The first (and only) type in this list provides an `index_mut()` method is `&mut [u8]`, via the `IndexMut<FullRange>` implementation for `[u8]`, so `&mut [u8]` is selected as receiver type. The return type of `index_mut()` is `&mut [u8]` as well.

So now, we hopefully understand, the type of `*(node.value.borrow_mut().index_mut(..))` is `[u8]`.

Thanks to the discussion of dereferencing, `node.value.borrow_mut()` can also be dereferenced with `*`. Since `node.value` has type `RefMut<&mut [u8]>`, it will be `&mut [u8]` after dereferencing, which can get the actual value simply. Finally after adding one more `&mut`, we can also match the type the function needed:

``println!("{:?}", ref_mut(&mut *node.value.borrow_mut()));``

## Conclusion

It may be confused if you are familiar with the `*` and `&` operator in C++ when you just step into the reference in Rust. Since they are two different things, we should avoid using C++ references to think about Rust references.

According to the question Why do references need to be explicitly dereferenced, these words reminded me:

So I’d treat `&` types in Rust like you would `*` types in C/C++, while keeping in mind the following points.

1. A Rust `&` type is stored as a pointer, sometimes with a length and other information (see below responses).

2. When you call `foo.bar()`, or access `foo.bar`, rust will automatically dereference foo if it has a type of `&Foo`.

3. There is a trait called `Deref` that some smart pointer types implement, to change how the * operator works.

Last updated