ProgrammingRust 開発者, API/ライブラリデザイナー

Rust における外部型との trait の動作を説明してください (孤児ルール)。あなたが宣言していない型の trait をどのように実装し、なぜそれが常に可能であるとは限らないのかを説明してください。

Hintsage AIアシスタントで面接を突破

答え

Rust では、型に対して trait を実装することは、以下の条件を満たす場合にのみ許可されます:

  • trait が現在の crate で宣言されている または
  • 型が現在の crate で宣言されている

これらの条件を孤児ルール (orphan rule) と呼びます。これは、異なる crate で同じ型に対して同じ trait の独立した実装が衝突するのを防ぐためのものです。

外部型に対して外部の trait を実装したい場合は、直接それを行うことはできません。通常は「newtype」パターンを使用します:型を自分の構造体の中にラップし、その後自分の型に対して trait を実装します。

例:

// 外部型と外部 trait (私たちの crate にはない) // struct ExternalType; trait ExternalTrait { ... } struct MyWrapper(ExternalType); impl ExternalTrait for MyWrapper { /* ... */ } // これでラッパーを介して作業します

ひっかけ問題

質問: 両方が公開されている場合、use と impl を通じて外部の trait を外部の型に対して実装できますか?

誤った答え: はい、単に自分の crate で impl を宣言すれば、すべてが機能します。

正しい答え: いいえ、コンパイラはそれを許可しません。trait または型が現在の crate で宣言されている場合にのみ trait を実装することが許可されます。そうでない場合は孤児ルールエラーになります。

エラーの例:

// extern crate other; // impl Display for other::ExternalType { ... } // 孤児ルールエラー

このトピックの微妙な点を知らないことによる実際のエラーの例


ストーリー

チームでは、外部のロガーを impl を通じてサポートする必要がありました。外部型に対してそれを実装しようとしたところ、孤児ルールエラーが発生し、その理由についての長い議論がありました。最終的には newtype を使用してアーキテクチャを再設計せざるを得ませんでした。


ストーリー

オープンソースプロジェクトで、別のライブラリの構造体に対して Debug を実装することを決定しましたが、孤児ルールによりそれが不可能でした。その結果、ユーザーは不便な workaround を利用せざるを得ず、自分のラッパーを作成する必要がありました。


ストーリー

重大なバグ: 外部の enum に対して FromStr を実装しようとした際、コンパイラが孤児ルールを通過させませんでした。開発者は安全でないメモリ変換によって問題を「解決」し、その結果、プロダクションで未定義の動作が発生しました。