借用チェック

Rust の 借用チェッカー は、値を借用する方法に制限を設けます。任意の値に対して、常に次の制限が課されます。

  • 値への共有参照を 1 つ以上持つことが出来ます。または、
  • 値への排他参照を 1 つだけ持つことが出来ます。
fn main() {
    let mut a: i32 = 10;
    let b: &i32 = &a;

    {
        let c: &mut i32 = &mut a;
        *c = 20;
    }

    println!("a: {a}");
    println!("b: {b}");
}
This slide should take about 10 minutes.
  • 要件は、競合する参照が同じ時点に存在しないことです。参照がどこで外されていても構いません。
  • 上記のコードは、ac を通じて可変として借用されていると同時に、b を通じて不変として借用されているため、コンパイルできません。
  • bprintln! ステートメントを c を導入するスコープの前に移動して、コードをコンパイル出来るようにします。
  • この変更後、コンパイラは c を通じたa の可変参照よりも前にしかbが使われていないことを認識します。これは「ノンレキシカル ライフタイム("non-lexical lifetimes")」と呼ばれる借用チェッカーの機能です。
  • 排他参照制約は非常に強力です。Rust はこの制約を使用して、データへの競合が発生しないようにするとともに、コードを最適化しています。たとえば、共有参照を通して得られる値は、その参照が存続する間、安全にレジスタにキャッシュすることが出来ます
  • 借用チェッカーは、構造体内の異なるフィールドへの排他参照を同時に取得するなど、多くの一般的なパターンに対応するように設計されています。しかし、状況によっては借用チェッカーがコードを正しく理解できず、「借用チェッカーとの戦い」に発展することが多くあります。