プログラミング言語Rustとは?
PythonやPhpよりRustでバッチ処理を作った方が圧倒的に早いので、ちゃんと学ぼうとしているときの覚書。
Gemini 3 Pro Previewと対話。
1. プログラミング言語Rustとは?
一言で言えば、C/C++と同等のパフォーマンスを持ちながら、コンパイル時にメモリ安全性を保証するシステムプログラミング言語。
「最も愛されるプログラミング言語」で長年1位を獲得し続けている。
参考: Rust (プログラミング言語) - Wikipedia
- 2006年:Mozillaで開発がスタート。
- 2015年:安定版となるRust 1.0がリリース。
- 2022年:Linux Kernel 6.1 にて、C言語に次ぐ「第2の公式言語」としてRustがマージ。
- 2025年:Microsoftは2030年までに自社の主要コードベースからCおよびC++を全面的に排除し、Rustへ移行する長期方針。
2. Rustの技術的特徴
① 所有権システム(Ownership & Borrowing)
- ルール: 値には必ず「所有者(変数)」が1つだけ存在する。
所有者がスコープを抜けると値は破棄(ドロップ)される。 - 借用(Borrowing): 参照渡しのような機能。
「不変の参照は複数作れる」が、「可変の参照は同時に1つしか作れない」というルール(RWLockのような概念)をコンパイル時に強制する。 - 効果: これにより、GCなしでのメモリ解放を実現し、さらにデータ競合(Data Race)をコンパイルエラーとして検出する。
例えると、メモリ上のデータは「1冊の貴重な本」。
プログラミング言語の世界(C++やJavaなど)では、この本をコピーしたり、みんなで同時に書き込んだりできるが、Rustの世界は物理法則に忠実。
- 所有権(Ownership)と ムーブ(Move): 本を持てるのは、常に世界でたった一人だけ。
最後に本を持っていた人が責任を持って捨てる(メモリを解放)。 - 借用(Borrowing): 見るだけなら、何人でも同時に貸していい。
貸している間、所有者も本を捨てたり書き換えたりできない(読んでいる人が困るから)。 - 可変の借用(Mutable Borrowing): 書き込みたいなら、貸せるのは「たった一人」だけ。
「書き込み権限(&mut)」を貸すときは、他の誰にも(見る権利さえも)貸してはいけない。
この厳格なルールのおかげで、Rustは実行してみないと分からないデータ競合をコンパイル時に100%排除できる。
② ゼロコスト抽象化
C++と同様、高レベルな記述(イテレータ、高階関数など)をしても、コンパイル(LLVMバックエンド)によって最適化された機械語に変換される。
つまり速くなる書き方はない。
読みやすく綺麗なコードを書くことに集中できる。
③ 現代的な型システムとエラー処理
- 代数的データ型 (Enum): 直和型をサポートしており、強力なパターンマッチングが可能。
- Result<T, E> / Option<T>: null や例外機構(Exception)が存在しない。
失敗する可能性のある処理は Result 型を返し、呼び出し元で明示的なハンドリングを強制する。
④ 強力なツールチェーン (Cargo)
ビルドツール兼パッケージマネージャである Cargo が標準で付属。
依存関係の管理、ビルド、テスト、ドキュメント生成、ベンチマークまでこれ1つで完結する。
C/C++のCMakeやMakeの複雑さに比べると、開発体験が非常に高い。
3. Rustのエコシステム
コーディング規約 (Lint / Formatter)
Rustには「公式が定めたスタイル」が存在し、議論の余地がほとんどない。
- cargo fmt コマンド一発で、コミュニティ標準のスタイル(インデント、改行、ブレース位置など)に自動整形される。
CIに組み込むのが一般的。 - clippy(静的解析ツール)は単なるスタイルチェックにとどまらず、「よりRustらしい書き方(Idiomatic Rust)」や「パフォーマンス改善」「潜在的なバグ」まで提案してくれる。
テスト (Testing)
Rustはテストフレームワークを言語機能として内蔵している。
外部ライブラリ(JUnitやPyTestのようなもの)を導入しなくても、即座にテスト駆動開発(TDD)が始められる。
- ユニットテスト: ソースコードと同じファイル内に #[test] 属性を付けた関数を書くだけでテストになる。
プライベート関数も直接テスト可能。 - 統合テスト: プロジェクトルートの tests/ ディレクトリにファイルを置くと、ライブラリの利用者視点(外部API経由)でのテストとして自動認識される。
- ドキュメンテーションテスト (Doctest): ドキュメント(コメント)内に書いたコード例(Example)も、テスト実行時に実際にコンパイル・実行る。
「ドキュメントのサンプルコードが古くて動かない」という「あるある」を防げる。 - 実行: cargo test コマンドで並列実行される。
ドキュメント生成
「ドキュメントはコードの近くにあるべき」という思想のもと、Markdownベースのドキュメント生成ツールが標準装備されている。
- rustdoc: ソースコード内の /// や //! で始まるコメントにMarkdownを記述し、cargo doc --open を叩くと、ハイパーリンク付きのHTMLドキュメントが生成され、ブラウザで開かれる。
- 特徴: 構造体、関数、トレイトなどの定義へ自動でジャンプできる。
標準ライブラリからサードパーティ製ライブラリ(Crates.io)まで、すべてのドキュメントのデザインが統一されており(docs.rs)、エンジニアにとって非常に読みやすい。
ベンチマーク
パフォーマンスを重視する言語であるため、計測文化が根付いている。
Rustのコンパイラ(Nightly版)には標準ベンチマーク機能があるが、安定版(Stable)では Criterion.rs というライブラリを使うのがデファクトスタンダード。
Criterion.rsの特徴
- 統計的処理を自動で行う(外れ値の除外、信頼区間の計算など)。
- 前回の実行結果と比較し、「有意に速くなった/遅くなった」を検知してレポートする。
- cargo bench コマンドで実行可能。
これにより、推測ではなく計測に基づいたパフォーマンスチューニングが可能。
4. AIに記述させることの親和性
AIコーディング支援とRustの相性は、「記述させるのは得意だが、論理的な整合性を取るのが難しい」という二面性がある。
Rust初心者がAIに丸投げすると、コンパイルエラーが取れずに詰む可能性が高い。
Positive (相性が良い点)
- コンパイラが強力なレビュアー: AIが適当なコードを書いても、Rustのコンパイラが厳格にチェックするため、「コンパイルさえ通れば正しく動く可能性が高い」。
動的言語(Python/JS)のように「実行時に謎のエラーで落ちるコード」をAIが生成するリスクは低減される。 - ボイラープレートの削減: impl ブロックの記述や、エラーハンドリングの定型文などはAIが非常に得意としており、生産性が劇的に向上する。
- 型情報による推論: 型システムが厳密であるため、AIもコンテキスト(引数の型や戻り値)を推測しやすく、精度の高い補完が効きやすい。
Negative (課題点)
- 所有権・ライフタイムの解決: AIは文法的に正しいコードは書けるが、「メモリの所有権やライフタイムの整合性」を深く理解してアーキテクチャを提案するのは苦手。
- コンパイルエラーの修正ループ: AIが生成したコードがBorrow Checker(借用チェッカー)に怒られ、それをAIに修正させようとすると、さらに複雑な(そして間違った)ライフタイム注釈を追加して泥沼化することがよくある。
AIを使ったRustプログラミングコツ by Gemini先生
- 処理より先にデータ(構造体)を作らせる
いきなり「〇〇機能を作って」と言わず、「この機能に必要な struct(構造体)を定義して」と頼んでください。
Rustはデータの型が決まれば、あとはパズルのようにコードが決まります。 - 関数は「1つずつ」書かせる
「全体を書いて」と頼むと、複雑なライフタイムエラーが出やすくなります。
「この構造体に、データを追加する関数だけ書いて」と、小さく切り出して指示してください。 - エラーが出たら「エラー文」をそのままコピペして聞く
Rustのコンパイラエラーは難しい専門用語(借用、ライフタイム等)が出ます。
エラー文をAIに貼り付け、「なぜこのエラーが出るのか、初心者向けに比喩を使って解説して」と聞いてください。修正案も出してくれます。 - 「初心者向けの書き方で」と指定する
AIは時々、マニアックで難しい書き方(高度なマクロや複雑なイテレータ)を提案します。
「unwrap や clone を使ってもいいので、一番わかりやすい書き方にして」と指示して、難易度を下げさせましょう。 - コードの「意味」を日本語で説明させる
書いてもらったコードの中に知らない記号(&, mut, ?, <T>など)があったら、「この記号はどういう役割?なぜここに必要?」と質問してください。