【Rust】ジェネリクスの取説

※Rustのバージョンは1.33.0 (stable)を使用しています。

Rustは所有権やライフタイム関連で詰まることが多い印象がありますが、私は同じくらい「型の指定方法」、特に「ジェネリクスでの型指定やトレイト境界指定」周りで詰まることが多いと感じています。
これは、Rustが特別複雑なことをしているわけではなく、網羅的なドキュメントや実例の載った解説が少ないためだと思います。最近は公式ドキュメントも充実してきましたが、それでも「これってどう書くの？」「そもそも出来るの？」という時になかなか情報が見つからないことが多々あります。（主に私の英語力が問題ということもありますが）
そこで、私の理解している範囲で、詰まりやすそうな部分とその周辺をまとめたいと思います。

※ジェネリクスやトレイトの導入部分は省略しています。the bookの該当部分に丁寧に書かれているので、そちらをお勧めします。

- [Generic Types, Traits, and Lifetimes - The Rust Programming Language(原文)](https://doc.rust-lang.org/book/ch10-00-generics.html)
- [ジェネリック型、トレイト、ライフタイム - The Rust Programming Language(和訳)](https://doc.rust-jp.rs/book-ja/ch10-00-generics.html)

# トレイト境界
トレイト境界(bounds)とは、ジェネリック型に対して「このトレイトを実装していなければならない」という制約を課すものであり、これにより、ジェネリック型はトレイト境界で指定されたトレイトのメソッド等を使用できるようになります。
トレイト境界の書き方は大きく分けて2通りありますが、どちらも`Type: Trait`の形で記述します。
## トレイト境界の記述場所
### 型引数宣言部に記述
```rust
fn my_fn<T: std::fmt::Debug>(val: T)  {
    println!("{:?}", val); // Debugを使用できる
}
```

### where節に記述
```rust
fn my_fn<T>(val: T) -> ()
where
    T: std::fmt::Debug,
{
    println!("{:?}", val); // Debugを使用できる
}

```
(where節の記述場所をわかりやすくするため、戻り値の空タプルを省略せず書いています。)
### どちらに記述すべきか
基本的にはどちらでも同じです。
が、where節の場合のみ、型指定部に型引数以外の情報を記述できます。

```rust:NG
// これはエラー
fn my_fn<Option<T>: std::fmt::Debug>(val: T) {
    println!("{:?}", Some(val));
}
```

```rust:OK
// これはOK
fn my_fn<T>(val: T)
where
    Option<T>: std::fmt::Debug,
{
    println!("{:?}", Some(val));
}
```
上記の例では、`T`ではなく`Option<T>`に対するトレイト境界を設定しています。型引数宣言部で指定できる型は、型引数のみに限られるので、このようなことはwhere節でのみ可能です。
この記事では今後、基本的にはwhere節での方法を使って説明していきます。

## トレイト境界を指定可能なアイテム
型引数を使うことのできるアイテムは、ほぼ全て、トレイト境界を指定できます。

```rust
// struct
struct MyStruct<T>
where
    T: std::fmt::Debug,
{
    val: T,
}

// "tupled" struct 正式には何て呼ぶの？
// where節がタプルの定義の後になることに注意！
struct MyTupledStruct<T>(T)
where
    T: std::fmt::Debug;

// impl (struct) ※
impl<T> MyStruct<T>
where
    T: std::fmt::Debug,
{
    // method ※
    fn my_method<U>(self, my_tupled_struct: MyTupledStruct<U>) -> (T, U)
    where
        U: std::fmt::Debug,
    {
        println!("{0:?}, {1:?}", self.val, my_tupled_struct.0);
        (self.val, my_tupled_struct.0)
    }
}

// trait
trait MyTrait<T>
where
    T: std::fmt::Debug,
{
    // method ※
    fn my_trait_method<U>(self, my_tupled_struct: MyTupledStruct<U>) -> (T, U)
    where
        U: std::fmt::Debug;
}

// impl (trait) ※
impl<T> MyTrait<T> for MyStruct<T>
where
    T: std::fmt::Debug,
{
    // method ※
    fn my_trait_method<U>(self, my_tupled_struct: MyTupledStruct<U>) -> (T, U)
    where
        U: std::fmt::Debug,
    {
        println!("{0:?}, {1:?}", self.val, my_tupled_struct.0);
        (self.val, my_tupled_struct.0)
    }
}
```
※ トレイト境界のある構造体やトレイトを使う場合、使う側で制約を満たすことを保証しなければならなりません。この場合、※のある場所は`std::fmt::Debug`のトレイト境界を設定して、制約を満たさなければエラーとなります。（制約がわかっているなら、再度記述しなくてもいいような気がするが…なぜだめなのでしょう。）
再度記述しなくてもいいような仕組みとして、「[関連型](#関連型)」というものがあります（トレイトに限りますが）。これについては後述します。

## 複数のトレイト境界の設定
一つの型に複数のトレイト境界を設定する場合は、`Type: Trait1 + Trait2`のように`+`で区切ります。
複数の型にトレイト境界を設定する場合は`Type1: Trait1, Type2: Trait2`のように`,`で区切ります。

```rust
fn my_fn<T, U>(a: T, b: T)
where
    T: std::fmt::Display + std::fmt::Debug,
    U: std::fmt::Display + std::fmt::Debug,
{
    println!("{0} {1}", a, b);
    println!("{0:?} {1:?}", a, b);
}
```
ちなみに、Rustでカンマ区切りの記述は、最後の要素にもカンマを付けて構いません(付けなくても問題なし)。rustfmtで整形した場合は、最後にカンマを付けるようです。

# デフォルトの型引数
Rustでは「デフォルト引数」は今のところ無いのですが、「デフォルト型引数」はあります。
デフォルト型引数の指定のある型引数が省略された場合は、デフォルト型が採用されます。
書き方は、ジェネリック型引数宣言部に`<型引数 = 型>`と書きます。もし、宣言部にトレイト境界を記述する場合は、`<型引数:トレイト境界 = 型>`と書きます。

### 構造体
```rust
struct MyStruct<T: Default = i64> {
    val: T,
}

impl MyStruct {
    fn my_method(&mut self) {
        self.val = i64::default()
    }
}
```

### 列挙型
```rust
enum MyEnum<T: Default = i64> {
    Empty,
    Value(T),
}

impl MyEnum {
    fn my_method(&mut self) {
        if let MyEnum::Value(ref mut x) = self {
            *x = i64::default();
        }
    }
}
```

### トレイト
デフォルト引数には`Self`も指定できます。

```rust
trait MyTrait<T = Self>
where
    T: std::ops::Add,
{
    fn my_method(self) -> T;
}

impl MyTrait for i64 {
    fn my_method(self) -> i64 {
        self + self
    }
}
```

ちなみに、関数にはデフォルト型引数は指定できません。

### 型引数を使うデフォルト型引数
デフォルト型引数に型引数を使った型を指定することもできます。

```rust
trait MyTrait<T, U = Option<T>> {
    fn my_method(self) -> U;
}

impl<T> MyTrait<T> for T {
    fn my_method(self) -> Option<T> {
        Some(self)
    }
}
```


# 関連型
トレイトには、関連型(associated type)と呼ばれる、型引数と似たようなジェネリックスの指定方法があります。

```rust
trait MyTrait {
    type MyType; // 関連型
    fn my_method(self) -> Self::MyType;
}

impl<T> MyTrait for T {
    type MyType = i64; // 実装時に関連型へ具体型を指定する
    fn my_method(self) -> i64 {
        0
    }
}
```
これは、ジェネリック型引数と同じく、使用する側が具体型を決められるような場所のみを提供します。具体的な型は、トレイト実装時に指定します。
関連型を使用する場合は、関連関数と同様に`トレイトの実装型::関連型`（上記例では`Self::MyType`部分）と記述します。

## 関連型へのトレイト境界
関連型へも、ジェネリック型引数と同様に、トレイト境界を指定可能です。
以下の書き方が一般的なようです。

```rust
trait MyTrait {
    // type 関連型: トレイト境界
    type MyType: std::fmt::Debug + std::fmt::Display;
    fn my_method(self) -> Self::MyType;
}
```
トレイト境界の書き方は、前述のトレイト境界の書き方と同様です。
また、where節に記述することも可能です。

```rust
trait MyTrait
where
    Self::MyType: std::fmt::Debug + std::fmt::Display,
{
    type MyType;
    fn my_method(self) -> Self::MyType;
}
```
どちらの書き方でも、おそらく動作に違いはありません。（何か違いを知っている方は教えてください。）

違う点としては、where節では関連型を使った型にトレイト境界を指定できますが、関連型に直接記述する方法では今のところ指定できません。

```rust:NG
trait MyTrait {
    type MyType;
    type Option<MyType>: std::fmt::Debug; // これは「今のところ」NG
    fn my_method(self) -> Self::MyType;
}
```

```:エラーメッセージ
generic associated types are unstable (see issue #44265) rustc(E0658)
```

```rust:OK
trait MyTrait
where
    Option<Self::MyType>: std::fmt::Debug, // これはOK
{
    type MyType;
    fn my_method(self) -> Self::MyType;
}

```
ただし、（後述の内容を少し先取りする形になりますが）関連型のあるトレイトをトレイト境界として指定した場合、関連型へのトレイト境界は省略出来るのですが、下記のような「関連型を使った型」は、再度トレイト境界を明示しないといけません。

```rust
trait MyTrait
where
    Self::MyType: std::fmt::Debug,
{
    type MyType;
    fn my_method(self) -> Self::MyType;
}

fn my_fn<T>(val: T)
where
    T: MyTrait,
 // T::MyType: std::fmt::Debug は省略できる
{
    println!("{:?}", val.my_method());
}

```

```rust
trait MyTrait
where
    Option<Self::MyType>: std::fmt::Debug,
{
    type MyType;
    fn my_method(self) -> Self::MyType;
}

fn my_fn<T>(val: T)
where
    T: MyTrait,
    Option<T::MyType>: std::fmt::Debug, //は省略できない
{
    println!("{:?}", Some(val.my_method()));
}
```

また、[ジェネリック関連型については、RFCとして公開されており](https://github.com/rust-lang/rfcs/blob/master/text/1598-generic_associated_types.md "rfcs/1598-generic_associated_types.md at master · rust-lang/rfcs · GitHub")、将来的に可能になるかもしれません。

## 関連型のメリット
### 型注釈を省略できる
ジェネリック型引数を使用した場合は、トレイトの実装型が決まっても、トレイトの型引数の型は未定なので、型（ジェネリック型）を明記しなければなりません。しかし、関連型は、**トレイトの実装型が決まれば、自動的に関連型も定まる**ため、明記する必要はありません。特に関連型を具体型に限定しない状態での記述が楽になるかと思います。

```rust:ジェネリック型引数
trait MyTrait<T> {
    fn my_method(&self) -> T;
}

// 型引数が2つ必要
fn my_fn<T, U>(val: T) -> U
where
    T: MyTrait<U>,
{
    val.my_method()
}
```

```rust:関連型
trait MyTrait {
    type MyType;
    fn my_method(&self) -> Self::MyType;
}

// 型引数が1つで済む
fn my_fn<T>(val: T) -> T::MyType
where
    T: MyTrait,
{
    val.my_method()
}
```

### 関連型へのトレイト境界を再度明示しなくてもよい
関連型へのトレイト境界も、使用時に再度記述する必要はありません。

```rust:ジェネリック型引数
trait MyTrait<T>
where
    T: std::fmt::Debug,
{
    fn my_method(&self) -> T;
}

fn my_fn<T, U>(val: T)
where
    T: MyTrait<U>,
    U: std::fmt::Debug, // ジェネリック型引数のトレイト境界は再度記述しなければならない
{
    println!("{:?}", val.my_method());
}
```


```rust:関連型
trait MyTrait {
    type MyType: std::fmt::Debug;
    fn my_method(&self) -> Self::MyType;
}

fn my_fn<T>(val: T)
where
    T: MyTrait, // 関連型のトレイト境界は再度記述しなくて良い
{
    println!("{:?}", val.my_method());
}
```

## 関連型のデメリット

### 一つの型の実装に対して複数パターンの関連型は指定できない
ある特定の型に対して、ある特定のトレイトは一つしか定義できません。しかし、型引数の場合は、一つの型が決まってもジェネリック型は決定しないため、ジェネリック型引数の具体型がかぶらない限り、複数のジェネリック型への実装を定義できます。

```rust:ジェネリック型引数
trait MyTrait<T> {
    fn my_method(&self) -> T;
}

// i32に対してMyTrait<T = i32>を実装
impl MyTrait<i32> for i32 {
    fn my_method(&self) -> i32 {
        self + 1
    }
}

// i32に対してMyTrait<T = Option<u32>>を実装
impl MyTrait<Option<u32>> for i32 {
    fn my_method(&self) -> Option<u32> {
        match (*self as i64) + 1 {
            a if a < 0 => Some(a as u32),
            _ => None,
        }
    }
}
```

対して、関連型はメリットにも書いたとおり、実装する型ごとに関連型が一意に決まるため、複数のパターンは実装できません。

```rust:関連型
trait MyTrait {
    type MyType;
    fn my_method(&self) -> Self::MyType;
}

// i32に対してMyTrait<MyType = i32>を実装
impl MyTrait for i32 {
    type MyType = i32;
    fn my_method(&self) -> i32 {
        self + 1
    }
}

// i32に対する実装が競合するためエラー
impl MyTrait for i32 {
    type MyType = Option<u32>;
    fn my_method(&self) -> Option<u32> {
        match (*self as i64) + 1 {
            a if a < 0 => Some(a as u32),
            _ => None,
        }
    }
}
```
この違いが、型引数と関連型の最も基本的な違いです。どちらを選ぶかは、「**この型は実装型に対して必ず一意に決まるものか**」を考えて判断するといいでしょう。

### 関連型にはデフォルト型は指定できない
ジェネリック型引数は、前述の通りデフォルトの型を決めることができますが、関連型には現在そのような機能はありません。

```rust
trait MyTrait {
    type MyType = i32; // デフォルト型は定義できないため、エラー
    fn my_method(&self) -> Self::MyType;
}
```

```:エラーメッセージ
associated type defaults are unstable (see issue #29661) rustc(E0658)
```
ただし、[デフォルト関連型については、RFCとして公開されており](https://github.com/rust-lang/rfcs/blob/master/text/2532-associated-type-defaults.md "rfcs/2532-associated-type-defaults.md at master · rust-lang/rfcs · GitHub")、nightly版で`#![feature(associated_type_defaults)]`を指定すると上記の書き方はエラーにはならないようです（うまくは動かないですが）。前向きに検討されているようには見えます。

## 関連型をトレイト境界で使用する
関連型が標準ライブラリで使われている例として、演算子があります。
`std::ops`にある`Add`(加算)や`Sub`(減算)等の演算子の多くには`Output`という関連型が定義されていて、演算結果の型として使われています。例えば`Add`の定義は以下のようになっています。

> ```rust
> pub trait Add<RHS=Self> {
>     type Output;
>
>     #[must_use]
>     fn add(self, rhs: RHS) -> Self::Output;
> }
> ```

各型は、『Add::Outputの型 = Addを実装している型 + RHSの型』のように使用されます。
この`Add`トレイトをトレイト境界に設定し、引数同士の加算が出来るようにしてみます。

### 関連型に型を指定する
関連型の型を指定するには、`トレイト<関連型 = 型>`と記述します。

```rust
fn my_fn<T>(x: T, y: T) -> T
where
    T: std::ops::Add<Output = T>, // T = T + Tが可能
{
    x + y
}
```
`RHS=Self=T`なので、`T = T + T`、全てT型の演算になります。

### 関連型にトレイト境界を指定する
関連型にトレイト境界を指定するには`関連型: トレイト境界`と記述します。
このとき、「関連型が実装されているトレイトの型」(下記例では`T::`)を指定しなければならない点には注意です。

```rust
fn my_fn<T>(x: T, y: T) -> T::Output
where
    T: std::ops::Add, // T::Output = T + T
    T::Output: std::fmt::Debug, // T::Output (T + T) はDebugを実装している
{
    let a = x + y;
    println!("{:?}", a);
    a
}
```
`Add`は`T`に実装されているので、その関連型`Output`は`T::Output`と指定します。
先ほどと違い、`Output`に特定の型として`T`を指定していないので、`T + T`は`T`ではなく`T::Output`のままとなります。
ちなみに、`std::ops::Add::Output`と書いても文法的には正しいのですが、何に対する実装かわからないため、この場合はエラーとなります。後述しますが、`T::Output`は省略せずに書くと`<T as std::ops::Add>::Output`となります。

# トレイトの継承
トレイトは、他言語で「インターフェイス」と呼ばれるものに似ています。そして、大体の言語ではインターフェイスを他のインターフェイスに継承出来るように、トレイトも他のトレイトに継承っぽいことが可能です[^1]。ただ、ちょっと使い勝手が違って「思てたんと違ーう！」となるかもしれません。
トレイトの継承の記述は、継承先のトレイトの定義部分で`trait SubTrait: SuperTrait`と書きます。

```rust
trait MySuperTrait {
    fn my_super_method(&self) -> i64;
}

// MySubTraitはMySuperTraitを継承する
trait MySubTrait: MySuperTrait {
    fn my_sub_method(&self) -> u64;
}
```

## サブトレイトの実装
上記の`MySubTrait`を実装の中に、`MySuperTrait`のメソッド`my_super_method`の実装をまとめることはできません。

```rust:NG
impl MySubTrait for i32 {
    // エラー　my_super_methodはMySubTraitのメソッドではない！
    fn my_super_method(&self) -> i64 {
        0i64
    }

    fn my_sub_method(&self) -> u64 {
        0u64
    }
}
```

```:エラーメッセージ
the trait bound `i32: MySuperTrait` is not satisfied
the trait `MySuperTrait` is not implemented for `i32` rustc(E0277)

method `my_super_method` is not a member of trait `MySubTrait`
not a member of trait `MySubTrait` rustc(E0407)
```

実際のところ、*`MySubTrait`は`MySuperTrait`のメソッドを持っていません。*全く別のトレイトして扱います。なので、`MySuperTrait`で定義したメソッドは`MySuperTrait`の実装として記述しなければなりません。

```rust:OK
impl MySuperTrait for i32 {
    // MySuperTraitのメソッドはMySuperTraitで定義する
    fn my_super_method(&self) -> i64 {
        0i64
    }
}

impl MySubTrait for i32 {
    // MySubTraitのメソッドはMySubTraitで定義する
    fn my_sub_method(&self) -> u64 {
        0u64
    }
}
```

## トレイトの継承＝`Self`へのトレイト境界
`MySubTrait`は`MySuperTrait`のメソッドを持っていないことは、以下のようにトレイトを明確化することでも確認できます。（[トレイトの明確化の詳細は後述します。](#トレイトの明確化)）

```rust:NG
fn my_fn<T>(val: T)
where
    T: MySubTrait,
{
    // エラー TをMySubTraitとして見た時に、my_super_methodは存在しない
    let _a = <T as MySubTrait>::my_super_method(&val);
}
```

```:エラーメッセージ
cannot find method or associated constant `my_super_method` in trait `MySubTrait`
help: a method with a similar name exists: `my_sub_method` rustc(E0576)
```

ちなみに以下の記述では、どのやり方でもトレイトが推論によって`MySuperTrait`に決まるため、問題なく動きます。

```rust:OK
fn my_fn<T>(val: T)
where
    T: MySubTrait,
{
    let _a = val.my_super_method();
    let _a = MySuperTrait::my_super_method(&val);
    let _a = MySubTrait::my_super_method(&val);
    let _a = T::my_super_method(&val);
}
```
このように、Rustにおける継承と呼ばれている機能は、サブトレイトを実装する型はスーパートレイトを実装していなければならないという制約を課すものと言えるでしょう。つまり、「**`Self`に対して、トレイト境界を設定する**」ものと考えた方がしっくりきます。
実際、以下の記述でも同じ動きをします。

```rust
trait MySuperTrait {
    fn my_super_method(&self) -> i64;
}

// where節で記述しても同じ
trait MySubTrait
where
    Self: MySuperTrait,
{
    fn my_sub_method(&self) -> u64;
}
```

# `Sized`トレイト
大抵の型はコンパイル時に既にサイズが決まっています。例えば`i32`は4バイト、`bool`は1バイトです。自分で定義した`struct`や`enum`も一部例外を除いて、コンパイル時にサイズが決まっています。

## サイズ不定型
ほぼ全ての型はコンパイル時にサイズが決まっていますが、サイズが決まっていない型も少しだけ存在します。以下の2つが代表的です。

- スライス(`[T]`、`str`)
- トレイトオブジェクト(`dyn Trait`)

`[T]`や`str`は、要素数がわからないため、また、トレイトオブジェクトは実装型がわからないため、サイズが不定となります。

```rust:NG
// Tには自動的にSizedトレイトの制約(T: Sized)がつく
fn my_fn<T>(val: T) -> *const T {
    &val
}

fn main() {
    let a: &str = "aaa";
    let b = my_fn(*a); // エラー TはSizedを要求している
}
```

## サイズ不定では出来ないこと
サイズ不定の型は、出来ないことが多いため、そのままでは扱いにくいです。そのため、通常は参照やポインタ、`Box`等（全て`Sized`になる[^2]）を通して扱います。

### 変数の型にはなれない

```rust
let _a: str; // NG
let _a: &str; // OK
```

### 関数の引数、戻り値の型にはなれない

```rust
// NG
fn my_fn_ng(val: dyn std::fmt::Debug) -> dyn std::fmt::Debug {
    println!("{:?}", val);
    val
}

// OK
fn my_fn_ok(val: Box<dyn std::fmt::Debug>) -> Box<dyn std::fmt::Debug> {
    println!("{:?}", val);
    val
}
```
(`T`が`Debug`を実装している場合、`Box<T>`も`Debug`を実装していることが保証されています)

### 列挙型の要素にはなれない

```rust
// NG
enum MyEnumNg {
    A(i32),
    B([i32]),
}

// OK
enum MyEnumOk<'a> {
    A(i32),
    B(&'a [i32]),
}
```

### 構造体やタプルの末尾を除く要素にはなれない

```rust
// NG
struct MyStructNg {
    a: [i32],
    b: i32,
}

// OK (この構造体はサイズ不定となる)
struct MyStructOk {
    a: i32,
    b: [i32],
}
```
ちなみに、OKと書いた`MyStructOk`ですが、これは確かにコンパイルは通りますが、実際にまともに作成する手段が無いためほぼ使えません。使うとしたら、unsafeコードを大量に書いて、スライスのような処理を自作する感じでしょうか。普段はあまり気にしなくても良いでしょう。

## `Sized`トレイトは暗黙的に実装されている
Rustには、コンパイル時にサイズが決まっていることを表現するため、`Sized`というトレイトが用意されています。`Sized`トレイト自体には、メソッドなどの機能はありません。`Sized`を実装している型はサイズが決定しているという「マーカー」の役割を持っています。

### サイズが決まっている型には、自動的に`Sized`トレイトが実装される
サイズが決まっている型は全て`Sized`トレイトを実装しています。自分で作った型も、コンパイル時にサイズが決まっていれば、自動的に`Sized`トレイトが実装されます。これを意図的に外すことは不可能です。

### ジェネリック型引数や関連型には、自動的に`Sized`トレイトの境界が設定される

ジェネリック型引数や関連型を定義した時、何も明示しなくても`Sized`トレイトの境界が設定されます。

```rust
// T: Sized
// MyStruct<T>: Sized
#[derive(Debug)]
struct MyStruct<T>(T);

fn main() {
    // MyStructはSizedを実装しているため、Tになれる
    my_fn(&MyStruct(0i32));
}

// T: Sized
fn my_fn<T>(x: &T)
where
    T: std::fmt::Debug,
{
    println!("{:?}", x);
}
```

## `?Sized`
型引数や関連型には、自動的に`Sized`の制約が付きますが、これではサイズ不定型を扱いたい場合に困ります。そのため、自動的に付く`Sized`の制約を取り除く方法が提供されています。トレイト境界に`?Sized`と記述することで、サイズ不定型を扱えるようになります。

```rust:NG
fn main() {
    // エラー T = str はサイズ不定型
    my_fn("foo");
}

fn my_fn<T>(x: &T)
where
    T: std::fmt::Debug,
{
    println!("{:?}", x);
}
```

```rust:OK
fn main() {
    my_fn("foo");
}

fn my_fn<T>(x: &T)
where
    T: std::fmt::Debug + ?Sized, // Tにサイズ不定型を許可する
{
    println!("{:?}", x);
}
```

## トレイト宣言時の`Self`は`Sized`ではない
例外として、トレイトの`Self`には暗黙的に`Sized`トレイト境界は設定されません。そのため、`str`や`[i32]`等のサイズ不定型への実装が可能となっています。

```rust
trait MyTrait {
    fn my_method_ref(&self);
    fn my_method_mut(&mut self);
}

// サイズ不定型への実装が可能
impl MyTrait for str {
    fn my_method_ref(&self) {}
    fn my_method_mut(&mut self) {}
}
```
また、`Sized`とは限らないため、`&self`や`&mut self`は引数に設定できても、`self`を引数にしたデフォルトメソッドは定義できません(`Sized`かどうかは実装する型依存のため、メソッド定義自体は可能です)。

```rust
trait MyTraitNg {
    fn my_method_ref(&self) {}
    fn my_method_mut(&mut self) {}
    fn my_method_own(self) {} // NG selfはsizedではないため、引数に設定できない
}

trait MyTraitOk {
    fn my_method_ref(&self);
    fn my_method_mut(&mut self);
    fn my_method_own(self); // OK メソッドの実体を作らず、定義のみなら可能
}
```
`Sized`トレイト境界を明示すれば、`self`を引数にしたデフォルトメソッドも定義できます。

```rust
trait MyTrait: Sized {
    fn my_method_ref(&self) {}
    fn my_method_mut(&mut self) {}
    fn my_method_own(self) {} // OK selfはsizedに限定されたため、引数に出来る
}
```

# トレイト・型の明確化（フルパス記法）
Rustでは、型やトレイトを明示しなくても、推論によって自動的に決定してくれます。
しかし、推論によって一つに決まらない場合は、プログラマが型やトレイトを明示しなくてはなりません。

## 値・関数実行時の型明確化
値作成時や、関数実行時にジェネリック型を明確にしたい場合は、`型or関数::<型引数の型>`と記述します。
（この`::<>`のことをturbofishと呼ぶらしい）
### 構造体
```rust
struct MyStruct<T>(T);

fn main() {
    // _aは全てMyStruct<i64>
    let _a = MyStruct(0i64);
    let _a = MyStruct::<i64>(0);
}
```

### 列挙型
```rust
enum MyEnum<T> {
    Empty,
    Value(T)
}

fn main() {
    // _aは全てMyEnum<i64>
    let _a = MyEnum::Value(1i64);
    let _a = MyEnum::Value::<i64>(1);
    let _a = MyEnum::Empty::<i64>;
}
```

### 関数
```rust
fn my_fn<T>(val: T) -> T {
    val
}

fn main() {
    // _aは全てOption<i64>
    let _a = my_fn(Some(0i64));
    let _a = my_fn(None::<i64>);
    let _a = my_fn::<Option<i64>>(None);
}
```
この辺の情報は、[The Rust Reference内のPaths](https://doc.rust-lang.org/reference/paths.html "Paths - The Rust Reference")に少なくとも載っているのですが、それ以外にどこに載っているのかわからないです。the bookのジェネリクス関係の説明にあって欲しいと思っています。

## トレイトの明確化
ある型に実装されているトレイトを明確化する場合は、`<型 as トレイト>::メソッドとか`と記述します。（フルパス記法と言うそうです。）
この書き方はキャスト(`v as Type`)に似ており、意味もまた似ています。しかし、キャストは実行時に型を変換するのに対し、**トレイトの明確化は何の処理も実行しません**。`<Type as Trait>::method()`は、`Type::method()`や`Trait::method()`を省略せずに書いただけです。

### 明確化が必要になる具体例

#### 名前競合を回避する
「[関連型をトレイト境界で使用する](#関連型をトレイト境界で使用する)」で説明した`Add`トレイト(加算)を使った例に、`Sub`トレイト(減算)のトレイト境界を追加してみます。`Sub`トレイトは、`Add`トレイトと似たような定義となっていて、両方共に`Output`という関連型を持っています。([API Document](https://doc.rust-lang.org/std/ops/trait.Sub.html "std::ops::Sub - Rust")参照)

```rust:NG
// エラー T::OutputはAddトレイトのOutputか、SubトレイトのOutputかわからない
fn my_fn<T>(x: T, y: T) -> T::Output
where
    T: Copy + std::ops::Add + std::ops::Sub,
    T::Output: std::fmt::Debug, // エラー 上に同じ
{
    println!("{:?}", x + y);
    x - y
}
```
上記コードはコンパイルエラーとなります。何故かと言うと`T`は`Add`トレイトと`Sub`トレイトを実装しているため、`T::Output`と書いた場合、どちらの`Output`を指すか決めることができないためです。

```:エラーメッセージ
ambiguous associated type `Output` in bounds of `T`
ambiguous associated type `Output`
note: associated type `T` could derive from `std::ops::Sub`
note: associated type `T` could derive from `std::ops::Add` rustc(E0221)
```
この手のエラーは「ambiguous(あいまいな)」関連型などと言われるので、言われたらトレイトを明確にしましょう。上記コードでは、加算結果に`Debug`を使用し、減算結果を戻り値に使用しているため、以下のようにします。

```rust:OK
fn my_fn<T>(x: T, y: T) -> <T as std::ops::Sub>::Output
where
    T: Copy + std::ops::Add + std::ops::Sub,
    <T as std::ops::Add>::Output: std::fmt::Debug,
{
    println!("{:?}", x + y);
    x - y
}
```

#### 循環を回避する
ここでは、ジェネリック型引数を持つトレイトをスーパートレイトに持つサブトレイトを定義してみます。その際、そのジェネリック型をサブトレイトの関連型としてみましょう。
特に意味はないですが、ジェネリック型引数を持つトレイトとして`Borrow`を使ってみます。(詳細は[API Document](https://doc.rust-lang.org/std/borrow/trait.Borrow.html "std::borrow::Borrow - Rust")参照)

```rust:NG
// エラー 定義がループしている
trait MyTrait: std::borrow::Borrow<Self::MyType> {
    type MyType;
}
```
上記コードはコンパイルエラーとなります。なぜでしょう。
エラーメッセージは以下のようになります。

```:エラーメッセージ
cycle detected when computing the supertraits of `MyTrait`
note: ...which again requires computing the supertraits of `MyTrait`, completing the cycle
note: cycle used when collecting item types in top-level module rustc(E0391)
```
`MyTrait`のスーパートレイト(`Borrow`)の計算時にループが検出されたと言っています。これは`Self`の定義には、スーパートレイトの`Borrow`の定義が必要で、`Borrow`の定義には`Self`が必要で…とループしています。名前は競合していないので、大丈夫な気もしますが、エラーとなるものはしょうがないのです。
どうすればいいかというと、`MyType`が`MyTrait`の関連型であることを明記し、`Borrow`を参照させなくします。

```rust:OK
trait MyTrait: std::borrow::Borrow<<Self as MyTrait>::MyType> {
    type MyType;
}
```

#### その他推論がうまく動かない場合
ここまで、`T::Output`のように、`型::関連型`のような記法を使ってきましたが、この型に記述して推論が動く型は限られているようです。型引数`T::`や`Self::`等はトレイトを記述しなくても推論されますが、`Enum<T>::`や`T::Assoc::`等はトレイトを明記しなければなりません。パスの表現が曖昧になるからでしょうか？
例えば、以下の例は戻り値でトレイトを明確化しなければなりません。

```rust:NG
fn my_fn<T>(x: Option<T>, y: Option<T>) -> Option<T>::Output
where
    Option<T>: std::ops::Add,
{
    x + y
}
```

```rust:OK
fn my_fn<T>(x: Option<T>, y: Option<T>) -> <Option<T> as std::ops::Add>::Output
where
    Option<T>: std::ops::Add,
{
    x + y
}
```

この辺は深く考えず、コンパイラに怒られたらフルパス記法を試してみる程度でいいかもしれません。

# 最後に
本当はもう少し書く予定でしたが、思っていた以上に記述量が多くなり、力尽きました。
嘘・大げさ・紛らわしい等の指摘や要望があれば、コメント等でお伝え下さい。

## 参考にしたページ
#### 英語

- [Generic Types, Traits, and Lifetimes - The Rust Programming Language](https://doc.rust-lang.org/book/ch10-00-generics.html)
- [Advanced Traits - The Rust Programming Language](https://doc.rust-lang.org/book/ch19-03-advanced-traits.html)
- [Rust Language Cheat Sheet](https://cheats.rs/)
- [They're not Generics; they're TypeParameters](http://bluejekyll.github.io/blog/rust/2017/08/06/type-parameters.html)

####日本語
- [ジェネリック型、トレイト、ライフタイム - The Rust Programming Language](https://doc.rust-jp.rs/book/second-edition/ch10-00-generics.html)
- [高度なトレイト - The Rust Programming Language](https://doc.rust-jp.rs/book/second-edition/ch19-03-advanced-traits.html)
- [RustのSizedとfatポインタ - 簡潔なQ](https://qnighy.hatenablog.com/entry/2017/03/04/131311)
- [Rustの名前解決(4/5) メソッド記法とメンバ変数と関連アイテムの解決 - 簡潔なQ](https://qnighy.hatenablog.com/entry/2017/03/30/070000)

[^1]: 古い"the book"では"継承"と呼ばれていますが、最新の"the book"では"継承"という表現は使われていないようです。
[^2]: サイズ不定型へのポインタは、通常のポインタよりもサイズが大きくなります。これは、参照するアドレス以外のデータ(スライスの要素数等)を持つためです。