# Strange coercion during comparison

**URL:** <https://users.rust-lang.org/t/strange-coercion-during-comparison/43153>\
**Category:** help\
**Created:** [May 24, 2020, 3:46am UTC](https://users.rust-lang.org/t/strange-coercion-during-comparison/43153 "2020-05-24T03:46:07Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![mschmidt](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mschmidt/32/15328_2.png) [@mschmidt](https://users.rust-lang.org/u/mschmidt)\
**Post date:** [May 24, 2020, 3:46am UTC](https://users.rust-lang.org/t/strange-coercion-during-comparison/43153/1 "2020-05-24T03:46:08Z")

</div>

Consider this:

```rust
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.

Thanks!

---

<div class="post-metadata">

**Author:** ![mbrubeck](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mbrubeck/32/648_2.png) [@mbrubeck](https://users.rust-lang.org/u/mbrubeck)\
**Post date:** [May 24, 2020, 4:26am UTC](https://users.rust-lang.org/t/strange-coercion-during-comparison/43153/2 "2020-05-24T04:26:35Z")

</div>

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.

> [@mschmidt](#):
>
> 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.

The full error message for this case is:

```rust
  = 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](https://doc.rust-lang.org/1.43.1/src/core/cmp.rs.html#1213-1225) from the standard library and tries to apply it:

```rust
    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.

> [@mschmidt](#):
>
> Another example is I cannot figure out why `&v == &s` works but `&s == &v` doesn't.

`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.

---

<div class="post-metadata">

**Author:** ![mschmidt](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mschmidt/32/15328_2.png) [@mschmidt](https://users.rust-lang.org/u/mschmidt)\
**Post date:** [May 24, 2020, 5:43am UTC](https://users.rust-lang.org/t/strange-coercion-during-comparison/43153/3 "2020-05-24T05:43:38Z")

</div>

Great answer! Thank you very much!

Things I learned from your post:

1. 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](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=43881cd8d250de6a054774b3d2659b04)

2. 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>`;

3. `&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.

4. I guess the simplest way to to write the comparison is `v == s`. Because `Vec<T>` implements `PartialEq<&[T]>`.

5. "Impls in libcore can't reference types in libstd." I guess this is because the "nostd" situation in embedded development. Is this correct?

---

<div class="post-metadata">

**Author:** ![mbrubeck](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mbrubeck/32/648_2.png) [@mbrubeck](https://users.rust-lang.org/u/mbrubeck)\
**Post date:** [May 24, 2020, 3:04pm UTC](https://users.rust-lang.org/t/strange-coercion-during-comparison/43153/4 "2020-05-24T15:04:30Z")

</div>

> [@mschmidt](#):
>
> `&v == s` is not valid because `Vec<T>` does not impl `PartialEq<[T]>` . (Why?)

I'm not sure! Possibly just an oversight. I found that there is an [open RFC issue](https://github.com/rust-lang/rfcs/issues/2917) proposing more Vec/slice impls, and I posed the question there.

> [@mschmidt](#):
>
> "Impls in libcore can't reference types in libstd." I guess this is because the "nostd" situation in embedded development. Is this correct?

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](https://blog.rust-lang.org/2020/01/30/Rust-1.41.0.html#relaxed-restrictions-when-implementing-traits) 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).

---

<div class="post-metadata">

**Author:** ![trentj](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/trentj/32/5690_2.png) [@trentj](https://users.rust-lang.org/u/trentj)\
**Post date:** [May 24, 2020, 4:03pm UTC](https://users.rust-lang.org/t/strange-coercion-during-comparison/43153/5 "2020-05-24T16:03:30Z")

</div>

I'm surprised you didn't try the simplest possible comparison:

```rust
    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:

```rust
    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.

---

<div class="post-metadata">

**Author:** ![system](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/system/32/51372_2.png) [@system](https://users.rust-lang.org/u/system)\
**Post date:** [August 22, 2020, 4:03pm UTC](https://users.rust-lang.org/t/strange-coercion-during-comparison/43153/6 "2020-08-22T16:03:37Z")

</div>

Closed on August 22, 2020, 4:03pm UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
