135

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
  • 53,120
  • 14
  • 139
  • 204
Jimmy Lu
  • 4,810
  • 7
  • 25
  • 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

4 Answers4

165

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
  • 122,748
  • 97
  • 336
  • 451
anderspitman
  • 9,230
  • 10
  • 40
  • 61
  • 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. – Kresten Oct 10 '20 at 13:40
  • [For people who forgot about C/C++ rules](https://stackoverflow.com/a/1143272/3924118) – nbro Dec 30 '22 at 00:44
138

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
  • 388,571
  • 95
  • 1,107
  • 1,366
  • 16
    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
  • 10
    @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
  • 2
    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
37

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

Note:

Reference mutability vs target mutability

A reference variable such as x, as in let x = &mut y, is a separate variable from the target variable y it is pointing to. In particular, x has its own location on the stack and mutability permissions. As such, if x is immutable, as it is here, then it cannot be reassigned to point to some other variable. That restriction is separate from the ability to mutate the target through it, as in *x = some_value; the target is a distinct variable with its own mutability permissions. However, if w is mutable, as in let mut w = &mut p, then it can indeed be reassigned to point to some other similarly typed variable: w = &mut z.

George
  • 2,451
  • 27
  • 37
  • Are you sure about the statement "To be able to mutate a value you need both a mutable binding and a mutable value"? The following works for me ` fn main() { let mut value = 4; println!("{}", value); let x = &mut value; println!("{}", x); *x = 5; println!("{}", x); } ` – user782220 Jun 18 '22 at 20:22
  • `value` is a location. The location contents is mutable. It currently contains `4`. `x` is a location on the stack. The location contents is immutable. It currently contains the address to `value`. The address type allows for mutation of that location contents. Consequently, though you cannot change `x` you can change what it refers to `*x`. These constraints are imposed at compile time in `safe rust` preventing certain code, in particular, the variable `value` will be unavailable while `x` has a mutable reference to it: there can only be one mutable reference to a variable at a time. – George Dec 08 '22 at 20:41
  • But $x$ is not a mutable binding is my point. – user782220 Dec 12 '22 at 02:54
  • I see your point. A reference is not a binding to the target. A reference is a separate variable that has its own mutability permissions. Specifically, `let x = &mut y` creates `x` as an immutable pointer variable located on the stack and containing the address to the variable `y` where, in this case, that location is mutable. On the other hand, `let mut x = &mut y` is a mutable pointer. In particular, the reassignment, `x = &mut z`, is now possible whereas before it is not. – George Dec 12 '22 at 05:10
1

Mutable Variable of Reference Type

When you have

let mut x: &T = value;

This means that x is variable that refers to an instance of T, as if by storing the memory address of the T instance in x's value. This reference (i.e. the "memory address") is the subject of mutability in this context: x can be modified to refer to a different instance of T like this:

x = some_other_T_instance;

but the referant (i.e. the value of the T instance to which x refers) cannot be changed via x:

// Illegal
*x = a_different_value;

Immutable variable of Mutable Reference type

When you have

let x: &mut T = value;

This means that x is a variable that refers to a mutable instance of T. In this case, the referent (i.e. the actual value) is the subject of mutability. It can be modified through the reference like this

*x = some_other_value;

but the reference itself (i.e. the "memory address" in the variable x) cannot:

// illegal
x = a_different_value;
RBF06
  • 2,013
  • 2
  • 21
  • 20