W3cubDocs

/Rust

Module std::ops

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 or compiler plugins 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 short-circuit, i.e., they only evaluate their second operand if it contributes to the result. Since this behavior is not enforceable by traits, && and || are not supported as overloadable operators.

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 Points.

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

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

impl Add for Point {
    type Output = Point;

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

impl Sub for Point {
    type Output = Point;

    fn sub(self, other: Point) -> Point {
        Point {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});

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);

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);

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

Structs

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

Bound

An endpoint of a range of keys.

GeneratorState Experimental

The result of a generator resumption.

Traits

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 -=.

CoerceUnsized Experimental

Trait that indicates that this is a pointer or a wrapper for one, where unsizing can be performed on the pointee.

DispatchFromDyn Experimental

This is used for object safety, to check that a method's receiver type can be dispatched on.

Generator Experimental

The trait implemented by builtin generator types.

Try Experimental

A trait for customizing the behavior of the ? operator.

© 2010 The Rust Project Developers
Licensed under the Apache License, Version 2.0 or the MIT license, at your option.
https://doc.rust-lang.org/std/ops/index.html