Rust は、Mozilla がブラウザを書くために特別に開発したものなので、このテクノロジーが Chromium でようやく使われ始めるようになるのは、理にかなったことです。システム ソフトウェア業界に莫大な貢献をしてくださっている Mozilla に感謝いたします。Rust は、安全性とパフォーマンスの両方を言語に期待できることを見事に証明しています。
C++ と Rust は、cxx、autocxx、bindgen、cbindgen、diplomat、(試験運用版の)crubit などのツールを使ってうまく連携できることがわかっています。ただし、制限事項もあります。やがて新しいツールや改良されたツールによって、こういった制限事項の状況は変わるものと期待できますが、今回の決断や説明は現在のテクノロジーの状況に基づいています。
現時点では、C++ から Rust への一方通行の利用のみをサポートします。Chromium は C++ で書かれており、main() から exit() までのスタック フレームの大半は C++ コードです。前述の方向を選んだ理由はここにあります。利用を一方向に限定することで、依存関係ツリーの形を制御します。Rust は C++ に依存することはできないので、依存関係の注入を除けば、Rust が C++ の型や関数を知ることはできません。こうすることで、Rust は任意の C++ コードではなく、C++ から API を通して渡された関数だけを実行できるようになります。
現時点では、サードパーティ製ライブラリのみをサポートします。サードパーティ製ライブラリはスタンドアロン コンポーネントとして書かれたもので、Chromium の実装についての暗黙的な知識は持ち合わせていません。つまり、シンプルで 1 つのタスクに特化した API を提供しています。言い換えれば、通常はインターフェースが狭く、複雑なポインタグラフや共有所有権は存在しません。C++ で使用するライブラリのレビューし、期待を満たすものであることを確認します。
Chromium での Rust と C++ の相互利用
これまで成功を収めてきたほとんどの C/C++ と Rust の相互利用事例は、狭い API(例 : QUIC や bluetooth のライブラリ、Linux ドライバ)や明確に分離されたコンポーネント(例 : IDL、IPC)によるものが中心でした。Chrome では、//content/public レイヤなど、基本的ではあるものの実に広範な C++ API が使われています。私たちは、こういった種類の API に対して Rust コンポーネントを構築することがどのような意味を持つのかについて検討しました。高レベルでは、C++ と Rust は異なるルールで動作するため、とても簡単に横道にそれてしまう可能性があることがわかりました。
たとえば、Rust は生存期間(推論または明示的記述による)と排他的可変性という 2 つの入力を使った静的解析で一時メモリの安全性を保証します。後者は、Chromium の大半の C++ の記述方法と互換性がありません。冗長な可変ポインタや、可変ポインタに到達する複数のパスを提供するポインタは、システムのいたるところに存在しています。循環する可変データ構造も存在します。(可変)ポインタが相互に連結した巨大な構造が含まれているブラウザのプロセスには、これが特に当てはまります。こういった C++ ポインタが複雑かつ長時間存在する形で Rust 参照にも使われるとすれば、C++ 作成者が Rust のエイリアス ルールを理解し、たとえば次のような方法で、それに違反する可能性を除かなければならなくなります。
1 つの関数から同じ可変ポインタを 2 回返し、1 つを保持できるようにする。
重複する複数のポインタの片方は可変として Rust に渡し、参照として同時に保持できるようにする。
共有または可変の参照を通して、Rust から状態の変化が見えるようにする。
コンパイラや型システムを通してサポートを提供する相互利用ツールがない場合、デベロッパーは Rust コンパイラが前提とする内容をすべて理解し、C++ 側からそれに違反することがないようにしなければなりません。この枠組みでは、C++ は安全でない Rust と同じであるも同然です。また、安全でない Rust はプロジェクトにとってコストがかかるものですが、そのコストはカプセル化を維持し、最低限にとどめることによって管理できます。同様に、C++ は非常に複雑なので、安全な Rust からカプセル化する必要があります。相互利用のために設計した狭い API は、同じようなカプセル化を提供できます。私たちは、言語間で広い API を許可できるような別の方法で、相互利用ツールがカプセル化を提供できるようになることを期待しています。
私たちは、この戦略に従って基準を定め、サードパーティのプロセスを通じて API レビューのレベルを維持する予定です。同時に、相互利用サポートの未来を見据え、Rust と C++ の間で合理的に行えることの限界を押し上げていきます。
その他の関連コンテンツ
メモリが安全でないことは業界全体の問題であり、この領域で変化を起こす戦略の 1 つが Rust の利用です。最近、Android と Apple がこの件に関してそれぞれすばらしいブログ投稿を公開しているので、興味がある方はぜひご覧ください。Chrome には数百万行の C++ があり、MiraclePtr などのプロジェクトを通じて C++ の安全性を向上する作業も懸命に行われています。