Rust 基礎講座 #1 Rust とは — 学ぶ理由、rustup のインストールと cargo の最初の一歩
最近の開発ツールの紹介文には「Rust で作った」という一文がやたらと目につきます。Python のパッケージマネージャー uv や検索ツール ripgrep のような CLI ツールがそうですし、Linux カーネルや Windows、Android の一部のコードも Rust で書かれ始めています。このシリーズは、その Rust を土台から学ぶ基礎 9 回です。変数と型から始めて、この言語の心臓である所有権と借用を越え、構造体と列挙型、エラー処理、コレクションとイテレータ、トレイトとジェネリクスを経て、ライフタイムとモジュールまで登ります。プログラミングが初めての方よりは、Python や JavaScript のような言語を 1 つ以上使ったことのある開発者を読者として想定しています。
Rust が解決した問題 — 安全と性能は二者択一だった #
Rust 以前の言語は、メモリ管理でどちらか一方を選ぶしかありませんでした。
- ガベージコレクタ(GC)に任せる側: Python、JavaScript、Go がこちらです。開発者はメモリを気にしなくて済みますが、ランタイムが代わりに働くコストと、GC が割り込む瞬間の遅延を受け入れることになります。
- 開発者が自分で管理する側: C と C++ がこちらです。性能は最大ですが、解放済みのメモリを再び使う(use-after-free)、境界を越えて読むといったミスが丸ごと開発者の責任になります。Microsoft と Chrome チームがそれぞれ自社のセキュリティ脆弱性を分析したところ、約 70% がこの種のメモリバグだったという結果は有名です。
Rust の答えは第三の道です。メモリを誰がいつ解放するかをコンパイル時に検査します。 ランタイムで GC が動くのではなく、コンパイラがコードを見て「この値はこの箇所で解放される」を事前に確定します。だから C 水準の性能を出しながら、メモリバグというクラス全体がコンパイル段階でふるい落とされます。この検査の規則が、第 3 回で扱う所有権(ownership)です。
もちろん代償はあります。所有権の規則に反したコードはそもそもコンパイルが通らないので、最初の数週間は「コンパイラと戦っている」感覚になります。この講座の目標は、その戦いをできるだけ短く終わらせることです。規則の理由を理解すれば、コンパイラは敵ではなく、デプロイ前にバグを捕まえてくれるレビュアーになります。
インストール — rustup の 1 行で済みます #
Rust の公式インストールツールは rustup です。コンパイラ(rustc)、ビルドツール(cargo)、ドキュメントまで一度にインストールし、その後のバージョン管理も担当します。
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shmacOS と Linux の場合で、Windows は rustup 公式サイトから rustup-init.exe をダウンロードして実行します。インストールが終わったら 2 つのコマンドで確認します。
rustc --version
cargo --versionRust は 6 週間ごとに新しい安定版が出て、rustup update の 1 行で更新できます。バージョンが上がるペースは速い一方で後方互換には厳格なので、バージョン差で例が壊れる心配はほとんどありません。この講座は現行標準の 2024 エディション基準で進めます。
cargo — プロジェクトの始まりと終わり #
実務で rustc を直接呼ぶことはほぼありません。プロジェクトの作成、ビルド、実行、依存関係の管理まで、すべて cargo の仕事です。
cargo new hello
cd hello
cargo runcargo new が作る構造は 2 つだけです。
hello/
├── Cargo.toml ← パッケージ情報と依存関係の宣言
└── src/
└── main.rs ← ソースコードのエントリーポイント[package]
name = "hello"
version = "0.1.0"
edition = "2024"コマンドは 3 つ覚えれば始められます。cargo run はビルドして実行、cargo build はビルドのみ、そして cargo check は実行ファイルを作らずコンパイル検査だけを行います。Rust はコンパイルエラーを頻繁に見る言語なので、コードを直すたびに cargo check で素早く確認するのが基本のリズムになります。
最初のプログラム、そして最初のコンパイルエラー #
fn main() {
let name = "Rust";
println!("こんにちは、{name}!");
}fn main がエントリーポイントで、println! の感嘆符は関数ではなくマクロだという印です。ここまでは他の言語と似ています。Rust らしい部分を見るために、わざとエラーを 1 つ出してみます。
fn main() {
let count = 1;
count = 2; // コンパイルエラー
}error[E0384]: cannot assign twice to immutable variable `count`
--> src/main.rs:3:5
|
2 | let count = 1;
| ----- first assignment to `count`
3 | count = 2;
| ^^^^^^^^^ cannot assign twice to immutable variable
|
help: consider making this binding mutable: `mut count`let で宣言した変数は既定で不変、というのが最初の規則ですが、いま注目すべきはエラーメッセージそのものです。どこが問題か、なぜ問題か、どう直せばよいか(help 行)まで教えてくれます。Rust 学習の半分は、このメッセージを読む習慣を身につけることです。エラーコードが気になったら rustc --explain E0384 で詳しい説明と例まで見られます。
まとめ #
- Rust は GC なしでメモリ安全を保証する言語です。解放のタイミングをランタイムではなくコンパイル時に確定する所有権規則が核心で、それによって C 水準の性能とメモリバグの遮断を同時に手に入れます。
- 代償は学習曲線です。規則に反したコードはコンパイルが通りませんが、その分、デプロイ後のクラッシュがコンパイルエラーへと前倒しされます。
- インストールは rustup の 1 行、プロジェクトは cargo がすべて担当します。
cargo new、cargo run、cargo checkの 3 つが基本のリズムです。 - エラーメッセージには原因と直し方まで書かれています。
rustc --explainとあわせて、メッセージを精読する習慣が最速の学習経路です。 - 次回は変数と型を扱います。不変が既定の
let、シャドーイング、そして関数が式で終わる Rust 特有の文法を見ていきます。