Mutable Reference vs. Taking and Returning Ownership

Option 1:

fn action(&self, item: &mut Item) -> Result<_, Error>;

Option 2:

fn action(&self, item: Item) -> Result<Item, Error>;

I see these as achieving the same goal. Can anyone highlight what the main differences are? Is one more idiomatic? Is one more optimal?

They are semantically different, with the second one, if there is an error you can no longer access item. In the first you can.

1 Like

One of the situations where option 1 doesn't work is, trying to change enum variant through &mut.

You can't take ownerships of fields of objects from &mut, even if it is temporary.
If you want to do such things, you should basically choose option 2.

This problem is related to panic safety.
See the documentation of take_mut crate for detail.
(This crate enables taking ownership temporarily from &mut in safe way, using unsafe internally.)

https://docs.rs/take_mut/0.2.2/take_mut/

1 Like

An alternative without unsafe would be to simply use mem::replace(), then write back the new value. This often works, provided you can make up a new instance of the type on the spot.

1 Like

Note that take_mut crate is safe because it aborts the entire process on panic.

1 Like