# 8.x Chapter 8 summary and quiz
> Ownership, the stack and heap, drops, moves, Copy and Clone reviewed, plus a quiz that exercises the whole ownership model at once.
Source: https://learnrust.net/chapter-8/chapter-8-summary-and-quiz/
The chapter the course was named after is behind you. If it felt smaller than its reputation, that was the plan: seven short lessons, each one move on the same diagram. Here's the whole picture at once, then a quiz that makes you play it.
## Quick review
Memory that a program requests at runtime must be given back **exactly once**; too early is a *use-after-free*, twice is a *double free*, never is a *leak*. The industry's three answers: trust the programmer (C/C++; fast and dangerous), pay a garbage collector (Java and friends; safe, with runtime cost and unpredictable pauses), or Rust's third way, **ownership**: compile-time rules that let the compiler write every give-it-back into the program before it runs. The rules fit in a breath: every value has an owner; one owner at a time; when the owner goes out of scope, the value is dropped.
The floor plan underneath: the **stack** is a fixed-size column of memory run with plate-stack discipline, holding one **frame** per unreturned function call (return bookmark, parameters, locals). Pushing and popping frames is just moving a marker, which is why stack allocation is nearly free, why locals never needed cleanup ceremony, and why deep recursion ends in a *stack overflow*. The stack's price is rigidity: every size known at compile time. Runtime-sized data lives on the **heap**, where the allocator hands out blocks on request. A `String` straddles both: a fixed-size handle in the frame (address, length, capacity) owning a heap block of text.
**Dropped** means the value's memory is given back at the owner's closing brace: a fixed place in the program, not a background process. Cleanup you can point at is the whole trick; it's how Rust gets collector-grade safety with zero collector.
**Moves** are what `=` means for owning types: the handle transfers, the old variable is dead, and using it is `error[E0382]`, whose anatomy you now read fluently (move-because-the-type-isn't-`Copy`, *value moved here*, *borrowed here after move*, and a `.clone()` diff if the compiler thinks it'd help). One owner at a time makes the double free unwritable. **Copy types** opt out because they live whole in their boxes (all integers, floats, `bool`, `char`, unit, all-Copy tuples, and `&str`, which copies only the view): for them `=` copies and both variables live. Functions follow the same physics: passing a `String` *gives it*, the parameter drops it on return, and the compiler's own note says which parameter "takes ownership of the value"; returning a value *gives it back*. Functions that only read text take `&str`; functions that keep it take `String`; and `+` consumes its left side because it owns, grows, and hands onward that very block. When two independent values is the genuine requirement, **`.clone()`** buys the deep copy with visible ink: the expensive thing in Rust is never silent, and the silent thing is never expensive.
And one promissory note, now due next chapter: the give-and-take-back tuple dance, the error-silencing clone, and the note "consider changing this parameter type to borrow instead" all point at the same door. You've been pushing values through it with `&mut` since lesson [1.6](@/chapter-1/reading-input.md). Chapter 9 opens it.
## Quiz time
**Question #1**
Three claims, true or false, one sentence of why:
a) When a Rust program assigns one `String` variable to another, the text is copied to a new heap block.
b) A value can be unusable while its variable's name is still in scope.
c) Dropping happens when Rust's runtime detects a value is no longer reachable.
Show solution
a) False: the handle moves and the block stays put; copying the text is exactly what `=` *won't* do silently (that's `.clone()`).
b) True: that's a moved-from variable, lesson [8.4](@/chapter-8/moves.md)'s warning box; scope governs the name, ownership governs the value.
c) False, twice over: nothing is detected and there is no collector; the drop point is the owner's closing brace, fixed at compile time.
**Question #2**
Compile or not? For each, one sentence.
a)
```rust
fn main() {
let x = 7;
let y = x;
println!("{x} {y}");
}
```
b)
```rust
fn main() {
let tag = String::from("fragile");
let label = tag;
println!("{tag}");
}
```
c)
```rust
fn main() {
let park = String::from("bench");
let view: &str = &park;
let second = view;
println!("{view} {second} {park}");
}
```
d)
```rust
fn main() {
let s = String::from("inner");
{
let t = s;
}
println!("{s}");
}
```
Show solution
a) Compiles (`7 7`): `i32` is Copy, so `=` copies and both live.
b) `error[E0382]`: `String` moves to `label`, and `tag` is used after its value left.
c) Compiles (`bench bench bench`): `&str` is Copy, so the *view* duplicates freely, and neither view affects `park`'s ownership.
d) `error[E0382]`: the value moves into the block's `t` and is dropped at the inner brace; the final line uses `s`, whose value is long gone even though its name is in scope.
**Question #3**
Read this error aloud, the way lesson [8.4](@/chapter-8/moves.md) did: say which line moved the value, which line used it illegally, and what the compiler's two suggestions (one note, one help) would each mean for the program.
```rust
fn main() {
let recipe = String::from("knead, rest, bake");
publish(recipe);
println!("saved: {recipe}");
}
fn publish(text: String) {
println!("publishing: {text}");
}
```
```
error[E0382]: borrow of moved value: `recipe`
--> src/main.rs:4:23
|
2 | let recipe = String::from("knead, rest, bake");
| ------ move occurs because `recipe` has type `String`, which does not implement the `Copy` trait
3 | publish(recipe);
| ------ value moved here
4 | println!("saved: {recipe}");
| ^^^^^^ value borrowed here after move
|
note: consider changing this parameter type in function `publish` to borrow instead if owning the value isn't necessary
--> src/main.rs:7:18
|
7 | fn publish(text: String) {
| ------- ^^^^^^ this parameter takes ownership of the value
| |
| in this function
help: consider cloning the value if the performance cost is acceptable
|
3 | publish(recipe.clone());
| ++++++++
```
Show solution
Line 3 moved the value: calling `publish(recipe)` gives the `String` to the `text` parameter, which drops it when `publish` returns. Line 4 uses it illegally: `recipe` is moved-from, a name owning nothing. The **note** proposes fixing the *signature*: if `publish` only reads the text (it does; it prints), it should borrow rather than take ownership, which is chapter 9's subject and the better fix. The **help** proposes fixing the *call site*: `recipe.clone()` would hand `publish` a deep copy and keep the original, at the price of duplicating the text; legal, but paying an allocation to avoid a `&`.
**Question #4**
Bug hunt. This program compiles and works, but a chapter 8 graduate should wince three times. Find the three wasteful or wrong-headed spots and say what each should be:
```rust
fn banner(title: String) -> String {
format!("== {title} ==")
}
fn main() {
let title = String::from("Daily Report");
let decorated = banner(title.clone());
println!("{decorated}");
println!("{}", title.clone());
}
```
Show solution
First: `banner` takes `String` but only reads the title to build its result; it should take `&str` (the function never keeps the text, so it shouldn't take ownership). Second: `banner(title.clone())` is the error-silencing clone from lesson [8.7](@/chapter-8/clone.md), duplicating the whole text to feed a function that shouldn't be consuming it; fix the signature and pass `&title`. Third: `title.clone()` in the last line clones for no reason at all; printing only *reads* the value, and `println!("{title}")` was already legal. Total honest cost of the fixed program: zero clones.
**Question #5**
Write a gift-tag program:
- An `ask` function: takes a prompt as `&str`, prints it, reads a line (lesson [1.6](@/chapter-1/reading-input.md)'s recipe), and returns the trimmed input as an owned `String`. Explain to yourself why the return type *must* be `String` and not a view of the input.
- A `make_tag` function: takes a recipient and a gift as `&str`s plus a count as `u32`, and returns a `String` like `To Maria: 3 x teacups` (lesson [5.5](@/chapter-5/formatting-strings.md)'s tools).
- A `with_length` function, just to feel this chapter in your fingers: takes the finished tag *by value* (`String`) and returns `(String, usize)`, the tag and its length in bytes, give-and-take-back style.
- `main` wires it together, asks for recipient, gift, and count (parse the count, lesson [5.6](@/chapter-5/parsing-strings-into-numbers.md)), and prints the tag plus its byte length.
A run should look like:
```
Who is the gift for?
What is the gift?
How many?
To Maria: 3 x teacups
(21 bytes)
```
Show solution
```rust
use std::io;
fn ask(prompt: &str) -> String {
println!("{prompt}");
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("failed to read input");
String::from(input.trim())
}
fn make_tag(recipient: &str, gift: &str, count: u32) -> String {
format!("To {recipient}: {count} x {gift}")
}
fn with_length(tag: String) -> (String, usize) {
let bytes = tag.len();
(tag, bytes)
}
fn main() {
let recipient = ask("Who is the gift for?");
let gift = ask("What is the gift?");
let count: u32 = ask("How many?").parse().expect("not a number");
let tag = make_tag(&recipient, &gift, count);
let (tag, bytes) = with_length(tag);
println!("{tag}");
println!("({bytes} bytes)");
}
```
The ownership tour, function by function: `ask` *must* return an owned `String` because its local `input` dies at its closing brace, so any view into it could not survive the return (chapter 9 turns that intuition into a compiler-enforced law); building a fresh `String` and moving it out is the correct shape. `make_tag` takes `&str`s because it only reads its inputs (`&recipient` lends the text, lesson [5.4](@/chapter-5/introduction-to-str.md)'s auto-conversion at work), takes `count` by Copy, and gives the caller ownership of the `format!` result. `with_length` is the deliberately awkward one: it takes the tag by value, so `main` must catch it again from the returned tuple via a shadowing `let`. After chapter 9 you'd write it as a `&str` parameter (or just call `.len()` directly) and delete the dance. The count parse is `ask("How many?").parse()`: the `String` returned by `ask` is consumed by the expression, dropped after `parse` reads it, which is fine, because nobody needed it afterwards.
## What's next
Chapter 9 keeps the biggest promise in the course. Every awkward moment in this chapter (the tuple dance, the defensive clone, the function that swallowed your `String`) dissolves into a single character you've been writing since lesson [1.6](@/chapter-1/reading-input.md): `&`. References, borrowing, and the famous borrow checker, which you'll find is not a wall but the chapter 8 rules with better manners.