]> git.proxmox.com Git - rustc.git/blame - src/doc/reference/src/expressions/operator-expr.md
New upstream version 1.60.0+dfsg1
[rustc.git] / src / doc / reference / src / expressions / operator-expr.md
CommitLineData
ea8adc8c
XL
1# Operator expressions
2
8faf50e0
XL
3> **<sup>Syntax</sup>**\
4> _OperatorExpression_ :\
5> &nbsp;&nbsp; &nbsp;&nbsp; [_BorrowExpression_]\
6> &nbsp;&nbsp; | [_DereferenceExpression_]\
7> &nbsp;&nbsp; | [_ErrorPropagationExpression_]\
8> &nbsp;&nbsp; | [_NegationExpression_]\
9> &nbsp;&nbsp; | [_ArithmeticOrLogicalExpression_]\
10> &nbsp;&nbsp; | [_ComparisonExpression_]\
11> &nbsp;&nbsp; | [_LazyBooleanExpression_]\
12> &nbsp;&nbsp; | [_TypeCastExpression_]\
13> &nbsp;&nbsp; | [_AssignmentExpression_]\
14> &nbsp;&nbsp; | [_CompoundAssignmentExpression_]
0531ce1d 15
6a06907d
XL
16Operators are defined for built in types by the Rust language.
17Many of the following operators can also be overloaded using traits in `std::ops` or `std::cmp`.
ea8adc8c
XL
18
19## Overflow
20
21Integer operators will panic when they overflow when compiled in debug mode.
6a06907d
XL
22The `-C debug-assertions` and `-C overflow-checks` compiler flags can be used to control this more directly.
23The following things are considered to be overflow:
24
25* When `+`, `*` or `-` create a value greater than the maximum value, or less than the minimum value that can be stored.
26 This includes unary `-` on the smallest value of any signed integer type.
27* Using `/` or `%`, where the left-hand argument is the smallest integer of a signed integer type and the right-hand argument is `-1`.
136023e0 28 These checks occur even when `-C overflow-checks` is disabled, for legacy reasons.
6a06907d 29* Using `<<` 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.
ea8adc8c 30
ea8adc8c
XL
31## Borrow operators
32
8faf50e0
XL
33> **<sup>Syntax</sup>**\
34> _BorrowExpression_ :\
35> &nbsp;&nbsp; &nbsp;&nbsp; (`&`|`&&`) [_Expression_]\
36> &nbsp;&nbsp; | (`&`|`&&`) `mut` [_Expression_]
0531ce1d 37
6a06907d
XL
38The `&` (shared borrow) and `&mut` (mutable borrow) operators are unary prefix operators.
39When applied to a [place expression], this expressions produces a reference (pointer) to the location that the value refers to.
40The memory location is also placed into a borrowed state for the duration of the reference.
41For a shared borrow (`&`), this implies that the place may not be mutated, but it may be read or shared again.
42For a mutable borrow (`&mut`), the place may not be accessed in any way until the borrow expires.
43`&mut` evaluates its operand in a mutable place expression context.
44If the `&` or `&mut` operators are applied to a [value expression], then a [temporary value] is created.
ff7c6d11
XL
45
46These operators cannot be overloaded.
ea8adc8c
XL
47
48```rust
49{
50 // a temporary with value 7 is created that lasts for this scope.
51 let shared_reference = &7;
52}
53let mut array = [-2, 3, 9];
54{
55 // Mutably borrows `array` for this scope.
56 // `array` may only be used through `mutable_reference`.
57 let mutable_reference = &mut array;
58}
59```
60
6a06907d 61Even though `&&` is a single token ([the lazy 'and' operator](#lazy-boolean-operators)), when used in the context of borrow expressions it works as two borrows:
0531ce1d
XL
62
63```rust
64// same meanings:
65let a = && 10;
66let a = & & 10;
67
68// same meanings:
69let a = &&&& mut 10;
70let a = && && mut 10;
71let a = & & & & mut 10;
72```
73
ea8adc8c
XL
74## The dereference operator
75
8faf50e0
XL
76> **<sup>Syntax</sup>**\
77> _DereferenceExpression_ :\
0531ce1d
XL
78> &nbsp;&nbsp; `*` [_Expression_]
79
6a06907d
XL
80The `*` (dereference) operator is also a unary prefix operator.
81When applied to a [pointer](../types/pointer.md) it denotes the pointed-to location.
82If the expression is of type `&mut T` or `*mut T`, and is either a local variable, a (nested) field of a local variable or is a mutable [place expression], then the resulting memory location can be assigned to.
ff7c6d11 83Dereferencing a raw pointer requires `unsafe`.
ea8adc8c 84
6a06907d 85On non-pointer types `*x` is equivalent to `*std::ops::Deref::deref(&x)` in an [immutable place expression context](../expressions.md#mutability) and `*std::ops::DerefMut::deref_mut(&mut x)` in a mutable place expression context.
ea8adc8c
XL
86
87```rust
88let x = &7;
89assert_eq!(*x, 7);
90let y = &mut 9;
91*y = 11;
92assert_eq!(*y, 11);
93```
94
ff7c6d11
XL
95## The question mark operator
96
8faf50e0
XL
97> **<sup>Syntax</sup>**\
98> _ErrorPropagationExpression_ :\
99> &nbsp;&nbsp; [_Expression_] `?`
0531ce1d 100
6a06907d
XL
101The question mark operator (`?`) unwraps valid values or returns erroneous values, propagating them to the calling function.
102It is a unary postfix operator that can only be applied to the types `Result<T, E>` and `Option<T>`.
ea8adc8c 103
6a06907d
XL
104When applied to values of the `Result<T, E>` type, it propagates errors.
105If the value is `Err(e)`, then it will return `Err(From::from(e))` from the enclosing function or closure.
106If applied to `Ok(x)`, then it will unwrap the value to evaluate to `x`.
ea8adc8c
XL
107
108```rust
109# use std::num::ParseIntError;
110fn try_to_parse() -> Result<i32, ParseIntError> {
111 let x: i32 = "123".parse()?; // x = 123
112 let y: i32 = "24a".parse()?; // returns an Err() immediately
113 Ok(x + y) // Doesn't run.
114}
115
116let res = try_to_parse();
117println!("{:?}", res);
118# assert!(res.is_err())
119```
120
6a06907d
XL
121When applied to values of the `Option<T>` type, it propagates `None`s.
122If the value is `None`, then it will return `None`.
123If applied to `Some(x)`, then it will unwrap the value to evaluate to `x`.
ff7c6d11
XL
124
125```rust
126fn try_option_some() -> Option<u8> {
127 let val = Some(1)?;
128 Some(val)
129}
130assert_eq!(try_option_some(), Some(1));
131
132fn try_option_none() -> Option<u8> {
133 let val = None?;
134 Some(val)
135}
136assert_eq!(try_option_none(), None);
137```
138
139`?` cannot be overloaded.
140
ea8adc8c
XL
141## Negation operators
142
8faf50e0
XL
143> **<sup>Syntax</sup>**\
144> _NegationExpression_ :\
145> &nbsp;&nbsp; &nbsp;&nbsp; `-` [_Expression_]\
146> &nbsp;&nbsp; | `!` [_Expression_]
0531ce1d 147
6a06907d
XL
148These are the last two unary operators.
149This table summarizes the behavior of them on primitive types and which traits are used to overload these operators for other types.
150Remember that signed integers are always represented using two's complement.
151The operands of all of these operators are evaluated in [value expression context][value expression] so are moved or copied.
ea8adc8c 152
6a06907d
XL
153| Symbol | Integer | `bool` | Floating Point | Overloading Trait |
154|--------|-------------|-------------- |----------------|--------------------|
155| `-` | Negation* | | Negation | `std::ops::Neg` |
156| `!` | Bitwise NOT | [Logical NOT] | | `std::ops::Not` |
ea8adc8c
XL
157
158\* Only for signed integer types.
159
160Here are some example of these operators
161
162```rust
163let x = 6;
164assert_eq!(-x, -6);
165assert_eq!(!x, -7);
166assert_eq!(true, !false);
167```
168
169## Arithmetic and Logical Binary Operators
170
8faf50e0
XL
171> **<sup>Syntax</sup>**\
172> _ArithmeticOrLogicalExpression_ :\
173> &nbsp;&nbsp; &nbsp;&nbsp; [_Expression_] `+` [_Expression_]\
174> &nbsp;&nbsp; | [_Expression_] `-` [_Expression_]\
175> &nbsp;&nbsp; | [_Expression_] `*` [_Expression_]\
176> &nbsp;&nbsp; | [_Expression_] `/` [_Expression_]\
177> &nbsp;&nbsp; | [_Expression_] `%` [_Expression_]\
178> &nbsp;&nbsp; | [_Expression_] `&` [_Expression_]\
179> &nbsp;&nbsp; | [_Expression_] `|` [_Expression_]\
180> &nbsp;&nbsp; | [_Expression_] `^` [_Expression_]\
181> &nbsp;&nbsp; | [_Expression_] `<<` [_Expression_]\
182> &nbsp;&nbsp; | [_Expression_] `>>` [_Expression_]
0531ce1d 183
6a06907d
XL
184Binary operators expressions are all written with infix notation.
185This 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.
186Remember that signed integers are always represented using two's complement.
187The operands of all of these operators are evaluated in [value expression context][value expression] so are moved or copied.
188
189| Symbol | Integer | `bool` | Floating Point | Overloading Trait | Overloading Compound Assignment Trait |
190|--------|-------------------------|---------------|----------------|--------------------| ------------------------------------- |
191| `+` | Addition | | Addition | `std::ops::Add` | `std::ops::AddAssign` |
192| `-` | Subtraction | | Subtraction | `std::ops::Sub` | `std::ops::SubAssign` |
193| `*` | Multiplication | | Multiplication | `std::ops::Mul` | `std::ops::MulAssign` |
194| `/` | Division* | | Division | `std::ops::Div` | `std::ops::DivAssign` |
136023e0 195| `%` | Remainder** | | Remainder | `std::ops::Rem` | `std::ops::RemAssign` |
6a06907d
XL
196| `&` | Bitwise AND | [Logical AND] | | `std::ops::BitAnd` | `std::ops::BitAndAssign` |
197| <code>&#124;</code> | Bitwise OR | [Logical OR] | | `std::ops::BitOr` | `std::ops::BitOrAssign` |
198| `^` | Bitwise XOR | [Logical XOR] | | `std::ops::BitXor` | `std::ops::BitXorAssign` |
199| `<<` | Left Shift | | | `std::ops::Shl` | `std::ops::ShlAssign` |
136023e0 200| `>>` | Right Shift*** | | | `std::ops::Shr` | `std::ops::ShrAssign` |
ea8adc8c 201
94b46f34
XL
202\* Integer division rounds towards zero.
203
136023e0
XL
204\*\* 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.
205
206\*\*\* Arithmetic right shift on signed integer types, logical right shift on
ea8adc8c
XL
207unsigned integer types.
208
209Here are examples of these operators being used.
210
211```rust
212assert_eq!(3 + 6, 9);
213assert_eq!(5.5 - 1.25, 4.25);
214assert_eq!(-5 * 14, -70);
215assert_eq!(14 / 3, 4);
216assert_eq!(100 % 7, 2);
217assert_eq!(0b1010 & 0b1100, 0b1000);
218assert_eq!(0b1010 | 0b1100, 0b1110);
219assert_eq!(0b1010 ^ 0b1100, 0b110);
220assert_eq!(13 << 3, 104);
221assert_eq!(-10 >> 2, -3);
222```
223
224## Comparison Operators
225
8faf50e0
XL
226> **<sup>Syntax</sup>**\
227> _ComparisonExpression_ :\
228> &nbsp;&nbsp; &nbsp;&nbsp; [_Expression_] `==` [_Expression_]\
229> &nbsp;&nbsp; | [_Expression_] `!=` [_Expression_]\
230> &nbsp;&nbsp; | [_Expression_] `>` [_Expression_]\
231> &nbsp;&nbsp; | [_Expression_] `<` [_Expression_]\
232> &nbsp;&nbsp; | [_Expression_] `>=` [_Expression_]\
233> &nbsp;&nbsp; | [_Expression_] `<=` [_Expression_]
0531ce1d 234
6a06907d
XL
235Comparison operators are also defined both for primitive types and many types in the standard library.
236Parentheses are required when chaining comparison operators. For example, the expression `a == b == c` is invalid and may be written as `(a == b) == c`.
ea8adc8c 237
6a06907d
XL
238Unlike 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.
239Many functions and macros in the standard library can then use that assumption (although not to ensure safety).
240Unlike the arithmetic and logical operators above, these operators implicitly take shared borrows of their operands, evaluating them in [place expression context][place expression]:
ea8adc8c 241
60c5eb7d
XL
242```rust
243# let a = 1;
244# let b = 1;
ea8adc8c
XL
245a == b;
246// is equivalent to
247::std::cmp::PartialEq::eq(&a, &b);
248```
249
250This means that the operands don't have to be moved out of.
251
252| Symbol | Meaning | Overloading method |
253|--------|--------------------------|----------------------------|
254| `==` | Equal | `std::cmp::PartialEq::eq` |
255| `!=` | Not equal | `std::cmp::PartialEq::ne` |
256| `>` | Greater than | `std::cmp::PartialOrd::gt` |
257| `<` | Less than | `std::cmp::PartialOrd::lt` |
258| `>=` | Greater than or equal to | `std::cmp::PartialOrd::ge` |
259| `<=` | Less than or equal to | `std::cmp::PartialOrd::le` |
260
261Here are examples of the comparison operators being used.
262
263```rust
264assert!(123 == 123);
265assert!(23 != -12);
266assert!(12.5 > 12.2);
267assert!([1, 2, 3] < [1, 3, 4]);
268assert!('A' <= 'B');
269assert!("World" >= "Hello");
270```
271
272## Lazy boolean operators
273
8faf50e0
XL
274> **<sup>Syntax</sup>**\
275> _LazyBooleanExpression_ :\
276> &nbsp;&nbsp; &nbsp;&nbsp; [_Expression_] `||` [_Expression_]\
0531ce1d
XL
277> &nbsp;&nbsp; | [_Expression_] `&&` [_Expression_]
278
6a06907d
XL
279The operators `||` and `&&` may be applied to operands of boolean type.
280The `||` operator denotes logical 'or', and the `&&` operator denotes logical 'and'.
281They 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.
282That is, `||` only evaluates its right-hand operand when the left-hand operand evaluates to `false`, and `&&` only when it evaluates to `true`.
ea8adc8c
XL
283
284```rust
285let x = false || true; // true
286let y = false && panic!(); // false, doesn't evaluate `panic!()`
287```
288
289## Type cast expressions
290
8faf50e0
XL
291> **<sup>Syntax</sup>**\
292> _TypeCastExpression_ :\
0bf4aa26 293> &nbsp;&nbsp; [_Expression_] `as` [_TypeNoBounds_]
0531ce1d 294
ea8adc8c
XL
295A type cast expression is denoted with the binary operator `as`.
296
6a06907d 297Executing an `as` expression casts the value on the left-hand side to the type on the right-hand side.
ea8adc8c
XL
298
299An example of an `as` expression:
300
301```rust
302# fn sum(values: &[f64]) -> f64 { 0.0 }
303# fn len(values: &[f64]) -> i32 { 0 }
304fn average(values: &[f64]) -> f64 {
305 let sum: f64 = sum(values);
306 let size: f64 = len(values) as f64;
307 sum / size
308}
309```
310
6a06907d 311`as` can be used to explicitly perform [coercions](../type-coercions.md), as well as the following additional casts.
cdc7bbd5
XL
312Any cast that does not fit either a coercion rule or an entry in the table is a compiler error.
313Here `*T` means either `*const T` or `*mut T`. `m` stands for optional `mut` in
314reference types and `mut` or `const` in pointer types.
ea8adc8c
XL
315
316| Type of `e` | `U` | Cast performed by `e as U` |
317|-----------------------|-----------------------|----------------------------------|
318| Integer or Float type | Integer or Float type | Numeric cast |
319| C-like enum | Integer type | Enum cast |
320| `bool` or `char` | Integer type | Primitive to integer cast |
321| `u8` | `char` | `u8` to `char` cast |
322| `*T` | `*V` where `V: Sized` \* | Pointer to pointer cast |
6a06907d 323| `*T` where `T: Sized` | Integer type | Pointer to address cast |
ea8adc8c 324| Integer type | `*V` where `V: Sized` | Address to pointer cast |
cdc7bbd5
XL
325| `&m₁ T` | `*m₂ T` \*\* | Reference to pointer cast |
326| `&m₁ [T; n]` | `*m₂ T` \*\* | Array to pointer cast |
3dfed10e
XL
327| [Function item] | [Function pointer] | Function item to function pointer cast |
328| [Function item] | `*V` where `V: Sized` | Function item to pointer cast |
329| [Function item] | Integer | Function item to address cast |
330| [Function pointer] | `*V` where `V: Sized` | Function pointer to pointer cast |
331| [Function pointer] | Integer | Function pointer to address cast |
cdc7bbd5 332| Closure \*\*\* | Function pointer | Closure to function pointer cast |
ea8adc8c 333
6a06907d 334\* or `T` and `V` are compatible unsized types, e.g., both slices, both the same trait object.
ea8adc8c 335
cdc7bbd5
XL
336\*\* only when `m₁` is `mut` or `m₂` is `const`. Casting `mut` reference to
337`const` pointer is allowed.
338
339\*\*\* only for closures that do not capture (close over) any local variables
94b46f34 340
ea8adc8c
XL
341### Semantics
342
17df50a5
XL
343#### Numeric cast
344
345* Casting between two integers of the same size (e.g. i32 -> u32) is a no-op
136023e0 346 (Rust uses 2's complement for negative values of fixed integers)
17df50a5
XL
347* Casting from a larger integer to a smaller integer (e.g. u32 -> u8) will
348 truncate
349* Casting from a smaller integer to a larger integer (e.g. u8 -> u32) will
350 * zero-extend if the source is unsigned
351 * sign-extend if the source is signed
352* Casting from a float to an integer will round the float towards zero
353 * `NaN` will return `0`
136023e0
XL
354 * Values larger than the maximum integer value, including `INFINITY`, will saturate to the maximum value of the integer type.
355 * Values smaller than the minimum integer value, including `NEG_INFINITY`, will saturate to the minimum value of the integer type.
17df50a5
XL
356* Casting from an integer to float will produce the closest possible float \*
357 * if necessary, rounding is according to `roundTiesToEven` mode \*\*\*
358 * on overflow, infinity (of the same sign as the input) is produced
359 * note: with the current set of numeric types, overflow can only happen
360 on `u128 as f32` for values greater or equal to `f32::MAX + (0.5 ULP)`
361* Casting from an f32 to an f64 is perfect and lossless
362* Casting from an f64 to an f32 will produce the closest possible f32 \*\*
363 * if necessary, rounding is according to `roundTiesToEven` mode \*\*\*
364 * on overflow, infinity (of the same sign as the input) is produced
ea8adc8c 365
e1599b0c
XL
366\* if integer-to-float casts with this rounding mode and overflow behavior are
367not supported natively by the hardware, these casts will likely be slower than
368expected.
369
370\*\* if f64-to-f32 casts with this rounding mode and overflow behavior are not
371supported natively by the hardware, these casts will likely be slower than
372expected.
373
374\*\*\* as defined in IEEE 754-2008 &sect;4.3.1: pick the nearest floating point
375number, preferring the one with an even least significant digit if exactly
376halfway between two floating point numbers.
377
17df50a5
XL
378#### Enum cast
379
380Casts an enum to its discriminant, then uses a numeric cast if needed.
381
382#### Primitive to integer cast
383
384* `false` casts to `0`, `true` casts to `1`
385* `char` casts to the value of the code point, then uses a numeric cast if needed.
386
387#### `u8` to `char` cast
388
389Casts to the `char` with the corresponding code point.
390
391#### Pointer to address cast
392
393Casting from a raw pointer to an integer produces the machine address of the referenced memory.
394If the integer type is smaller than the pointer type, the address may be truncated; using `usize` avoids this.
395
396#### Address to pointer cast
397
398Casting from an integer to a raw pointer interprets the integer as a memory address and produces a pointer referencing that memory.
399
400<div class="warning">
401
402Warning:
403This interacts with the Rust memory model, which is still under development.
404A pointer obtained from this cast may suffer additional restrictions even if it is bitwise equal to a valid pointer.
405Dereferencing such a pointer may be [undefined behavior] if aliasing rules are not followed.
406
407</div>
408
409A trivial example of sound address arithmetic:
410
411```rust
412let mut values: [i32; 2] = [1, 2];
413let p1: *mut i32 = values.as_mut_ptr();
414let first_address = p1 as usize;
415let second_address = first_address + 4; // 4 == size_of::<i32>()
416let p2 = second_address as *mut i32;
417unsafe {
418 *p2 += 1;
419}
420assert_eq!(values[1], 3);
421```
422
ea8adc8c
XL
423## Assignment expressions
424
8faf50e0
XL
425> **<sup>Syntax</sup>**\
426> _AssignmentExpression_ :\
48663c56 427> &nbsp;&nbsp; [_Expression_] `=` [_Expression_]
0531ce1d 428
5869c6ff 429An *assignment expression* moves a value into a specified place.
ea8adc8c 430
5099ac24
FG
431An assignment expression consists of a [mutable] [assignee expression], the *assignee operand*, followed by an equals sign (`=`) and a [value expression], the *assigned value operand*.
432In its most basic form, an assignee expression is a [place expression], and we discuss this case first.
433The more general case of destructuring assignment is discussed below, but this case always decomposes into sequential assignments to place expressions, which may be considered the more fundamental case.
5869c6ff 434
5099ac24 435### Basic assignments
ea8adc8c 436
6a06907d 437Evaluating assignment expressions begins by evaluating its operands.
5099ac24
FG
438The assigned value operand is evaluated first, followed by the assignee expression.
439For destructuring assignment, subexpressions of the assignee expression are evaluated left-to-right.
5869c6ff 440
6a06907d 441> **Note**: This is different than other expressions in that the right operand is evaluated before the left one.
5869c6ff 442
6a06907d
XL
443It then has the effect of first [dropping] the value at the assigned place, unless the place is an uninitialized local variable or an uninitialized field of a local variable.
444Next it either [copies or moves] the assigned value to the assigned place.
5869c6ff
XL
445
446An assignment expression always produces [the unit value][unit].
447
448Example:
449
ea8adc8c 450```rust
5869c6ff
XL
451let mut x = 0;
452let y = 0;
ea8adc8c
XL
453x = y;
454```
455
5099ac24
FG
456### Destructuring assignments
457
458Destructuring assignment is a counterpart to destructuring pattern matches for variable declaration, permitting assignment to complex values, such as tuples or structs.
459For instance, we may swap two mutable variables:
460
461```rust
462let (mut a, mut b) = (0, 1);
463// Swap `a` and `b` using destructuring assignment.
464(b, a) = (a, b);
465```
466
467In contrast to destructuring declarations using `let`, patterns may not appear on the left-hand side of an assignment due to syntactic ambiguities.
468Instead, a group of expressions that correspond to patterns are designated to be [assignee expressions][assignee expression], and permitted on the left-hand side of an assignment.
469Assignee expressions are then desugared to pattern matches followed by sequential assignment.
470The desugared patterns must be irrefutable: in particular, this means that only slice patterns whose length is known at compile-time, and the trivial slice `[..]`, are permitted for destructuring assignment.
471
472The desugaring method is straightforward, and is illustrated best by example.
473
474```rust
475# struct Struct { x: u32, y: u32 }
476# let (mut a, mut b) = (0, 0);
477(a, b) = (3, 4);
478
479[a, b] = [3, 4];
480
481Struct { x: a, y: b } = Struct { x: 3, y: 4};
482
483// desugars to:
484
485{
486 let (_a, _b) = (3, 4);
487 a = _a;
488 b = _b;
489}
490
491{
492 let [_a, _b] = [3, 4];
493 a = _a;
494 b = _b;
495}
496
497{
498 let Struct { x: _a, y: _b } = Struct { x: 3, y: 4};
499 a = _a;
500 b = _b;
501}
502```
503
504Identifiers are not forbidden from being used multiple times in a single assignee expression.
505
506[Underscore expressions][_UnderscoreExpression_] and empty [range expressions][_RangeExpression_] may be used to ignore certain values, without binding them.
507
508Note that default binding modes do not apply for the desugared expression.
509
ea8adc8c
XL
510## Compound assignment expressions
511
8faf50e0
XL
512> **<sup>Syntax</sup>**\
513> _CompoundAssignmentExpression_ :\
514> &nbsp;&nbsp; &nbsp;&nbsp; [_Expression_] `+=` [_Expression_]\
515> &nbsp;&nbsp; | [_Expression_] `-=` [_Expression_]\
516> &nbsp;&nbsp; | [_Expression_] `*=` [_Expression_]\
517> &nbsp;&nbsp; | [_Expression_] `/=` [_Expression_]\
518> &nbsp;&nbsp; | [_Expression_] `%=` [_Expression_]\
519> &nbsp;&nbsp; | [_Expression_] `&=` [_Expression_]\
520> &nbsp;&nbsp; | [_Expression_] `|=` [_Expression_]\
521> &nbsp;&nbsp; | [_Expression_] `^=` [_Expression_]\
522> &nbsp;&nbsp; | [_Expression_] `<<=` [_Expression_]\
523> &nbsp;&nbsp; | [_Expression_] `>>=` [_Expression_]
0531ce1d 524
6a06907d 525*Compound assignment expressions* combine arithmetic and logical binary operators with assignment expressions.
5869c6ff
XL
526
527For example:
528
529```rust
530let mut x = 5;
531x += 1;
532assert!(x == 6);
533```
534
6a06907d 535The syntax of compound assignment is a [mutable] [place expression], the *assigned operand*, then one of the operators followed by an `=` as a single token (no whitespace), and then a [value expression], the *modifying operand*.
5869c6ff 536
6a06907d
XL
537Unlike other place operands, the assigned place operand must be a place expression.
538Attempting to use a value expression is a compiler error rather than promoting it to a temporary.
5869c6ff 539
6a06907d 540Evaluation of compound assignment expressions depends on the types of the operators.
5869c6ff 541
6a06907d
XL
542If both types are primitives, then the modifying operand will be evaluated first followed by the assigned operand.
543It will then set the value of the assigned operand's place to the value of performing the operation of the operator with the values of the assigned operand and modifying operand.
5869c6ff 544
6a06907d 545> **Note**: This is different than other expressions in that the right operand is evaluated before the left one.
5869c6ff 546
6a06907d
XL
547Otherwise, this expression is syntactic sugar for calling the function of the overloading compound assigment trait of the operator (see the table earlier in this chapter).
548A mutable borrow of the assigned operand is automatically taken.
5869c6ff
XL
549
550For example, the following expression statements in `example` are equivalent:
ea8adc8c
XL
551
552```rust
5869c6ff
XL
553# struct Addable;
554# use std::ops::AddAssign;
555
556impl AddAssign<Addable> for Addable {
557 /* */
558# fn add_assign(&mut self, other: Addable) {}
559}
560
561fn example() {
562# let (mut a1, a2) = (Addable, Addable);
563 a1 += a2;
564
565# let (mut a1, a2) = (Addable, Addable);
566 AddAssign::add_assign(&mut a1, a2);
567}
ea8adc8c 568```
ff7c6d11 569
17df50a5
XL
570Like assignment expressions, compound assignment expressions always produce [the unit value][unit].
571
5869c6ff
XL
572<div class="warning">
573
6a06907d
XL
574Warning: The evaluation order of operands swaps depending on the types of the operands:
575with primitive types the right-hand side will get evaluated first, while with non-primitive types the left-hand side will get evaluated first.
576Try not to write code that depends on the evaluation order of operands in compound assignment expressions.
577See [this test] for an example of using this dependency.
5869c6ff
XL
578
579</div>
580
581[copies or moves]: ../expressions.md#moved-and-copied-types
582[dropping]: ../destructors.md
6a06907d
XL
583[logical and]: ../types/boolean.md#logical-and
584[logical not]: ../types/boolean.md#logical-not
585[logical or]: ../types/boolean.md#logical-or
586[logical xor]: ../types/boolean.md#logical-xor
5869c6ff 587[mutable]: ../expressions.md#mutability
416331ca 588[place expression]: ../expressions.md#place-expressions-and-value-expressions
5099ac24 589[assignee expression]: ../expressions.md#place-expressions-and-value-expressions
17df50a5 590[undefined behavior]: ../behavior-considered-undefined.md
5869c6ff 591[unit]: ../types/tuple.md
416331ca 592[value expression]: ../expressions.md#place-expressions-and-value-expressions
f9f354fc 593[temporary value]: ../expressions.md#temporaries
5099ac24 594[this test]: https://github.com/rust-lang/rust/blob/1.58.0/src/test/ui/expr/compound-assignment/eval-order.rs
ff7c6d11 595[float-float]: https://github.com/rust-lang/rust/issues/15536
3dfed10e
XL
596[Function pointer]: ../types/function-pointer.md
597[Function item]: ../types/function-item.md
0531ce1d
XL
598
599[_BorrowExpression_]: #borrow-operators
600[_DereferenceExpression_]: #the-dereference-operator
601[_ErrorPropagationExpression_]: #the-question-mark-operator
602[_NegationExpression_]: #negation-operators
603[_ArithmeticOrLogicalExpression_]: #arithmetic-and-logical-binary-operators
604[_ComparisonExpression_]: #comparison-operators
605[_LazyBooleanExpression_]: #lazy-boolean-operators
606[_TypeCastExpression_]: #type-cast-expressions
607[_AssignmentExpression_]: #assignment-expressions
608[_CompoundAssignmentExpression_]: #compound-assignment-expressions
609
416331ca
XL
610[_Expression_]: ../expressions.md
611[_TypeNoBounds_]: ../types.md#type-expressions
5099ac24
FG
612[_RangeExpression_]: ./range-expr.md
613[_UnderscoreExpression_]: ./underscore-expr.md