Smart pointers are types that act like a pointer but add a capability — ownership, reference counting, or interior mutability. The simplest is Box<T>: a value that lives on the heap.
Box: a value on the heap
Box<T> stores its T on the heap and holds a pointer to it on the stack. It owns the value (drops it when the Box drops) and otherwise behaves like the value itself. Most of the time you don't need it — values live happily on the stack. You reach for Box in three specific situations.
When you need a Box
One: a recursive type, like a tree node that contains itself — without indirection its size would be infinite, so Box breaks the cycle. Two: a large value you want to move cheaply (move the pointer, not the bytes). Three: a trait object, Box<dyn Trait>, which you met in the Traits track — a fixed-size handle to a differently-sized concrete type.
The recursive type classic
A type like enum List { Cons(i32, List), Nil } won't compile — Rust can't compute its size because it nests forever. Wrap the recursive field in a Box — Cons(i32, Box<List>) — and the size becomes 'an i32 plus a pointer,' finite and known. This is the textbook reason Box exists.