Operator Overloading
Rust overloads operators via traits in std::ops (Add, Sub, Mul, Index, etc.), keeping syntax familiar without hidden magic.
Recipe
use std::ops::Add;
#[derive(Clone, Copy, Debug)]
struct Vec2 { x: f32, y: f32 }
impl Add for Vec2 {
type Output = Vec2;
fn add(self, rhs: Self) -> Self::Output {
Self { x: self.x + rhs.x, y: self.y + rhs.y }
}
}When to reach for this: Domain types where +, [], or * match mathematical or container semantics.
Working Example
use std::ops::{Add, Index};
struct Matrix<T> { data: Vec<T>, cols: usize }
impl<T: Copy + Add<Output = T>> Add for Matrix<T> {
type Output = Self;
fn add(self, rhs: Self) -> Self {
let data = self.data.iter().zip(&rhs.data)
.map(|(a, b)| *a + *b).collect();
Self { data, cols: self.cols }
}
}
impl<T> Index<usize> for Matrix<T> {
type Output = T;
fn index(&self, i: usize) -> &Self::Output { &self.data[i] }
}What this demonstrates:
Addwith associatedOutputtypeIndexfor[]syntax- Bounds on type param for element-wise add
Deep Dive
Common traits: Add, Sub, Mul, Div, Rem, Neg, Not, BitAnd, Shl, Index, IndexMut, Deref.
Gotchas
- Confusing semantics -
+for unrelated meaning hurts readability. Fix: Named methods for odd ops. - Forgetting
Outputtype - Required associated type. Fix:type Output = Selfcommon. Add<&Self>variants - May need second impl for references. Fix: impl for owned and ref separately if needed.- Panicking
Index- Should match slice rules or useget. Fix: Document panic contract. - Auto ops vs manual -
+=usesAddAssign. Fix: Implement both for ergonomics.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
Methods .add() | Unclear operator meaning | Natural math types |
| Builder pattern | Construction not addition | Vector math |
| Macros | DSL-specific syntax | Standard ops fit |
FAQs
+= requires?
`AddAssign` trait.Compare operators?
`PartialEq`, `PartialOrd` - not ops traits.Custom precedence?
Cannot change language precedence.Reference rhs?
`impl Add<&Vec2> for Vec2` etc.Commutativity?
Not enforced - document if important.Float PartialEq?
Separate from operator traits.IndexMut?
Enables `m[i] = v`.Deref coercion?
`Deref`/`DerefMut` enable smart pointer ops.no_std ops?
`core::ops` same traits.clippy?
Lints on impl with odd types.Related
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.