AsRef と Borrow

例えばAsRef<T>トレイトを実装済のUがある時、それから&Tを得られます。

このトレイトを実装している 1つにStruct std::path::Path::newメソッドがあります。定義は以下の通り。

impl Path {
  pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &Path {
    // snap
  }
}

ちなみに OsStringOsStr はプラットフォーム毎の固有の文字を安全に扱う為の型のようです。

戻って、::newAsRef<OsStr>を持ったサイズ不定型sを受け取ります。

ここでTrait std::convert::AsRef を見ると以下のような箇所があります。

impl AsRef<OsStr> for str
impl AsRef<OsStr> for String

よって&str&StringなどはAsRef<OsStr> + ?Sizedを満たすのでこのような書き方で動きます。

use std::path::Path;

let str = "foo";

Path::new(str);
Path::new(&str.to_string());

似たものにBorrowがあります。AsRefのようにUから&Tを取得できるトレイトですが、得たTに関してのHashEqOrdの結果が変換前と同じ結果になることが要求されます。

(この項目は違いがあまり違いが理解できてません🙇Borrowはブランケット実装によってすべてのTで自分を借りれる::borrowを持っているので、「1番渡してほしいのはTだけどUでもいいよ、だけどUは上記に対してTと同じ結果を返すものにしてね」という場合はBorrow、「手間だからTになれるUなら何でもいいよ」な場合はAsRefかな的な🤔)