付録G: Rustの作られ方と“Nightly Rust”

この付録は、Rustのでき方と、それがRust開発者としてあなたにどう影響するかについてです。 この本の出力は安定版Rust 1.21.0で生成されていますが、コンパイルできるいかなる例も、 それより新しいRustのどんな安定版でもコンパイルでき続けられるはずということに触れました。 この節は、これが本当のことであると保証する方法を説明します!

停滞なしの安定性

言語として、Rustはコードの安定性について大いに注意しています。Rustには、その上に建築できる岩のように硬い基礎であってほしく、 物事が定期的に変わっていたら、それは実現できません。同時に新しい機能で実験できなければ、もはや何も変更できないリリースの時まで、 重大な瑕疵(かし)を発見できなくなるかもしれません。

この問題に対する我々の解決策は「停滞なしの安定性」と呼ばれるもので、ガイドの原則は以下の通りです: 安定版Rustの新しいバージョンにアップグレードするのを恐れる必要は何もないはずです。各アップグレードは痛みのないもののはずですが、 新しい機能、より少ないバグ、高速なコンパイル時間も齎すべきです。

シュポシュポ!リリースチャンネルと列車に乗ること

Rust開発は、電車のダイヤに合わせて処理されます。つまり、全開発はRustリポジトリのmasterブランチで行われます。 リリースはソフトウェアのリリーストレインモデル(software release train model)に従い、これはCisco IOSや他のソフトウェアプロジェクトで活用されています。 Rustにはリリースチャンネルが3つあります:

注釈: software release train modelとは、あるバージョンのソフトウェアリリースの順番を列車に見立て、 列車のダイヤのように、決まった間隔でリリースに持って行く手法のことの模様。一つの列車は、Rustの場合、 ナイトリー、ベータ、安定版の順に「駅」に停車していくものと思われる。

  • ナイトリー
  • ベータ
  • 安定版

多くのRust開発者は主に安定版チャンネルを使用しますが、新しい実験的な機能を試したい方は、 ナイトリーやベータを使用するかもしれません。

こちらが、開発とリリースプロセスの動き方の例です: RustチームがRust1.5のリリースに取り掛かっていると想定しましょう。 そのリリースは、2015年の11月に発生しましたが、現実的なバージョンナンバーを与えてくれるでしょう。 新しい機能がRustに追加されます: 新しいコミットがmasterブランチに着地します。毎晩、新しいナイトリ版のRustが生成されます。 毎日がリリース日で、これらのリリースは、リリースインフラにより自動で作成されます。故に、 時間が経てばリリースは、毎晩1回、以下のような見た目になります:

nightly: * - - * - - *

6週間ごとに、新しいリリースを準備するタイミングになります!Rustリポジトリのbetaブランチが、 ナイトリで使用されるmasterブランチから枝分かれします。さて、リリースが二つになりました:

nightly: * - - * - - *
                     |
beta:                *

ほとんどのRustユーザはベータリリースを積極的には使用しませんが、自身のCIシステム内でベータに対してテストを行い、 Rustが不具合の可能性を発見するのを手伝います。その間も、やはりナイトリリリースは毎晩あります:

注釈: CIはContinuous Integration(継続統合といったところか)のことと思われる。開発者のコードを1日に何度も、 メインのブランチに統合することらしい。

nightly: * - - * - - * - - * - - *
                     |
beta:                *

不具合が見つかったとしましょう。よいことに、不具合が安定版のリリースにこっそり持ち込まれる前にベータリリースをテストする時間がありました! 修正がmasterに適用されるので、ナイトリは修正され、それから修正がbetaブランチにバックポートされ、 ベータの新しいリリースが生成されます:

nightly: * - - * - - * - - * - - * - - *
                     |
beta:                * - - - - - - - - *

最初のベータが作成されてから6週間後、安定版のリリースの時間です!stableブランチがbetaブランチから生成されます:

nightly: * - - * - - * - - * - - * - - * - * - *
                     |
beta:                * - - - - - - - - *
                                       |
stable:                                *

やりました!Rust1.5が完了しました!ですが、1つ忘れていることがあります: 6週間が経過したので、 のバージョンのRust(1.6)の新しいベータも必要です。従って、stablebetaから枝分かれした後に、 次のバージョンのbetanightlyから再度枝分かれします:

nightly: * - - * - - * - - * - - * - - * - * - *
                     |                         |
beta:                * - - - - - - - - *       *
                                       |
stable:                                *

これが「トレイン・モデル」と呼ばれます。6週間ごとにリリースが「駅を出発する」からですが、 安定版リリースとして到着する前にベータチャンネルの旅をそれでもしなければなりません。

Rustは6週間ごとに時計仕掛けのようにリリースされます。あるRustリリースの日付を知っていれば、 次のリリースの日付もわかります: 6週間後です。6週間ごとにリリースを組むことのいい側面は、次の列車がすぐにやってくることです。 ある機能が偶然、特定のリリースを逃しても、心配する必要はありません: 別のリリースがすぐに起きます! これにより、リリースの締め切りが近い洗練されていない可能性のある機能をこっそり持ち込むプレッシャーが減る助けになるのです。

このプロセスのおかげで、Rustの次のビルドを常に確認し、アップグレードするのが容易であると自身に対して確かめることができます: ベータリリースが予想した通りに動かなければ、チームに報告して、次の安定版のリリースが起きる前に直してもらうことができるのです! ベータリリースでの破損はどちらかといえば稀ですが、rustcもソフトウェアの一種であり、バグは確実に存在します。

安定しない機能

このリリースモデルにはもう一つ掴み所があります: 安定しない機能です。Rustは「機能フラグ」と呼ばれるテクニックを使用して、 あるリリースで有効にする機能を決定します。新しい機能が活発に開発中なら、masterに着地し、 故にナイトリーでは機能フラグの背後に存在します。ユーザとして、絶賛作業中の機能を試したいとお望みならば、 可能ですが、ナイトリリリースのRustを使用し、ソースコードに適切なフラグを注釈して同意しなければなりません。

ベータか安定リリースのRustを使用しているなら、機能フラグは使用できません。これが、永遠に安定であると宣言する前に、 新しい機能を実用に供することができる鍵になっています。最先端を選択するのをお望みの方はそうすることができ、 岩のように硬い経験をお望みの方は、安定版に執着し自分のコードが壊れることはないとわかります。停滞なしの安定性です。

この本は安定な機能についての情報のみ含んでいます。現在進行形の機能は、変化中であり、 確実にこの本が執筆された時と安定版ビルドで有効化された時で異なるからです。ナイトリ限定の機能についてのドキュメンテーションは、 オンラインで発見できます。

RustupとRustナイトリの役目

rustupは、グローバルかプロジェクトごとにRustのリリースチャンネルを変更しやすくしてくれます。 標準では、安定版のRustがインストールされます。例えば、ナイトリをインストールするには:

$ rustup install nightly

rustupでインストールした全ツールチェーン(Rustのリリースと関連するコンポーネント)も確認できます。 こちらは、著者の一人のWindowsコンピュータの例です:

> rustup toolchain list
stable-x86_64-pc-windows-msvc (default)
beta-x86_64-pc-windows-msvc
nightly-x86_64-pc-windows-msvc

おわかりのように、安定版のツールチェーンが標準です。ほとんどのRustユーザは、ほとんどの場合、安定版を使用します。 あなたもほとんどの場合安定版を使用したい可能性がありますが、最前線の機能が気になるので、特定のプロジェクトではナイトリを使用したいかもしれません。 そうするためには、そのプロジェクトのディレクトリでrustup overrideを使用して、そのディレクトリにいる時に、 rustupが使用するべきツールチェーンとしてナイトリ版のものをセットします。

$ cd ~/projects/needs-nightly
$ rustup override set nightly

これで ~/projects/needs-nightly内でrustccargoを呼び出す度に、rustupは既定の安定版のRustではなく、 ナイトリRustを使用していることを確かめます。Rustプロジェクトが大量にある時には、重宝します。

RFCプロセスとチーム

では、これらの新しい機能をどう習うのでしょうか?Rustの開発モデルは、Request For Comments (RFC; コメントの要求)プロセスに従っています。 Rustに改善を行いたければ、RFCと呼ばれる提案を書き上げます。

誰もがRFCを書いてRustを改善でき、提案はRustチームにより査読され議論され、このチームは多くの話題のサブチームから構成されています。 RustのWebサイトにはチームの完全なリストがあり、 プロジェクトの各分野のチームも含みます: 言語設計、コンパイラ実装、インフラ、ドキュメンテーションなどです。 適切なチームが提案とコメントを読み、自身のコメントを書き、最終的にその機能を受け入れるか拒否するかの同意があります。

機能が受け入れられれば、Rustリポジトリでissueが開かれ、誰かがそれを実装します。うまく実装できる人は、 そもそもその機能を提案した人ではないかもしれません!実装の準備ができたら、 「安定しない機能」節で議論したように、機能ゲートの背後のmasterに着地します。

時間経過後、一旦ナイトリリリースを使用するRust開発者が新しい機能を試すことができたら、チームのメンバーがその機能と、 ナイトリでどう機能しているかについて議論し、安定版のRustに導入すべきかどうか決定します。 決定が進行させることだったら、機能ゲートは取り除かれ、その機能はもう安定と考えられます! Rustの新しい安定版リリースまで、列車に乗っているのです。