Why does slice == array_ref work while array_ref == slice doesn't compile? And why can I compare a slice (reference) with an (owned) array value while integers and references to integers don't compare?
P.S.: And why does array == slice work while array_ref == slice doesn't?
It all boils down to what PartialEq impls are available in the standard library. There's no deep insight to be had or anything interesting here, really â T == U compiles if and only if impl PartialEq<U> for T exists. This is not symmetric, so it doesn't automatically imply U == T compiling.
Oh, I thought that unsized coercions are involved somehow. But looks like since const generics are stable, there are implementations of PartialEq for arrays (with generic length).
But I don't find any implementation PartialEq<&[A; N]> for &[B], which would be needed for slice == array_ref. Or did I miss it somewhere? So I guess unsized coercions are involved somehow?
Another question: How can the standard library have these implementations since Rust 1.0.0 whereas const generics weren't available back then?
x.eq(y) can also be written x == y , and x.ne(y) can be written x != y . We use the easier-to-read infix notation in the remainder of this documentation.
src: PartialEq in std::cmp - Rust
But then what's the problem? That is exactly why you don't need to put the reference into the type parameter itself â the method already takes &self and &Rhs, not self and Rhs.
No, it would translate into (&&a).eq(&&b) (method calls auto-ref!), and there's an impl PartialEq<&U> for &T, which removes one level of reference from both sides.
Okay, to be precise, let's say it translates to ::std::cmp::PartialEq::eq(&&a, &&b);, and yeah one level of references get removed though the generic impl. So it calls ::std::cmp::PartialEq::eq(&a, &b);.
My point is that the the &'s in the eq method definition (both on &self and on the RHS) correspond to the &'s added by the == operator, which is why I found this misleading:
I.e. for a == &b to work, I need an impl PartialEq<&TypeOfB> for TypeOfA, and not an impl PartialEq<TypeOfB> for TypeOfA. (see PlaygroundPlayground)
Compiling playground v0.0.1 (/playground)
error[E0277]: can't compare `[u8]` with `&[u8; 1]`
--> src/main.rs:6:55
|
6 | assert!(<[u8] as PartialEq<&[u8; 1]>>::eq(&slice, &array_ref));
| --------------------------------- ^^^^^^^^^^ no implementation for `[u8] == &[u8; 1]`
| |
| required by a bound introduced by this call
|
= help: the trait `PartialEq<&[u8; 1]>` is not implemented for `[u8]`
= help: the following other types implement trait `PartialEq<Rhs>`:
<&[B] as PartialEq<[A; N]>>
<&[T] as PartialEq<Vec<U, A>>>
<&mut [B] as PartialEq<[A; N]>>
<&mut [T] as PartialEq<Vec<U, A>>>
<[A; N] as PartialEq<&[B]>>
<[A; N] as PartialEq<&mut [B]>>
<[A; N] as PartialEq<[B; N]>>
<[A; N] as PartialEq<[B]>>
and 3 others
For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to previous error
I don't think it's misleading, you are misinterpreting the answer. It is true that the RHS type doesn't have to be a reference. If you want to compare T and U, then neither T nor U has to be a reference. It is not the case that a type must be a reference in order to be comparable for equality.
What is true is that the LHS and the RHS have to be the same as the Self and Rhs types being compared on the two sides of the == sign. Thus, if you want to compare e.g. Foo with &Bar then there has to be an impl PartialEq<&Bar> for Foo. But this has nothing to do with "references". This is just how the == operator is desugared.