Skip to content

Commit 4df4225

Browse files
authored
Merge pull request #915 from Havvy/ca2
Compound operator expressions
2 parents 50af691 + 61d063f commit 4df4225

File tree

1 file changed

+75
-23
lines changed

1 file changed

+75
-23
lines changed

src/expressions/operator-expr.md

+75-23
Original file line numberDiff line numberDiff line change
@@ -202,18 +202,18 @@ types. Remember that signed integers are always represented using two's
202202
complement. The operands of all of these operators are evaluated in [value
203203
expression context][value expression] so are moved or copied.
204204

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>&#124;</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>&#124;</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` |
217217

218218
\* Integer division rounds towards zero.
219219

@@ -441,24 +441,76 @@ x = y;
441441
> &nbsp;&nbsp; | [_Expression_] `<<=` [_Expression_]\
442442
> &nbsp;&nbsp; | [_Expression_] `>>=` [_Expression_]
443443
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:
452479

453480
```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+
}
457496
```
458497

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
459510
[place expression]: ../expressions.md#place-expressions-and-value-expressions
460511
[value expression]: ../expressions.md#place-expressions-and-value-expressions
461512
[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
462514
[float-float]: https://github.com/rust-lang/rust/issues/15536
463515
[`unit` type]: ../types/tuple.md
464516
[Function pointer]: ../types/function-pointer.md

0 commit comments

Comments
 (0)