Rustで&[T]を必要とする場所に&vの形でVec<T>を渡すと&[T]に変換されます。
私は最初RustがVec<T>を特別扱いしているのだと思っていたのですが、そうではありません。
これはDerefトレイトの動作です。
Derefは次のように定義されています。
pub trait Deref {
type Target: ?Sized;
fn deref(&self) -> &Self::Target;
}
自分への参照をTargetへの参照に変換するというメソッドが定義されています。
また、Derefのドキュメントには次のように書かれています。
If
TimplementsDeref<Target = U>, andxis a value of typeT, then:
In immutable contexts,
*x(whereTis neither a reference nor a raw pointer) is equivalent to*Deref::deref(&x).
Values of type&Tare coerced to values of type&U
Timplicitly implements all the (immutable) methods of the typeU.
これを翻訳すると:
TがDeref<Target = U>を実装し、xがT型の値のとき:
- イミュータブルの文脈では、
*xは (Tが参照でも生ポインタでもないとき)*Deref::deref(&x)と同値。&T型の値は&U型の値に強制される。Tは型Uの全ての(イミュータブルな)メソッドを暗黙的に実装する。
となります。
つまり冒頭の疑問の答えは、Vec<T>がTarget = [T]としてDerefを実装しているのでドキュメントの二つ目の項目に当てはまり、コンパイラが自動的にスライスへの参照に変換してくれるからということになります。
他にもiterなどのメソッドはVecのメソッドではなくsliceのメソッドで、三つ目のルールからv.iter()というのはv.deref().iter()に自動的に変換されています。
ミュータブル版のDerefMutもあります。