-
Notifications
You must be signed in to change notification settings - Fork 539
Open
Description
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 toAddAssign::add_assign
, and evaluates operands left-to-right, as with most Rust expressions.
Metadata
Metadata
Assignees
Labels
No labels