]> git.proxmox.com Git - rustc.git/blame - src/doc/reference/src/expressions/operator-expr.md
New upstream version 1.23.0+dfsg1
[rustc.git] / src / doc / reference / src / expressions / operator-expr.md
CommitLineData
ea8adc8c
XL
1# Operator expressions
2
3Operators are defined for built in types by the Rust language. Many of the
4following operators can also be overloaded using traits in `std::ops` or
5`std::cmp`.
6
7## Overflow
8
9Integer operators will panic when they overflow when compiled in debug mode.
10The `-C debug-assertions` and `-C overflow-checks` compiler flags can be used
11to control this more directly. The following things are considered to be
12overflow:
13
14* When `+`, `*` or `-` create a value greater than the maximum value, or less
15 than the minimum value that can be stored. This includes unary `-` on the
16 smallest value of any signed integer type.
17* Using `/` or `%`, where the left-hand argument is the smallest integer of a
18 signed integer type and the right-hand argument is `-1`.
19* Using `<<` or `>>` where the right-hand argument is greater than or equal to
20 the number of bits in the type of the left-hand argument, or is negative.
21
22## Grouped expressions
23
24An expression enclosed in parentheses evaluates to the result of the enclosed
25expression. Parentheses can be used to explicitly specify evaluation order
26within an expression.
27
28An example of a parenthesized expression:
29
30```rust
31let x: i32 = 2 + 3 * 4;
32let y: i32 = (2 + 3) * 4;
33assert_eq!(x, 14);
34assert_eq!(y, 20);
35```
36
37## Borrow operators
38
39The `&` (shared borrow) and `&mut` (mutable borrow) operators are unary prefix
40operators. When applied to an lvalue produce a reference (pointer) to the
41location that the value refers to. The lvalue is also placed into a borrowed
42state for the duration of the reference. For a shared borrow (`&`), this
43implies that the lvalue may not be mutated, but it may be read or shared again.
44For a mutable borrow (`&mut`), the lvalue may not be accessed in any way until
45the borrow expires. `&mut` evaluates its operand in a mutable lvalue context.
46If the `&` or `&mut` operators are applied to an rvalue, a temporary value is
47created; the lifetime of this temporary value is defined by [syntactic
48rules](expressions.html#temporary-lifetimes). These operators cannot be overloaded.
49
50```rust
51{
52 // a temporary with value 7 is created that lasts for this scope.
53 let shared_reference = &7;
54}
55let mut array = [-2, 3, 9];
56{
57 // Mutably borrows `array` for this scope.
58 // `array` may only be used through `mutable_reference`.
59 let mutable_reference = &mut array;
60}
61```
62
63## The dereference operator
64
65The `*` (dereference) operator is also a unary prefix operator. When applied to
66a [pointer](types.html#pointer-types) it denotes the pointed-to location. If
67the expression is of type `&mut T` and `*mut T`, and is either a local
68variable, a (nested) field of a local variance or is a mutable lvalue, then the
69resulting [lvalue](expressions.html#lvalues-and-rvalues) can be
70assigned to. Dereferencing a raw pointer requires `unsafe`.
71
72On non-pointer types `*x` is equivalent to `*std::ops::Deref::deref(&x)` in an
73[immutable lvalue context](expressions.html#mutability) and
74`*std::ops::Deref::deref_mut(&mut x)` in a mutable lvalue context.
75
76```rust
77let x = &7;
78assert_eq!(*x, 7);
79let y = &mut 9;
80*y = 11;
81assert_eq!(*y, 11);
82```
83
84## The `?` operator.
85
86The `?` ("question mark") operator can be applied to values of the `Result<T,
87E>` type to propagate errors. If applied to `Err(e)` it will return
88`Err(From::from(e))` from the enclosing function or closure. If applied to
89`Ok(x)` it will unwrap the value to return `x`. Unlike other unary operators
90`?` is written in postfix notation. `?` cannot be overloaded.
91
92```rust
93# use std::num::ParseIntError;
94fn try_to_parse() -> Result<i32, ParseIntError> {
95 let x: i32 = "123".parse()?; // x = 123
96 let y: i32 = "24a".parse()?; // returns an Err() immediately
97 Ok(x + y) // Doesn't run.
98}
99
100let res = try_to_parse();
101println!("{:?}", res);
102# assert!(res.is_err())
103```
104
105## Negation operators
106
107These are the last two unary operators. This table summarizes the behavior of
108them on primitive types and which traits are used to overload these operators
109for other types. Remember that signed integers are always represented using
110two's complement. The operands of all of these operators are evaluated in
111rvalue context so are moved or copied.
112
113| Symbol | Integer | `bool` | Floating Point | Overloading Trait |
114|--------|-------------|-------------|----------------|--------------------|
115| `-` | Negation* | | Negation | `std::ops::Neg` |
116| `!` | Bitwise NOT | Logical NOT | | `std::ops::Not` |
117
118\* Only for signed integer types.
119
120Here are some example of these operators
121
122```rust
123let x = 6;
124assert_eq!(-x, -6);
125assert_eq!(!x, -7);
126assert_eq!(true, !false);
127```
128
129## Arithmetic and Logical Binary Operators
130
131Binary operators expressions are all written with infix notation. This table
132summarizes the behavior of arithmetic and logical binary operators on
133primitive types and which traits are used to overload these operators for other
134types. Remember that signed integers are always represented using two's
135complement. The operands of all of these operators are evaluated in rvalue
136context so are moved or copied.
137
138| Symbol | Integer | `bool` | Floating Point | Overloading Trait |
139|--------|-------------------------|-------------|----------------|--------------------|
140| `+` | Addition | | Addition | `std::ops::Add` |
141| `-` | Subtraction | | Subtraction | `std::ops::Sub` |
142| `*` | Multiplication | | Multiplication | `std::ops::Mul` |
143| `/` | Division | | Division | `std::ops::Div` |
144| `%` | Remainder | | Remainder | `std::ops::Rem` |
145| `&` | Bitwise AND | Logical AND | | `std::ops::BitAnd` |
146| <code>&#124;</code> | Bitwise OR | Logical OR | | `std::ops::BitOr` |
147| `^` | Bitwise XOR | Logical XOR | | `std::ops::BitXor` |
148| `<<` | Left Shift | | | `std::ops::Shl` |
149| `>>` | Right Shift* | | | `std::ops::Shr` |
150
151\* Arithmetic right shift on signed integer types, logical right shift on
152unsigned integer types.
153
154Here are examples of these operators being used.
155
156```rust
157assert_eq!(3 + 6, 9);
158assert_eq!(5.5 - 1.25, 4.25);
159assert_eq!(-5 * 14, -70);
160assert_eq!(14 / 3, 4);
161assert_eq!(100 % 7, 2);
162assert_eq!(0b1010 & 0b1100, 0b1000);
163assert_eq!(0b1010 | 0b1100, 0b1110);
164assert_eq!(0b1010 ^ 0b1100, 0b110);
165assert_eq!(13 << 3, 104);
166assert_eq!(-10 >> 2, -3);
167```
168
169## Comparison Operators
170
171Comparison operators are also defined both for primitive types and many type in
172the standard library. Parentheses are required when chaining comparison
173operators. For example, the expression `a == b == c` is invalid and may be
174written as `(a == b) == c`.
175
176Unlike arithmetic and logical operators, the traits for
177overloading the operators the traits for these operators are used more
178generally to show how a type may be compared and will likely be assumed to
179define actual comparisons by functions that use these traits as bounds. Many
180functions and macros in the standard library can then use that assumption
181(although not to ensure safety). Unlike the arithmetic and logical operators
182above, these operators implicitly take shared borrows of their operands,
183evaluating them in lvalue context:
184
185```rust,ignore
186a == b;
187// is equivalent to
188::std::cmp::PartialEq::eq(&a, &b);
189```
190
191This means that the operands don't have to be moved out of.
192
193| Symbol | Meaning | Overloading method |
194|--------|--------------------------|----------------------------|
195| `==` | Equal | `std::cmp::PartialEq::eq` |
196| `!=` | Not equal | `std::cmp::PartialEq::ne` |
197| `>` | Greater than | `std::cmp::PartialOrd::gt` |
198| `<` | Less than | `std::cmp::PartialOrd::lt` |
199| `>=` | Greater than or equal to | `std::cmp::PartialOrd::ge` |
200| `<=` | Less than or equal to | `std::cmp::PartialOrd::le` |
201
202Here are examples of the comparison operators being used.
203
204```rust
205assert!(123 == 123);
206assert!(23 != -12);
207assert!(12.5 > 12.2);
208assert!([1, 2, 3] < [1, 3, 4]);
209assert!('A' <= 'B');
210assert!("World" >= "Hello");
211```
212
213## Lazy boolean operators
214
215The operators `||` and `&&` may be applied to operands of boolean type. The
216`||` operator denotes logical 'or', and the `&&` operator denotes logical
217'and'. They differ from `|` and `&` in that the right-hand operand is only
218evaluated when the left-hand operand does not already determine the result of
219the expression. That is, `||` only evaluates its right-hand operand when the
220left-hand operand evaluates to `false`, and `&&` only when it evaluates to
221`true`.
222
223```rust
224let x = false || true; // true
225let y = false && panic!(); // false, doesn't evaluate `panic!()`
226```
227
228## Type cast expressions
229
230A type cast expression is denoted with the binary operator `as`.
231
232Executing an `as` expression casts the value on the left-hand side to the type
233on the right-hand side.
234
235An example of an `as` expression:
236
237```rust
238# fn sum(values: &[f64]) -> f64 { 0.0 }
239# fn len(values: &[f64]) -> i32 { 0 }
240fn average(values: &[f64]) -> f64 {
241 let sum: f64 = sum(values);
242 let size: f64 = len(values) as f64;
243 sum / size
244}
245```
246
247`as` can be used to explicitly perform [coercions](type-coercions.html), as
248well as the following additional casts. Here `*T` means either `*const T` or
249`*mut T`.
250
251| Type of `e` | `U` | Cast performed by `e as U` |
252|-----------------------|-----------------------|----------------------------------|
253| Integer or Float type | Integer or Float type | Numeric cast |
254| C-like enum | Integer type | Enum cast |
255| `bool` or `char` | Integer type | Primitive to integer cast |
256| `u8` | `char` | `u8` to `char` cast |
257| `*T` | `*V` where `V: Sized` \* | Pointer to pointer cast |
258| `*T` where `T: Sized` | Numeric type | Pointer to address cast |
259| Integer type | `*V` where `V: Sized` | Address to pointer cast |
260| `&[T; n]` | `*const T` | Array to pointer cast |
261| [Function pointer](types.html#function-pointer-types) | `*V` where `V: Sized` | Function pointer to pointer cast |
262| Function pointer | Integer | Function pointer to address cast |
263
264\* or `T` and `V` are compatible unsized types, e.g., both slices, both the
265same trait object.
266
267### Semantics
268
269* Numeric cast
270 * Casting between two integers of the same size (e.g. i32 -> u32) is a no-op
271 * Casting from a larger integer to a smaller integer (e.g. u32 -> u8) will
272 truncate
273 * Casting from a smaller integer to a larger integer (e.g. u8 -> u32) will
274 * zero-extend if the source is unsigned
275 * sign-extend if the source is signed
276 * Casting from a float to an integer will round the float towards zero
277 * **[NOTE: currently this will cause Undefined Behavior if the rounded
278 value cannot be represented by the target integer type][float-int]**.
279 This includes Inf and NaN. This is a bug and will be fixed.
280 * Casting from an integer to float will produce the floating point
281 representation of the integer, rounded if necessary (rounding strategy
282 unspecified)
283 * Casting from an f32 to an f64 is perfect and lossless
284 * Casting from an f64 to an f32 will produce the closest possible value
285 (rounding strategy unspecified)
286 * **[NOTE: currently this will cause Undefined Behavior if the value
287 is finite but larger or smaller than the largest or smallest finite
288 value representable by f32][float-float]**. This is a bug and will
289 be fixed.
290* Enum cast
291 * Casts an enum to its discriminant, then uses a numeric cast if needed.
292* Primitive to integer cast
293 * `false` casts to `0`, `true` casts to `1`
294 * `char` casts to the value of the code point, then uses a numeric cast if needed.
295* `u8` to `char` cast
296 * Casts to the `char` with the corresponding code point.
297
298[float-int]: https://github.com/rust-lang/rust/issues/10184
299[float-float]: https://github.com/rust-lang/rust/issues/15536
300
301## Assignment expressions
302
303An _assignment expression_ consists of an
abe05a73
XL
304[lvalue](expressions.html#lvalues-and-rvalues) expression followed by an equals
305sign (`=`) and an [rvalue](expressions.html#lvalues-and-rvalues) expression.
ea8adc8c 306
abe05a73
XL
307Evaluating an assignment expression [drops](destructors.html) the left-hand
308operand, unless it's an unitialized local variable or field of a local variable,
309and [either copies or moves](expressions.html#moved-and-copied-types) its
310right-hand operand to its left-hand operand. The left-hand operand must be an
311lvalue: using an rvalue results in a compiler error, rather than promoting it
312to a temporary.
ea8adc8c
XL
313
314```rust
315# let mut x = 0;
316# let y = 0;
317x = y;
318```
319
320## Compound assignment expressions
321
322The `+`, `-`, `*`, `/`, `%`, `&`, `|`, `^`, `<<`, and `>>` operators may be
323composed with the `=` operator. The expression `lval OP= val` is equivalent to
324`lval = lval OP val`. For example, `x = x + 1` may be written as `x += 1`.
325Any such expression always has the [`unit`](types.html#tuple-types) type.
326These operators can all be overloaded using the trait with the same name as for
327the normal operation followed by 'Assign', for example, `std::ops::AddAssign`
328is used to overload `+=`. As with `=`, `lval` must be an lvalue.
329
330```rust
331let mut x = 10;
332x += 4;
333assert_eq!(x, 14);
334```