Ownership Preview
Ownership is Rust's core memory model: one owner per value, moves transfer responsibility, and borrows allow temporary access under compile-time rules. This page previews the ideas before the Ownership section.
Search across all documentation pages
Ownership is Rust's core memory model: one owner per value, moves transfer responsibility, and borrows allow temporary access under compile-time rules. This page previews the ideas before the Ownership section.
fn main() {
let s = String::from("hello");
let t = s; // move
// println!("{s}"); // error: moved
let len = measure(&t);
println!("{t} has length {len}");
}
fn measure(text: &String) -> usize {
text.len()
}When to reach for this: Whenever you pass data between functions, store it in structs, or share it across threads - ownership rules apply everywhere.
fn append(mut s: String, suffix: &str) -> String {
s.push_str(suffix);
s
}
fn print_both(first: &str, second: &str) {
println!("{first} {second}");
}
fn main() {
let greeting = String::from("Hello");
let full = append(greeting, ", Rust!");
let slice: &str = &full;
print_both(slice, "welcome.");
}What this demonstrates:
append takes ownership of greeting and returns updated String&str borrows string data without owning itString coerces to &str via Deref (deref coercion)Copy duplicates on assignment (i32, bool, char)String, Vec) move on assignmentdrop runs automatically&T, &mut T) are borrowed views with lifetime limitslet a = 5;
let b = a; // Copy - both valid
let v1 = vec![1, 2];
let v2 = v1; // Move - v1 invalid&T or exactly one &mut T at a timelet x = 42; // stack
let s = String::from("x"); // pointer + capacity + len on stack, bytes on heapString. Fix: Clone (s.clone()) if you need a duplicate, or borrow instead.fn print(s: String) forces callers to give up the string. Fix: Use &str or &String.&mut to the same data - Compile error. Fix: Restructure scopes, use RefCell in single-threaded interior mutability, or split fields.fn bad() -> &String cannot work. Fix: Return owned value or take input by reference with lifetime tied to input.Cow.| Alternative | Use When | Don't Use When |
|---|---|---|
Borrow &T | Read-only access | Caller must keep owning for your return lifetime |
Clone | Cheap duplicate needed | Hot path with large data |
Rc/Arc | Shared ownership | Single clear owner exists |
Cow<'a, T> | Maybe borrow, maybe own | Ownership is always clear |
Ownership and lifetimes free memory deterministically at compile time for most code, with zero runtime GC cost.
Scalars, tuples/arrays of Copy types, and types explicitly marked Copy. String and Vec are not Copy.
Clone explicitly. There is no implicit copy for non-Copy types.
A trait run automatically when a value goes out of scope. String frees heap memory in drop.
Passing by value moves. Passing by reference &T borrows without moving ownership.
Yes. Fields are owned like local variables. The struct is the owner of its fields.
A borrowed view into contiguous data: &[T] or &str. Slices do not own memory.
Moves are pointer copies for heap types. No reference counting unless you choose Rc/Arc.
Owned data moves into futures. Send/Sync bound shared state across tasks (see Concurrency section).
See the Ownership section starting with Ownership Basics.
Copy/Clone& vs &mutStack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.
Reviewed by Chris St. John·Last updated Jul 19, 2026