TL;DR
値どうしが互いを参照し合い、参照がループになった状態。参照カウントで管理していると、ループの中の値のカウントが 0 にならず、メモリリークになる。
なぜ必要か
木構造のように、親と子が互いを指したいデータ構造はよくある。何も考えずに双方向の参照を作ると、値が解放されなくなる。
仕組み
The Rust Programming Language によると、Rust で Rc<T> と RefCell<T> を組み合わせると、値が互いを指すループを作れる。スコープを抜けてもループの中の値のカウントは 1 のままなので、メモリは解放されない。Rust はメモリリークを完全には防がず、メモリリークはメモリ安全とみなしている。
循環を避けるには Weak<T> を使う。Rc::downgrade で作る弱い参照は、strong_count ではなく weak_count を増やす。弱い参照は所有を表さず、値を解放するかどうかに影響しないので、ループに弱い参照が含まれていれば、強い参照が 0 になった時点でループが切れる。弱い参照から値を使うときは upgrade を呼び、値が既にドロップされていれば None が返る。
例
木構造では、親は子を所有し、子は親を所有しない。そこで、親から子へは Rc、子から親へは Weak で指す。
struct Node {
value: i32,
parent: RefCell<Weak<Node>>,
children: RefCell<Vec<Rc<Node>>>,
}[作って学ぶ]ブラウザのしくみ──HTTP、HTML、CSS、JavaScriptの裏側 でも、DOM ツリーを作るときに同じ理由で Rc と Weak を使い分けている。