Rustには2つの主な参照の種類があります:
&T):読み取り専用のアクセスを提供します。&mut T):参照する値を変更することを可能にします。ルール:
構文の例:
fn read(val: &i32) { println!("{}", val); } fn write(val: &mut i32) { *val += 1; } let mut x = 5; read(&x); write(&mut x);
質問: 1つの関数の異なるスコープで同じ変数に2つの可変参照を作成できますか?
回答: いいえ、たとえ参照が異なるブロックで作成されても、借用解析のスコープは関数全体または変数全体をカバーし、コンパイラが参照が交差しないことを正確に証明できない場合です。これにより、コンパイルエラーが発生することがよくあります:
let mut x = 10; let r1 = &mut x; { let r2 = &mut x; // エラー! }
物語
パーサの開発中、開発者は読み取りと書き込みの最適化のために、同じバッファに可変参照と不変参照を同時に保持しようとしました。その結果、コードはコンパイルされず、unsafeでルールを「迂回」した後、データリークのバグが発生しました。
物語
データ処理プロジェクトの開始時に、参加者の1人がネストされたスコープを含む複雑なコードの「reanalyze borrow checker」を行いませんでした。その結果、参照の交差により、明示的な位置の指示がソースコードにない「cannot borrow as mutable because it's also borrowed as immutable」エラーが発生しました。
物語
マルチスレッドコードでは、共有データへのアクセスに通常の参照を使用しました。並行スレッドでデータを変更しようとすると、コンパイラの予期しないエラーや、unsafeコードを通じてborrow checkerを迂回する際のデータレースが発生しました。