std::ops - Rust (original) (raw)
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 Addtrait, 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 andoperator 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 andAdd<&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});
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
A (half-open) range bounded inclusively below and exclusively above (start..end
).
A range only bounded inclusively below (start..
).
An unbounded range (..
).
A range bounded inclusively below and above (start..=end
).
A range only bounded exclusively above (..end
).
A range only bounded inclusively above (..=end
).
YeetExperimental
Implement FromResidual<Yeet<T>>
on your type to enabledo yeet expr
syntax in functions returning your type.
An endpoint of a range of keys.
Used to tell an operation whether it should exit early or go on as usual.
CoroutineStateExperimental
The result of a coroutine resumption.
OneSidedRangeBoundExperimental
An internal helper for split_off
functions indicating which end a OneSidedRange
is bounded on.
The addition operator +
.
The addition assignment operator +=
.
An async-aware version of the Fn trait.
An async-aware version of the FnMut trait.
An async-aware version of the FnOnce trait.
The bitwise AND operator &
.
The bitwise AND assignment operator &=
.
The bitwise OR operator |
.
The bitwise OR assignment operator |=
.
The bitwise XOR operator ^
.
The bitwise XOR assignment operator ^=
.
Used for immutable dereferencing operations, like *v
.
Used for mutable dereferencing operations, like in *v = 1;
.
The division operator /
.
The division assignment operator /=
.
Custom code within the destructor.
The version of the call operator that takes an immutable receiver.
The version of the call operator that takes a mutable receiver.
The version of the call operator that takes a by-value receiver.
Used for indexing operations (container[index]
) in immutable contexts.
Used for indexing operations (container[index]
) in mutable contexts.
The multiplication operator *
.
The multiplication assignment operator *=
.
The unary negation operator -
.
The unary logical negation operator !
.
RangeBounds
is implemented by Rust’s built-in range types, produced by range syntax like ..
, a..
, ..b
, ..=c
, d..e
, or f..=g
.
The remainder operator %
.
The remainder assignment operator %=
.
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.
The left shift assignment operator <<=
.
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.
The right shift assignment operator >>=
.
The subtraction operator -
.
The subtraction assignment operator -=
.
CoerceUnsizedExperimental
Trait that indicates that this is a pointer or a wrapper for one, where unsizing can be performed on the pointee.
CoroutineExperimental
The trait implemented by builtin coroutine types.
DerefPureExperimental
Perma-unstable marker trait. Indicates that the type has a well-behaved Deref(and, if applicable, DerefMut) implementation. This is relied on for soundness of deref patterns.
DispatchFromDynExperimental
DispatchFromDyn
is used in the implementation of dyn-compatibility checks (specifically allowing arbitrary self types), to guarantee that a method’s receiver type can be dispatched on.
FromResidualExperimental
Used to specify which residuals can be converted into which crate::ops::Try types.
IntoBoundsExperimental
Used to convert a range into start and end bounds, consuming the range by value.
OneSidedRangeExperimental
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.
ReceiverExperimental
Indicates that a struct can be used as a method receiver. That is, a type can use this type as a type of self
, like this:
ResidualExperimental
Allows retrieving the canonical type implementing Try that has this type as its residual and allows it to hold an O
as its output.
TryExperimental
The ?
operator and try {}
blocks.