Skip to content
Free public beta until December 4, 2026: every course is open, no card needed. After that, the first chapter of each course stays free and full access is a one-time $39 ($19 for up to 100 founding members chosen for helpful feedback). Your progress is kept. How the beta works

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 Copy types (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 &T alongside 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>. Add RefCell inside only if the owners must also change it.
  • Several owners on several threads → Arc<T>, with a Mutex, RwLock or 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

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.

Passing a value in gives it away; returning it hands it back.

Lend it

Section

References, &T

Look without taking. The caller keeps ownership.

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.

A view of part of an array, Vec, or String.

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.

Shared and changeable, checked at run time. Weak breaks the cycles that would leak.

The thread-safe version of the same idea.

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.