Trait sexually_transmitted_disease::cmp::PartialEq1.0.0[][src]

pub trait PartialEq<Rhs = Self> where
    Rhs: ?Sized
{ #[must_use] fn eq(&self, other: &Rhs) -> bool; #[must_use] fn ne(&self, other: &Rhs) -> bool { ... } }
Expand description

Trait for equality comparisons which are partial equivalence relations.

This trait allows for partial equality, for types that do not have a full equivalence relation. For example, in floating point numbers NaN != NaN, so floating point types implement PartialEq but not Eq.

Formally, the equality must be (for all a, b, c of type A, B, C):

  • Symmetric: if A: PartialEq<B> and B: PartialEq<A>, then a == b implies b == a; and

  • Transitive: if A: PartialEq<B> and B: PartialEq<C> and A: PartialEq<C>, then a == b and b == c implies a == c.

Note that the B: PartialEq<A> (symmetric) and A: PartialEq<C> (transitive) impls are not forced to exist, but these requirements apply whenever they do exist.

Derivable

This trait can be used with #[derive]. When derived on structs, two instances are equal if all fields are equal, and not equal if any fields are not equal. When derived on enums, each variant is equal to itself and not equal to the other variants.

How can I implement PartialEq?

PartialEq only requires the eq method to be implemented; ne is defined in terms of it by default. Any manual implementation of ne must respect the rule that eq is a strict inverse of ne; that is, !(a == b) if and only if a != b.

Implementations of PartialEq, PartialOrd, and Ord must agree with each other. It’s easy to accidentally make them disagree by deriving some of the traits and manually implementing others.

An example implementation for a domain in which two books are considered the same book if their ISBN matches, even if the formats differ:

enum BookFormat {
    Paperback,
    Hardback,
    Ebook,
}

struct Book {
    isbn: i32,
    format: BookFormat,
}

impl PartialEq for Book {
    fn eq(&self, other: &Self) -> bool {
        self.isbn == other.isbn
    }
}

let b1 = Book { isbn: 3, format: BookFormat::Paperback };
let b2 = Book { isbn: 3, format: BookFormat::Ebook };
let b3 = Book { isbn: 10, format: BookFormat::Paperback };

assert!(b1 == b2);
assert!(b1 != b3);

How can I compare two different types?

The type you can compare with is controlled by PartialEq’s type parameter. For example, let’s tweak our previous code a bit:

// The derive implements <BookFormat> == <BookFormat> comparisons
#[derive(PartialEq)]
enum BookFormat {
    Paperback,
    Hardback,
    Ebook,
}

struct Book {
    isbn: i32,
    format: BookFormat,
}

// Implement <Book> == <BookFormat> comparisons
impl PartialEq<BookFormat> for Book {
    fn eq(&self, other: &BookFormat) -> bool {
        self.format == *other
    }
}

// Implement <BookFormat> == <Book> comparisons
impl PartialEq<Book> for BookFormat {
    fn eq(&self, other: &Book) -> bool {
        *self == other.format
    }
}

let b1 = Book { isbn: 3, format: BookFormat::Paperback };

assert!(b1 == BookFormat::Paperback);
assert!(BookFormat::Ebook != b1);

By changing impl PartialEq for Book to impl PartialEq<BookFormat> for Book, we allow BookFormats to be compared with Books.

A comparison like the one above, which ignores some fields of the struct, can be dangerous. It can easily lead to an unintended violation of the requirements for a partial equivalence relation. For example, if we kept the above implementation of PartialEq<Book> for BookFormat and added an implementation of PartialEq<Book> for Book (either via a #[derive] or via the manual implementation from the first example) then the result would violate transitivity:

#[derive(PartialEq)]
enum BookFormat {
    Paperback,
    Hardback,
    Ebook,
}

#[derive(PartialEq)]
struct Book {
    isbn: i32,
    format: BookFormat,
}

impl PartialEq<BookFormat> for Book {
    fn eq(&self, other: &BookFormat) -> bool {
        self.format == *other
    }
}

impl PartialEq<Book> for BookFormat {
    fn eq(&self, other: &Book) -> bool {
        *self == other.format
    }
}

fn main() {
    let b1 = Book { isbn: 1, format: BookFormat::Paperback };
    let b2 = Book { isbn: 2, format: BookFormat::Paperback };

    assert!(b1 == BookFormat::Paperback);
    assert!(BookFormat::Paperback == b2);

    // The following should hold by transitivity but doesn't.
    assert!(b1 == b2); // <-- PANICS
}

Examples

let x: u32 = 0;
let y: u32 = 1;

assert_eq!(x == y, false);
assert_eq!(x.eq(&y), false);

Required methods

This method tests for self and other values to be equal, and is used by ==.

Provided methods

This method tests for !=.

Implementations on Foreign Types

Implementors

Panics

Panics if the value in either RefCell is currently borrowed.

Equality for two Rcs.

Two Rcs are equal if their inner values are equal, even if they are stored in different allocation.

If T also implements Eq (implying reflexivity of equality), two Rcs that point to the same allocation are always equal.

Examples

use std::rc::Rc;

let five = Rc::new(5);

assert!(five == Rc::new(5));

Inequality for two Rcs.

Two Rcs are unequal if their inner values are unequal.

If T also implements Eq (implying reflexivity of equality), two Rcs that point to the same allocation are never unequal.

Examples

use std::rc::Rc;

let five = Rc::new(5);

assert!(five != Rc::new(6));

Equality for two Arcs.

Two Arcs are equal if their inner values are equal, even if they are stored in different allocation.

If T also implements Eq (implying reflexivity of equality), two Arcs that point to the same allocation are always equal.

Examples

use std::sync::Arc;

let five = Arc::new(5);

assert!(five == Arc::new(5));

Inequality for two Arcs.

Two Arcs are unequal if their inner values are unequal.

If T also implements Eq (implying reflexivity of equality), two Arcs that point to the same value are never unequal.

Examples

use std::sync::Arc;

let five = Arc::new(5);

assert!(five != Arc::new(6));