Ref mut vs &mut vs mut &

Hello,

In my opinion, there is no difference between those functions:

fn fun1(ref mut a: i32) {
    *a = 1;
    let mut b = 0;
    fun1(b)
}
fn fun2(a: &mut i32) {
    *a = 1;
    let mut b = 0;
    fun2(&mut b)
}
fn fun3(mut a: &i32) {
    *a = 1; // error
    let mut b = 0;
    fun3(&b)
}

Except the last one which doesn't compile because a is behind & reference, but a is mut !!!

Thank you in advance for your answers.

What's your question? They are all different.

fun1 desugars as follows:

The pattern ref mut a is matched against the actual argument, so this is like

fn fun1(mut argument: i32) {
    let ref mut a = argument;
    *a = 1;
    let mut b = 0;
    fun1(b)
}

Then, the ref mut a patterns means that the value is bound by mutable reference, so this is equivalent to

fn fun1(mut argument: i32) {
    let a = &mut argument;
    *a = 1;
    let mut b = 0;
    fun1(b)
}

Finally, to avoid any confusion, we can remove the usage of mut pattern in the argument by doing an additional copy/move step (in this case it’s a copy), which means you best think of your function as doing

fn fun1(arg: i32) {
    let mut var = arg;
    let a = &mut var;
    *a = 1;
    let mut b = 0;
    fun1(b)
}

In comparison to fun2 you thus see, it takes a i32 by value, stores it in a local mutable variable inside of the function, and furthermore mutations, as done with the *a = 1 only apply to that local copy of the value.

This means that a function like fun1 (ignoring the infinite recursion business here…) will not mutate the variable you pass, on the call-site, whereas a function like fun2 – taking a &mut i32 argument – would!

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.