Operators are defined for built in types by the Rust language. Many of the following operators can also be overloaded using traits in std::ops
or std::cmp
.
Integer operators will panic when they overflow when compiled in debug mode. The -C debug-assertions
and -C overflow-checks
compiler flags can be used to control this more directly. The following things are considered to be overflow:
+
, *
or -
create a value greater than the maximum value, or less than the minimum value that can be stored. This includes unary -
on the smallest value of any signed integer type./
or %
, where the left-hand argument is the smallest integer of a signed integer type and the right-hand argument is -1
.<<
or >>
where the right-hand argument is greater than or equal to the number of bits in the type of the left-hand argument, or is negative.An expression enclosed in parentheses evaluates to the result of the enclosed expression. Parentheses can be used to explicitly specify evaluation order within an expression.
An example of a parenthesized expression:
# #![allow(unused_variables)] #fn main() { let x: i32 = 2 + 3 * 4; let y: i32 = (2 + 3) * 4; assert_eq!(x, 14); assert_eq!(y, 20); #}
The &
(shared borrow) and &mut
(mutable borrow) operators are unary prefix operators. When applied to an lvalue produce a reference (pointer) to the location that the value refers to. The lvalue is also placed into a borrowed state for the duration of the reference. For a shared borrow (&
), this implies that the lvalue may not be mutated, but it may be read or shared again. For a mutable borrow (&mut
), the lvalue may not be accessed in any way until the borrow expires. &mut
evaluates its operand in a mutable lvalue context. If the &
or &mut
operators are applied to an rvalue, a temporary value is created; the lifetime of this temporary value is defined by syntactic rules. These operators cannot be overloaded.
# #![allow(unused_variables)] #fn main() { { // a temporary with value 7 is created that lasts for this scope. let shared_reference = &7; } let mut array = [-2, 3, 9]; { // Mutably borrows `array` for this scope. // `array` may only be used through `mutable_reference`. let mutable_reference = &mut array; } #}
The *
(dereference) operator is also a unary prefix operator. When applied to a pointer it denotes the pointed-to location. If the expression is of type &mut T
and *mut T
, and is either a local variable, a (nested) field of a local variance or is a mutable lvalue, then the resulting lvalue can be assigned to. Dereferencing a raw pointer requires unsafe
.
On non-pointer types *x
is equivalent to *std::ops::Deref::deref(&x)
in an immutable lvalue context and *std::ops::Deref::deref_mut(&mut x)
in a mutable lvalue context.
# #![allow(unused_variables)] #fn main() { let x = &7; assert_eq!(*x, 7); let y = &mut 9; *y = 11; assert_eq!(*y, 11); #}
?
operator.The ?
("question mark") operator can be applied to values of the Result<T, E>
type to propagate errors. If applied to Err(e)
it will return Err(From::from(e))
from the enclosing function or closure. If applied to Ok(x)
it will unwrap the value to return x
. Unlike other unary operators ?
is written in postfix notation. ?
cannot be overloaded.
# #![allow(unused_variables)] #fn main() { # use std::num::ParseIntError; fn try_to_parse() -> Result<i32, ParseIntError> { let x: i32 = "123".parse()?; // x = 123 let y: i32 = "24a".parse()?; // returns an Err() immediately Ok(x + y) // Doesn't run. } let res = try_to_parse(); println!("{:?}", res); # assert!(res.is_err()) #}
These are the last two unary operators. This table summarizes the behavior of them on primitive types and which traits are used to overload these operators for other types. Remember that signed integers are always represented using two's complement. The operands of all of these operators are evaluated in rvalue context so are moved or copied.
Symbol | Integer | bool |
Floating Point | Overloading Trait |
---|---|---|---|---|
- |
Negation* | Negation | std::ops::Neg |
|
! |
Bitwise NOT | Logical NOT | std::ops::Not |
* Only for signed integer types.
Here are some example of these operators
# #![allow(unused_variables)] #fn main() { let x = 6; assert_eq!(-x, -6); assert_eq!(!x, -7); assert_eq!(true, !false); #}
Binary operators expressions are all written with infix notation. This table summarizes the behavior of arithmetic and logical binary operators on primitive types and which traits are used to overload these operators for other types. Remember that signed integers are always represented using two's complement. The operands of all of these operators are evaluated in rvalue context so are moved or copied.
Symbol | Integer | bool |
Floating Point | Overloading Trait |
---|---|---|---|---|
+ |
Addition | Addition | std::ops::Add |
|
- |
Subtraction | Subtraction | std::ops::Sub |
|
* |
Multiplication | Multiplication | std::ops::Mul |
|
/ |
Division | Division | std::ops::Div |
|
% |
Remainder | Remainder | std::ops::Rem |
|
& |
Bitwise AND | Logical AND | std::ops::BitAnd |
|
| |
Bitwise OR | Logical OR | std::ops::BitOr |
|
^ |
Bitwise XOR | Logical XOR | std::ops::BitXor |
|
<< |
Left Shift | std::ops::Shl |
||
>> |
Right Shift* | std::ops::Shr |
* Arithmetic right shift on signed integer types, logical right shift on unsigned integer types.
Here are examples of these operators being used.
# #![allow(unused_variables)] #fn main() { assert_eq!(3 + 6, 9); assert_eq!(5.5 - 1.25, 4.25); assert_eq!(-5 * 14, -70); assert_eq!(14 / 3, 4); assert_eq!(100 % 7, 2); assert_eq!(0b1010 & 0b1100, 0b1000); assert_eq!(0b1010 | 0b1100, 0b1110); assert_eq!(0b1010 ^ 0b1100, 0b110); assert_eq!(13 << 3, 104); assert_eq!(-10 >> 2, -3); #}
Comparison operators are also defined both for primitive types and many type in the standard library. Parentheses are required when chaining comparison operators. For example, the expression a == b == c
is invalid and may be written as (a == b) == c
.
Unlike arithmetic and logical operators, the traits for overloading the operators the traits for these operators are used more generally to show how a type may be compared and will likely be assumed to define actual comparisons by functions that use these traits as bounds. Many functions and macros in the standard library can then use that assumption (although not to ensure safety). Unlike the arithmetic and logical operators above, these operators implicitly take shared borrows of their operands, evaluating them in lvalue context:
a == b; // is equivalent to ::std::cmp::PartialEq::eq(&a, &b);
This means that the operands don't have to be moved out of.
Symbol | Meaning | Overloading method |
---|---|---|
== |
Equal | std::cmp::PartialEq::eq |
!= |
Not equal | std::cmp::PartialEq::ne |
> |
Greater than | std::cmp::PartialOrd::gt |
< |
Less than | std::cmp::PartialOrd::lt |
>= |
Greater than or equal to | std::cmp::PartialOrd::ge |
<= |
Less than or equal to | std::cmp::PartialOrd::le |
Here are examples of the comparison operators being used.
# #![allow(unused_variables)] #fn main() { assert!(123 == 123); assert!(23 != -12); assert!(12.5 > 12.2); assert!([1, 2, 3] < [1, 3, 4]); assert!('A' <= 'B'); assert!("World" >= "Hello"); #}
The operators ||
and &&
may be applied to operands of boolean type. The ||
operator denotes logical 'or', and the &&
operator denotes logical 'and'. They differ from |
and &
in that the right-hand operand is only evaluated when the left-hand operand does not already determine the result of the expression. That is, ||
only evaluates its right-hand operand when the left-hand operand evaluates to false
, and &&
only when it evaluates to true
.
# #![allow(unused_variables)] #fn main() { let x = false || true; // true let y = false && panic!(); // false, doesn't evaluate `panic!()` #}
A type cast expression is denoted with the binary operator as
.
Executing an as
expression casts the value on the left-hand side to the type on the right-hand side.
An example of an as
expression:
# #![allow(unused_variables)] #fn main() { # fn sum(values: &[f64]) -> f64 { 0.0 } # fn len(values: &[f64]) -> i32 { 0 } fn average(values: &[f64]) -> f64 { let sum: f64 = sum(values); let size: f64 = len(values) as f64; sum / size } #}
as
can be used to explicitly perform coercions, as well as the following additional casts. Here *T
means either *const T
or *mut T
.
Type of e |
U |
Cast performed by e as U |
---|---|---|
Integer or Float type | Integer or Float type | Numeric cast |
C-like enum | Integer type | Enum cast |
bool or char |
Integer type | Primitive to integer cast |
u8 |
char |
u8 to char cast |
*T |
*V where V: Sized * |
Pointer to pointer cast |
*T where T: Sized |
Numeric type | Pointer to address cast |
Integer type | *V where V: Sized |
Address to pointer cast |
&[T; n] |
*const T |
Array to pointer cast |
Function pointer | *V where V: Sized |
Function pointer to pointer cast |
Function pointer | Integer | Function pointer to address cast |
* or T
and V
are compatible unsized types, e.g., both slices, both the same trait object.
false
casts to 0
, true
casts to 1
char
casts to the value of the code point, then uses a numeric cast if needed.u8
to char
cast char
with the corresponding code point.An assignment expression consists of an lvalue expression followed by an equals sign (=
) and an rvalue expression.
Evaluating an assignment expression drops the left-hand operand, unless it's an unitialized local variable or field of a local variable, and either copies or moves its right-hand operand to its left-hand operand. The left-hand operand must be an lvalue: using an rvalue results in a compiler error, rather than promoting it to a temporary.
# #![allow(unused_variables)] #fn main() { # let mut x = 0; # let y = 0; x = y; #}
The +
, -
, *
, /
, %
, &
, |
, ^
, <<
, and >>
operators may be composed with the =
operator. The expression lval OP= val
is equivalent to lval = lval OP val
. For example, x = x + 1
may be written as x += 1
. Any such expression always has the unit
type. These operators can all be overloaded using the trait with the same name as for the normal operation followed by 'Assign', for example, std::ops::AddAssign
is used to overload +=
. As with =
, lval
must be an lvalue.
# #![allow(unused_variables)] #fn main() { let mut x = 10; x += 4; assert_eq!(x, 14); #}
© 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/reference/expressions/operator-expr.html