1.17.1. 整合性

整合性とは、ある型とメソッドに対して、その型にそのメソッドを実装する正しい選択肢が 1 つだけ存在することを意味します。

孤児ルールとは、ローカルクレートのいずれか側がトレイトまたは型である場合、その型に対してそのトレイトを実装できることを意味します。 例:

  • ローカルで定義した型は Debug トレイトを実装できる
  • ローカルで定義したトレイトを bool に対して実装できる
  • Debugbool に対して実装することはできない。どちらの側もローカルではないため

孤児ルールには例外があります。以下で説明します。

1.17.2. ブランケット実装

ブランケット実装(一般実装とも呼ばれる)とは、Rust がトレイト境界を満たすすべての型に対してデフォルト実装を許可することを意味します。

テンプレートは次の通りです:

impl<T> MyTrait for T where T: ...

Enter fullscreen mode Exit fullscreen mode

これは、あるトレイトを実装するすべての型に対して MyTrait を実装することを意味します。

例:

impl<T: Display> ToString for T {}

Enter fullscreen mode Exit fullscreen mode

これは、Display を実装するすべての型に対して ToString を実装することを意味します。

この例はまだテンプレート形式で書かれていません。テンプレート形式では次のようになります:

impl<T> ToString for T where T: Display {}

Enter fullscreen mode Exit fullscreen mode

トレイトを定義したクレートだけがブランケット実装を使用できることに注意してください。既存のトレイトにブランケット実装を追加すると破壊的変更になります。

1.17.3. 基本型

一部の型は非常に基本的なため、孤児ルールに違反する場合でも、誰でもそれらにトレイトを実装できるようにする必要があります。これらの型は #[fundamental] とマークされており、現在 &T&mut TBox<T>Pin<P> が含まれます。

  • 補足: Pin<P> の主な目的は、値が移動できないことを保証することです。つまり、std::mem::replacestd::mem::swapstd::mem::take などの操作が値の物理アドレスを変更するのを防ぐことです
  • 孤児ルールの目的では、これらの型は孤児ルールチェックが行われる前に実際に消去されます

注: 基本型にブランケット実装を使用することも破壊的変更とみなされます。

1.17.4. カバー実装

外部の型に対して外部のトレイトを実装する必要がある場合があります。これをカバー実装と呼びます。これは孤児ルールによって確立された狭い例外を使用します。外部の型に対して外部のトレイトを非常に特定のケースで実装することを許可します。

注: カバー実装は Covered Implementation または Override Implementation のいずれかを指すことがあります。ここでは Covered Implementation を指します。Override Implementation とは、構造体がトレイトを実装し、独自のメソッドを提供する場合に、デフォルト実装をオーバーライドできることを意味します。

この形式のテンプレートは次の通りです:

impl<P1..=Pn> ForeignTrait<T1..=Tn> for T0

Enter fullscreen mode Exit fullscreen mode

  • P1..=Pn および T1..=T0 はパラメータの数を指します

この形式は、次のすべての条件が満たされた場合にのみ許可されます:

  • T1..=Tn の少なくとも 1 つがローカル型である
  • そのようなローカル型の最初のものの前に TP1..=Pn のジェネリック型の 1 つ)が現れてはならない
  • ジェネリック型パラメータ P は、T0..Ti に中間型でラップされている限り現れることができる
    • TVec<T> などの別の型の型パラメータとして現れる場合、T はラップされているとみなされる
    • T が単独で現れる場合、または &T などの基本型の背後に現れる場合、ラップされていない

簡単な例:

impl From<MyType> for Vec<i32>

Enter fullscreen mode Exit fullscreen mode

これは、外部の From<MyType> トレイトを外部の Vec<i32> 型に対して実装します。

より複雑な例をいくつか示します。上記のルールを使用して理解できます:

実装 有効?
impl<T> From<T> for MyType OK
impl<T> From<T> for MyType<T> OK
impl<T> From<MyType> for Vec<T> OK
impl<T> ForeignTrait<MyType, T> for Vec<T> OK
-------------------------------------------- ------------
impl<T> ForeignTrait for T Not OK
impl<T> From<T> for T Not OK
impl<T> From<Vec<T>> for T Not OK
impl<T> From<MyType<T>> for T Not OK
impl<T> From<T> for Vec<T> Not OK
impl<T> ForeignTrait<T, MyType> for Vec<T> Not OK

カバー実装が破壊的変更になるかどうかは、具体的な状況によって異なります:

  • 既存のトレイトに新しい実装を追加し、上記の条件を満たす少なくとも 1 つの新しいローカル型を含む場合は、非破壊的変更
  • 上記の条件を満たさない既存のトレイトの実装を追加するのは、破壊的変更

注:

  • impl<T> ForeignTrait<MyType, T> for Vec<T> は有効
  • impl<T> ForeignTrait<T, MyType> for Vec<T> は無効