第1章: Rustの歴史と設計思想

学習目標

  • Rustが生まれた歴史的背景を理解する
  • Rustの設計思想とトレードオフを学ぶ
  • Rustが解決しようとした問題を知る
  • 他の言語との比較から、Rustの立ち位置を把握する

---

1.1 プログラミング言語史におけるRustの誕生

1.1.1 システムプログラミングの課題

システムプログラミングの世界は、長年にわたり2つの陣営に分かれていました:

┌─────────────────────────────────────────────────────────┐
│                  システムプログラミングの二極化            │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  【C/C++陣営】                   【高水準言語陣営】        │
│                                                         │
│  ✓ 高速                          ✓ メモリ安全            │
│  ✓ ハードウェア制御              ✓ 生産性が高い           │
│  ✗ メモリ安全性なし              ✗ パフォーマンスが低い    │
│  ✗ データ競合の危険              ✗ GCによるレイテンシ      │
│                                                         │
│         「速いが危険」   vs   「安全だが遅い」            │
│                                                         │
└─────────────────────────────────────────────────────────┘

この二極化は、長年にわたりfalse dichotomy(誤った二分法)として受け入れられてきました。

1.1.2 Mozillaの問題:Firefoxとセキュリティ

2006年、Mozilla Foundationは深刻な問題に直面していました:

統計データ(2006-2010)

  • Firefoxのセキュリティバグの 70%以上 がメモリ安全性の問題
  • Use-after-free、バッファオーバーフロー、NULL pointer dereference
  • これらはすべて C++の手動メモリ管理 に起因

Firefox Security Bugs (2006-2010)
────────────────────────────────────
Memory Safety:           ████████████████████████ 70%
Logic Errors:            ████████ 20%
Other:                   ███ 10%

Graydon Hoareの洞察(Rust作者、当時Mozilla Research):

> 「私たちはC++でブラウザを書いている。C++は高速だが、メモリ安全性がない。 > このトレードオフは本当に必要なのか?理論的には、コンパイル時に安全性を保証できるはずだ。」

1.1.3 Rustプロジェクトの開始(2006-2015)

タイムライン

2006  Graydon Hoare、個人プロジェクトとしてRustを開始
      │  OCaml実装、実験的な型システム
      │
2009  Mozillaが公式にスポンサー
      │  プロトタイプから本格的な言語開発へ
      │
2010  初めて公開発表
      │  コンパイラをOCamlからRustへ self-hosting
      │
2012  Rust 0.1リリース
      │  所有権システムの基礎を導入
      │
2015  Rust 1.0リリース - 安定版
      │  後方互換性の保証開始
      │
2018  Rust 2018 Edition
      │  エルゴノミクス改善、async/await導入準備
      │
2021  Rust 2021 Edition
      │  async/await安定化、エラー処理改善
      │
2024  Rust Foundation設立後の成長期
      │  産業界での広範な採用

---

1.2 Rustの設計思想:ゼロコスト抽象化

1.2.1 コアとなる設計原則

Rustは3つの柱の上に構築されています:

┌─────────────────────────────────────────────────────────┐
│                   Rustの3つの柱                          │
├─────────────────────────────────────────────────────────┤
│                                                         │
│    ┌────────────┐      ┌────────────┐      ┌────────────┐│
│    │            │      │            │      │            ││
│    │  Memory    │      │    Zero    │      │Concurrent  ││
│    │   Safety   │◄────►│    Cost    │◄────►│   Safety   ││
│    │            │      │Abstraction │      │            ││
│    └────────────┘      └────────────┘      └────────────┘│
│                                                         │
│   「安全」          「パフォーマンス」        「並行性」   │
│                                                         │
└─────────────────────────────────────────────────────────┘

1. メモリ安全性(Memory Safety)

C++の問題

// C++: コンパイルは通るが、実行時にクラッシュ
std::vector<int> vec = {1, 2, 3};
int* ptr = &vec[0];
vec.push_back(4);  // vecが再割り当てされるかも
std::cout << *ptr; // Use-after-free! 未定義動作

Rustの解決策

// Rust: コンパイル時にエラー
let mut vec = vec![1, 2, 3];
let ptr = &vec[0];
vec.push(4);  // コンパイルエラー!
              // "cannot borrow `vec` as mutable
              //  because it is also borrowed as immutable"
println!("{}", ptr);

なぜコンパイル時にエラーにできるのか?

Rustは所有権システム(Ownership System)を採用しています:

  • すべての値には1つの所有者が存在
  • 所有者がスコープを抜けると、値は自動的に解放
  • 借用(borrow)には厳格なルールがある

これにより、コンパイル時に以下を保証:

  • Use-after-free なし
  • Double-free なし
  • NULL pointer dereference なし
  • データ競合なし

2. ゼロコスト抽象化(Zero-Cost Abstraction)

Bjarne Stroustrup(C++の父)の原則

> 「使わない機能にはコストを払わない。使う機能は手書き以上に効率化できない。」

Rustはこの原則を型システムで実現

// 高水準な抽象化
let sum: i32 = vec![1, 2, 3, 4, 5]
    .iter()
    .filter(|&x| x % 2 == 0)
    .map(|x| x * 2)
    .sum();

// コンパイル後は手書きループと同等の機械語に!
// 実行時オーバーヘッドなし

コンパイル後(最適化されたアセンブリ)

; シンプルなループと加算命令のみ
; イテレータのオーバーヘッドは完全に消える
mov     eax, 12      ; 結果を直接計算
ret

3. 並行安全性(Concurrency without Data Races)

従来の言語の問題

// C言語: コンパイルは通るが、データ競合
int counter = 0;

void* thread_func(void* arg) {
    for (int i = 0; i < 100000; i++) {
        counter++;  // データ競合!
    }
    return NULL;
}

Rustの解決策

// Rust: データ競合はコンパイル時にエラー
use std::sync::Arc;
use std::sync::Mutex;
use std::thread;

let counter = Arc::new(Mutex::new(0));
let mut handles = vec![];

for _ in 0..10 {
    let counter = Arc::clone(&counter);
    let handle = thread::spawn(move || {
        let mut num = counter.lock().unwrap();
        *num += 1;
    });
    handles.push(handle);
}

for handle in handles {
    handle.join().unwrap();
}

println!("Result: {}", *counter.lock().unwrap());

型システムによる保証

  • Arc: スレッド間で安全に共有可能(参照カウント)
  • Mutex: 排他制御を強制
  • Send / Sync トレイト: スレッド安全性を型で表現

---

1.3 Rustが解決した問題とトレードオフ

1.3.1 解決した問題

1. メモリ安全性とパフォーマンスの両立

従来:

  • C/C++: 高速だが、脆弱性の温床
- 2023年のセキュリティ脆弱性の約70%がメモリ安全性の問題(CVE統計)
  • Java/Python: 安全だが、GCによるレイテンシ
- GCポーズ: 1-100ms(リアルタイムシステムには不向き)

Rustの解決:

  • コンパイル時にメモリ安全性を保証
  • 実行時オーバーヘッドなし(GC不要)

2. データ競合の撲滅

┌─────────────────────────────────────────────────────────┐
│          並行プログラミングの安全性スペクトラム            │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  C/C++         Java/Go         Rust                     │
│  ───────       ───────         ─────                    │
│  全て手動      ランタイム       コンパイル時             │
│  ミスし放題    チェック         型チェック               │
│                                                         │
│  速い ◄─────────────────────────────────► 安全          │
│       Rustはこの両端を達成                               │
│                                                         │
└─────────────────────────────────────────────────────────┘

3. Null参照の問題

Tony Hoare(Null参照の発明者)の謝罪:

> 「I call it my billion-dollar mistake.」 > (これは私の10億ドルの過ちだ)

Rustの解決:

// Rust: Nullは存在しない。代わりにOption<T>
fn find_user(id: u32) -> Option<User> {
    // ...
}

match find_user(42) {
    Some(user) => println!("Found: {}", user.name),
    None => println!("Not found"),
}
// コンパイラがNoneケースの処理を強制

1.3.2 トレードオフと学習曲線

Rustの代償

┌─────────────────────────────────────────────────────────┐
│              学習曲線の比較                              │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  難しさ                                                  │
│    ▲                                                    │
│    │                           ╱ Rust                   │
│    │                      ╱╱╱╱                          │
│    │                 ╱╱╱╱                               │
│    │            ╱╱╱╱                                    │
│    │       ╱╱╱╱     C++                                 │
│    │  ╱╱╱╱    ╱ Python/Go                              │
│    │╱╱╱╱╱╱╱╱                                            │
│    └────────────────────────────────────► 時間          │
│                                                         │
│  Rust: 初期は急勾配だが、プラトーに達すると生産性向上    │
└─────────────────────────────────────────────────────────┘

学習の障壁

  • 所有権システム:従来の言語にない概念
- "fighting with the borrow checker"(借用チェッカーとの戦い) - 多くの初学者がここで挫折

  • ライフタイム注釈:明示的なメモリ寿命の管理
   // 初心者が恐れるコード
   fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
       if x.len() > y.len() { x } else { y }
   }
   

  • エラーハンドリング:Result型の強制
- Goの if err != nil よりも厳格 - ? 演算子の理解が必要

しかし、これらは投資に値する

> 「If it compiles, it usually works.」 > (コンパイルが通れば、大抵動く)

  • コンパイル時に多くのバグを捕捉
  • リファクタリングが安全
  • 並行プログラミングが怖くない

---

1.4 Rustと他の言語の比較

1.4.1 性能比較(Computer Language Benchmarks Game)

                    実行時間(正規化)
                    ─────────────────
C (gcc)             1.0x    ████
Rust                1.03x   ████
C++ (g++)           1.12x   █████
Go                  2.83x   ████████████
Java (OpenJDK)      1.89x   ████████
Python (CPython)    71.9x   ███████████████████████████████████████

                    メモリ使用量(正規化)
                    ─────────────────
C                   1.0x    ███
Rust                1.08x   ███
C++                 1.34x   ████
Go                  3.70x   ███████████
Java                6.20x   ██████████████████
Python              9.64x   █████████████████████████████

Rustの強み

  • C/C++と同等の性能
  • メモリ使用量も最小クラス
  • GC言語よりも予測可能なレイテンシ

1.4.2 言語パラダイム比較

特性 C C++ Rust Go Java
メモリ安全性
GC不要
ゼロコスト抽象化
並行安全性(型) 部分的 部分的
パターンマッチング 限定的 限定的
トレイト/インターフェース
マクロシステム
学習曲線

1.4.3 ユースケース別の選択

Rust が最適

  • システムプログラミング(OS、ドライバ)
  • 組み込みシステム
  • Webサーバー(高負荷)
  • ゲームエンジン
  • ブロックチェーン
  • CLI ツール

C/C++ が依然として優位

  • 既存のエコシステム(Linux kernel)
  • リアルタイムシステム(RustのLLVMが未対応な場合)
  • ハードウェア固有の最適化が必要な場合

Go が優位

  • マイクロサービス(高速開発)
  • ネットワークサーバー(GCの影響が小さい)
  • 社内ツール(学習コストの低さ)

---

1.5 Rustのエコシステムと産業界での採用

1.5.1 主要な採用事例

1. Mozilla(原点)

  • Firefox: Servo(新しいレンダリングエンジン)の成果を統合
  • Stylo: CSS エンジンをRustで再実装(4xの高速化)

2. Microsoft

  • Windows の一部コンポーネントをRustで再実装
  • Azure IoT Edge のセキュリティクリティカルな部分

3. AWS(Amazon Web Services)

  • Firecracker: Lambda と Fargate のマイクロVM
  • Bottlerocket: コンテナ専用OS
  • s2n-quic: QUICプロトコル実装

4. Google

  • Android の Bluetooth スタック
  • Fuchsia OS のコアコンポーネント

5. Meta(Facebook)

  • Mononoke: Mercurial のサーバー
  • Diem(旧Libra)ブロックチェーン

6. Cloudflare

  • エッジコンピューティングプラットフォーム
  • DDoS対策システム

1.5.2 統計データ(2024年)

Stack Overflow Developer Survey

  • 最も愛されている言語: 8年連続1位
  • 87.6% の開発者が「また使いたい」と回答

GitHub

  • スター数トップ10のプロジェクトにRustが多数
  • 年々増加する新規プロジェクト

Crate.io(Rustのパッケージレジストリ)

  • 150,000+ クレート(パッケージ)
  • 毎日数百の新規クレート
  • ---

    1.6 Rustの哲学:Fearless Concurrency

    1.6.1 "Fearless"の意味

    Rustのスローガン:"Fearless Concurrency"(恐れなき並行性)

    ┌─────────────────────────────────────────────────────────┐
    │          従来の並行プログラミング vs Rust                │
    ├─────────────────────────────────────────────────────────┤
    │                                                         │
    │  【従来】                        【Rust】                │
    │                                                         │
    │  ┌──────────────┐              ┌──────────────┐        │
    │  │ コードを書く  │              │ コードを書く  │        │
    │  └───────┬──────┘              └───────┬──────┘        │
    │          │                             │               │
    │          ▼                             ▼               │
    │  ┌──────────────┐              ┌──────────────┐        │
    │  │ コンパイル    │              │ コンパイル    │        │
    │  └───────┬──────┘              └───────┬──────┘        │
    │          │                             │               │
    │          ▼                             │               │
    │  ┌──────────────┐                      │               │
    │  │ 実行          │                     │               │
    │  └───────┬──────┘                      │               │
    │          │                             │               │
    │          ▼                             │               │
    │  ┌──────────────┐                      │               │
    │  │ データ競合!  │              エラーはここで捕捉!    │
    │  │ デバッグ地獄  │                     │               │
    │  └───────┬──────┘                      ▼               │
    │          │                      ┌──────────────┐       │
    │          │                      │ 安全に実行    │       │
    │          │                      └──────────────┘       │
    │          │                                             │
    │          └───► 「実行時」           「コンパイル時」     │
    │                                                         │
    └─────────────────────────────────────────────────────────┘
    

    1.6.2 Rustの約束

    Rustがコンパイル時に保証すること:

  • メモリ安全性
- Use-after-free なし - Buffer overflow なし - Null pointer dereference なし

  • スレッド安全性
- データ競合なし - Send / Sync トレイトによる型レベルの保証

  • 型安全性
- 強力な型推論 - パターンマッチングの網羅性チェック

しかし、Rustが保証しないこと

  • 論理エラー:アルゴリズムの間違い
  • リソースリーク:メモリ以外(ファイルハンドル等)
  • デッドロック:型システムでは防げない

---

1.7 まとめ:なぜRustを学ぶのか?

1.7.1 Rustを学ぶべき理由

1. 未来の標準になる可能性

  • Linux kernel が Rust をサポート(6.1以降)
  • NIST(米国標準技術研究所)がメモリ安全言語を推奨

2. キャリアの価値

  • 需要が高い(求人数増加)
  • 高給与(Stack Overflow調査)

3. より良いプログラマになる

  • メモリ管理の深い理解
  • 並行処理の正しい考え方
  • 型システムの力

4. 楽しい

  • コンパイラが親切(エラーメッセージが詳細)
  • エコシステムが充実(Cargo、Crates.io)
  • コミュニティが温かい

1.7.2 学習のロードマップ

┌─────────────────────────────────────────────────────────┐
│              Rust学習の推奨パス(3ヶ月)                 │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  Week 1-2:  基本構文(変数、関数、制御構文)              │
│             ├─ 「The Book」Chapter 1-4                  │
│             └─ Rustlings 演習                           │
│                                                         │
│  Week 3-4:  所有権システム(山場!)                     │
│             ├─ 「The Book」Chapter 4                    │
│             ├─ 所有権の可視化演習                        │
│             └─ 借用チェッカーとの戦い                    │
│                                                         │
│  Week 5-6:  構造体、Enum、パターンマッチング             │
│             ├─ 「The Book」Chapter 5-6                  │
│             └─ 小さなCLIツール作成                       │
│                                                         │
│  Week 7-8:  エラー処理、ジェネリクス、トレイト            │
│             ├─ 「The Book」Chapter 9-10                 │
│             └─ 実用的なライブラリ設計                    │
│                                                         │
│  Week 9-10: モジュール、テスト、Cargo                    │
│             └─ 実際のプロジェクトを開始                  │
│                                                         │
│  Week 11-12: 並行処理、スマートポインタ                  │
│              └─ 非同期プログラミング入門                 │
│                                                         │
└─────────────────────────────────────────────────────────┘

1.7.3 次のステップ

次の章では、Rustの環境構築とCargoツールチェーンを学びます。実際にRustプログラムを書く準備を整えましょう。

心構え

  • 借用チェッカーとの戦いは誰もが通る道
  • エラーメッセージをよく読む(驚くほど親切)
  • コミュニティに質問する(Rust Users Forum、Discord)

---

参考資料

公式ドキュメント

歴史的資料

コミュニティ