Sized トレイトについて。

基礎知識

Sized トレイトは固定メモリサイズの型 (型から参照されるヒープ領域のサイズなどは除外) に自動で付加されるマーカートレイトである。一方、そうでない型は !Sized とマークされ、それらは DST (Dynamically Sized Type) と呼ばれる。

代表例

Sized になる型
  • 一般的な型 (u32Vec<u32> など)
  • 参照型 (&u32&str など)
  • 配列型 ([u32; 256] など)
  • 構造体型かつ全てのフィールドが Sized
!Sized になる型
  • スライス型 ([u32][i32] など)
  • 文字列スライス型 (str のこと)
  • トレイトオブジェクト (dyn Display など)
  • 構造体型かつ一部のフィールドが !Sized

関係各所でのルール

関係各所で Sized に関する独特のルールがある。

API ドキュメント

rustdoc による API ドキュメントでは、型ごとに Auto Trait Implementations の項目があり、自動実装されたトレイトが一覧できる。しかし、Sized は文書化されず、!Sized のみが文書化される。そのため、Sized かどうかは !Sized を探すことになる。

型パラメタ

型パラメタは暗黙で Sized 境界を持つ。

暗黙の境界が不要な場合、?Sized を指定すればよい。

(後述の通り、トレイトの Self は例外。)

トレイトとその Self

トレイトとその Self には特殊な扱いがされる。

Sized を指定する方法

Self は型パラメタの一種だが、トレイトの Self は暗黙の Sized 境界を持たない。

必要な場合、明示的に指定しなければならない。

指定方法は幾つかある。

  • where キーワードで Self: Sized とする方法。

  • その糖衣構文でトレイト宣言時に TraitName: Sized とする方法。

  • 上記のどれかで Sized の代わりに、Sized を実装したトレイトを使う方法。

Sized を指定した場合

トレイトの Self における Sized は以下のように振る舞う。

  • 引数や戻り値にて値渡しが可能になる。

    ※ これはトレイト以外と同じ。

  • トレイトの本体において、SelfSized 境界を指定した場合。

    そのトレイトのトレイトオブジェクトが作れなくなる。

  • トレイトのメソッドにおいて、SelfSized 境界を指定した場合。

    そのメソッドをトレイトオブジェクトから呼べなくなる。