Skip to main content
The < (less-than) operator is a binary comparison operator that evaluates whether the left-hand operand is strictly less than the right-hand operand, returning a bool. At the compiler level, the < operator is syntactic sugar for the lt method provided by the std::cmp::PartialOrd trait.
let a = 1;
let b = 2;

// Standard syntax
let result = a < b;

// Desugared equivalent
let result = std::cmp::PartialOrd::lt(&a, &b);

Trait Implementation

To use the < operator with a specific type, that type must implement PartialOrd. Because PartialOrd has a supertrait bound on PartialEq, any type supporting < must also support the == operator.
use std::cmp::Ordering;

pub trait PartialOrd<Rhs = Self>: PartialEq<Rhs>
where
    Rhs: ?Sized,
{
    fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;

    // The `<` operator directly invokes this provided method
    #[inline]
    fn lt(&self, other: &Rhs) -> bool {
        matches!(self.partial_cmp(other), Some(Ordering::Less))
    }
}

Evaluation Mechanics

  1. Delegation to partial_cmp: The default implementation of lt calls partial_cmp, which returns an Option<std::cmp::Ordering>.
  2. Strict Evaluation: The < operator evaluates to true only if partial_cmp returns Some(Ordering::Less).
  3. Incomparable Values: If partial_cmp returns None (which occurs with incomparable values, such as floating-point NaN), the < operator evaluates to false.
  4. Borrowing: The operator implicitly takes immutable references to both operands (&self and &Rhs). It does not consume or move the values being compared.

Type Constraints

Rust enforces strict type safety during comparison. The < operator does not perform implicit type coercion. Both operands must resolve to the same type, or the left-hand type must explicitly implement PartialOrd<Rhs> where Rhs is the type of the right-hand operand.
// Valid: Same types
let valid = 5_i32 < 10_i32;

// Invalid: Compilation error due to mismatched types (i32 vs f64)
// let invalid = 5_i32 < 10.0_f64; 

Derivation

For custom structs and enums, the compiler can automatically generate the < operator logic using #[derive(PartialOrd)]. Because of the supertrait bound, #[derive(PartialEq)] is also strictly required; attempting to derive PartialOrd without deriving PartialEq results in a compilation error. When derived:
  • Structs: Evaluates fields lexicographically, top-to-bottom.
  • Enums: Evaluates based on the discriminant (the declared order of variants), followed by lexicographical comparison of any data contained within the variants.
Tired of Poor Rust Skills? Fix That With Deep Grasping!Learn More