liveBook · Manning

Borrow checker

As explained in Idiomatic Rust

The borrow checker is the Rust compiler component that verifies ownership, borrowing, and reference validity at compile time.

The borrow checker is Rust’s compile-time check on borrowing and reference validity. An owned value passed to a function can be bound with `mut` inside that function, but an immutable reference cannot be made mutable that way: the function has borrowed the data, not taken ownership of it. section 9.5 section 3.2.4

A mutable parameter is not a mutable borrow

In `fn mutability(a: i32, mut b: i32)`, the function can increment `b` but not `a`. The caller’s `b` is unaffected: `i32` implements `Copy`, so this call copies its value. For a non-`Copy` owned value, passing by value moves ownership instead. Neither case turns an immutable reference into a mutable one. section 9.5

Listing 9.3 Using RefCell for interior mutability
let immutable_string =                              #1
  String::from("This string cannot be changed");   
// immutable_string.push_str("... or can it?"); // error: cannot borrow
`immutable_string` as mutable, as it is not declared as mutable       #2
dbg!(&immutable_string);

let not_so_immutable_string = RefCell::from(immutable_string);    #3
not_so_immutable_string
    .borrow_mut()
    .push_str("... or can it?");    #4
dbg!(&not_so_immutable_string);

The failed mutation of an immutable `String` contrasts with `RefCell::borrow_mut()`. `RefCell` owns the moved string and provides an interior-mutability alternative; it does not change the mutability of an existing reference. section 9.5

Lifetimes give the compiler information for checking whether references remain valid. They are often inferred; when the compiler cannot infer a needed relationship, an explicit lifetime such as `'a` can express it. A reference cannot remain valid longer than the referenced object or the scope in which the reference was created. section 3.2.4

struct Iter<'a, T> {
    next: Option<ListItemPtr<T>>,
    data: Option<ItemData<T>>,
    phantom: PhantomData<&'a T>,
}
struct IterMut<'a, T> {
    next: Option<ListItemPtr<T>>,
    data: Option<ItemData<T>>,
    phantom: PhantomData<&'a T>,
}

The iterator structs carry `'a` through `PhantomData<&'a T>` while storing pointers to list items. Their later `next()` implementations use `unsafe` to produce references—a more involved case than an ordinary borrowed parameter. section 3.2.4

How Idiomatic Rust covers it

How deep it goes
Explains borrowing through function calls and lifetime inference through iterators, then shows an iterator implementation requiring unsafe code.
Examples
Contrasts mutable function parameters with borrowed data, mutates a String through RefCell, and adds lifetime markers to linked-list iterators.
What it assumes
Assumes familiarity with Rust functions and references while explaining lifetime notation and when explicit annotations are needed.
What you can do after
Diagnose/debug with it when a mutation or reference-lifetime error requires distinguishing ownership, borrowing, and explicit lifetime relationships.
How it connects
Connects ownership, mutable references, Copy, interior mutability, lifetimes, PhantomData, and unsafe iterator implementations.

Also explained in

Compare how 4 books explain borrow checker →

Related concepts

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