Deref coercions
型エラーが起きている時に、
自動的に .deref()
が呼び出される
Rustの参照解決型変換(Deref coercion)は、型が期待される場所で、自動的に参照を解除してターゲット型のメソッドや関数を呼び出す仕組みです。この機能を利用すると、 Deref
トレイトを実装している型が持つ参照先の型のメソッドや機能をそのまま使えます。
2. String
と str
の例
String
型は可変な文字列を表し、 str
(文字列スライス)のすべてのメソッドを利用できます。これは、 String
が Deref<Target=str>
を実装しているためです。
rustfn main() {
let s = String::from("hello world");
// Stringに対してstrのメソッドsplit_atを直接呼び出す
let (first, second) = s.split_at(5);
println!("First: '{}', Second: '{}'", first, second);
// 出力: First: 'hello', Second: ' world'
}
String
は Deref<Target=str>
を実装しているため、 s.split_at(5)
は自動的に &String
→ &str
に変換されます。
str
のすべてのメソッド(例: split_at
, find
など)は String
でもそのまま利用可能です。
s
は、
&String
じゃなくて
String
なのに、なぜDerefが使えるの?

メソッド呼び出し時の特殊な挙動
Rustには「オブジェクト安全なメソッド呼び出しの糖衣構文」があり、メソッド呼び出し時に以下の手順が自動的に行われます:
値が参照される(借用される)
値(String型)がそのままではメソッドの型に合わない場合、自動的に参照(&Stringや&mut String)が作られます。
Derefが適用される
借用された型がDerefを実装している場合、Derefを使ってターゲット型(strなど)に変換されます。
ターゲット型のメソッドが呼び出される
最終的にターゲット型(この場合はstr)のメソッドが実行されます。
まじか、めっちゃ連鎖するやん

3. Vec<u8>
と &[u8]
の例
Vec<T>
は動的配列を表します。 Vec<u8>
(バイトの配列)は Deref<Target=[T]>
を実装しているため、 &Vec<u8>
は自動的に &[u8]
(バイトスライス)に変換されます。
rustfn process_bytes(slice: &[u8]) {
println!("Processing bytes: {:?}", slice);
}
fn main() {
let v = vec![1, 2, 3, 4, 5];
// Vec<u8>を受け取り、&[u8]が必要な関数に渡す
process_bytes(&v);
// 手動でデリファレンスしても同じ結果
process_bytes(&*v);
}
Vec<u8>
は Deref<Target=[u8]>
を実装しているため、 &Vec<u8>
→ &[u8]
の変換が自動的に行われます。
手動でデリファレンスしても同じ結果ですが、参照解決型変換により簡潔に記述できます。
---
4. 連続した参照解決の例
Rustでは参照解決型変換を連続して適用できます。たとえば、 Rc<String>
に対して str
のメソッドを直接呼び出す場合、次のような変換が連続して行われます:
&Rc<String>
→ &String
→ &str
rustuse std::rc::Rc;
fn main() {
let r = Rc::new(String::from("hello world"));
// Rc<String>に対してsplit_atを直接呼び出す
let (first, second) = r.split_at(5);
println!("First: '{}', Second: '{}'", first, second);
// 出力: First: 'hello', Second: ' world'
}
r.split_at(5)
では次の変換が自動的に行われます:
1. &Rc<String>
→ &String
( Rc<T>
の Deref
による)
2. &String
→ &str
( String
の Deref
による)
str
のメソッド split_at
を直接 Rc<String>
に対して呼び出せるようになります。