Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ウォークスルー: 典型的なコントリビューション

バグの修正、パフォーマンスの改善、機能設計の支援、既存機能へのフィードバックの提供など、Rust コンパイラにコントリビュートする方法は_非常にたくさん_あります。 この章は、その表面をなぞるものですらありません。 代わりに、新機能の設計と実装を順を追って説明します。 ここで説明する手順やプロセスのすべてが、すべてのコントリビューションに必要なわけではありません。 必要に応じて、その点も指摘するようにします。

一般に、コントリビューションに関心があるものの、どこから始めればよいかわからない場合は、遠慮なく質問してください!

概要

この章で説明する機能は、マクロ用の ? Kleene 演算子です。 基本的には、次のようなものを書けるようにしたいと考えています。

macro_rules! foo {
    ($arg:ident $(, $optional_arg:ident)?) => {
        println!("{}", $arg);

        $(
            println!("{}", $optional_arg);
        )?
    }
}

fn main() {
    let x = 0;
    foo!(x); // OK! "0" を出力する
    foo!(x, x); // OK! "0 0" を出力する
}

つまり基本的に、マクロ内の $(pat)? マッチャーは、他の正規表現構文と同様に、「このパターンは 0 回または 1 回出現できる」という意味です。

アイデアから安定版 Rust の機能に至るまでには、いくつもの手順がありました。 以下は簡単な一覧です。 これらについては、以下で順番に見ていきます。 先ほど述べたように、これらすべてがあらゆる種類のコントリビューションに必要なわけではありません。

  • アイデアの議論/Pre-RFC Pre-RFC は、機能の初期ドラフトまたは設計に関する議論です。 この段階は、設計空間を少し具体化し、 アイデアに関するさまざまな利点や問題点を把握することを目的としています。 より広い読者に提示する前に、自分のアイデアについて早期のフィードバックを得る優れた方法です。 元の議論はこちらで確認できます。
  • RFC これは、検討のために自分のアイデアをコミュニティへ正式に提示する段階です。 RFC はこちらで確認できます。
  • 実装 自分のアイデアをコンパイラに不安定な形で実装します。 元の実装はこちらで確認できます。
  • 場合によっては反復/改良 コミュニティが nightly コンパイラや std であなたの 機能を使って経験を積むにつれて、調整が必要になる可能性のある設計上の選択について 追加のフィードバックが寄せられることがあります。 この特定の機能は、いくつもの反復経ました
  • 安定化 機能が十分に成熟すると、Rust チームメンバーが 安定化を提案することがあります。 合意があれば、それで完了です。
  • ひと休み あなたの機能は、安定版 Rust の機能になりました!

Pre-RFC と RFC

注: 一般に、Rust やそのエコシステムに対する_新しい_機能や実質的な 変更を提案するのでなければ、RFC プロセスに従う必要はありません。 代わりに、実装へ直接進むことができます。

RFC を開くべきタイミングに関する公式ガイドラインはこちらで確認できます。

RFC は、提案する機能や変更を詳細に説明する文書です。 誰でも RFC を書くことができます。 プロセスは Rust チームメンバーを含め、全員に対して同じです。

RFC を開くには、GitHub 上の rust-lang/rfcs リポジトリで PR を開きます。 詳細な手順は README で確認できます。

RFC を開く前に、自分のアイデアを「具体化」するための調査を行うべきです。 性急に提案された RFC は、受け入れられない傾向があります。 一般には、動機、影響、欠点、および他の機能との潜在的な相互作用について、十分な説明があるべきです。

それが大変そうに聞こえるなら、実際に大変だからです。 でも心配はいりません! コンパイラハッカーでなくても、pre-RFC を行うことで有益なフィードバックを得ることができます。 これは、そのアイデアに関する_非公式な_議論です。 これを行うのに最適な場所は internals.rust-lang.org です。 投稿は特定の構成に従う必要はありません。 まとまったアイデアである必要すらありません。 通常は大量のフィードバックが得られ、それを取り入れて優れた RFC を作成できます。

(もう 1 つの実践的なヒント: 関連する過去のアイデアについて、RFC リポジトリと internals を検索してみてください。 多くの場合、アイデアはすでに検討されており、 却下されているか、後で再試行するために延期されています。 これにより、あなた自身と他の全員の時間を節約できます)

この例の場合、pre-RFC スレッドの参加者が 構文上の曖昧さと潜在的な解決策を指摘しました。 また、全体的なフィードバックは好意的に見えました。 このケースでは議論はかなり早く収束しましたが、 アイデアによっては、はるかに多くの議論が行われることもあります(たとえば、なんと 684 件ものコメントを受け取ったこの RFC を参照してください!)。 そのような場合でも、落胆しないでください。 それはコミュニティがあなたのアイデアに関心を持っているという意味ですが、おそらく何らかの調整が必要なのです。

私たちの ? マクロ機能に関する RFC も、RFC スレッドでいくらか議論されました。 ほとんどの RFC と同様に、議論だけでは答えられない質問がいくつかありました。 判断するには、その機能を使用した経験が必要だったのです。 そのような質問は、RFC の「未解決の質問」セクションに記載されています。 また、RFC の議論の過程では、議論の流れを反映するために、RFC 文書自体を更新したくなることもおそらくあるでしょう(たとえば、新しい代替案や過去の取り組みを追加したり、提案自体の一部を変更することにしたりする場合があります)。

最終的に、議論が合意に達し、少し落ち着いてきたように見えると、 Rust チームメンバーが、3 つの可能な処分のいずれかを伴って「最終コメント期間」(FCP)へ進むことを提案する場合があります。 これは、その人が、適切なチームの他のメンバーに RFC をレビューしてコメントしてほしいと考えていることを意味します。 さらに議論が続く場合があり、その結果、さらなる変更や未解決の質問が追加されることがあります。 ある時点で全員が満足すると、RFC は FCP に入ります。これは、 人々が異議を提起できる最後の機会です。 FCP が終了すると、その処分が採択されます。 3 つの可能な処分は次のとおりです。

  • Merge: 機能を受け入れる。 こちらが、私たちの ? マクロ機能をマージする提案です。
  • Close: この機能は、現在の形では Rust に適していない。 あなたの RFC がこのようになっても落胆しないでください。また、個人的に受け止めないでください。 これはあなた自身への評価ではなく、Rust が 別の方向へ進むというコミュニティの決定です。
  • Postpone: この方向に進むことへの関心はあるが、現時点では行わない。 これは多くの場合、該当する Rust チームに、その機能をプロセスを通じて 安定化まで導く余力がないために起こります。 多くの場合、その機能がチームのロードマップに合わない場合がこれに該当します。 延期されたアイデアは、後で再検討されることがあります。

RFC がマージされると、PR は RFCs リポジトリにマージされます。 新しい tracking issuerust-lang/rust リポジトリに作成され、その機能の進捗を追跡し、 未解決の質問、実装の進捗、ブロッカーなどについて議論します。 こちらが、私たちの ? マクロ機能に関する tracking issue です。

Experimental RFC (eRFC)

eRFC は RFC プロセスの一種で、高レベルの必要性は明確だが、 設計空間が大きすぎて詳細な仕様を最初から確定できない複雑な機能に使われます。 最終的な設計を提供する代わりに、eRFC は一定期間の積極的な実験を認可するための 高レベルな戦略を概説します。 これにより、チームは feature gate の背後で機能を実装し、 実践的なデータを収集できます。そのデータは、その後の安定化に向けた正式な RFC に反映されます。 このプロセスは coroutines のような主要機能で使われましたが(RFC 2033 を参照)、 明示的な “eRFC” ラベルは今日ではほとんど使われていません。 現在このプロジェクトでは一般に、初期バージョンに対して標準の RFC を承認し、最終的な安定化の前に nightly channel を通じて反復することが好まれています。

実装

コンパイラに変更を加えるには、rust-lang/rust リポジトリに対して PR を開きます。

機能、変更、バグ修正、改善によっては、実装は 比較的簡単な場合もあれば、大きな取り組みになる場合もあります。 経験豊富なコンパイラ開発者に、いつでも助けやメンターシップを求めることができます。 また、あなたの機能を実装するのがあなた自身である必要はありません。 ただし、自分で実装しない場合、誰か他の人が実装するまでにしばらくかかる可能性があることは覚えておいてください。

? マクロ機能については、私はコンパイラにおける マクロ展開の関連部分を理解する必要がありました。 個人的には、コード内のコメントを改善することは、自分がそれを理解しているかを 確認するうえで役立つ方法だと思っていますが、 望まないのであればそうする必要はありません。

その後、RFC に記述されているとおりに、元の機能を実装しました。 新しい機能が実装されると、それは feature gate の背後に置かれます。つまり、 その機能を使うには #![feature(my_feature_name)] を使用する必要があります。 feature gate は、その機能が安定化されると削除されます。

ほとんどのバグ修正や改善には feature gate は必要ありません。 単に変更や改善を行うことができます。

rust-lang/rust で PR を開くと、bot があなたの PR をレビュー担当者に割り当てます。 一緒に作業している特定の Rust チームメンバーがいる場合は、 スレッドに r? @reviewer-github-id(例: r? @eddyb)というコメントを残すことで、そのレビュー担当者をリクエストできます。誰をリクエストすればよいかわからない場合は、 誰もリクエストしないでください。 bot が、変更したファイルに基づいて自動的に誰かを割り当てます。

レビュー担当者は、あなたの PR を承認する前に変更を求めることがあります。また、コメントを残した後に PR に “S-waiting-on-author” ラベルを付けることがあります。これは、要求された変更をあなたが行うまで PR がブロックされていることを意味します。 変更の反復作業が完了したら、@rustbot ready というコメントを残すことで、 PR を再び S-waiting-on-review としてマークできます。これにより、 S-waiting-on-author ラベルが削除され、S-waiting-on-review ラベルが追加されます。

質問したり、理解できないことや同意できないことについて議論したりしてかまいません。 ただし、Rust チームの誰かが承認しない限り、PR はマージされないことを認識してください。 レビュー担当者が r=me after fixing ... のようなコメントを残した場合、それはそのレビュー担当者が PR を承認しており、 軽微な問題を修正した後に @bors r=reviewer-github-id(例: @bors r=eddyb)というコメントでマージできることを意味します。 r=someone には権限が必要であり、r=someone とコメントしたときに bors が “🔑 Insufficient privileges…” のように言う場合があることに注意してください。 その場合は、レビュー担当者にあなたの PR を再確認してもらうよう依頼する必要があります。

レビュー担当者が PR を承認すると、それは @bors というさらに別の bot のキューに入ります。 @bors は CI のビルドおよびマージキューを管理します。 あなたの PR が @bors キューの先頭に到達すると、@bors は GitHub Actions 上であなたの PR に対して すべてのテストを実行し、マージを試します。 これが完了するには多くの時間がかかります。 すべてのテストに合格すると、PR はマージされ、次の nightly コンパイラの一部になります!

レビュー過程で一部の PR に起こり得ることがいくつかあります

  • 変更が十分に大きい場合、レビュー担当者は PR に対して FCP を要求することがあります。 これにより、該当するチームのすべてのメンバーが変更をレビューする機会を得ます。
  • 変更が破壊的変更を引き起こす可能性がある場合、レビュー担当者は crater の実行を要求することがあります。 これは、あなたの変更を含むコンパイラをコンパイルし、その変更済みコンパイラで crates.io 上のすべての crate のコンパイルを試みます。 これは、エコシステムの大きな部分に影響するコンパイラの挙動変更を導入したかどうかを 確認するための優れたスモークテストです。
  • あなたの PR の diff が大きい場合やレビュー担当者が忙しい場合、先にマージされてしまった他の PR と マージコンフリクトが発生することがあります。 通常の git の手順を使って、これらのマージコンフリクトを修正する必要があります。

新機能やそれに類するものを行っていない場合(たとえば バグを修正している場合)は、これで終わりです! ご貢献ありがとうございます :)

実装を洗練する

nightly で新機能を使う経験が蓄積されるにつれて、軽微な変更が 提案されたり、未解決の質問が解決されたりすることがあります。 更新や変更は、上で説明したように、他の変更を実装する場合と同じプロセスを経ます (つまり、PR を提出し、レビューを受け、@bors を待つ、などです)。

一部の変更は、FCP と Rust チームメンバーによるレビューを必要とするほど大きい場合があります。

? マクロ機能については、元の実装後にいくつかの異なる反復を経ました: 1, 2, 3. その過程で、? は区切り記号を取るべきではないと判断しました。これは以前、RFC に未解決の問題として記載されていたものです。 また、曖昧性解消の戦略も変更しました。? を他の繰り返し演算子(例: +*)の区切りトークンとして使用できる機能を削除することにしました。ただし、これは破壊的変更であるため、エディション境界を越えて行うことにしました。 したがって、この新機能は 2018 エディションでのみ有効にできます。元の RFC からのこれらの差異には、別の FCP が必要でした。

安定化

最後に、この機能が nightly でしばらく試用された後、言語チームのメンバーが これを安定化する動議を提出しました

安定化レポート を作成する必要があり、そこには以下を含めます。

  • 振る舞いの簡単な説明と RFC からの差異
  • どのエディションが影響を受けるか、およびその影響
  • 興味深い側面を示すいくつかのテストへのリンク

この機能の安定化レポートはこちらです。

その後、機能ゲートを削除し、機能をデフォルトで(2018 エディションで)有効にするために、PR が作成されます。 この機能についての注記が Release notes に追加されます。

機能を安定化する手順は、機能の安定化で確認できます。