The cure is nearly always order: finish reading before you write.
Notes:
- rustc gives E0502 three spans: where the loan starts, the write it collides with, and its later use. The third is the one people skip, and the one that explains the error.
- **Q:** "Should I just add `.clone()`?" It compiles, but on a `String` or `Vec` it builds a second heap value when you only needed to read, and early in a kernel there is no allocator to build it with. On a `Copy` value it is the copy-out cure spelled longer. The next slide is the exam version.
---
## Fix a borrow error without `clone()`
Name the rule, quote the two conflicting borrows, and give the smallest edit:
```rust
let mut scores = [72, 95, 88];
let best = &scores[1]; // a shared loan
scores.sort(); // a write while it lives: E0502
println!("{best}"); // the loan's later use
```
- **Reorder:** print `best` before the `sort`, so the loan ends first
- **Copy it out:** `let best = scores[1];` holds an `i32`, not a loan
Practice: ↓ Problem 3.
Notes:
- On Midterm 1. Practice Set 1 Problem 2 is this shape, and its fix is the copy-out cure.
- `clone()` compiles too, but on a `String` or `Vec` it builds a second heap value when you only needed to read; on a `Copy` value it is the copy-out cure spelled longer. Copying out works only for `Copy` values: on a `Vec`, `let top = names[1];` is E0507 (Problem 3 (a)).
- **Q:** "Is `unsafe` a fix?" No. `unsafe` does not switch the borrow checker off, and PS1 Problem 2 rules it out anyway.
--
## Problem 3: fix it without `clone()`
Give the error code and the two uses that conflict, then the smallest fix that keeps the intent. `std::mem::swap` exchanges the values behind two `&mut`.
```rust
// (a) show the name at index 1, then sort
let mut names = vec![String::from("sh"), String::from("init")];
let top = &names[1]; names.sort(); println!("{top}");
// (b) swap the first and last cells
let mut grid = [1, 2, 3];
let a = &mut grid[0]; let b = &mut grid[2]; std::mem::swap(a, b);
// (c) show a report, then shelve it; shelve takes a String
let report = String::from("all clear");
let view = &report; shelve(report); println!("{view}");
// (d)
let mut job = (3, String::from("sh"));
let n = job.0; job = (n + 1, String::from("login")); println!("{n}");
```
--
## Problem 3 · solution
**(a) E0502.** `top` is a shared loan into `names`, still used by the `println!`, and `sort` needs `&mut names` in between. Copying out does not work: a `String` is not `Copy`, and `let top = names[1];` is ``error[E0507]: cannot move out of index of `Vec` ``. Print before sorting, so the loan ends first. Storing the index 1 compiles, but after the sort index 1 holds `"sh"`.
**(b) E0499.** Two `&mut` into `grid` are alive at the swap; the checker does not compare 0 with 2. Use `grid.swap(0, 2);`, one exclusive borrow that does the two-index work itself, giving `[3, 2, 1]`. `split_at_mut` also works.
**(c) E0505.** `shelve(report)` moves `report` while `view` still borrows it, and `view` is used afterwards. Move the `println!` above the call.
**(d) Compiles, and prints 3.** `n` is a copy of the `i32` in `job.0`, not a reference, so no loan is alive when `job` is overwritten. This is the copy-out cure. Write `let n = &job.0;` instead and the assignment is ``error[E0506]: cannot assign to `job` because it is borrowed``.
---
## Lifetimes by example
Given a signature, say which input the result borrows from; then whether a call site is accepted.
| Signature | The result may not outlive |
|---|---|
| `fn f<'a>(x: &'a str, y: &str) -> &'a str` | `x`; it may outlive `y` |
| `fn g<'a>(x: &'a str, y: &'a str) -> &'a str` | whichever of `x` and `y` dies first |
| `fn h(x: &str) -> &str` | `x`: one input, so no `'a` is needed |
| `fn k(x: &str, y: &str) -> &str` | nothing yet: E0106, the signature must say |
Practice: ↓ Problem 4.
Notes:
- On Midterm 1: "lifetimes by example" is its scope line. Work the call site from the table: find the input the result is tied to, and check that it is still alive at the result's last use.
- A lifetime describes; it never extends. Returning a reference to a local is E0515, whatever you annotate.
- **Q:** "Which should I write, `f` or `g`?" The one that is true. If the result comes from `x` alone, `g` claims more than is true and refuses callers whose `y` dies early (↓ elision, under 03r-lifetimes).
--
## Problem 4: which lifetime?
Does each compile as written? If not, give the fixed signature, or say why no annotation helps. `format!` builds a `String` the way `println!` prints one. `…` stands for a body that returns part of an input.
```rust
fn trim_nul(buf: &[u8]) -> &[u8] { … } // (a)
fn value_of(text: &str, key: &str) -> &str { … } // (b) returns part of text
struct Index { words: Vec<&str> } // (c)
fn greeting(name: &str) -> &str { // (d)
let text = format!("hello, {name}");
&text
}
```
--
## Problem 4 · solution
**(a) Compiles.** One input lifetime, so by elision rule 2 the result borrows from `buf`.
**(b) E0106.** Tie the result to `text` alone: `fn value_of<'a>(text: &'a str, key: &str) -> &'a str`. Putting `'a` on `key` too compiles, but refuses a caller whose key dies before the result is used.
**(c) E0106** on the `&str` inside the `Vec`. Write `struct Index<'a> { words: Vec<&'a str> }`: an `Index` is good only while the text its words point into is. The lifetime goes wherever a reference appears, even inside another type.
**(d) The signature is fine** by rule 2, but the body is ``error[E0515]: cannot return reference to local variable `text` ``. `text` is dropped at the closing brace, and no annotation can make it live longer: a lifetime describes, it never extends. Return the `String` itself: `fn greeting(name: &str) -> String`.
---
## Summary
- One owner; its closing brace is the `free()`
- A move copies the handle and kills the old name
- `Copy` types own nothing to release, so they stay put
- `&` shared, `&mut` exclusive: many readers or one writer
- A borrow ends at its last use; overlap is refused
- `'a` names the input a result borrows from
- On Midterm 1: moves, borrow fixes, lifetimes by example
Notes:
- One sentence per bullet, in the order of the page.
- **Q:** "How should I study this for Midterm 1?" Practice Set 1 Part A, Problems 1 and 2, then the page's Problems 1 to 4.
---
## [Before Thursday](../prep/02-cs326-2026-09-03-prep-ownership/): check yourself
You build a page allocator modeled by hand with a `Vec` and moves alone, under `cargo test`. Prep: about 25 minutes.
**1.** After `let b = a;` where `a: String`, what happens at run time, and what at compile time?
**2.** Which of these are `Copy`: `usize`, `bool`, `String`, `Vec`, `(usize, usize)`?
**3.** A function takes a `Vec` by value and calls `.push` on it; the caller needs the list afterward. Without `&`, what must it do?
Notes:
- Walk the prep page (about 25 minutes). What you build: a page allocator modeled with a `Vec` of free page numbers and moves, with no `&` yet. Green is `oslings run` passing; then `oslings submit` before you leave.
- The three questions are the prep's own Check yourself; the answers are on the prep page.
- **Q:** "What if I do not finish on Thursday?" Submit anyway: the tests that pass earn their share. Finish at a make-up session (office hours, on the class network) for three quarters, or anywhere else for half, and submit again.
---
## [Before Friday](../prep/02-cs326-2026-09-04-prep-borrowing/): check yourself
You lend instead of moving: shared slices for readers, an exclusive one for a writer, and a result that needs a lifetime. Under `cargo test`. Prep: about 25 minutes.
**1.** `let a = &mut page; let b = &mut page; use_both(a, b);` is rejected; with `&page` it is fine. Why?
**2.** `fn shorter(a: &str, b: &str) -> &str` does not compile. What is missing, and what does adding `<'a>` to it promise?
**3.** A struct holds a `&mut u64` to a variable `n`. While that struct value is alive, may the function that owns `n` read `n` directly?
Notes:
- Walk the prep page (about 25 minutes). What you build is the one line on the slide; point at the prep's "What you will build" paragraph rather than listing its pieces.
- The three questions are the prep's own Check yourself; the answers are on the prep page.
- **Q:** "Do I need Thursday's exercise finished first?" No: `03r` stands on its own. It does assume you can read E0382, because a borrow is the cure for it.
---
## Next week
[Week 3](03-cs326-2026-09-08-structs-enums-and-match/): structs, `impl`, enums and `match`. Read its Essentials before Tuesday.
Notes:
- Week 3 also gives `Drop` its full treatment: a drop that runs your own code, which is the idea under `37k`'s lock guard.
- **Q:** "Is Week 3 on Midterm 1?" Yes: structs, `impl`, enums, `Option` and exhaustive `match` are all in scope. Midterm 1 is Thursday, October 15.