Would it make sense for std::cmd::Reverse<T> to implement Borrow? I started thinking it would be nice in the following situation, but maybe there's a reason why it doesn't.
I have lots of logic that's almost identical for the forward and backward operations (iterating through the elements stopping when the sum reaches a threshold, etc.). I want to implemented some generic functions like so:
fn helper<T>(data: BTreeMap<T, u64>)
where T: Borrow<u64> + Ord
{
}
But I can't make use of the Reverse<T> in my BTreeMap because I can't think of a bound to get the T out of both a T and a Reverse<T>.
Here's a playground of an example with more fleshed out code example: Rust Playground
Is there a reason Reverse<T> doesn't implement Borrow<T>?
Maybe there's another technique for avoiding this type of code duplication?
Reverse<T> must not implement Borrow<T> because that would violate the rules for Borrow implementations; reversing ordering means Ord is not implemented equivalently.
In particular Eq , Ord and Hash must be equivalent for borrowed and owned values: x.borrow() == y.borrow() should give the same result as x == y .
It could implement AsRef<T>, though. I don't see any previous issues filed about that, so maybe no one has thought about it yet.
While this wouldn't be helpful for OP, do you know why Deref isn't implemented for Reverse as well? I think I read an argument against implementing Deref for container types like Reverse, but it slipped my mind. Because it's a pattern I see rather often (i.e. pretty much every extractor in the major web frameworks looks like Reverse and implements Deref, axum::Json for example).
Edit: I think I found the answer I was looking for:
a value of the type transparently behaves like a value of the target type;
Given that Reverse<T> behaves differently to T when it comes to ordering and comparison, deref coercion doesn't sound desirable.
That would be equally as bad as implementing Borrow, and it would now allow implicit conversions. In this Playground, if you un-comment the type annotations, the ordering flips. Ouch!
Absolutely right. Only considered type signatures and not trait implementations when I compared Reverse to a type like axum::Json. While the latter is purely a container used for serialization/extraction of the typed payload from a HTTP request, the former obviously changes the logic of the wrapped type in a significant manner that makes deref coercion undesirable.