Rust, as a language, offers two novel paradigms:
-
lifetimes,
-
exclusive pointers (references), noted
&mut
.For a presentation of that second point, see Rust, a unique perspective
Now, you may ask why Rust was designed this way, and the answers can be pretty interesting, but it does not change the fact that Rust works this way. An exclusive reference, by design, must be exclusive.
To rephrase your question:
what is the point of exclusive references for simple types such as integers? More generally, how useful can it be to have a
&mut
reference on something that isCopy
?
At that point, multi-threading is the answer: contrary to other languages, Rust opts into thread-safe paradigms by default (i.e., thread-safety is opt-out rather than opt-in). This raises two questions:
-
how is
&mut
needed for thread-safety / to avoid data-races?Well, you can use exclusive references to mutate data (that's why the are called "mutable references" in an overly simplifying manner, and why the carry
mut
in their rather than the more aptuniq
...) in an unsynchronized manner (e.g., imagine doing*xr += 1;
in your example).So now imagine doing
let xr1 = mutable_ref_to(x)
; (pseudo-code), andlet xr2 = mutable_ref_to(x);
If that were possible, then you would be able to go and usexr1
in one thread to do*xr1 +=1
andxr2
in another thread and do*xr2 += 1
. This would result in a data race, meaning that the value ofx
"afterwards" would be undefined. -
how do I opt-out of thread safety? How do I get non-exclusive mutable references to simple types such as integers (or other
Copy
types)?The answer is to stop using exclusive references, and to instead wrap your type (e.g., and integer) in a
Cell
use a shared reference (& _
) to thatCell
:use std::cell::Cell; let x = Cell::new(10); let xr = &x; // "mutable but non-exclusive reference to `x`" println!("{}", x.get()); // 10 xr.set(42); // mutate! println!("{}", x.get()); // 42
- (For those wondering if
&Cell
contradicts what I said about the data race in my first point, know that it is not possible toSend
a mutable reference of type&Cell
to another thread becauseCell
is notSync
, i.e., precisely becauseCell
offers "shared mutation" (also called interior mutability) that is notSync
-hronized / thread-safe.
- (For those wondering if