所有権(ownership)は、Rust が「GC なしでメモリ安全」を実現するための背骨だ。 最初はコンパイラと喧嘩しているように感じるが、ルールは驚くほど少ない。 夜が明けるまでに、その地図を描いてしまおう。
所有権の三つのルール
Rust の所有権は、たった三つの規則に集約される。
- 各値には、それを所有する変数(owner)がただ一つだけ存在する。
- owner はある時点でただ一つ。
- owner がスコープを抜けると、値は
dropされる。
ムーブ(move)
値を別の変数に代入すると、所有権は移動する。元の変数はもう使えない。
fn main() {
let s1 = String::from("inherent vice");
let s2 = s1; // 所有権が s1 -> s2 へムーブ
// println!("{s1}"); // ← コンパイルエラー: value borrowed after move
println!("{s2}"); // OK
}String はヒープ上のバッファを持つため、コピーではなくムーブになる。
二重解放(double free)をコンパイル時に潰すための設計だ。
借用(borrow)
所有権を渡さずに値へアクセスしたいときは、参照を借りる。
fn length(s: &String) -> usize {
s.len()
}
fn main() {
let s = String::from("turn on, tune in");
let n = length(&s); // 不変借用。所有権は s に残る
println!("{s}は {n} バイト");
}借用には二つの規則がある。
- 任意の時点で、不変参照は何個でも OR 可変参照はちょうど一つ。
- 参照は、参照先より長生きしてはいけない(ライフタイム)。
この「共有 xor 可変」こそが、データ競合をコンパイル時に排除する核心だ。
まとめ
所有権は制約ではなく、メモリ安全の証明をコンパイラに肩代わりさせる契約だ。 借用チェッカーと喧嘩した夜の数だけ、ランタイムのクラッシュが消えていく。