[Rust] to_string メソッド等は呼び出し時に自動参照外しされない

Rust では基本的に自動で参照外しが行われ、例えば `&&&Foo` 型に対して Self 引数 `self: &Foo` を持つメソッドが呼ばれたりします。

ところが、`ToString` トレイト等は参照型に対してブランケット実装されるため、参照外しせずにメソッドが呼ばれます。

# 1. 自動参照外しされる場合とされない場合

## 1.1. 基本的には自動参照外しされる

Rust では基本的に自動で参照外しが行われます。

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

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

// 
let foo: &&&Foo = &&&Foo;

// 完全修飾構文の関数引数での自動参照外し
<Foo as Something>::something(**foo); // self: &Foo
<Foo as Something>::something(*foo);  // 自動参照外し: &&Foo -> &Foo
<Foo as Something>::something(foo);   // 自動参照外し: &&&Foo -> &Foo
// <&Foo as Something>::something(*foo); // エラー発生
// <&Foo as Something>::something(foo);  // エラー発生
// <&&Foo as Something>::something(foo); // エラー発生

// メソッド探索におけるレシーバの自動参照外し
(**foo).something(); // self: &Foo
(*foo).something();  // 自動参照外し: &&Foo -> &Foo
foo.something();     // 自動参照外し: &&&Foo -> &Foo
```

※関数引数等での自動参照外しとメソッド探索における自動参照外しは仕組みが異なります (本記事では詳細は不説明) 。

関数引数は型強制サイトのため、自動参照外しされます。

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

メソッド呼び出しにおける参照外し等について、詳しくは別記事にしました。

参考「[[Rust] メソッド呼び出し時におけるメソッド探索の仕組み: 自動参照 & 自動参照外し及び Unsized 型強制 - Qiita](https://qiita.com/kerupani129/items/8dba9f5bb2c009c4d08d)」

## 1.2. 参照型が実装するメソッドではメソッド探索で自動参照外しされない

参照型にメソッドが実装されている場合は、メソッド呼び出しにおけるメソッド探索で参照外しされる前にメソッドが決定するため、理論上参照外しした場合に一致するメソッドがあったとしても参照外しされません。

※完全修飾構文で呼び出す場合はメソッド探索されず、`self` 引数でない引数や変数束縛と同様に自動参照外しされます。

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

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

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

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

// 
let foo: &&&Foo = &&&Foo;

// 完全修飾構文の関数引数での自動参照外し
<Foo as Something>::something(**foo); // self: &Foo
<Foo as Something>::something(*foo);  // 自動参照外し: &&Foo -> &Foo
<Foo as Something>::something(foo);   // 自動参照外し: &&&Foo -> &Foo
<&Foo as Something>::something(*foo); // self: &&Foo
<&Foo as Something>::something(foo);  // 自動参照外し: &&&Foo -> &&Foo
<&&Foo as Something>::something(foo); // self: &&&Foo

// メソッド探索におけるレシーバの自動参照外し
(**foo).something(); // self: &Foo
(*foo).something();  // self: &&Foo  // 自動参照外しされない
foo.something();     // self: &&&Foo // 自動参照外しされない
```

上記のコードをブランケット実装にすると以下のようになります (`&&&&Foo` 等にも実装されます) 。

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

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

impl<T: Something> Something for &T { // ブランケット実装
    fn something(&self) {
        print!("&");
        Something::something(&**self); // 明示的な参照外し
    }
}

// ... メソッド呼び出し略
```

参考「[Using Trait Bounds to Conditionally Implement Methods - Traits: Defining Shared Behavior - The Rust Programming Language](https://doc.rust-lang.org/book/ch10-02-traits.html#using-trait-bounds-to-conditionally-implement-methods)」(「ブランケット実装」)

# 2. 自動参照外しされない標準ライブラリトレイトの例

## 2.1. `Display` トレイトと `ToString` トレイト

`Display` トレイトは参照 (可変参照も含む) に対して再帰的にブランケット実装され、さらに `Display` トレイトを実装する型に対して `ToString` トレイトがブランケット実装されます。

```rust:使用例
use std::fmt;

struct Foo;
impl fmt::Display for Foo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Foo")
    }
}

// 
let foo: &&&Foo = &&&Foo;

// 完全修飾構文の関数引数での自動参照外し
<Foo as ToString>::to_string(**foo); // self: &Foo
<Foo as ToString>::to_string(*foo);  // 自動参照外し: &&Foo -> &Foo
<Foo as ToString>::to_string(foo);   // 自動参照外し: &&&Foo -> &Foo
<&Foo as ToString>::to_string(*foo); // self: &&Foo
<&Foo as ToString>::to_string(foo);  // 自動参照外し: &&&Foo -> &&Foo
<&&Foo as ToString>::to_string(foo); // self: &&&Foo

// メソッド探索におけるレシーバの自動参照外し
(**foo).to_string(); // self: &Foo
(*foo).to_string();  // self: &&Foo  // 自動参照外しされない
foo.to_string();     // self: &&&Foo // 自動参照外しされない
```

ブランケット実装は以下のようにされます。

```rust:参照に対する&nbsp;Display&nbsp;トレイト等のブンラケット実装&nbsp;(マクロ使用)
macro_rules! fmt_refs {
    ($($tr:ident),*) => {
        $(
        // ... 略
        impl<T: ?Sized + $tr> $tr for &T {
            fn fmt(&self, f: &mut Formatter<'_>) -> Result { $tr::fmt(&**self, f) }
        }
        // ... 略
        )*
    }
}

fmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp }
```

```rust:参照に対する&nbsp;Display&nbsp;トレイトのブンラケット実装&nbsp;(※理論上のソースコード)
impl<T: ?Sized + Display> Display for &T {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result { Display::fmt(&**self, f) }
}
```

```rust:ToString&nbsp;トレイトのブンラケット実装
impl<T: fmt::Display + ?Sized> ToString for T {
    // ... 略
    #[inline]
    default fn to_string(&self) -> String {
        // ... 略
    }
}
```

参考「[Display for &'_ T - Display in std::fmt - Rust](https://doc.rust-lang.org/std/fmt/trait.Display.html#impl-Display-83)」
参考「[ToString for T - ToString in std::string - Rust](https://doc.rust-lang.org/std/string/trait.ToString.html#impl-ToString-6)」

## 2.2. `Clone` トレイトと `ToOwned` トレイト

`Clone` トレイトは参照に対して再帰的にブランケット実装され、さらに `Clone` トレイトを実装する型に対して `ToOwned` トレイトがブランケット実装されます。

`Clone` トレイトは `Display` トレイトと異なり、可変参照は実装しません。
つまり、可変参照で `to_owned` メソッドを呼んだ場合は `ToOwned` を実装する型が見つかるまでは自動参照外しおよび自動参照が行われます。
ただし、どんな場合でも完全に参照が取り除かれるわけではありません。

```rust:使用例
// 
let foo: &&i32 = &&23;

let bar = foo.to_owned(); // bar は &i32 型: to_owned(self: &&i32) -> &i32 (foo は自動参照外しされない)

// 
let baz: &mut &i32 = &mut &23;

let qux = baz.to_owned(); // qux は i32 型: to_owned(self: &i32) -> i32 (baz は 1 段階自動参照外しされる)

// 
let quux: &mut i32 = &mut 23;

let corge = quux.to_owned(); // corge は i32 型: to_owned(self: &i32) -> i32 (quux は自動参照外しおよび自動参照される)
```

ブランケット実装は以下のようにされます。

```rust:Clone&nbsp;トレイトのブンラケット実装
    impl<T: ?Sized> Clone for &T {
        // ... 略
        fn clone(&self) -> Self {
            *self
        }
    }
```

```rust:ToOwned&nbsp;トレイトのブンラケット実装
impl<T> ToOwned for T
where
    T: Clone,
{
    // ... 略
    fn to_owned(&self) -> T {
        self.clone()
    }
    // ... 略
}
```

参考「[Clone for &amp;'_ T - Clone in std::clone - Rust](https://doc.rust-lang.org/std/clone/trait.Clone.html#impl-Clone-121)」
参考「[ToOwned for T - ToOwned in std::borrow - Rust](https://doc.rust-lang.org/std/borrow/trait.ToOwned.html#impl-ToOwned-5)」