andrey
andrey

Reputation: 1595

Checking equality of custom structs

I'm trying to check equality of two (functionally identical) structs.

#[derive(PartialEq, Debug)]
pub struct TypeA<'a>(&'a str);

#[derive(PartialEq, Debug)]
pub struct TypeB<'a>(&'a str);

impl<'a> TypeA<'a> {
    pub fn new(n: &str) -> TypeA {
        TypeA(n)
    }
}

impl<'a> TypeB<'a> {
    pub fn new(n: &str) -> TypeB {
        TypeB(n)
    }
}

fn main() {
    assert_eq!(TypeA::new("A"), TypeB::new("A"));
}

It returns the error:

error[E0308]: mismatched types
  --> src/main.rs:20:5
   |
20 |     assert_eq!(TypeA::new("A"), TypeB::new("A"));
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `TypeA`, found struct `TypeB`
   |
   = note: expected type `TypeA<'_>`
              found type `TypeB<'_>`
   = note: this error originates in a macro outside of the current crate

It seems like deriving PartialEq isn't working. Is the only solution to implement it manually between these two types? Is the problem somewhere else entirely?

Upvotes: 16

Views: 17648

Answers (1)

Vladimir Matveev
Vladimir Matveev

Reputation: 128181

Deriving PartialEq does work; but Rust does not have a notion of structural equality of different types. If you write #[derive(PartialEq)] on one type, it does not mean that values of this type could be compared with values of another type, even if it has the same internal structure. It only means that values of this type can be compared between themselves.

However, PartialEq has a type parameter for the right-hand side operand (creatively named Rhs), which means you can implement PartialEq multiple times for a single type with different type arguments. #[derive(PartialEq)] will only implement PartialEq<X> when applied on X, but that doesn't stop you from implementing PartialEq<Y> for other values of Y yourself.

In this case, you do need to implement PartialEq manually for these types, in both directions:

impl<'a, 'b> PartialEq<TypeB<'b>> for TypeA<'a> {
    fn eq(&self, other: &TypeB<'b>) -> bool {
        self.0 == other.0
    }
}

impl<'a, 'b> PartialEq<TypeA<'a>> for TypeB<'b> {
    fn eq(&self, other: &TypeA<'a>) -> bool {
        self.0 == other.0
    }
}

Afterwards you will be able to use == or assert_eq!() for these pairs of types. Remember that you can still keep #[derive(PartialEq)] on your types if you need it too!

Upvotes: 25

Related Questions