Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The || operator in Rust is the logical OR operator. It performs a boolean disjunction between two expressions of type bool, returning true if at least one of the operands evaluates to true, and false otherwise.
fn main() {
    let expr1 = true;
    let expr2 = false;
    let _result = expr1 || expr2; // Evaluates to true
}

Evaluation Semantics

The || operator strictly employs short-circuit (lazy) evaluation. The evaluation order is strictly left-to-right:
  1. The left-hand side (LHS) expression is evaluated first.
  2. If the LHS evaluates to true, the entire expression immediately resolves to true. The right-hand side (RHS) expression is never evaluated.
  3. The RHS is evaluated if and only if the LHS evaluates to false.
This mechanical behavior guarantees that side effects or computationally expensive operations on the RHS are bypassed if the LHS satisfies the disjunction.
fn returns_true() -> bool { true }
fn panics() -> bool { panic!("This will not execute") }

fn main() {
    // The panic is never triggered because the LHS is true.
    let _evaluation = returns_true() || panics(); 
}

Logical OR vs. Bitwise OR

While || provides short-circuiting logical disjunction, the single pipe | acts as the bitwise OR operator. When applied to bool values, | performs an eager evaluation, meaning both the LHS and RHS are always evaluated regardless of the LHS’s result.
use std::panic;

fn returns_true() -> bool { true }
fn panics() -> bool { panic!("This executes and panics") }

fn main() {
    // Both functions are executed; no short-circuiting occurs.
    // Because `|` evaluates eagerly, `panics()` is guaranteed to be called.
    let result = panic::catch_unwind(|| {
        let _eager_evaluation = returns_true() | panics(); 
    });
    
    assert!(result.is_err());
}

Type Constraints

Rust’s strong, static typing requires that both operands provided to the || operator strictly resolve to the bool primitive type. Rust does not support implicit type coercion to bool, meaning concepts like “truthiness” or “falsiness” for integers, pointers, or options do not apply. Attempting to use || on non-boolean types results in a compile-time type mismatch error.

Operator Overloading

Unlike most arithmetic and bitwise operators in Rust (such as + via std::ops::Add or | via std::ops::BitOr), the logical || operator cannot be overloaded via traits. This is a deliberate language design choice made to strictly preserve its short-circuiting guarantees. Custom trait implementations would inherently require the eager evaluation of both operands before invoking the trait method, which would violate the expected lazy evaluation semantics of a logical OR.

Precedence and Associativity

  • Associativity: Left-to-right. An expression like a || b || c is parsed as (a || b) || c.
  • Precedence: The || operator has lower precedence than the logical AND operator (&&), comparison operators (==, !=, <), and arithmetic operators. It has higher precedence than assignment operators (=, +=) and the range operators (.., ..=).
fn main() {
    // && is evaluated before ||
    let result = true || false && false; // Evaluates to: true || (false && false) -> true
    assert_eq!(result, true);
}

Syntactic Overloading (Closures)

At the lexical level, the || token is also used in Rust’s grammar to define an anonymous function (closure) that accepts zero parameters. While the token is identical, the compiler differentiates between the logical operator and the closure delimiter based on syntactic context.
fn main() {
    // Logical OR operator
    let _boolean_logic = true || false;

    // Zero-parameter closure definition
    let _closure_definition = || println!("Zero arguments");
}
Master Rust with Deep Grasping Methodology!Learn More