The section on compound assignment expressions currently states:
If both types are primitives, then the modifying operand will be evaluated first followed by the assigned operand.
This suggests that when both operands are primitive types, the right-hand side is always evaluated before the left-hand side.
However, this behavior is not preserved when using generic code, even with primitive types. Consider the following example:
fn main() {
println!("i32, i32: {:?}", order_i32());
println!("i32, i32 (Generic): {:?}", order::<i32, i32>());
println!("String, &str (Generic): {:?}", order::<String, &str>());
}
fn order_i32() -> Vec<&'static str> {
let mut order = vec![];
{
order.push("left");
(0,)
}
.0 += {
order.push("right");
0
};
order
}
fn order<T, U>() -> Vec<&'static str>
where
T: Default,
U: Default,
T: std::ops::AddAssign<U>,
{
let mut order = vec![];
{
order.push("left");
(T::default(),)
}
.0 += {
order.push("right");
U::default()
};
order
}
Output:
i32, i32: ["right", "left"]
i32, i32 (Generic): ["left", "right"]
String, &str (Generic): ["left", "right"]
This shows that even when both operands are i32, the evaluation order is reversed if the operation is generic (i.e., uses the AddAssign trait explicitly). This contradicts the current documentation, or at least suggests that it is oversimplified.
Suggested improvement:
Clarify that:
- The "right-then-left" evaluation order only applies to non-generic code involving primitive types, due to compiler desugaring.
- In generic contexts (even with primitive types),
a += b behaves like a method call to AddAssign::add_assign, and evaluates operands left-to-right, as with most Rust expressions.
The section on compound assignment expressions currently states:
This suggests that when both operands are primitive types, the right-hand side is always evaluated before the left-hand side.
However, this behavior is not preserved when using generic code, even with primitive types. Consider the following example:
Output:
This shows that even when both operands are
i32, the evaluation order is reversed if the operation is generic (i.e., uses theAddAssigntrait explicitly). This contradicts the current documentation, or at least suggests that it is oversimplified.Suggested improvement:
Clarify that:
a += bbehaves like a method call toAddAssign::add_assign, and evaluates operands left-to-right, as with most Rust expressions.