mcpField
M
m04-zero-cost

m04-zero-cost

github.com/actionbook開発1.6k3.4k 回インストール9 週間前に更新
リポジトリ

m04-zero-cost について

m04-zero-costは、型の抽象化方法を選ぶRust開発者向けの学習スキルです。ディスパッチ、性能、コンパイル時間のトレードオフを通じて、ジェネリクス、トレイトオブジェクト、enumを比較します。

主な機能

  1. 01抽象レベルを選ぶための問い
  2. 02静的・動的ディスパッチの比較
  3. 03ジェネリクス、トレイトオブジェクト、enumの指針
  4. 04オブジェクトセーフ性の確認
  5. 05Rustエラーコードのガイド

活用シーン

  1. 01性能重視コードのディスパッチ選択
  2. 02異種コレクションの設計
  3. 03プラグインアーキテクチャの型の検討

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/actionbook/rust-skills --skill m04-zero-cost

インストール後、Claude Code で/m04-zero-costを入力して読み込まれたか確認します。

詳細

ゼロコスト抽象化

レイヤー 1:言語の仕組み

中心となる問い

コンパイル時または実行時のポリモーフィズムが必要ですか?

ジェネリクスとトレイトオブジェクトのどちらかを選ぶ前に、次を確認します。

  • コンパイル時に型が判明していますか?
  • 異種コレクションが必要ですか?
  • パフォーマンスで何を優先しますか?

エラー → 設計上の問い

エラーただ言うのではなく代わりに問う
E0277「トレイト境界を追加する」この抽象化は適切なレベルですか?
E0308「型を修正する」型を統一するべきですか、それとも別々にするべきですか?
E0599「トレイトをインポートする」このトレイトは適切な抽象化ですか?
E0038「オブジェクトセーフにする」動的ディスパッチは本当に必要ですか?

思考のヒント

トレイト境界を追加する前に、次を確認します。

  1. どのような抽象化が必要ですか?

    • 動作は同じで型が異なる → トレイト
    • 動作は異なり、型は同じ → enum
    • 抽象化は不要 → 具象型
  2. 型はいつ判明しますか?

    • コンパイル時 → ジェネリクス(静的ディスパッチ)
    • 実行時 → トレイトオブジェクト(動的ディスパッチ)
  3. どのトレードオフを優先しますか?

    • パフォーマンス → ジェネリクス
    • コンパイル時間 → トレイトオブジェクト
    • 柔軟性 → 状況によります

上位をたどる ↑

型システムに阻まれた場合:

E0277 (trait bound not satisfied)
    ↑ Ask: Is the abstraction level correct?
    ↑ Check: m09-domain (what behavior is being abstracted?)
    ↑ Check: m05-type-driven (should use newtype?)
解消しないエラーたどり先問い
複雑なトレイト境界m09-domain抽象化は適切ですか?
オブジェクトセーフティの問題m05-type-driventypestate が役立ちますか?
型の爆発m10-performancedyn のオーバーヘッドを許容できますか?

下位をたどる ↓

設計から実装へ:

"Need to abstract over types with same behavior"
    ↓ Types known at compile time → impl Trait or generics
    ↓ Types determined at runtime → dyn Trait

"Need collection of different types"
    ↓ Closed set → enum
    ↓ Open set → Vec<Box<dyn Trait>>

"Need to return different types"
    ↓ Same type → impl Trait
    ↓ Different types → Box<dyn Trait>

クイックリファレンス

パターンディスパッチコードサイズ実行時コスト
fn foo<T: Trait>()静的+肥大化ゼロ
fn foo(x: &dyn Trait)動的最小vtable 検索
impl Trait return静的+肥大化ゼロ
Box<dyn Trait>動的最小割り当て + vtable

構文の比較

// Static dispatch - type known at compile time
fn process(x: impl Display) { }      // argument position
fn process<T: Display>(x: T) { }     // explicit generic
fn get() -> impl Display { }         // return position

// Dynamic dispatch - type determined at runtime
fn process(x: &dyn Display) { }      // reference
fn process(x: Box<dyn Display>) { }  // owned

エラーコードリファレンス

エラー原因簡単な修正
E0277型がトレイトを実装していないimpl を追加するか、境界を変更する
E0308型が一致しないジェネリックパラメーターを確認する
E0599メソッドが見つからないuse でトレイトをインポートする
E0038トレイトがオブジェクトセーフではないジェネリクスを使うか、設計を見直す

選択ガイド

シナリオ選択理由
パフォーマンスが重要ジェネリクス実行時コストがゼロ
異種コレクションdyn Trait実行時に型が異なる
プラグインアーキテクチャdyn Traitコンパイル時に型が不明
コンパイル時間の短縮dyn Trait単相化が少ない
小規模で既知の型セットenum間接参照がない

オブジェクトセーフティ

トレイトが次の条件を満たす場合、オブジェクトセーフです。

  • Self: Sized 境界を持たない
  • Self を返さない
  • ジェネリックメソッドを持たない
  • オブジェクトセーフでないメソッドには where Self: Sized を使う

アンチパターン

アンチパターン問題点より良い方法
すべてを過度にジェネリックにするコンパイル時間、複雑さ可能な場合は具象型を使う
型が既知なのに dyn を使う不要な間接参照ジェネリクス
複雑なトレイト階層理解しにくいよりシンプルな設計
オブジェクトセーフティを無視する柔軟性が制限される必要に応じて dyn を使えるよう計画する

関連スキル

場合参照先
型駆動設計m05-type-driven
ドメインの抽象化m09-domain
パフォーマンスに関する懸念m10-performance
Send/Sync 境界m07-concurrency

コメント