You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/expressions/operator-expr.md
+50-31Lines changed: 50 additions & 31 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -902,9 +902,8 @@ Attempting to use a value expression is a compiler error rather than promoting i
902
902
r[expr.compound-assign.operand-order]
903
903
Evaluation of compound assignment expressions depends on the types of the operands.
904
904
905
-
r[expr.compound-assign.primitive-order]
906
-
If both types are primitives and the expression is non-generic (i.e., directly uses concrete types), then the modifying operand will be evaluated first followed by the assigned operand.
907
-
It 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.
905
+
r[expr.compound-assign.primitives]
906
+
If the types of both operands are known, prior to monomorphization, to be primitive, the right hand side is evaluated first, the left hand side is evaluated next, and the place given by the evaluation of the left hand side is mutated by applying the operator to the values of both sides.
908
907
909
908
```rust
910
909
# usecore::{num::Wrapping, ops::AddAssign};
@@ -948,49 +947,69 @@ fn main() {
948
947
```
949
948
950
949
> [!NOTE]
951
-
> This is different than other expressions in that the right operand is evaluated before the left one.
952
-
953
-
> [!NOTE]
954
-
> This right-before-left evaluation only occurs in non-generic code involving primitive types.
955
-
> In all other cases---including generic contexts or non-primitive types---the expression is desugared into a trait method call, and operands are evaluated left to right.
950
+
> This is unusual. Elsewhere left to right evaluation is the norm.
951
+
>
952
+
> See the [eval order test] for more examples.
956
953
957
954
r[expr.compound-assign.trait]
958
-
Otherwise, this expression is syntactic sugar for calling the function of the overloading compound assignment trait of the operator (see the table earlier in this chapter).
959
-
A mutable borrow of the assigned operand is automatically taken.
955
+
Otherwise, this expression is syntactic sugar for using the corresponding trait for the operator (see [expr.arith-logic.behavior]) and calling its method with the left hand side as the [receiver] and the right hand side as the next argument.
960
956
961
-
For example, the following expression statements in `example` are equivalent:
957
+
For example, the following two statements are equivalent:
962
958
963
959
```rust
964
-
# structAddable;
965
960
# usestd::ops::AddAssign;
966
-
967
-
implAddAssign<Addable> forAddable {
968
-
/* */
969
-
# fnadd_assign(&mutself, other:Addable) {}
970
-
}
971
-
972
-
fnexample() {
973
-
# let (muta1, a2) = (Addable, Addable);
974
-
a1+=a2;
975
-
976
-
# let (muta1, a2) = (Addable, Addable);
977
-
AddAssign::add_assign(&muta1, a2);
961
+
fnf<T:AddAssign+Copy>(mutx:T, y:T) {
962
+
x+=y; // Statement 1.
963
+
x.add_assign(y); // Statement 2.
978
964
}
979
965
```
980
966
967
+
> [!NOTE]
968
+
> Surprisingly, desugaring this further to a fully qualified method call is not equivalent, as there is special borrow checker behavior when the mutable reference to the first operand is taken via [autoref].
969
+
>
970
+
> ```rust
971
+
> # usestd::ops::AddAssign;
972
+
> fnf<T:AddAssign+Copy>(mutx:T) {
973
+
> // Here we used `x` as both the LHS and the RHS. Because the
974
+
> // mutable borrow of the LHS needed to call the trait method
975
+
> // is taken implicitly by autoref, this is OK.
976
+
> x+=x; //~ OK
977
+
> x.add_assign(x); //~ OK
978
+
> }
979
+
> ```
980
+
>
981
+
> ```rust,compile_fail,E0503
982
+
> # usestd::ops::AddAssign;
983
+
> fnf<T:AddAssign+Copy>(mutx:T) {
984
+
> // We can't desugar the above to the below, as once we take the
985
+
> // mutable borrow of `x` to pass the first argument, we can't
986
+
> // pass `x` by value in the second argument because the mutable
987
+
> // reference is still live.
988
+
> <TasAddAssign>::add_assign(&mutx, x);
989
+
> //~^ ERROR cannot use `x` because it was mutably borrowed
990
+
> }
991
+
> ```
992
+
>
993
+
> ```rust,compile_fail,E0503
994
+
> # usestd::ops::AddAssign;
995
+
> fnf<T:AddAssign+Copy>(mutx:T) {
996
+
> // As above.
997
+
> (&mutx).add_assign(x);
998
+
> //~^ ERROR cannot use `x` because it was mutably borrowed
999
+
> }
1000
+
> ```
1001
+
981
1002
r[expr.compound-assign.result]
982
-
Like assignment expressions, compound assignment expressions always produce [the unit value][unit].
0 commit comments