this Rust line works...
title = subfield.value.clone().unwrap_or_else(|| "".to_string());
...and this doesn't:
title = subfield.value.unwrap_or_else(|| "".to_string());
...with the help text explaining:
cannot move out of `subfield.value` which is behind a shared reference
move occurs because `subfield.value` has type `std::option::Option<std::string::String>`, which does not implement the `Copy` trait
Can you add to that explanation, including an explanation of the "shared reference" note?
Certainly. The error is indicating that Rust is trying to move subfield.value (an Option<String>) but can't because it's behind a shared reference.
To explain this further, let's discuss the different types of references and the concept of ownership in Rust:
-
Shared References (
&T): A shared reference in Rust allows read-only access to a value of typeT, and you can have as many shared references to a value as you want. The key point is that you cannot mutate the value through a shared reference. -
Mutable References (
&mut T): A mutable reference in Rust allows read-write access to a value of typeT. The rule with mutable references is that you can only have one mutable reference to a particular piece of data in a particular scope. -
Ownership and
move: In Rust, each value has a variable that owns it. When the owner goes out of scope, Rust will automatically clean up the value. The concept ofmoveis related to this ownership model. When you assign a value to another variable or pass it to a function, Rust will move the value instead of copying it (for types that don't implement theCopytrait). After the move, the original variable can no longer be used.
The unwrap_or_else function needs to take ownership (i.e., it needs to perform a move) of the Option<String> to be able to return the contained String if it exists. However, in your second line of code, subfield.value is behind a shared reference (because you're inside a reference to subfield), so you're not allowed to move out of it, hence the error.
The reason the first line of code works (title = subfield.value.clone().unwrap_or_else(|| "".to_string());) is because clone() creates a copy of Option<String>, and unwrap_or_else() is taking ownership of this copy, not the original value. This is allowed in Rust, and it doesn't violate the borrowing rules.
I hope this explanation helps clarify the issue!
(chatgpt-4)