Edited at

RustでVec<T>に&を付けると&[T]が得られる理由

Rustで&[T]を必要とする場所に&vの形でVec<T>を渡すと&[T]に変換されます。

私は最初、標準ライブラリだからこんなことができると思っていたのですが、違いました。

これはDerefトレイトの動作です。

Derefは次のように定義されています。

pub trait Deref {

type Target: ?Sized;
fn deref(&self) -> &Self::Target;
}

自分への参照をTargetへの参照に変換するというメソッドが定義されています。

また、Derefのドキュメントには次のように書かれています。


If T implements Deref<Target = U>, and x is a value of type T, then:


  • In immutable contexts, *x on non-pointer types is equivalent to
    *Deref::deref(&x).

  • Values of type &T are coerced to values of type &U


  • T implicitly implements all the (immutable) methods of the type U.


TDeref<Target = U>を実装し、xT型の値のとき:


  • イミュータブルコンテクストでは、非ポインタ型での*x*Deref::deref(&x)と同値。


  • &T型の値は&U型の値に強制される。


  • Tは型Uの全ての(イミュータブルな)メソッドを暗黙的に実装する。

つまり冒頭の疑問の答えは、Vec<T>Target = [T]としてDerefを実装しているのでドキュメントの二つ目の項目に当てはまり、コンパイラが自動的にスライスへの参照に変換してくれるからということになります。

また、実はlenなどのメソッドはVecのメソッドではなくsliceのメソッドで、三つ目のルールからv.len()というのはv.deref().len()に自動的に変換されているようです。

ちなみに、ミュータブル版のDerefMutもあります。