Operator Overloading

Operator overloading is implementing a trait from the std::ops module — such as Add for + or Mul for * — so that an operator works on your own custom type instead of only on built-in numbers.

Learn Operator Overloading in our free Rust course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.

Part of the free Rust course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

In this lesson you'll implement Add , Sub , and Mul for a 2-D vector, understand the associated Output type, add += with AddAssign and indexing with Index , and learn why operators are traits in the first place.

What You'll Learn in This Lesson

1️⃣ The Add Trait and the Output Type

When you write a + b , Rust rewrites it to a.add(b) using the Add trait. Add declares an associated type Output — the type the operation produces — and one method, add . Implement them for your struct and + simply works.

Here type Output = Vector2 because adding two vectors gives a vector. For symmetric same-type math you'll often just write type Output = Self .

2️⃣ Many Operators, Different Right-Hand Types

A single type can implement several operator traits. And the right-hand side doesn't have to be the same type as Self : lets you multiply a Vector2 by a plain f64 scalar. The generic parameter on the trait is the type of the operand on the right.

3️⃣ AddAssign (+=) and Index ([])

Compound assignment operators have their own traits: += is AddAssign , which mutates &mut self in place and has no Output type. The indexing syntax container[i] for reading comes from the Index trait, which returns a reference to the element.

Notice add_assign takes &mut self and returns nothing — it edits the existing value. Index still has an Output type (the element type) and returns it by reference .

Your turn. Fill in the blank marked ___ , then run it.

Give a Complex type real + and * operators. Run it with cargo run and check the output.

📋 Quick Reference — std::ops Traits

Practice quiz

In Rust, operators are implemented as:

  • Built-in magic only
  • Macros
  • Traits in the std::ops module
  • Keywords

Answer: Traits in the std::ops module. Each operator maps to a trait in std::ops, so overloading means implementing it.

Which trait powers the + operator?

  • Add
  • Plus
  • Sum
  • Concat

Answer: Add. The + operator corresponds to the Add trait and its add method.

When you write a + b, what does the compiler call?

  • a.plus(b)
  • add(a, b)
  • b.add(a)
  • a.add(b)

Answer: a.add(b). a + b is rewritten as a.add(b) using the Add trait.

What is the Output associated type for?

  • The input type
  • The type the operation produces
  • The error type
  • The trait name

Answer: The type the operation produces. Output names the result type of the operation, set with type Output = ...;.

For same-type math, Output is usually:

  • type Output = Self;
  • type Output = ();
  • type Output = bool;
  • omitted

Answer: type Output = Self;. Symmetric same-type math commonly uses type Output = Self.

Which trait makes Vector2 * f64 (scalar) work?

  • Mul
  • Scale
  • Mul<f64>
  • MulAssign

Answer: Mul<f64>. The generic parameter sets the right-hand type, so Mul<f64> multiplies by a scalar.

Which trait powers the += operator?

  • Add
  • AddAssign
  • PlusEq
  • Increment

Answer: AddAssign. AddAssign powers +=, mutating self in place.

Does AddAssign have an Output associated type?

  • Yes
  • Only for floats
  • Same as Add
  • No, it mutates in place and returns nothing

Answer: No, it mutates in place and returns nothing. add_assign takes &mut self and returns nothing, so AddAssign has no Output.

What does the Index trait power, and what does it return?

  • += returning a value

Index powers container[i] reads and returns a reference to the element.

Is v * 2.0 working enough to make 2.0 * v work too?

  • Yes, operators are commutative
  • Only with derive
  • No, you must also impl Mul<Vector2> for f64
  • Only for integers

Answer: No, you must also impl Mul<Vector2> for f64. Operators aren't automatically commutative; the reverse needs its own impl.