Ownership when Adding Strings with `+` Operator

Not quite correct. First of all, += may be implemented differently than what + does. Moreover, if you write a = a + b and if the type of a isn't Copy, then you temporarily move out of a which means in case of a panic during execution of std::ops::Add::add, the value a would be set to no value. This leads to the compiler refusing this operation in some contexts:

#[derive(Debug)]
struct Person {
    name: String,
    height: u32,
}

fn foo(person: &mut Person) {
    person.height = person.height + 5; // this works
    //person.name = person.name + " Doe"; // but this doesn't compile
    person.name += " Doe"; // even though it does the same as this
}

fn main() {
    let mut p = Person {
        name: "John".to_string(),
        height: 100,
    };
    foo(&mut p);
    println!("{p:?}");
}

(Playground)

In the example above, person.height = person.height + 5; works fine. But person.name = person.name + " Doe"; does not work because if that operation would panic, then person.name would not be valid anymore.


Sometimes this isn't a problem, like when you do the operation direction in main, because a panic would cause p to be dropped.

#[derive(Debug)]
struct Person {
    name: String,
    height: u32,
}

// Try to uncomment this:

//impl Drop for Person {
//    fn drop(&mut self) {
//    }
//}

fn main() {
    let mut p = Person {
        name: "John".to_string(),
        height: 100,
    };
    p.height = p.height + 5;
    p.name = p.name + " Doe"; // in this context, the line works, unless `Person` implements `Drop`
    p.name += " Doe";
    println!("{p:?}");
}

(Playground)

However, that only works if Person doesn't have a drop handler, because if it had, then p.name might be invalid when the drop handler runs.


P.S.: Regarding consuming a value and returning a new one versus working on &mut references, I found this post by @steffahn very enlightening (which is why I came up with the above examples in regard to panic behavior and partial moves).