Skip to content

Commit e715205

Browse files
committed
TRPL: mutability
1 parent 1114fcd commit e715205

File tree

1 file changed

+177
-1
lines changed

1 file changed

+177
-1
lines changed

src/doc/trpl/mutability.md

+177-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,179 @@
11
% Mutability
22

3-
Coming Soon
3+
Mutability, the ability to change something, works a bit differently in Rust
4+
than in other languages. The first aspect of mutability is its non-default
5+
status:
6+
7+
```rust,ignore
8+
let x = 5;
9+
x = 6; // error!
10+
```
11+
12+
We can introduce mutability with the `mut` keyword:
13+
14+
```rust
15+
let mut x = 5;
16+
17+
x = 6; // no problem!
18+
```
19+
20+
This is a mutable [variable binding][vb]. When a binding is mutable, it means
21+
you’re allowed to change what the binding points to. So in the above example,
22+
it’s not so much that the value at `x` is changing, but that the binding
23+
changed from one `i32` to another.
24+
25+
[vb]: variable-bindings.html
26+
27+
If you want to change what the binding points to, you’ll need a [mutable reference][mr]:
28+
29+
```rust
30+
let mut x = 5;
31+
let y = &mut x;
32+
```
33+
34+
[mr]: references-and-borrowing.html
35+
36+
`y` is an immutable binding to a mutable reference, which means that you can’t
37+
bind `y` to something else (`y = &mut z`), but you can mutate the thing that’s
38+
bound to `y`. (`*y = 5`) A subtle distinction.
39+
40+
Of course, if you need both:
41+
42+
```rust
43+
let mut x = 5;
44+
let mut y = &mut x;
45+
```
46+
47+
Now `y` can be bound to another value, and the value it’s referencing can be
48+
changed.
49+
50+
It’s important to note that `mut` is part of a [pattern][pattern], so you
51+
can do things like this:
52+
53+
```rust
54+
let (mut x, y) = (5, 6);
55+
56+
fn foo(mut x: i32) {
57+
# }
58+
```
59+
60+
[pattern]: patterns.html
61+
62+
# Interior vs. Exterior Mutability
63+
64+
However, when we say something is ‘immutable’ in Rust, that doesn’t mean that
65+
it’s not able to be changed: We mean something has ‘exterior mutability’. Consider,
66+
for example, [`Arc<T>`][arc]:
67+
68+
```rust
69+
use std::sync::Arc;
70+
71+
let x = Arc::new(5);
72+
let y = x.clone();
73+
```
74+
75+
[arc]: ../std/sync/struct.Arc.html
76+
77+
When we call `clone()`, the `Arc<T>` needs to update the reference count. Yet
78+
we’ve not used any `mut`s here, `x` is an immutable binding, and we didn’t take
79+
`&mut 5` or anything. So what gives?
80+
81+
To this, we have to go back to the core of Rust’s guiding philosophy, memory
82+
safety, and the mechanism by which Rust guarantees it, the
83+
[ownership][ownership] system, and more specifically, [borrowing][borrowing]:
84+
85+
> You may have one or the other of these two kinds of borrows, but not both at
86+
> the same time:
87+
>
88+
> * 0 to N references (`&T`) to a resource.
89+
> * exactly one mutable reference (`&mut T`)
90+
91+
[ownership]: ownership.html
92+
[borrowing]: borrowing.html#The-Rules
93+
94+
So, that’s the real definition of ‘immutability’: is this safe to have two
95+
pointers to? In `Arc<T>`’s case, yes: the mutation is entirely contained inside
96+
the structure itself. It’s not user facing. For this reason, it hands out `&T`
97+
with `clone()`. If it handed out `&mut T`s, though, that would be a problem.
98+
99+
Other types, like the ones in the [`std::cell`][stdcell] module, have the
100+
opposite: interior mutability. For example:
101+
102+
```rust
103+
use std::cell::RefCell;
104+
105+
let x = RefCell::new(42);
106+
107+
let y = x.borrow_mut();
108+
```
109+
110+
[stdcell]: ../std/cell/index.html
111+
112+
RefCell hands out `&mut` references to what’s inside of it with the
113+
`borrow_mut()` method. Isn’t that dangerous? What if we do:
114+
115+
```rust,ignore
116+
use std::cell::RefCell;
117+
118+
let x = RefCell::new(42);
119+
120+
let y = x.borrow_mut();
121+
let z = x.borrow_mut();
122+
# (y, z);
123+
```
124+
125+
This will in fact panic, at runtime. This is what `RefCell` does: it enforces
126+
Rust’s borrowing rules at runtime, and `panic!`s if they’re violated. This
127+
allows us to get around another aspect of Rust’s mutability rules. Let’s talk
128+
about it first.
129+
130+
## Field-level mutability
131+
132+
Mutabilty is a property of either a borrow (`&mut`) or a binding (`let mut`).
133+
This means that, for example, you cannot have a [`struct`][struct] with
134+
some fields mutable and some immutable:
135+
136+
```rust,ignore
137+
struct Point {
138+
x: i32,
139+
mut y: i32, // nope
140+
}
141+
```
142+
143+
The mutability of a struct is in its binding:
144+
145+
```rust,ignore
146+
struct Point {
147+
x: i32,
148+
y: i32,
149+
}
150+
151+
let mut a = Point { x: 5, y: 6 };
152+
153+
a.x = 10;
154+
155+
let b = Point { x: 5, y: 6};
156+
157+
b.x = 10; // error: cannot assign to immutable field `b.x`
158+
```
159+
160+
[struct]: structs.html
161+
162+
However, by using `Cell<T>`, you can emulate field-level mutability:
163+
164+
```
165+
use std::cell::Cell;
166+
167+
struct Point {
168+
x: i32,
169+
y: Cell<i32>,
170+
}
171+
172+
let mut point = Point { x: 5, y: Cell::new(6) };
173+
174+
point.y.set(7);
175+
176+
println!("y: {:?}", point.y);
177+
```
178+
179+
This will print `y: Cell { value: 7 }`. We’ve successfully updated `y`.

0 commit comments

Comments
 (0)