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
T
implementsDeref<Target = U>
, andx
is a value of typeT
, then:
In immutable contexts,
*x
(whereT
is neither a reference nor a raw pointer) 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 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
もあります。