|
| Bitwise OR | [Logical OR] | | `std::ops::BitOr` | `std::ops::BitOrAssign` |
| `^` | Bitwise XOR | [Logical XOR] | | `std::ops::BitXor` | `std::ops::BitXorAssign` |
| `<<` | Left Shift | | | `std::ops::Shl` | `std::ops::ShlAssign` |
| `>>` | Right Shift*** | | | `std::ops::Shr` | `std::ops::ShrAssign` |
\* Integer division rounds towards zero.
\*\* Rust uses a remainder defined with [truncating division](https://en.wikipedia.org/wiki/Modulo_operation#Variants_of_the_definition). Given `remainder = dividend % divisor`, the remainder will have the same sign as the dividend.
\*\*\* Arithmetic right shift on signed integer types, logical right shift on
unsigned integer types.
Here are examples of these operators being used.
```rust
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
> **Syntax**\
> _ComparisonExpression_ :\
> [_Expression_] `==` [_Expression_]\
> | [_Expression_] `!=` [_Expression_]\
> | [_Expression_] `>` [_Expression_]\
> | [_Expression_] `<` [_Expression_]\
> | [_Expression_] `>=` [_Expression_]\
> | [_Expression_] `<=` [_Expression_]
Comparison operators are also defined both for primitive types and many types 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 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 [place expression context][place expression]:
```rust
# let a = 1;
# let b = 1;
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.
```rust
assert!(123 == 123);
assert!(23 != -12);
assert!(12.5 > 12.2);
assert!([1, 2, 3] < [1, 3, 4]);
assert!('A' <= 'B');
assert!("World" >= "Hello");
```
## Lazy boolean operators
> **Syntax**\
> _LazyBooleanExpression_ :\
> [_Expression_] `||` [_Expression_]\
> | [_Expression_] `&&` [_Expression_]
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`.
```rust
let x = false || true; // true
let y = false && panic!(); // false, doesn't evaluate `panic!()`
```
## Type cast expressions
> **Syntax**\
> _TypeCastExpression_ :\
> [_Expression_] `as` [_TypeNoBounds_]
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:
```rust
# 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](../type-coercions.md), as well as the following additional casts.
Any cast that does not fit either a coercion rule or an entry in the table is a compiler error.
Here `*T` means either `*const T` or `*mut T`. `m` stands for optional `mut` in
reference types and `mut` or `const` in pointer types.
| Type of `e` | `U` | Cast performed by `e as U` |
|-----------------------|-----------------------|----------------------------------|
| Integer or Float type | Integer or Float type | Numeric cast |
| Enumeration | 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` | Integer type | Pointer to address cast |
| Integer type | `*V` where `V: Sized` | Address to pointer cast |
| `&m₁ T` | `*m₂ T` \*\* | Reference to pointer cast |
| `&m₁ [T; n]` | `*m₂ T` \*\* | Array to pointer cast |
| [Function item] | [Function pointer] | Function item to function pointer cast |
| [Function item] | `*V` where `V: Sized` | Function item to pointer cast |
| [Function item] | Integer | Function item to address cast |
| [Function pointer] | `*V` where `V: Sized` | Function pointer to pointer cast |
| [Function pointer] | Integer | Function pointer to address cast |
| Closure \*\*\* | Function pointer | Closure to function pointer cast |
\* or `T` and `V` are compatible unsized types, e.g., both slices, both the same trait object.
\*\* only when `m₁` is `mut` or `m₂` is `const`. Casting `mut` reference to
`const` pointer is allowed.
\*\*\* only for closures that do not capture (close over) any local variables
### Semantics
#### Numeric cast
* Casting between two integers of the same size (e.g. i32 -> u32) is a no-op
(Rust uses 2's complement for negative values of fixed integers)
* Casting from a larger integer to a smaller integer (e.g. u32 -> u8) will
truncate
* Casting from a smaller integer to a larger integer (e.g. u8 -> u32) will
* zero-extend if the source is unsigned
* sign-extend if the source is signed
* Casting from a float to an integer will round the float towards zero
* `NaN` will return `0`
* Values larger than the maximum integer value, including `INFINITY`, will saturate to the maximum value of the integer type.
* Values smaller than the minimum integer value, including `NEG_INFINITY`, will saturate to the minimum value of the integer type.
* Casting from an integer to float will produce the closest possible float \*
* if necessary, rounding is according to `roundTiesToEven` mode \*\*\*
* on overflow, infinity (of the same sign as the input) is produced
* note: with the current set of numeric types, overflow can only happen
on `u128 as f32` for values greater or equal to `f32::MAX + (0.5 ULP)`
* Casting from an f32 to an f64 is perfect and lossless
* Casting from an f64 to an f32 will produce the closest possible f32 \*\*
* if necessary, rounding is according to `roundTiesToEven` mode \*\*\*
* on overflow, infinity (of the same sign as the input) is produced
\* if integer-to-float casts with this rounding mode and overflow behavior are
not supported natively by the hardware, these casts will likely be slower than
expected.
\*\* if f64-to-f32 casts with this rounding mode and overflow behavior are not
supported natively by the hardware, these casts will likely be slower than
expected.
\*\*\* as defined in IEEE 754-2008 §4.3.1: pick the nearest floating point
number, preferring the one with an even least significant digit if exactly
halfway between two floating point numbers.
#### Enum cast
Casts an enum to its discriminant, then uses a numeric cast if needed.
Casting is limited to the following kinds of enumerations:
* [Unit-only enums]
* [Field-less enums] without [explicit discriminants], or where only unit-variants have explicit discriminants
#### Primitive to integer cast
* `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
Casts to the `char` with the corresponding code point.
#### Pointer to address cast
Casting from a raw pointer to an integer produces the machine address of the referenced memory.
If the integer type is smaller than the pointer type, the address may be truncated; using `usize` avoids this.
#### Address to pointer cast
Casting from an integer to a raw pointer interprets the integer as a memory address and produces a pointer referencing that memory.