Why is `n += m` not same with `n.add_assign(m)`?


#1

My question is why does Rust choice such design about += ( AddAssign ).

struct Num {
    value: useize,
}

impl<'a> AddAssign<&'a Num> for Num {
    fn add_assign(&mut self, other: &'a Num) {
        self.value += other.value;
    }
}

fn main() {
    let mut num = Num { value: 42 };
    let num2 = Num { value: 41 };

    num += &num2;  // It works

    // (&mut num) += &num2;  // It does not work
    // cannot use `+=` on type `&mut Num`

    (&mut num).add_assign(&num2);  // It works

    num.add_assign(&num2);  // It works

Why does Rust not translate += to add_assign() simply ?


#2
// (&mut num) += &num2;  // It does not work
// cannot use `+=` on type `&mut Num`

This is because += operates on the value, even though it will call AddAssign with a reference. It should work if you wrote *(&mut num) += &num2; just like you’d normally assign *(&mut num) = (expr).

(&mut num).add_assign(&num2);  // It works

In this case, you’re getting the benefit of autorefs/derefs, briefly described here in the source.

Ultimately these will all be made equivalent to the UFCS form something like:
<Num as AddAssign<&Num>>::add_assign(&mut num, &num2)