Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checking equality of custom structs

Tags:

rust

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?

like image 925
andrey Avatar asked Feb 02 '16 18:02

andrey


1 Answers

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!

like image 164
Vladimir Matveev Avatar answered Oct 23 '22 23:10

Vladimir Matveev