# Ownership, places, and moves

Learn what moves, what gets copied, and when a borrow is enough.

Canonical: https://rust.robertdevore.com/course/03-ownership/
Author: Robert DeVore
Technical baseline: Rust 1.98.1, edition 2024; verified 2026-09-06.

## A value and the place holding it

A **place** is a location a program can refer to: a local variable, a field, an indexed element, or a dereferenced pointer. A **value** is what the location currently holds. Moving a value transfers it out of a place. The heap allocation it owns may stay at the same address.

`String` owns and tracks a UTF-8 buffer. If two independent strings both tried to free that buffer, the program could free the same memory twice. Moving a `String` makes the source unavailable until reinitialized. The new owner normally drops the value when its drop scope ends.


### Run the example

```sh
cargo run --locked --example 03_ownership
```

```rust
fn label(text: &str) -> usize {
    text.len()
}
fn main() {
    let original = String::from("WARN retry");
    let bytes = label(&original);
    let stored = original;
    assert_eq!(bytes, 10);
    assert_eq!(stored, "WARN retry");
}
```

[View the tested source](https://github.com/robertdevore/rust.robertdevore.com/blob/main/examples/03_ownership.rs)


`label(&original)` lends access, so it does not take ownership of the string. `let stored = original` does transfer the value. No second character buffer is needed. The compiler may optimize away the move itself. A move in Rust source does not promise a particular machine instruction.

## Copy is a type property

Some types implement `Copy`: using their values in a move-like context implicitly copies them and leaves the source usable. Integers are familiar examples. Heap versus stack is not the rule: references can be copied, and a stack-resident struct can own a non-`Copy` resource. A type implementing `Drop` cannot also implement `Copy`.

`Clone` requests duplication explicitly, but its meaning depends on the type. Cloning a `String` duplicates its text; cloning an `Rc` adds an owner to shared data. Before adding `.clone()` to fix an error, ask what the caller needs: ownership, a temporary borrow, or a separate copy it can change.

## Follow destruction, not just allocation

Values are normally dropped when their drop scope ends; moving transfers that responsibility. Fields can sometimes be moved separately, leaving a partially moved struct whose remaining fields are still usable. A type with a destructor restricts such moves because its destructor expects an intact value. Leaking memory with safe operations is possible: Rust does not promise that every destructor always runs. Never base an unsafe abstraction's soundness solely on a caller eventually calling `drop`.

The early model “one owner” describes ordinary owning values, not a ban on shared ownership. `Rc` and `Arc` coordinate multiple owning handles through a reference count. They do not automatically make the contained data mutable or thread-safe.

## Compiler drill


**Intentionally fails on Rust 1.98.1.** Run `rustc --edition=2024 drills/moved.rs` from the repository.

```rust
fn main() {
    let original = String::from("record");
    let stored = original;
    println!("{original} {stored}");
}
```

<details><summary>Actual compiler diagnostic · Rust 1.98.1</summary>

```text
error[E0382]: borrow of moved value: `original`
 --> drills/moved.rs:4:16
  |
2 |     let original = String::from("record");
  |         -------- move occurs because `original` has type `String`, which does not implement the `Copy` trait
3 |     let stored = original;
  |                  -------- value moved here
4 |     println!("{original} {stored}");
  |                ^^^^^^^^ value borrowed here after move
  |
help: consider cloning the value if the performance cost is acceptable
  |
3 |     let stored = original.clone();
  |                          ++++++++

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0382`.
```

</details>


The diagnostic identifies the earlier move and the later use. Repair the design before considering duplication. Can the recipient borrow? Can the original caller stop using the value? Are two independently editable strings actually required?

## Exercise

Repair the drill without cloning. Then make a second version in which two independent strings are deliberately required and justify the clone in one sentence. In each version, identify which binding is responsible for dropping which allocation.

<details><summary>Solution and acceptance check</summary>

For shared read-only access, use `let stored = &original`; printing both is then valid. Alternatively print only the new owner after a move. For two independently editable strings, use `let stored = original.clone()` and mutate one to show the other remains unchanged. The two allocations each have an owner and are each dropped once in ordinary execution.

</details>

Sources: [places and moves](https://doc.rust-lang.org/reference/expressions.html#place-expressions-and-value-expressions), [destructors](https://doc.rust-lang.org/reference/destructors.html), and [`Copy`](https://doc.rust-lang.org/std/marker/trait.Copy.html).

