Why does T not implement AsRef<T>?
AsRef
and Borrow
are pretty similar at first glance, but they are used for different things. The Book describes the difference between them pretty well:
Choose
Borrow
when you want to abstract over different kinds of borrowing, or when you’re building a data structure that treats owned and borrowed values in equivalent ways, such as hashing and comparison.Choose
AsRef
when you want to convert something to a reference directly, and you’re writing generic code.
In your case Borrow
is a more reasonable choice because there is no conversion involved.
As for the question of why AsRef
is not implemented between different integral types, I guess this would go against the intent of Rust to be expressive about casts; I think it's similar to the question Why can't I compare two integers of different types?.
Here's an authoritative answer by Aaron Turon:
Borrow
provides a blanket implementationT: Borrow<T>
, which is essential for making the above collections work well.AsRef
provides a different blanket implementation, basically&T: AsRef<U>
wheneverT: AsRef<U>
, which is important for APIs likefs::open
that can use a simpler and more flexible signature as a result. You can't have both blanket implementations due to coherence, so each trait is making the choice that's appropriate for its use case.
I think that is one of the differences of AsRef
and Borrow
.
That is, Borrow<T>
is implemented directly for &T
, while AsRef<T>
is not implemented for &T
.
Funny thing is that AsRef<U>
is implemented for &T
if T implements AsRef<U>
. That is, if you can use AsRef
with a type, you can use it with a reference to the same time.
And another funny thing is that Borrow<T>
is implemented for &T
but also for T
!