2月1日、Naman Goel氏が「Swift is a more convenient Rust」と題したブログ記事を公開した(元々は2023年10月に古いブログで投稿していた)。この記事では、SwiftとRustの類似性と、設計思想における相違点について詳しく紹介されている。

以下に、その内容を紹介する。
SwiftとRustの共通点と違い
Rustは、ガベージコレクション(GC)に頼らず、所有権という概念を通じてメモリ管理の問題を解決した高速なシステム言語である。一方、SwiftもまたGCを持たず、タグ付き列挙型(Tagged Enums)、パターンマッチング、第一級関数、ジェネリクスを備えた強力な型システムなど、Rustと共通する多くのモダンな機能を備えている。両者ともにLLVMベースのコンパイラを採用し、ネイティブコードやWASMへのコンパイルが可能だ。
しかし、両者の決定的な違いはその「アプローチの方向性」にある。Rustはボトムアップ(低レイヤーから高レイヤーへ)の言語であり、Swiftはトップダウン(高レイヤーから低レイヤーへ)の言語であると言える。
メモリ管理のデフォルト値
Rustはデフォルトで「移動(Move)」や「借用(Borrow)」を活用し、参照カウント(Rc, Arc)や Cow(Copy-on-Write)を使用するには明示的な記述が必要となる。これに対し、SwiftはデフォルトでCopy-on-Writeセマンティクスを持つ値型を中心に据えている。
Swiftでは、利便性を優先して自動参照カウント(ARC)や値型のコピーが背後で行われるが、パフォーマンスが必要な場合には所有権システムをオプトインし、値の「移動」を明示することでコピーを回避できる。Rustはデフォルトで「高速」であり、Swiftはデフォルトで「簡潔かつ容易」だ。
構文による抽象化
Swiftの構文は、高度な関数型言語の概念をC系言語に近い外見で包み込んでいる。
パターンマッチング
Rustの match 式は、Swiftでは馴染み深い switch 文として実装されている。
Rustの例:
enum Coin {
Penny,
Nickel,
Dime,
Quarter,
}
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
}
}
Swiftの例:
enum Coin {
case penny
case nickel
case dime
case quarter
}
func valueInCents(coin: Coin) -> Int {
switch coin {
case .penny: 1
case .nickel: 5
case .dime: 10
case .quarter: 25
}
}
Swiftの switch は実際には式として機能し、フォールスルー(自動的な次のケースへの遷移)も行わない。さらに、列挙型自体にメソッドを持たせることも可能だ。
オプショナル型とエラーハンドリング
Rustの Option<T> は、Swiftでは T? という糖衣構文で提供される。Swiftでは Some(val) で包む作業をコンパイラが透過的に行うため、記述が簡略化されている。
let val: T?
if let val {
// valは型Tとして扱える
}
エラーハンドリングにおいても、Swiftは do-catch と try キーワードを用いるが、実態はRustの Result 型に近い挙動を、既存のプログラマに馴染みのある構文で再現している。
コンパイラによる支援の形態
Rustのコンパイラは問題を厳格に指摘し、解決策を提示する。例えば、自己参照的な再帰的列挙型を定義する場合、Rustは Box<> の使用を強制する。
Rustの例:
enum TreeNode<T> {
Leaf(T),
Branch(Vec<Box<TreeNode<T>>>),
}
Swiftの例:
indirect enum TreeNode<T> {
case leaf(T)
case branch([TreeNode<T>])
}
Swiftでは indirect キーワードを指定するだけで、メモリ上の配置(Box化など)はコンパイラが自動的に処理する。
Swiftの機能とトレードオフ
SwiftはObjective-Cの代替として設計された経緯から、現実的で広範な機能を備えている。
- クラスと継承
- async-await / async-sequences
- アクター(Actors)
- getter / setter
- 遅延初期化プロパティ(lazy properties)
- プロパティラッパー(property wrappers)
- Result Builders(SwiftUIなどで利用)
利便性の代償として、SwiftはRustよりもバイナリサイズや実行速度で劣る傾向にある。RustはシステムプログラミングやOS、ブラウザエンジンの開発に適しており、SwiftはUI開発やサーバーサイド、アプリケーション開発に適している。
クロスプラットフォームへの展開
「SwiftはAppleプラットフォーム専用」という認識は過去のものになりつつある。
- Windows: The Browser CompanyがArcブラウザのWindows版開発にSwiftを利用している。
- Linux: AppleがサーバーサイドSwiftを公式に推進しており、FoundationライブラリのSwiftへの移植とオープンソース化も完了している。
- 組み込み: 「Embedded Swift」が発表され、Playdateのような小型デバイスでの動作も実現している。
- Wasm: Swift-Wasmチームの成果が公式のSwiftコアに統合された。
結論
Swiftは完璧な言語ではない。コンパイル時間はRustと同様に長く、パッケージエコシステムもRustの crates.io ほど成熟してはいない。しかし、ABI安定性を備え、GCなしで動作し、必要に応じて低レイヤーの制御も可能なSwiftは、現在すでにクロスプラットフォーム開発における「より便利なRustの代替」としての地位を確立し始めている。
詳細はSwift is a more convenient Rustを参照していただきたい。