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 implementation T: Borrow<T>, which is essential for making the above collections work well. AsRef provides a different blanket implementation, basically &T: AsRef<U> whenever T: AsRef<U>, which is important for APIs like fs::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!

Tags:

Rust