[Rust] 引数 self や戻り値の型 Self に基づくメソッドディスパッチ

Rust では、関数等の引数や戻り値の型からジェネリック型 `T` を解決 (静的ディスパッチ) することができますが、トレイトのメソッドの引数 `self` や戻り値の型 `Self` から具体的な型を解決することもできます。

# 1. 引数 `self` の型による静的ディスパッチ

まず、引数 `self` の型による静的ディスパッチを確認します。

```rust
trait FooBarBaz {
    fn something(&self);
}

struct Foo;
impl FooBarBaz for Foo {
    fn something(&self) {
        println!("Foo");
    }
}

struct Bar;
impl FooBarBaz for Bar {
    fn something(&self) {
        println!("Bar");
    }
}

struct Baz;
impl FooBarBaz for Baz {
    fn something(&self) {
        println!("Baz");
    }
}

//
let foo = Foo;
foo.something();
Foo::something(&foo);
FooBarBaz::something(&foo); // 静的ディスパッチ: type Self = Foo;

let bar = Bar;
bar.something();
Bar::something(&bar);
FooBarBaz::something(&bar); // 静的ディスパッチ: type Self = Bar;

let baz = Baz;
baz.something();
Baz::something(&baz);
FooBarBaz::something(&baz); // 静的ディスパッチ: type Self = Baz;
```

※ `<Foo as FooBarBaz>` のような曖昧さ回避は、構造体等の型が複数のトレイトを実装している等、メソッドが重複している場合に「トレイトを明示する」ために使うもので、本記事で言っているのは「構造体等の型を解決する」内容なので、別物です。

`self` は `&Self` 型なので、ジェネリック型 `T` を解決するのと同様に、`FooBarBaz::something(&foo)` のようなトレイトのメソッド呼び出しでも具体的な構造体等の型をコンパイラが解釈することができます。

参考「[Methods - Rust By Example](https://doc.rust-lang.org/rust-by-example/fn/methods.html)」
参考「[Performance of Code Using Generics - Generic Data Types - The Rust Programming Language](https://doc.rust-lang.org/book/ch10-01-syntax.html#performance-of-code-using-generics)」
参考「[Traits - Rust By Example](https://doc.rust-lang.org/rust-by-example/trait.html)」

※ `&self` は `self: &Self` のシンタックスシュガー (「簡略表記 `self`」) で、関数の引数等で参照外しに用いられる「参照パターン」ではありません。

参考「[Functions - The Rust Reference](https://doc.rust-lang.org/reference/items/functions.html)」(「簡略表記 `self`」、`ShorthandSelf`)
参考「[Reference patterns - Patterns - The Rust Reference](https://doc.rust-lang.org/reference/patterns.html#reference-patterns)」(「参照パターン」、`ReferencePattern`)

# 2. 戻り値の型 `Self` による静的ディスパッチ

Rust では戻り値の型からも、引数の型の場合と同様に `Self` を解決することができます。

```rust
trait FooBarBaz {
    fn something() -> Self;
}

struct Foo;
impl FooBarBaz for Foo {
    fn something() -> Self {
        println!("Foo");
        Self {}
    }
}

struct Bar;
impl FooBarBaz for Bar {
    fn something() -> Self {
        println!("Bar");
        Self {}
    }
}

struct Baz;
impl FooBarBaz for Baz {
    fn something() -> Self {
        println!("Baz");
        Self {}
    }
}

//
let _foo = Foo::something();
let _foo: Foo = FooBarBaz::something(); // 静的ディスパッチ: type Self = Foo;

let _bar = Bar::something();
let _bar: Bar = FooBarBaz::something(); // 静的ディスパッチ: type Self = Bar;

let _baz = Baz::something();
let _baz: Baz = FooBarBaz::something(); // 静的ディスパッチ: type Self = Baz;
```

参考「[Disambiguating Function Calls - Call expressions - The Rust Reference](https://doc.rust-lang.org/reference/expressions/call-expr.html#disambiguating-function-calls)」

`Default::default()` や　`FromIterator::from_iter` メソッド等でも戻り値 `Self` が使われています。

```rust:Default&#58;&#58;default&nbsp;メソッドのシグネチャ
pub trait Default: Sized {
    // ...
    fn default() -> Self;
}
```

```rust:Default&#58;&#58;default()&nbsp;の使用例
let i: i8 = Default::default(); // 静的ディスパッチ: type Self = i8;
```

```rust:FromIterator&#58;&#58;from_iter&nbsp;メソッドのシグネチャ
pub trait FromIterator<A>: Sized {
    // ...
    fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self;
}
```

```rust:Iterator&#58;&#58;collect&nbsp;メソッドのデフォルト定義
pub trait Iterator {
    // ...
    type Item;
    // ...
    fn collect<B: FromIterator<Self::Item>>(self) -> B
    where
        Self: Sized,
    {
        FromIterator::from_iter(self) // 静的ディスパッチ: type Self = B;
    }
    // ...
}
```

参考「[Default in std::default - Rust](https://doc.rust-lang.org/std/default/trait.Default.html)」
参考「[collect - Iterator in std::iter - Rust](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.collect)」
参考「[FromIterator in std::iter - Rust](https://doc.rust-lang.org/std/iter/trait.FromIterator.html)」

# 3. トレイトオブジェクトによる動的ディスパッチ

トレイトオブジェクトを使うことで動的ディスパッチをすることもできます。
この場合、戻り値の型 `Self` によるディスパッチはできません。

```rust
trait FooBarBaz {
    fn something(&self);
}

struct Foo;
impl FooBarBaz for Foo {
    fn something(&self) {
        println!("Foo");
    }
}

struct Bar;
impl FooBarBaz for Bar {
    fn something(&self) {
        println!("Bar");
    }
}

struct Baz;
impl FooBarBaz for Baz {
    fn something(&self) {
        println!("Baz");
    }
}

//
let foo_bar_baz: &dyn FooBarBaz = &Foo;
foo_bar_baz.something();           // 動的ディスパッチ: type Self = Foo;
FooBarBaz::something(foo_bar_baz); // 動的ディスパッチ: type Self = Foo;

let foo_bar_baz: &dyn FooBarBaz = &Bar;
foo_bar_baz.something();           // 動的ディスパッチ: type Self = Bar;
FooBarBaz::something(foo_bar_baz); // 動的ディスパッチ: type Self = Bar;

let foo_bar_baz: &dyn FooBarBaz = &Baz;
foo_bar_baz.something();           // 動的ディスパッチ: type Self = Baz;
FooBarBaz::something(foo_bar_baz); // 動的ディスパッチ: type Self = Baz;

// Note: Rust でトレイトオブジェクトをダウンキャストするには少し手間が必要で、
//       以下のように単純に as で変換することは不可。
//       すなわち、FooBarBaz トレイトを実装するメソッド以外は簡単には呼べない。
//
// (foo_bar_baz as &Foo).something();
// Foo::something(foo_bar_baz as &Foo);
```

参考「[Trait Objects Perform Dynamic Dispatch - Using Trait Objects That Allow for Values of Different Types - The Rust Programming Language](https://doc.rust-lang.org/book/ch17-02-trait-objects.html#trait-objects-perform-dynamic-dispatch)」

トレイトオブジェクトへの変換は、Unsized 型強制によるものです。

```rust
// ... 略
let foo_bar_baz: &dyn FooBarBaz = &Foo; // Unsized 型強制: &Foo -> &dyn FooBarBaz
// ... 略
```

参考「[Unsized Coercions - Type coercions - The Rust Reference](https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions)」