auto deref or auto ref ?


trait Double {
    fn double(self) -> usize;
}

impl<'a> Double for &'a String {
    fn double(self) -> usize { self.len()}
}

impl<'a, 'b, 'c> Double for &'a &'b &'c String {
    fn double(self) -> usize { self.len() * 2 }
}

pub fn main() {
    let x = "hello".to_string(); println!("x:String     => {}", x.double());
    let x = &x;                  println!("x:&String    => {}", x.double());
    let x = &x;                  println!("x:&&String   => {}", x.double());
    let x = &x;                  println!("x:&&&String  => {}", x.double());
    let x = &x;                  println!("x:&&&&String => {}", x.double());
}

OUTPUT:
x:String     => 5
x:&String    => 5
x:&&String   => 10
x:&&&String  => 10
x:&&&&String => 10

how the compiler decide the ord of auto-deref or auto-ref?
if we remove &&&String version of impl:
trait Double {
    fn double(self) -> usize;
}

impl<'a> Double for &'a String {
    fn double(self) -> usize { self.len()}
}

pub fn main() {
    let x = "hello".to_string(); println!("x:String     => {}", x.double());
    let x = &x;                  println!("x:&String    => {}", x.double());
    let x = &x;                  println!("x:&&String   => {}", x.double());
    let x = &x;                  println!("x:&&&String  => {}", x.double());
    let x = &x;                  println!("x:&&&&String => {}", x.double());
}

OUTPUT:
x:String     => 5
x:&String    => 5
x:&&String   => 5
x:&&&String  => 5
x:&&&&String => 5

if we remove the &String version of impl:
trait Double {
    fn double(self) -> usize;
}

impl<'a, 'b, 'c> Double for &'a &'b &'c String {
    fn double(self) -> usize { self.len() * 2 }
}

pub fn main() {
    let x = "hello".to_string(); println!("x:String     => {}", x.double());  // error
    let x = &x;                  println!("x:&String    => {}", x.double());  // error
    let x = &x;                  println!("x:&&String   => {}", x.double());
    let x = &x;                  println!("x:&&&String  => {}", x.double());
    let x = &x;                  println!("x:&&&&String => {}", x.double());
}

まとめ:xのメソッド検索では、最大1回の自動参照のみが作成され、自動解参照が実行されます.1つの変数xに対して探索方法fを探す場合、具体的なアルゴリズムは以下の通りである.
1、現在のxに方法fがあるかどうか、呼び出されているかどうか.
2、ない場合は、x上で自動的に&xを参照し、&x上に方法fがあれば呼び出す.
3、ない場合は*xを試し、見つけたり失敗したりするまで3ステップ繰り返します.