Why do we need to implement AsRef<T> for T
and then get a reference of T
by as_ref
? why not just use &T
?
I'm not sure I understand what you are referring to? There is no impl AsRef<T> for T
implementation in the standard library. There is one for impl AsRef<T> for &T
, so I don't see why you wouldn't be able to just pass &T
to an interface that expects AsRef<T>
.
This is an example from path:
impl AsRef<Path> for Path {
fn as_ref(&self) -> &Path {
self
}
}
Sorry for any added confusion from my previous answer, but there is no impl AsRef<T> for &T
implementation, the one I linked is for impl AsRef<U> for &T where T: AsRef<U>
. So indeed if we want to pass a &T
to something that expects AsRef<T>
, T
must implement AsRef<T>
, you are completely right. Read more about it in AsRef in std::convert - Rust. The Borrow
trait on the other hand is reflexive, so you might want to use it instead of AsRef
.
Ideally every type T
would implement AsRef<T>
. But due to coherence -- the necessity to avoid overlapping implementations -- one has to choose between a blanket "lifting over references" implementation and a blanket "reflective" implementation.
Since AsRef<T>
got the blanket "lifting over references" implementation (in contrast with Borrow
), every type has to supply the reflexive implementation individually. (Why there isn't a builtin derive to make this more common, I couldn't say.)
I assume it's purely for convenience. I think it's obvious why there is impl AsRef<Path> for PathBuf
? But PathBuf
and &Path
are often used interchangeably in code, and PathBuf: Deref<Output=Path>
. This can lead to some minor user confusion whether your variable is &Path
or &PathBuf
. Implementing AsRef<Path>
for Path
allows end users to treat those cases uniformly, without annoying compiler errors, and it also makes refactoring owned and borrowed paths a bit easier.
I don't think it's common to impl AsRef<T> for T
otherwise.