Every way to share data
Move it, copy it, lend it with & or &mut, clone it, count it with Rc or Arc, or send it down a channel. Who owns the value decides which.
Ask two questions: does the other code need the value after you're done with it, and does anyone need to change it?
- The other code can have it for good → move it: pass it by value.
Small
Copytypes (numbers,bool,char) are copied instead, so you keep yours too. - The other code only needs to look for a while → lend it with
&T. As many shared borrows as you like, at the same time. - The other code needs to change it for a while → lend it with
&mut T. Exactly one, and no&Talongside it. - Both sides really need their own copy →
.clone(). It's an honest, visible cost; fine for small values and a smell inside a hot loop. - Several owners, one thread, and nobody knows who finishes last
(a graph node, a shared config in a GUI) →
Rc<T>. AddRefCellinside only if the owners must also change it. - Several owners on several threads →
Arc<T>, with aMutex,RwLockor atomic inside if anyone writes. - One thread produces values and another consumes them → don't share at all: send each value down a channel, so ownership moves with the message.
Try them in that order. Each step down the list costs a little more, either at run time or in how much the compiler can check for you.
Hand it over
Section
The ownership rules
One owner at a time, and the value is dropped when its owner goes away.
Section
Moves
Assigning or passing a String moves it; the old name can't be used again (E0382).
Formal. Assigning a value, passing it to a function, or returning it
moves it, unless its type implements Copy, in which case the bits are
duplicated and the source stays usable. Integers, floats, bool,
char, one more kind of value met in Chapter 8, and tuples/arrays of
Copy types are Copy;
String, Vec, and any type with a Drop implementation are not (a
type can't be both Copy and Drop). clone() is the explicit way to
duplicate a non-Copy value.
In plain English. Small, simple values get copied automatically.
Anything that owns memory somewhere else gets handed over instead, and if
you really want two, you ask for a copy with clone().
Example. let x = 5; let y = x; leaves both usable. let s = String::from("hi"); let t = s; leaves only t. let t = s.clone();
leaves both.
Why this rule exists. Copying a number is free; silently copying a large buffer is not. Making deep copies explicit keeps their cost visible, and moving keeps ownership single.
Which types are copied instead of moved, and why a String can't be.
Section
Ownership and functions
Passing a value in gives it away; returning it hands it back.
Lend it
Section
References, &T
Look without taking. The caller keeps ownership.
Section
Mutable references, &mut T
Change it in place without taking it.
Formal. At any point in a program, a value may have either any
number of shared references (&T) or exactly one mutable reference
(&mut T), but not both; and no reference may be used after the value
it refers to is gone. Violations are compile errors (E0499 for two
mutable borrows, E0502 for a mutable borrow alongside a shared one).
In plain English. Many people may read something at once, or one person may change it, never both at the same time. And you can't keep a pointer to something that has been thrown away.
Example. let r = &v; v.push(4); println!("{r:?}"); is E0502:
push needs to change v while r is still reading it (and push may
move the vector's contents, leaving r pointing at freed memory).
Why this rule exists. Reading and writing the same data at the same time is the root of data races and use-after-free bugs. Ruling it out at compile time removes those bugs from safe Rust.
Many readers or one writer, never both.
Term
slice
Example
fn total(xs: &[i32]) -> i32 accepts a whole Vec<i32>, an array, or any part of one: total(&v[1..3]).Duplicate it
Section
clone
A deep, explicit copy. Both sides own their own value afterwards.
Section
Copy types
The small values that are duplicated automatically on every assignment.
Share ownership
A reference count; the value is dropped when the last Rc goes.
Section
Rc<RefCell>, and cycles
Shared and changeable, checked at run time. Weak breaks the cycles that would leak.
The thread-safe version of the same idea.
Section
Shared state in a web service
The same choice made for every request handler at once.
Don't share: send it
Section
Channels
Sending a value moves it to the receiving thread, so nothing is shared at all.
Section
Async channels
mpsc, oneshot, broadcast and watch for tasks, each for a different shape of conversation.