@@ -202,18 +202,18 @@ types. Remember that signed integers are always represented using two's
202
202
complement. The operands of all of these operators are evaluated in [ value
203
203
expression context] [ value expression ] so are moved or copied.
204
204
205
- | Symbol | Integer | ` bool ` | Floating Point | Overloading Trait |
206
- | --------| -------------------------| -------------| ----------------| --------------------|
207
- | ` + ` | Addition | | Addition | ` std::ops::Add ` |
208
- | ` - ` | Subtraction | | Subtraction | ` std::ops::Sub ` |
209
- | ` * ` | Multiplication | | Multiplication | ` std::ops::Mul ` |
210
- | ` / ` | Division* | | Division | ` std::ops::Div ` |
211
- | ` % ` | Remainder | | Remainder | ` std::ops::Rem ` |
212
- | ` & ` | Bitwise AND | Logical AND | | ` std::ops::BitAnd ` |
213
- | <code >| ; </code > | Bitwise OR | Logical OR | | ` std::ops::BitOr ` |
214
- | ` ^ ` | Bitwise XOR | Logical XOR | | ` std::ops::BitXor ` |
215
- | ` << ` | Left Shift | | | ` std::ops::Shl ` |
216
- | ` >> ` | Right Shift** | | | ` std::ops::Shr ` |
205
+ | Symbol | Integer | ` bool ` | Floating Point | Overloading Trait | Overloading Compound Assignment Trait |
206
+ | --------| -------------------------| -------------| ----------------| --------------------| ------------------------------------- |
207
+ | ` + ` | Addition | | Addition | ` std::ops::Add ` | ` std::ops::AddAssign ` |
208
+ | ` - ` | Subtraction | | Subtraction | ` std::ops::Sub ` | ` std::ops::SubAssign ` |
209
+ | ` * ` | Multiplication | | Multiplication | ` std::ops::Mul ` | ` std::ops::MulAssign ` |
210
+ | ` / ` | Division* | | Division | ` std::ops::Div ` | ` std::ops::DivAssign ` |
211
+ | ` % ` | Remainder | | Remainder | ` std::ops::Rem ` | ` std::ops::RemAssign ` |
212
+ | ` & ` | Bitwise AND | Logical AND | | ` std::ops::BitAnd ` | ` std::ops::BitAndAssign ` |
213
+ | <code >| ; </code > | Bitwise OR | Logical OR | | ` std::ops::BitOr ` | ` std::ops::BitOrAssign ` |
214
+ | ` ^ ` | Bitwise XOR | Logical XOR | | ` std::ops::BitXor ` | ` std::ops::BitXorAssign ` |
215
+ | ` << ` | Left Shift | | | ` std::ops::Shl ` | ` std::ops::ShlAssign ` |
216
+ | ` >> ` | Right Shift** | | | ` std::ops::Shr ` | ` std::ops::ShrAssign ` |
217
217
218
218
\* Integer division rounds towards zero.
219
219
@@ -441,24 +441,76 @@ x = y;
441
441
>   ;  ; | [ _ Expression_ ] ` <<= ` [ _ Expression_ ] \
442
442
>   ;  ; | [ _ Expression_ ] ` >>= ` [ _ Expression_ ]
443
443
444
- The ` + ` , ` - ` , ` * ` , ` / ` , ` % ` , ` & ` , ` | ` , ` ^ ` , ` << ` , and ` >> ` operators may be
445
- composed with the ` = ` operator. The expression ` place_exp OP= value ` is
446
- equivalent to ` place_expr = place_expr OP val ` . For example, ` x = x + 1 ` may be
447
- written as ` x += 1 ` . Any such expression always has the [ ` unit ` type] .
448
- These operators can all be overloaded using the trait with the same name as for
449
- the normal operation followed by 'Assign', for example, ` std::ops::AddAssign `
450
- is used to overload ` += ` . As with ` = ` , ` place_expr ` must be a [ place
451
- expression] .
444
+ * Compound assignment expressions* combine arithmetic and logical binary
445
+ operators with assignment expressions.
446
+
447
+ For example:
448
+
449
+ ``` rust
450
+ let mut x = 5 ;
451
+ x += 1 ;
452
+ assert! (x == 6 );
453
+ ```
454
+
455
+ The syntax of compound assignment is a [ mutable] [ place expression] , the
456
+ * assigned operand* , then one of the operators followed by an ` = ` as a single
457
+ token (no whitespace), and then a [ value expression] , the * modifying operand* .
458
+
459
+ Unlike other place operands, the assigned place operand must be a place
460
+ expression. Attempting to use a value expression is a compiler error rather
461
+ than promoting it to a temporary.
462
+
463
+ Evaluation of compound assignment expressions depends on the types of the
464
+ operators.
465
+
466
+ If both types are primitives, then the modifying operand will be evaluated
467
+ first followed by the assigned operand. It will then set the value of the
468
+ assigned operand's place to the value of performing the operation of the
469
+ operator with the values of the assigned operand and modifying operand.
470
+
471
+ > ** Note** : This is different than other expressions in that the right operand
472
+ > is evaluated before the left one.
473
+
474
+ Otherwise, this expression is syntactic sugar for calling the function of the
475
+ overloading compound assigment trait of the operator (see the table earlier in
476
+ this chapter). A mutable borrow of the assigned operand is automatically taken.
477
+
478
+ For example, the following expression statements in ` example ` are equivalent:
452
479
453
480
``` rust
454
- let mut x = 10 ;
455
- x += 4 ;
456
- assert_eq! (x , 14 );
481
+ # struct Addable ;
482
+ # use std :: ops :: AddAssign ;
483
+
484
+ impl AddAssign <Addable > for Addable {
485
+ /* */
486
+ # fn add_assign (& mut self , other : Addable ) {}
487
+ }
488
+
489
+ fn example () {
490
+ # let (mut a1 , a2 ) = (Addable , Addable );
491
+ a1 += a2 ;
492
+
493
+ # let (mut a1 , a2 ) = (Addable , Addable );
494
+ AddAssign :: add_assign (& mut a1 , a2 );
495
+ }
457
496
```
458
497
498
+ <div class =" warning " >
499
+
500
+ Warning: The evaluation order of operands swaps depending on the types of the
501
+ operands: with primitive types the right-hand side will get evaluated first,
502
+ while with non-primitive types the left-hand side will get evaluated first.
503
+ Try not to write code that depends on the evaluation order of operands in
504
+ compound assignment expressions. See [ this test] for an example of using this
505
+ dependency.
506
+
507
+ </div >
508
+
509
+ [ mutable ] : ../expressions.md#mutability
459
510
[ place expression ] : ../expressions.md#place-expressions-and-value-expressions
460
511
[ value expression ] : ../expressions.md#place-expressions-and-value-expressions
461
512
[ temporary value ] : ../expressions.md#temporaries
513
+ [ this test ] : https://github.com/rust-lang/rust/blob/master/src/test/ui/expr/compound-assignment/eval-order.rs
462
514
[ float-float ] : https://github.com/rust-lang/rust/issues/15536
463
515
[ `unit` type ] : ../types/tuple.md
464
516
[ Function pointer ] : ../types/function-pointer.md
0 commit comments