Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The PartialEq implementation for tuples isn't general enough #105092

Open
Michael-F-Bryan opened this issue Nov 30, 2022 · 1 comment
Open

The PartialEq implementation for tuples isn't general enough #105092

Michael-F-Bryan opened this issue Nov 30, 2022 · 1 comment
Labels
C-bug Category: This is a bug. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@Michael-F-Bryan
Copy link

A coworker recently ran into a situation where tuples aren't comparable even when their individual elements are. I was able to boil it down to the following code snippet:

fn main() {
    assert_partial_eq::<A, B>();
    assert_partial_eq::<C, D>();
    assert_partial_eq::<(A, C), (B, D)>();
}

fn assert_partial_eq<A, B>() where A: PartialEq<B> {}

#[derive(Debug, PartialEq)] struct A;
#[derive(Debug, PartialEq)] struct B;
#[derive(Debug, PartialEq)] struct C;
#[derive(Debug, PartialEq)] struct D;

impl PartialEq<A> for B { fn eq(&self, other: &A) -> bool { true } }
impl PartialEq<B> for A { fn eq(&self, other: &B) -> bool { true } }

impl PartialEq<C> for D { fn eq(&self, other: &C) -> bool { true } }
impl PartialEq<D> for C { fn eq(&self, other: &D) -> bool { true } }

(playground)

I expected the above snippet to compile and run successfully, but the code fails to compile.

Compiling playground v0.0.1 (/playground)
error[[E0277]](https://doc.rust-lang.org/stable/error-index.html#E0277): can't compare `(A, C)` with `(B, D)`
  --> src/main.rs:19:25
   |
19 |     assert_partial_eq::<(A, C), (B, D)>();
   |                         ^^^^^^ no implementation for `(A, C) == (B, D)`
   |
   = help: the trait `PartialEq<(B, D)>` is not implemented for `(A, C)`
   = help: the following other types implement trait `PartialEq<Rhs>`:
             ()
             (A, Z, Y, X, W, V, U, T)
             (B, A, Z, Y, X, W, V, U, T)
             (C, B, A, Z, Y, X, W, V, U, T)
             (D, C, B, A, Z, Y, X, W, V, U, T)
             (E, D, C, B, A, Z, Y, X, W, V, U, T)
             (T,)
             (U, T)
           and 5 others
note: required by a bound in `assert_partial_eq`
  --> src/main.rs:22:39
   |
22 | fn assert_partial_eq<A, B>() where A: PartialEq<B> {}
   |                                       ^^^^^^^^^^^^ required by this bound in `assert_partial_eq`

I always thought the standard library would have something like this:

impl<LHS1, LHS2, RHS1, RHS2> PartialEq<(RHS1, RHS2)> for (LHS1, LHS2)
where 
  LHS1: PartialEq<RHS1>,
  LHS2: PartialEq<RHS2>,
{
  ...
}

But it seems like it only implements PartialEq when the left-hand side tuple and right-hand side tuple have the exact same type.

Meta

This is reproducible on the Rust playground using stable (1.65.0).

@Michael-F-Bryan Michael-F-Bryan added the C-bug Category: This is a bug. label Nov 30, 2022
@Jules-Bertholet
Copy link
Contributor

See also #20063
@rustbot label T-libs-api

@rustbot rustbot added the T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. label Dec 10, 2023
copybara-service bot pushed a commit to google/googletest-rust that referenced this issue Nov 11, 2024
…nt-wise.

This adds special cases in `verify_eq!` so that, when doing `eq` matching on sequences of tuples-like elements, the matcher applies tuple matching, distributing `eq` pointwise.

This improves the ergonomics of tests that check for tuple contents, such as:

```rust
let hash_map: std::collections::HashMap<String, String> =
        std::collections::HashMap::from([
            ("a".into(), "A".into()),
            ("b".into(), "B".into())]);
    verify_eq!(hash_map, {("a", "A"), ("b", "B")})
```

because the matcher for `&str` is compatible with `&String`.  The specialization applies on the inner structure; without it, the general matcher on tuples doesn't apply in the above case due to the definition of `PartialEq` on whole
tuples, which is currently limited by rust-lang/rust#105092.

PiperOrigin-RevId: 693858563
copybara-service bot pushed a commit to google/googletest-rust that referenced this issue Nov 11, 2024
…nt-wise.

This adds special cases in `verify_eq!` so that, when doing `eq` matching on sequences of tuples-like elements, the matcher applies tuple matching, distributing `eq` pointwise.

This improves the ergonomics of tests that check for tuple contents, such as:

```rust
let hash_map: std::collections::HashMap<String, String> =
        std::collections::HashMap::from([
            ("a".into(), "A".into()),
            ("b".into(), "B".into())]);
    verify_eq!(hash_map, {("a", "A"), ("b", "B")})
```

because the matcher for `&str` is compatible with `&String`.  The specialization applies on the inner structure; without it, the general matcher on tuples doesn't apply in the above case due to the definition of `PartialEq` on whole
tuples, which is currently limited by rust-lang/rust#105092.

PiperOrigin-RevId: 693858563
copybara-service bot pushed a commit to google/googletest-rust that referenced this issue Nov 12, 2024
This adds special cases in `verify_eq!` so that, when doing `eq` matching on sequences of tuple elements, the matcher applies tuple matching, distributing `eq` pointwise.

This improves the ergonomics of tests that check for tuple contents, such as:

```rust
let hash_map: std::collections::HashMap<String, String> =
    std::collections::HashMap::from([
        ("a".into(), "A".into()),
        ("b".into(), "B".into())]);
verify_eq!(hash_map, {("a", "A"), ("b", "B")})
```

because the matcher for `&str` is compatible with `&String`.

The specialization applies on the inner structure; without it, the general matcher on tuples doesn't apply in the above case due to the definition of `PartialEq` on whole tuples, which is currently limited by rust-lang/rust#105092.

PiperOrigin-RevId: 693858563
copybara-service bot pushed a commit to google/googletest-rust that referenced this issue Nov 12, 2024
This adds special cases in `verify_eq!` so that, when doing `eq` matching on sequences of tuple elements, the matcher applies tuple matching, distributing `eq` pointwise.

This improves the ergonomics of tests that check for tuple contents, such as:

```rust
let hash_map: std::collections::HashMap<String, String> =
    std::collections::HashMap::from([
        ("a".into(), "A".into()),
        ("b".into(), "B".into())]);
verify_eq!(hash_map, {("a", "A"), ("b", "B")})
```

because the matcher for `&str` is compatible with `&String`.

The specialization applies on the inner structure; without it, the general matcher on tuples doesn't apply in the above case due to the definition of `PartialEq` on whole tuples, which is currently limited by rust-lang/rust#105092.

PiperOrigin-RevId: 693858563
copybara-service bot pushed a commit to google/googletest-rust that referenced this issue Nov 12, 2024
This adds special cases in `verify_eq!` so that, when doing `eq` matching on sequences of tuple elements, the matcher applies tuple matching, distributing `eq` pointwise.

This improves the ergonomics of tests that check for tuple contents, such as:

```rust
let hash_map: std::collections::HashMap<String, String> =
    std::collections::HashMap::from([
        ("a".into(), "A".into()),
        ("b".into(), "B".into())]);
verify_eq!(hash_map, {("a", "A"), ("b", "B")})
```

because the matcher for `&str` is compatible with `&String`.

The specialization applies on the inner structure; without it, the general matcher on tuples doesn't apply in the above case due to the definition of `PartialEq` on whole tuples, which is currently limited by rust-lang/rust#105092.

PiperOrigin-RevId: 695528259
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants