Ruta graveolens  ·  notes from a language experiment  ·  cultivated since 2025

Comparison Operators

Comparison operators compare two values and produce a bool result.

Equality Operators

Equality operators work on integers, booleans, strings, the unit type, and the aggregate types: structs, arrays, and enums.

OperatorNameDescription
==EqualTrue if operands are equal
!=Not equalTrue if operands are not equal

Two strings are equal if they have the same length and identical byte content.

Two unit values are always equal.

Equality on the aggregate types is structural: two aggregate values are equal if and only if they have the same type and their components — determined recursively by this rule down to scalar leaves — are equal. Specifically, two struct values are equal if and only if they have the same struct type and all corresponding fields are equal.

Two array values are equal if and only if they have the same element type and length and their elements are equal index-by-index. (Two array types of different lengths are distinct types and cannot be compared; see rule 4.3:10.)

Two enum values are equal if and only if they have the same enum type, are the same variant, and — for a variant carrying a payload — their payload fields are equal field-by-field. Two values of different variants are never equal.

A raw-pointer leaf (a *const T or *mut T field or element reached while comparing an aggregate) compares by address: two raw pointers are equal if and only if they hold the same address. The pointees are not examined.

Equality borrows its operands: evaluating a == b or a != b reads both operands without consuming them. An affine or linear value may therefore be compared without discharging its move obligation, and both operands remain usable afterward.

Equality is structural by default. Trait-based refinement of equality — opting a type out of comparison, or giving it a user-defined equality (a PartialEq-style mechanism) — is deferred until traits exist (RUE-246). A related future consideration, once floating-point types exist, is the partial-equality of NaN (where NaN != NaN), which motivates the eventual PartialEq/Eq split; today no leaf type has such a value, so structural equality is a total equivalence.

fn main() -> i32 {
    let a = 1 == 1;    // true
    let b = 1 != 2;    // true
    let c = true == false;  // false (bool equality)
    let d = "hello" == "hello";  // true (string equality)
    let e = () == ();  // true (unit equality)
    if a && b && !c && d && e { 1 } else { 0 }
}
struct Point { x: i32, y: i32 }

fn main() -> i32 {
    let p1 = Point { x: 1, y: 2 };
    let p2 = Point { x: 1, y: 2 };
    let p3 = Point { x: 1, y: 3 };
    if p1 == p2 && p1 != p3 { 1 } else { 0 }
}

Arrays compare element-by-element; nested aggregates recurse. Comparing does not consume the operands, so a and b remain usable afterward.

fn main() -> i32 {
    let a = [1, 2, 3];
    let b = [1, 2, 3];
    let equal = a == b;      // borrows a and b
    if equal && a[0] == b[0] { 1 } else { 0 }
}

Ordering Operators

Ordering operators work only on integers.

OperatorNameDescription
<Less thanTrue if left < right
>Greater thanTrue if left > right
<=Less or equalTrue if left <= right
>=Greater or equalTrue if left >= right

Ordering operators on boolean, string, unit, or aggregate (struct, array, or enum) values are a compile-time error. Implementations MUST reject such programs.

fn main() -> i32 {
    let a = 1 < 2;     // true
    let b = 5 >= 5;    // true
    if a && b { 1 } else { 0 }
}

Precedence

Comparison operators have lower precedence than arithmetic, shift, and bitwise operators, and higher precedence than the logical operators && and ||. (The complete precedence ladder, which matches Rust's, is given in rule 4.3a:13.)

fn main() -> i32 {
    if 1 + 2 == 3 { 1 } else { 0 }  // 1 (comparison after arithmetic)
}

Type Checking

Both operands of a comparison MUST have the same type.

When one operand has a known type, the other is inferred to have the same type.

Associativity

Comparison operators cannot be chained. Expressions like a < b < c or a == b == c are compile-time errors.

To compare multiple values, use logical operators:

fn main() -> i32 {
    let a = 1;
    let b = 2;
    let c = 3;
    if a < b && b < c { 1 } else { 0 }  // correct way to chain comparisons
}