Rustコーディング
ワークフロー
-
オリエンテーション。 コードを書く前に、プロジェクトの信頼できる情報源を読む:
rust-toolchain.toml、Cargo.toml(edition、rust-version、[lints]、[workspace])、clippy.toml、rustfmt.toml、.cargo/config.toml、CI設定、justfile、Makefile、またはxtask(標準のチェックコマンド)。変更するモジュールとその隣接モジュールを読み、それらのヘルパー、エラー型、パターンを再利用する。 完了条件: エディション、MSRV、リントポリシー、すべてのdisallowed-methods/disallowed-typesエントリ、プロジェクトのチェックコマンドを説明できること。 -
型をモデル化する。 Typesに従い、制御フローの前にデータを設計する。ライブラリの公開APIを変更する場合:
references/api.mdを読む。 完了条件: 変更が依存するすべての不変条件が、型にエンコードされているか、その不変条件を名付けたメッセージを持つexpectによって保持されていること。 -
タイトループで実装する。 小さなステップで作業し、各ステップの後に
cargo checkを実行する。診断メッセージ全体を読む:help:行には通常修正方法が書かれており、rustc --explain E0502でエラーコードの詳細がわかる。依存関係のAPIについては、ロックされたバージョン(Cargo.lock)のソースを$CARGO_HOME/registry/src/以下で読む。一括リネームはrust-analyzerのリネーム機能またはast-grepを使う;cargo clippy --fixで機械的に適用可能な提案を適用する。バグ修正:まず回帰テストを書き、それが赤くなるのを確認する。 完了条件: 変更した行に警告がなくコンパイルが通り、回帰テストが修正前に赤くなり修正後に緑になること。 -
検証する。 ステップ1のプロジェクトのコマンドを実行する。そうでない場合は:
cargo fmt --all cargo clippy --workspace --all-targets --all-features -- -D warnings cargo test --workspace --all-features[lints]ポリシーがないプロジェクト:cargo clippy --all-targets -- -W clippy::pedanticも実行し、変更した行のヒットを修正する。- 相互に排他的なフィーチャー:
--all-featuresをCIがテストする各フィーチャーセットに置き換える。 cargo nextestはドキュメントテストをスキップする:cargo test --docを追加する。- 公開ドキュメントを変更した場合:
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features。 unsafeに触れた場合:references/unsafe.mdを読む。- リントの原因を修正する。抑制が適切な場合、
#[expect(clippy::lint_name, reason = "...")]のスコープを最小の項目に限定する。 完了条件: すべてのコマンドが終了コード0で終了し、変更した行に警告がなく、すべての新しい抑制にreasonが付いていること。
-
差分を自己レビューする。 記憶ではなく完全な
git diffを、Rulesおよび差分が触れる各参照ファイルのルールと照らし合わせて再読する。 完了条件: すべてのハンクがタスクに必要であり、プロトタイプコードやdbg!/todo!が削除され、ドキュメントコメントが動作と一致し、すべての該当ルールがすべてのハンクに当てはまること。
他者のコードをレビューする:ステップ1を実行し、可能であればステップ4のコマンドを実行した後、ステップ5をその差分に適用する。各発見事項をpath:line、ルール、修正方法として報告する。
ルール
所有権
- パラメータでは借用を使用する:
&str、&[T]、&Path、&T。関数が値を格納または消費する場合にのみ、String、Vec<T>、またはTを値で受け取る。 - すべての
.clone()には理由がある:呼び出し先が所有権を必要とするか、値が安価なハンドルである(Arc::clone(&handle))。 - 借用チェッカーが拒否した場合、まず構造を再編する:借用の期間を短くする、フィールドを個別に借用する、
std::mem::take/replace、Vecへのインデックス。共有可変所有権(Rc<RefCell<_>>、Arc<Mutex<_>>)は最後の手段。 - 呼び出し側が反復のみ行う場合は、
impl Iterator<Item = T>を返す。
型
- 不正な状態を表現不可能にする:
boolフラグとOptionフィールドではなく、状態ごとにデータを持つenum;ID、単位、検証済みの値にはnewtype(struct Port(NonZeroU16))。 - 検証ではなくパースする:信頼できない入力を境界で一度だけ変換し(
TryFrom、FromStr、#[serde(try_from = "Raw")])、パースされた型を内部に渡す。 - 自分が所有するenumでは網羅的にマッチする。
_アームが適切なのは、将来のバリアントもそのブランチを取るべき場合のみ。 - 整数の変換には
From/TryFromを使用する;asは暗黙に切り詰めや符号反転を行う。
エラーとパニック
- ライブラリ:障害ドメインごとに
thiserrorのenum。バイナリ:anyhow::Resultと.context(...)。 - パニックはバグを意味する。
unwrap()はテスト内でのみ使用;プロダクションコードでは?、または失敗が不可能である不変条件を述べたexpect("...")を使用する。
現在のイディオム
古いパターンが訓練データを支配している。rust-versionが許す場合は現在の形式を優先する;新しいcrateはedition = "2024"を使用する。clippy::incompatible_msrvは新しいstd APIのみをキャッチする;言語とCargoの機能はcargo +<msrv> checkが必要。
| 優先するもの | 優先しないもの | 導入バージョン |
|---|---|---|
std::sync::LazyLock、OnceLock | lazy_static!、once_cell | 1.80、1.70 |
let Some(x) = opt else { return ... }; | match + 早期リターン | 1.65 |
if let Some(x) = a && x > 0 | ネストしたif let | 1.88、edition 2024 |
トレイトのネイティブasync fn | #[async_trait](dyn Traitには引き続き必要) | 1.75 |
| `async | {}クロージャ、AsyncFn`境界 | |
#[expect(lint, reason = "...")] | #[allow(lint)] | 1.81 |
&raw const x、&raw mut x | ptr::addr_of! | 1.82 |
opt.is_some_and(f)、opt.is_none_or(f) | map_or(false, f)、map_or(true, f) | 1.70、1.82 |
std::hint::black_box | criterion::black_box | 1.66 |
共有ポリシーのためのCargo.toml内の[lints] | すべてのcrateルートの#![warn(...)] | 1.74 |
cargo::ビルドスクリプトディレクティブ | cargo: | 1.77 |
ドキュメントとコメント
- 公開アイテムには
///ドキュメントを付ける:失敗する可能性のある関数には# Errors、パニックする関数には# Panics、例は?を使用したドキュメントテストとして。 - コメントはなぜを説明する;コードは何を示す。
依存関係
- ワークスペースがすでに依存しているものを再利用し(
[workspace.dependencies]、cargo tree -i <crate>)、stdで要件を満たせる場合はstdを優先する。 - 追加するときは
cargo add(MSRV対応)を使用し、使用するフィーチャーのみを有効にする。
参考文献
現在のブランチに合致するものを読み込む:
references/api.md:ライブラリの公開APIの設計または変更、命名、トレイト実装、semver。references/errors.md:エラー型の定義、伝播、パニック対Result。references/async.md:async、tokio、スレッド、チャネル、ロック、アトミック。references/unsafe.md:unsafe、FFI、生ポインタ、手動のSend/Sync。references/cargo.md:Cargo.toml、ワークスペース、フィーチャー、プロファイル、ビルドスクリプト、crateの選択。references/lints.md:crateまたはワークスペースのリント設定のセットアップ。references/testing.md:テストの作成、プロパティテストとスナップショットテスト、ベンチマーク。references/perf.md:測定されたホットパスの最適化。