TL;DR

ある参照がコードのある時点以降で使われないことをコンパイラが立証できる場合に、Rust コンパイラがスコープの末尾ではなく、参照が最後に使われた時点を生存期間の終端として扱う機能である。

なぜ必要か

以前のコンパイラでは、参照が複数の文にまたがると、生存期間がそれらを囲む最も内側のブロックの末尾まで延びていた。そのため、もう使っていない参照があるだけで借用ルールに違反したと判定され、人為的なブロックで囲むなどの回避策が必要だった。NLL は生存期間を字句的なスコープではなく制御フローグラフから推論し、こうしたコードを通せるようにした。

例

RFC 2094 に挙げられている例である。slice は capitalize の呼び出しより後で使われていない。それでも、以前のコンパイラは slice の借用がブロックの末尾まで続くとみなし、data.push をエラーにしていた。

let mut data = vec!['a', 'b', 'c'];
let slice = &mut data[..];
capitalize(slice);
data.push('d'); // NLL 以前はエラー

関連

出典