# Module std::ops

1.0.0 · source ·
Expand description

Overloadable operators.

Implementing these traits allows you to overload certain operators.

Some of these traits are imported by the prelude, so they are available in every Rust program. Only operators backed by traits can be overloaded. For example, the addition operator (`+`) can be overloaded through the `Add` trait, but since the assignment operator (`=`) has no backing trait, there is no way of overloading its semantics. Additionally, this module does not provide any mechanism to create new operators. If traitless overloading or custom operators are required, you should look toward macros to extend Rust’s syntax.

Implementations of operator traits should be unsurprising in their respective contexts, keeping in mind their usual meanings and operator precedence. For example, when implementing `Mul`, the operation should have some resemblance to multiplication (and share expected properties like associativity).

Note that the `&&` and `||` operators are currently not supported for overloading. Due to their short circuiting nature, they require a different design from traits for other operators like `BitAnd`. Designs for them are under discussion.

Many of the operators take their operands by value. In non-generic contexts involving built-in types, this is usually not a problem. However, using these operators in generic code, requires some attention if values have to be reused as opposed to letting the operators consume them. One option is to occasionally use `clone`. Another option is to rely on the types involved providing additional operator implementations for references. For example, for a user-defined type `T` which is supposed to support addition, it is probably a good idea to have both `T` and `&T` implement the traits `Add<T>` and `Add<&T>` so that generic code can be written without unnecessary cloning.

## Examples

This example creates a `Point` struct that implements `Add` and `Sub`, and then demonstrates adding and subtracting two `Point`s.

    use std::ops::{Add, Sub};

    #[derive(Debug, Copy, Clone, PartialEq)]
    struct Point {
        x: i32,
        y: i32,
    }

    impl Add for Point {
        type Output = Self;

        fn add(self, other: Self) -> Self {
            Self {x: self.x + other.x, y: self.y + other.y}
        }
    }

    impl Sub for Point {
        type Output = Self;

        fn sub(self, other: Self) -> Self {
            Self {x: self.x - other.x, y: self.y - other.y}
        }
    }

    assert_eq!(Point {x: 3, y: 3}, Point {x: 1, y: 0} + Point {x: 2, y: 3});
    assert_eq!(Point {x: -1, y: -3}, Point {x: 1, y: 0} - Point {x: 2, y: 3});

Run

See the documentation for each trait for an example implementation.

The `Fn`, `FnMut`, and `FnOnce` traits are implemented by types that can be invoked like functions. Note that `Fn` takes `&self`, `FnMut` takes `&mut self` and `FnOnce` takes `self`. These correspond to the three kinds of methods that can be invoked on an instance: call-by-reference, call-by-mutable-reference, and call-by-value. The most common use of these traits is to act as bounds to higher-level functions that take functions or closures as arguments.

Taking a `Fn` as a parameter:

    fn call_with_one<F>(func: F) -> usize
        where F: Fn(usize) -> usize
    {
        func(1)
    }

    let double = |x| x * 2;
    assert_eq!(call_with_one(double), 2);

Run

Taking a `FnMut` as a parameter:

    fn do_twice<F>(mut func: F)
        where F: FnMut()
    {
        func();
        func();
    }

    let mut x: usize = 1;
    {
        let add_two_to_x = || x += 2;
        do_twice(add_two_to_x);
    }

    assert_eq!(x, 5);

Run

Taking a `FnOnce` as a parameter:

    fn consume_with_relish<F>(func: F)
        where F: FnOnce() -> String
    {
        // `func` consumes its captured variables, so it cannot be run more
        // than once
        println!("Consumed: {}", func());

        println!("Delicious!");

        // Attempting to invoke `func()` again will throw a `use of moved
        // value` error for `func`
    }

    let x = String::from("x");
    let consume_and_return_x = move || x;
    consume_with_relish(consume_and_return_x);

    // `consume_and_return_x` can no longer be invoked at this point

Run

## Structs

- Yeet Experimental
  Implement `FromResidual<Yeet<T>>` on your type to enable `do yeet expr` syntax in functions returning your type.
- Range
  A (half-open) range bounded inclusively below and exclusively above (`start..end`).
- RangeFrom
  A range only bounded inclusively below (`start..`).
- RangeFull
  An unbounded range (`..`).
- RangeInclusive
  A range bounded inclusively below and above (`start..=end`).
- RangeTo
  A range only bounded exclusively above (`..end`).
- RangeToInclusive
  A range only bounded inclusively above (`..=end`).

## Enums

- CoroutineState Experimental
  The result of a coroutine resumption.
- Bound
  An endpoint of a range of keys.
- ControlFlow
  Used to tell an operation whether it should exit early or go on as usual.

## Traits

- CoerceUnsized Experimental
  Trait that indicates that this is a pointer or a wrapper for one, where unsizing can be performed on the pointee.
- Coroutine Experimental
  The trait implemented by builtin coroutine types.
- DispatchFromDyn Experimental
  `DispatchFromDyn` is used in the implementation of object safety checks (specifically allowing arbitrary self types), to guarantee that a method’s receiver type can be dispatched on.
- FromResidual Experimental
  Used to specify which residuals can be converted into which `crate::ops::Try` types.
- OneSidedRange Experimental
  `OneSidedRange` is implemented for built-in range types that are unbounded on one side. For example, `a..`, `..b` and `..=c` implement `OneSidedRange`, but `..`, `d..e`, and `f..=g` do not.
- Residual Experimental
  Allows retrieving the canonical type implementing `Try` that has this type as its residual and allows it to hold an `O` as its output.
- Try Experimental
  The `?` operator and `try {}` blocks.
- Add
  The addition operator `+`.
- AddAssign
  The addition assignment operator `+=`.
- BitAnd
  The bitwise AND operator `&`.
- BitAndAssign
  The bitwise AND assignment operator `&=`.
- BitOr
  The bitwise OR operator `|`.
- BitOrAssign
  The bitwise OR assignment operator `|=`.
- BitXor
  The bitwise XOR operator `^`.
- BitXorAssign
  The bitwise XOR assignment operator `^=`.
- Deref
  Used for immutable dereferencing operations, like `*v`.
- DerefMut
  Used for mutable dereferencing operations, like in `*v = 1;`.
- Div
  The division operator `/`.
- DivAssign
  The division assignment operator `/=`.
- Drop
  Custom code within the destructor.
- Fn
  The version of the call operator that takes an immutable receiver.
- FnMut
  The version of the call operator that takes a mutable receiver.
- FnOnce
  The version of the call operator that takes a by-value receiver.
- Index
  Used for indexing operations (`container[index]`) in immutable contexts.
- IndexMut
  Used for indexing operations (`container[index]`) in mutable contexts.
- Mul
  The multiplication operator `*`.
- MulAssign
  The multiplication assignment operator `*=`.
- Neg
  The unary negation operator `-`.
- Not
  The unary logical negation operator `!`.
- RangeBounds
  `RangeBounds` is implemented by Rust’s built-in range types, produced by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`.
- Rem
  The remainder operator `%`.
- RemAssign
  The remainder assignment operator `%=`.
- Shl
  The left shift operator `<<`. Note that because this trait is implemented for all integer types with multiple right-hand-side types, Rust’s type checker has special handling for `_ << _`, setting the result type for integer operations to the type of the left-hand-side operand. This means that though `a << b` and `a.shl(b)` are one and the same from an evaluation standpoint, they are different when it comes to type inference.
- ShlAssign
  The left shift assignment operator `<<=`.
- Shr
  The right shift operator `>>`. Note that because this trait is implemented for all integer types with multiple right-hand-side types, Rust’s type checker has special handling for `_ >> _`, setting the result type for integer operations to the type of the left-hand-side operand. This means that though `a >> b` and `a.shr(b)` are one and the same from an evaluation standpoint, they are different when it comes to type inference.
- ShrAssign
  The right shift assignment operator `>>=`.
- Sub
  The subtraction operator `-`.
- SubAssign
  The subtraction assignment operator `-=`.