Chapter 15.1 - Add contrast between Box<T> and &T

Open
#4,652 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
45/100
Issue type
Documentation
Clarity
Mostly clear
Activity status
Stale
Tech stack
rust
Domain
documentation

Research direction

Start with Chapter 15.1, especially “Getting a Recursive Type with a Known Size,” and review the existing explanation of Box for recursive types. Compare it with the referenced regular-reference example and document the lifetime and ownership distinction, including when each approach is appropriate. Done means the chapter clearly addresses both alternatives without disrupting its existing explanation.

Written by the indexing model from the issue text.

Description

Chapter 15.1 introduces the smart pointer type Box<T> and explains how to work with recursive types. In the section “Getting a Recursive Type with a Known Size”, the book uses Box<T> as indirection to give the recursive type List a known size. While reading this section, I noticed the compiler suggestion:

help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
  |
2 |     Cons(i32, Box<List>),
  |               ++++    +

This suggests that regular references (i.e., &) can also be used to break the cycle. I therefore tried writing the following code, which also compiles:

#[derive(Debug)]
pub enum List<'a, T> {
    Cons(T, &'a List<'a, T>),
    Nil,
}

use crate::List::{Cons, Nil};

fn main() {
    let list = Cons(1, &Cons(2, &Cons(3, &Nil)));
    println!("{list:?}",);
}

In this example, a regular reference is used instead of Box<T> to break the recursive cycle. I think other readers might also consider this approach when thinking about recursive types, so it could be helpful to compare and contrast these two ways of breaking the cycle.

From my understanding (feel free to correct me or add further insights!), the main difference between using a regular reference and using Box<T> for List lies in the lifetime relationship between a parent List and its child List. From Chapter 10.1, we know that when a reference is stored as a field in a struct or enum, its lifetime must be explicitly specified. In my code snippet, I add a lifetime parameter 'a to List and use it to describe the lifetime of the reference to the child List. This introduces a lifetime constraint between a parent List and its child.

In contrast, when Box<T> is used to break the cycle, each Box<T> owns its contents on the heap and cleans them up independently, so the lifetimes of different list nodes are not explicitly tied together in the type definition. A brief discussion of this distinction in Chapter 15.1 might help readers better understand why the smart pointer Box<T> is often a better choice than a regular reference when defining a recursive type.

Dominant language
Rust
Stars
18.3k
Forks
4.1k
Avg merge
14m
Merged PRs (30d)
1

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from rust-lang/book

All issues in rust-lang/book

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.