liveBook · Manning

Ownership

As explained in Refactoring to Rust

The association in which a designated handle controls when a piece of memory is allocated and deallocated.

Ownership tells Rust which handle controls a value’s memory. Each value has one owner at a time. When that owner goes out of scope, the value is dropped. The compiler enforces these rules before the program runs, rather than leaving the programmer to track every allocation and deallocation mentally. section 2.1 section 1.4.2

Passing artwork to a function

Suppose art1 owns an Artwork value. Calling admire_art(art1) passes the owned value into a parameter named art. Ownership moves from art1 to art, so art1 cannot be used for a second call. Code that looks like an ordinary repeated function call therefore produces a moved-value compiler error. section 2.2 section 2.1

Listing 2.5 A program attempting to admire the same art twice
struct Artwork {
  name: String,
}

fn admire_art(art: Artwork) {
  println!("Wow, {} really makes you think.", art.name);
}

fn main() {
  let art1 = Artwork { name: "The Ordeal of Owain".to_string() };

  admire_art(art1);
  admire_art(art1);
}

The second admire_art(art1) call makes the ownership question concrete: the first call has already moved the value. section 2.1

$ cargo run
error[E0382]: use of moved value: `art1`
  --> src/main.rs:11:16
   |
8  |     let art1 = Artwork {};
   |         ---- move occurs because `art1` has type `Artwork`, which
   |              does not implement the `Copy` trait
9  |
10 |     admire_art(art1);
   |                ---- value moved here
11 |     admire_art(art1);
   |                ^^^^ value used here after move

error: aborting due to previous error; 1 warning emitted

The compiler identifies both where the move occurred and where the moved value was used again. section 2.1

Compare that with manual memory management: moving a free(name) call into a greeting function changes which code is responsible for the allocation. Callers must then be checked for later uses. Rust records ownership in the program’s types and rejects uses that violate its rules, helping prevent use-after-free errors without a background garbage collector. section 2.2 section 1.4.2

Ownership works alongside borrowing and lifetimes. That relationship matters when sharing memory across a foreign function interface: responsibility for freeing a resource must remain clear even when another language uses it. section 2.0 section 1.3

How Refactoring to Rust covers it

How deep it goes
Defines the one-owner rules and works through a function-argument move and rejected reuse, without detailing ownership implementation.
Examples
Demonstrates an artwork passed twice to a function and greeting code whose free(name) call changes deallocation responsibility.
What it assumes
Starts with a Cargo-created Rust project and a simple struct, introducing ownership as a basic Rust concept.
What you can do after
Diagnose/debug with it by recognizing a moved-value error and identifying why a former owner cannot reuse the value.
How it connects
Connects ownership to borrowing, lifetimes, FFI, and manual memory management.

Also explained in

Compare how 6 books explain ownership →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Refactoring to Rust. The section links point to the parts of the book it draws on.