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