Equality Traits
Part of the Object Oriented Programming section of Coddy's Rust journey — lesson 38 of 61.
Comparing two instances of a custom struct with == doesn't work by default in Rust. The compiler doesn't know how to determine if two structs are equal—you need to tell it by implementing the PartialEq trait.
Like Debug and Copy, you can derive PartialEq automatically:
#[derive(PartialEq)]
struct Coordinate {
x: i32,
y: i32,
}
let a = Coordinate { x: 5, y: 10 };
let b = Coordinate { x: 5, y: 10 };
let c = Coordinate { x: 3, y: 7 };
println!("{}", a == b); // true
println!("{}", a == c); // false
When derived, PartialEq compares each field of the struct. Two instances are equal only if all their corresponding fields match.
You'll also encounter Eq, which is a marker trait that indicates total equality—meaning every value equals itself. Most types satisfy this, but floating-point numbers don't (because NaN != NaN). For structs with integer fields, you can safely derive both:
#[derive(PartialEq, Eq)]
struct Coordinate {
x: i32,
y: i32,
}
Eq has no methods of its own—it simply signals that the type has reflexive equality. Some standard library features require Eq in addition to PartialEq, so it's common to derive both together for types that qualify.
Challenge
EasyLet's build a color matching system that demonstrates how the PartialEq and Eq traits enable comparison between struct instances!
You'll create two files to organize your color comparison logic:
color.rs: Define a publicColorstruct with three public fields:red,green, andblue(allu8). Derive bothPartialEqandEqso that two colors can be compared using==. When derived, Rust will consider two colors equal only if all three RGB components match exactly.main.rs: Bring in your color module and create twoColorinstances using the inputs provided. Compare them using==and print whether they match or not.
Your output should indicate whether the two colors are the same:
Color 1: rgb({r1}, {g1}, {b1})
Color 2: rgb({r2}, {g2}, {b2})
Colors match: {true/false}For example, with inputs 255, 128, 0, 255, 128, 0:
Color 1: rgb(255, 128, 0)
Color 2: rgb(255, 128, 0)
Colors match: trueAnd with inputs 100, 100, 100, 200, 200, 200:
Color 1: rgb(100, 100, 100)
Color 2: rgb(200, 200, 200)
Colors match: falseYou will receive six inputs: the RGB values for the first color (three values), followed by the RGB values for the second color (three values). Parse each as u8.
Cheat sheet
To compare custom structs using ==, implement the PartialEq trait by deriving it:
#[derive(PartialEq)]
struct Coordinate {
x: i32,
y: i32,
}
let a = Coordinate { x: 5, y: 10 };
let b = Coordinate { x: 5, y: 10 };
println!("{}", a == b); // true
When derived, PartialEq compares all fields—two instances are equal only if all corresponding fields match.
The Eq trait is a marker trait indicating total equality (every value equals itself). Most types satisfy this, except floating-point numbers (because NaN != NaN). For structs with integer fields, derive both traits together:
#[derive(PartialEq, Eq)]
struct Coordinate {
x: i32,
y: i32,
}
Eq has no methods—it signals reflexive equality. Some standard library features require Eq in addition to PartialEq.
Try it yourself
mod color;
use color::Color;
fn main() {
// Read the six RGB values
let mut input = String::new();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let r1: u8 = input.trim().parse().expect("Invalid input");
input.clear();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let g1: u8 = input.trim().parse().expect("Invalid input");
input.clear();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let b1: u8 = input.trim().parse().expect("Invalid input");
input.clear();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let r2: u8 = input.trim().parse().expect("Invalid input");
input.clear();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let g2: u8 = input.trim().parse().expect("Invalid input");
input.clear();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let b2: u8 = input.trim().parse().expect("Invalid input");
// TODO: Create two Color instances using the parsed values
// TODO: Print Color 1 in the format: Color 1: rgb(r, g, b)
// TODO: Print Color 2 in the format: Color 2: rgb(r, g, b)
// TODO: Compare the two colors using == and print: Colors match: {true/false}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Methods and Behavior
Intro Implementation BlocksThe Self ParameterMutable MethodsAssociated FunctionsMultiple Implementation BlocksMethod ChainingRecap - Rectangle Actions4Project: Virtual Pet
Defining the PetFeeding the Pet7Standard Traits
The Debug TraitThe Display TraitClone and CopyEquality TraitsRecap - Printable Point10Project: Document System
The Draw TraitText Component2Encapsulation and Modules
Modules BasicsThe Public KeywordPrivate FieldsGettersSettersRecap - Secure Locker5Generics
Generic StructsGeneric MethodsMultiple Generic TypesGeneric FunctionsRecap - Coordinate Point8Traits as Bounds
Trait Bounds SyntaxMultiple BoundsThe Where ClauseReturning Types with TraitsRecap - Generic Printer11Design Patterns in Rust
Newtype PatternCompositionThe Drop TraitFrom and IntoRecap - Smart Pointer Mock