# Using `#[derive(Eq)]` and `#[derive(PartialEq)]`

Deriving `Eq`/`PartialEq` works by checking whether two values are equal according
to their type structure.




## Structural equality

Deriving `Eq`/`PartialEq` for enums/structs works in a similar way to the one in `std`,
by comparing all the available fields, but, in the contrast:
1. Does not overconstrain generic parameters.
2. Implements `PartialEq::ne()` method as well, to propagate possible efficient
   implementations of this method from the underlying types.


### Structs

For structs all the available fields are checked for equality.

```rust
# use std::marker::PhantomData;
# use derive_more::{Eq, PartialEq};
#
trait Trait {
    type Assoc;
}
impl<T: ?Sized> Trait for T {
    type Assoc = u8;
}

#[derive(Debug, Eq, PartialEq)]
struct Foo<A, B, C: Trait + ?Sized> {
    a: A,
    b: PhantomData<B>,
    c: C::Assoc,
}

#[derive(Debug)]
struct NoEq;

assert_eq!(Foo::<_, NoEq, NoEq> { a: 3, b: PhantomData, c: 0 }, Foo { a: 3, b: PhantomData, c: 0 });
assert_ne!(Foo::<_, NoEq, NoEq> { a: 3, b: PhantomData, c: 0 }, Foo { a: 0, b: PhantomData, c: 3 });
```
This generates code equivalent to:
```rust
# use std::marker::PhantomData;
#
# trait Trait {
#     type Assoc;
# }
# impl<T: ?Sized> Trait for T {
#     type Assoc = u8;
# }
#
# struct Foo<A, B, C: Trait + ?Sized> {
#     a: A,
#     b: PhantomData<B>,
#     c: C::Assoc,
# }
#
impl<A, B, C: Trait + ?Sized> PartialEq for Foo<A, B, C>
where
    A: PartialEq,
    PhantomData<B>: PartialEq, // `B: PartialEq` is generated by `std` instead
    C::Assoc: PartialEq,       // `C: PartialEq` is generated by `std` instead
{
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (Self { a: self_0, b: self_1, c: self_2 }, Self { a: other_0, b: other_1, c: other_2 }) => {
                self_0 == other_0 && self_1 == other_1 && self_2 == other_2
            }
        }
    }
    fn ne(&self, other: &Self) -> bool {
        match (self, other) {
            (Self { a: self_0, b: self_1, c: self_2 }, Self { a: other_0, b: other_1, c: other_2 }) => {
                self_0 != other_0 || self_1 != other_1 || self_2 != other_2
            }
        }
    }
}

impl<A, B, C: Trait + ?Sized> Eq for Foo<A, B, C>
where
    Self: PartialEq,
    A: Eq,
    PhantomData<B>: Eq, // `B: Eq` is generated by `std` instead
    C::Assoc: Eq,       // `C: Eq` is generated by `std` instead
{}
```


### Enums

For enums the first check is whether these two values represent the same variant,
and after that we check fields equality.

```rust
# use std::marker::PhantomData;
# use derive_more::{Eq, PartialEq};
#
# trait Trait {
#     type Assoc;
# }
# impl<T: ?Sized> Trait for T {
#     type Assoc = u8;
# }
#
#[derive(Debug, Eq, PartialEq)]
enum Foo<A, B, C: Trait + ?Sized> {
    A(A),
    B { b: PhantomData<B> },
    C(C::Assoc),
}
#
# #[derive(Debug)]
# struct NoEq;

assert_eq!(Foo::<_, NoEq, NoEq>::A(3), Foo::A(3));
assert_ne!(Foo::<_, NoEq, NoEq>::A(3), Foo::A(0));

assert_eq!(Foo::<u16, NoEq, NoEq>::B { b: PhantomData }, Foo::B { b: PhantomData });

assert_eq!(Foo::<i32, NoEq, NoEq>::C(3), Foo::C(3));
assert_ne!(Foo::<i32, NoEq, NoEq>::C(3), Foo::C(0));
```
This generates code equivalent to:
```rust
# use std::marker::PhantomData;
#
# trait Trait {
#     type Assoc;
# }
# impl<T: ?Sized> Trait for T {
#     type Assoc = u8;
# }
#
# enum Foo<A, B, C: Trait + ?Sized> {
#     A(A),
#     B { b: PhantomData<B> },
#     C(C::Assoc),
# }
#
impl<A, B, C: Trait + ?Sized> PartialEq for Foo<A, B, C>
where
    A: PartialEq,
    PhantomData<B>: PartialEq, // `B: PartialEq` is generated by `std` instead
    C::Assoc: PartialEq,       // `C: PartialEq` is generated by `std` instead
{
    fn eq(&self, other: &Self) -> bool {
        std::mem::discriminant(self) == std::mem::discriminant(other) &&
            match (self, other) {
                (Self::A(self_0), Self::A(other_0)) => { self_0 == other_0 }
                (Self::B { b: self_0 }, Self::B { b: other_0 }) => { self_0 == other_0 }
                (Self::C(self_0), Self::C(other_0)) => { self_0 == other_0 }
                _ => unsafe { std::hint::unreachable_unchecked() }
            }
    }
    fn ne(&self, other: &Self) -> bool {
        std::mem::discriminant(self) != std::mem::discriminant(other) ||
            match (self, other) {
                (Self::A(self_0), Self::A(other_0)) => { self_0 != other_0 }
                (Self::B { b: self_0 }, Self::B { b: other_0 }) => { self_0 != other_0 }
                (Self::C(self_0), Self::C(other_0)) => { self_0 != other_0 }
                _ => unsafe { std::hint::unreachable_unchecked() }
            }
    }
}

impl<A, B, C: Trait + ?Sized> Eq for Foo<A, B, C>
where
    Self: PartialEq,
    A: Eq,
    PhantomData<B>: Eq, // `B: Eq` is generated by `std` instead
    C::Assoc: Eq,       // `C: Eq` is generated by `std` instead
{}
```


### Ignoring

Both `#[eq(skip)]` and `#[partial_eq(skip)]` attributes could be used to ignore
fields, a whole struct or enum variants in the expansion.

```rust
# use derive_more::{Eq, PartialEq};
#
#[derive(Debug)]
struct NoEq; // doesn't implement `Eq`/`PartialEq`

#[derive(Debug, Eq, PartialEq)]
struct Foo {
    num: i32,
    // This attribute is seen by both `Eq` and `PartialEq` macros,
    // so the repetition is unnecessary.
    #[eq(skip)] // or #[eq(ignore)]
    ignored: f32,
}

#[derive(Debug, Eq, PartialEq)]
// This attribute is also seen by both `Eq` and `PartialEq` macros.
// Makes all fields of this struct being ignored.
#[partial_eq(skip)] // or #[partial_eq(ignore)]
struct Bar(f32, NoEq);

#[derive(Debug, Eq, PartialEq)]
enum Enum {
    Foo(i32, #[eq(skip)] NoEq),
    #[eq(skip)]
    Bar(NoEq),
    Baz,
}

assert_eq!(Foo { num: 0, ignored: 1.0 }, Foo { num: 0, ignored: 1.0 });
assert_eq!(Foo { num: 0, ignored: 1.0 }, Foo { num: 0, ignored: 2.0 });
assert_ne!(Foo { num: 0, ignored: 1.0 }, Foo { num: 1, ignored: 1.0 });

assert_eq!(Bar(0.0, NoEq), Bar(0.0, NoEq));
assert_eq!(Bar(0.0, NoEq), Bar(1.0, NoEq));

assert_eq!(Enum::Foo(0, NoEq), Enum::Foo(0, NoEq));
assert_ne!(Enum::Foo(0, NoEq), Enum::Foo(1, NoEq));

assert_eq!(Enum::Bar(NoEq), Enum::Bar(NoEq));

assert_eq!(Enum::Baz, Enum::Baz);

// NOTE: Different variants are still not equal despite being ignored!
//       Ignoring a variant only ignores all its fields during comparison.
assert_ne!(Enum::Foo(0, NoEq), Enum::Bar(NoEq));
assert_ne!(Enum::Foo(0, NoEq), Enum::Baz);
assert_ne!(Enum::Bar(NoEq), Enum::Baz);
```
This generates code equivalent to:
```rust
# struct NoEq;
#
# struct Foo { num: i32, ignored: f32 }
#
impl PartialEq for Foo {
    fn eq(&self, __other: &Self) -> bool {
        match (self, __other) {
            (Self { num: __self_0, .. }, Self { num: __other_0, .. }) => { __self_0 == __other_0 }
        }
    }
    fn ne(&self, __other: &Self) -> bool {
        match (self, __other) {
            (Self { num: __self_0, .. }, Self { num: __other_0, .. }) => { __self_0 != __other_0 }
        }
    }
}
impl Eq for Foo
where
    i32: Eq,
{}

# struct Bar(i32, NoEq);
#
impl PartialEq for Bar {
    fn eq(&self, __other: &Self) -> bool { true }
}
impl Eq for Bar {}

# enum Enum {
#     Foo(i32, NoEq),
#     Bar(NoEq),
#     Baz,
# }
#
impl PartialEq for Enum {
    fn eq(&self, __other: &Self) -> bool {
        std::mem::discriminant(self) == std::mem::discriminant(__other) &&
            match (self, __other) {
                (Self::Foo(__self_0, _, ), Self::Foo(__other_0, _, )) => { __self_0 == __other_0 }
                _ => true,
            }
    }
    fn ne(&self, __other: &Self) -> bool {
        std::mem::discriminant(self) != std::mem::discriminant(__other) ||
            match (self, __other) {
                (Self::Foo(__self_0, _, ), Self::Foo(__other_0, _, )) => { __self_0 != __other_0 }
                _ => false,
        }
    }
}
```
