This code does not compile:
fn ref_on_int<T>(_: T) where T: AsRef<i32> {}
fn main() {
ref_on_int(&0_i32)
}
because
the trait bound `i32: std::convert::AsRef<i32>` is not satisfied
Why is it so?
This could be useful for example with a newtype like
struct MyInt(i32);
impl AsRef<i32> for MyInt {
/* etc. */
}
then you could indifferently pass a reference on an i32 or a reference on a MyInt, because in the memory we have in both cases an i32.
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
Borrowwhen 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
AsRefwhen 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:
Borrowprovides a blanket implementationT: Borrow<T>, which is essential for making the above collections work well.AsRefprovides a different blanket implementation, basically&T: AsRef<U>wheneverT: AsRef<U>, which is important for APIs likefs::openthat 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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With