111

Here are two function signatures I saw in the Rust documentation:

fn modify_foo(mut foo: Box<i32>) { *foo += 1; *foo }
fn modify_foo(foo: &mut i32) { *foo += 1; *foo }

Why the different placement of mut?

It seems that the first function could also be declared as

fn modify_foo(foo: mut Box<i32>) { /* ... */ }
Peter Hall
  • 43,946
  • 11
  • 101
  • 168
Jimmy Lu
  • 4,400
  • 6
  • 24
  • 30
  • 4
    For C++ programmers: the difference is similar to [pointer `const` vs `pointee` const](https://stackoverflow.com/q/21476869/183120). – legends2k Sep 21 '20 at 16:20

3 Answers3

136

If you're coming from C/C++, it might also be helpful to think of it basically like this:

// Rust          C/C++
    a: &T     == const T* const a; // can't mutate either
mut a: &T     == const T* a;       // can't mutate what is pointed to
    a: &mut T == T* const a;       // can't mutate pointer
mut a: &mut T == T* a;             // can mutate both

You'll notice that these are inverses of each other. C/C++ take a "blacklist" approach, where if you want something to be immutable you have to say so explicitly, while Rust takes a "whitelist" approach, where if you want something to be mutable you have to say so explicitly.

Nathan Long
  • 118,336
  • 94
  • 325
  • 435
anderspitman
  • 7,690
  • 9
  • 38
  • 53
  • 5
    This is a great table. It may be worthwhile to note that `&mut T` references are also analogous to `T* restrict` pointers in C: they may not be aliased. `&T` references have no such constraint and there is no reference type analogous to non-`restrict`-qualified `T*` pointers. – trent Oct 11 '19 at 21:03
  • 2
    I don't have a C background, but I still think this explains it better (with the comments) as opposed to the accepted answer, sometimes simpler is better than longer. – kres0345 Oct 10 '20 at 13:40
121

mut foo: T means you have a variable called foo that is a T. You are allowed to change what the variable refers to:

let mut val1 = 2;
val1 = 3; // OK

let val2 = 2;
val2 = 3; // error: re-assignment of immutable variable

This also lets you modify fields of a struct that you own:

struct Monster { health: u8 }

let mut orc = Monster { health: 93 };
orc.health -= 54;

let goblin = Monster { health: 28 };
goblin.health += 10; // error: cannot assign to immutable field

foo: &mut T means you have a variable that refers to (&) a value and you are allowed to change (mut) the referred value (including fields, if it is a struct):

let val1 = &mut 2;
*val1 = 3; // OK

let val2 = &2;
*val2 = 3; // error: cannot assign to immutable borrowed content

Note that &mut only makes sense with a reference - foo: mut T is not valid syntax. You can also combine the two qualifiers (let mut a: &mut T), when it makes sense.

Shepmaster
  • 326,504
  • 69
  • 892
  • 1,159
  • 13
    I see. I guess it's like in C++ where you can have `int const*` vs. `int *const` to achieve different things. – Jimmy Lu Feb 18 '15 at 15:57
  • 4
    @Shepmaster You might want to add that `mut` on a binding allows you to mutate inside the structure (if it is a struct). – Scott Olson Feb 18 '15 at 15:59
  • I guess it stands out to me why rust doesn't seem to allow the syntax `let foo: mut Type`? It seems that since we already have the inevitable `& mut` in which `mut` can't appear on the left hand side, it's more uniform to say that `mut` can only appear on the right hand side? – Jimmy Lu Feb 18 '15 at 15:59
  • @ScottOlson, can you please elaborate or point me to a source to explain the `mut` binding before a structure? – Jimmy Lu Feb 18 '15 at 16:01
  • 9
    @BeyondSora Don't think of `&mut Type` as `&(mut Type)`, but as `(&mut) Type`. The keyword `mut` isn't used in types in general, but there is a type of reference called `&mut`. – Scott Olson Feb 18 '15 at 16:02
  • 2
    @BeyondSora You can see the latest edit of the above answer. The basic explanation is when you can mutate a structure, you can mutate as far into the structure as you want (its fields, its fields' fields, etc). There are no `const` fields. This is safe since Rust guarantees when you can mutate something, no one else can read or mutate it at the same time. – Scott Olson Feb 18 '15 at 16:05
  • 3
    @ScottOlson So, what you're saying is that `&mut` is just a "convenient" notation to avoid introducing a new keyword, but actually it is a different concept from the lhs usual `mut` keyword ? – didierc Feb 18 '15 at 20:04
  • 3
    @didierc Yeah. You can think of `&T` and `&mut T` as sugar for `Ref` and `RefMut` (types I just made up). – Scott Olson Feb 18 '15 at 21:56
  • 1
    Although the technical name of a `&mut` is a pattern, I suggest to consider `&`, `&mut` as keywords or tokens at the beginning, which has nothing to do with the key word `mut`, to make it less confused. – psionic12 Jul 17 '21 at 14:19
19

The following natural language translation seems to clear things up for me...

let x = value;
  x {binds immutably} to {immutable value}

let mut x = value;
  x {binds mutably} to {possibly mutable value}

let x = &value;
  x {binds immutably} to {a reference to} {immutable value}

let x = &mut value;
  x {binds immutably} to {a reference to} {mutable value}

let mut x = &value;
  x {binds mutably} to {a reference to} {immutable value}

let mut x = &mut value;
  x {binds mutably} to {a reference to} {mutable value}

where

  • {binds mutably} means the binding can be reassigned
  • {mutable value} means the value's contents can change
  • To be able to mutate a value you need both a mutable binding and a mutable value
George
  • 1,796
  • 22
  • 32