fn main() {
let v = vec![2,3];
let n = vec![2,3];
let s = n.as_slice();
//println!("{}", s == &v);
//println!("{}", v == &s);
//println!("{}", &s == v);
//println!("{}", &v == s);
//println!("{}", &s == &v);
println!("{}", &v == &s);
println!("{}", s == v.as_slice());
}
All non-working lines have been commented out, only the bottom two is accepted by the compiler.
However I don't quite understand why some of the commented lines is failing.
For example, the first one: s == &v
s is of type &[], and I guess &v would be coerced into the a slice to match.
To my surprise, the error message is: no implementation for [{integer}] == std::vec::Vec<{integer}>, It seems that both s and &v are implicitly stripped of &, instead of &v being coerced.
Another example is I cannot figure out why &v == &s works but &s == &v doesn't.
The operands aren't coerced here; coercion happens only when the “expected” type is a single type. Since PartialEq<T> may be implemented by multiple types, the compiler doesn’t know what to coerce to.
The full error message for this case is:
= help: the trait `std::cmp::PartialEq<std::vec::Vec<{integer}>>` is not implemented for `[{integer}]`
= note: required because of the requirements on the impl of `std::cmp::PartialEq<&std::vec::Vec<{integer}>>` for `&[{integer}]`
Since both types are references, the compiler finds this impl from the standard library and tries to apply it:
impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &A
where
A: PartialEq<B>,
but it fails because the A: PartialEq<B> bound isn’t met, which is what the first part of the error message is telling you.
Vec<T> implements PartialEq<&[T]>, but &[T] does not implement PartialEq<Vec<T>>. This is because the slice type is in libcore while Vec is in libstd. Impls in libcore can't reference types in libstd.
The trait PartialEq can be impl'd asymmetrically. If I only impl PartialEq<Bar> for Foo, but not otherwise, then Bar == Foo is invalid; playground
There is a blanket impl PartialEq<&B> for &A where A: PartialEq<B> which basically means to write &A == &B, A must impl PartialEq<B>;
&v == s is not valid because Vec<T> does not impl PartialEq<[T]>. (Why?) There is a similar looking trait impl PartialEq<[B; N]> for Vec<A> but it's for arrays, not slices.
I guess the simplest way to to write the comparison is v == s. Because Vec<T> implements PartialEq<&[T]>.
"Impls in libcore can't reference types in libstd." I guess this is because the "nostd" situation in embedded development. Is this correct?
I'm not sure! Possibly just an oversight. I found that there is an open RFC issue proposing more Vec/slice impls, and I posed the question there.
At some level, yes. More directly, it's because libraries in Rust can't have circular dependencies: std depends on core, so core must be compiled before std and can't depend on std.
However, it looks like recent changes to the rules about impls have made it possible for these missing impls to exist in libstd rather than libcore. There is a proposal to add them, in that RFC issue (above).
I'm surprised you didn't try the simplest possible comparison:
println!("{}", v == s);
//println!("{}", s == v); // doesn't work for the same reason as &s == &v
Since &[T] and Vec<T> both dereference to [T], you might also use * to compare them:
println!("{}", *v == *s);
println!("{}", *s == *v); // also works because both *s and *v are [i32]
Comparison operators (==, !=, >=, <=, >, and <) implicitly reference their arguments, so *v == *s desugars to something like <[i32] as PartialEq>::partial_eq(&*v, &*s). Nothing is being moved here.