Skip to content

Instantly share code, notes, and snippets.

@birkin
Last active May 17, 2023 11:07
Show Gist options
  • Save birkin/57952fa4052167ddb8b5c98ec8beb920 to your computer and use it in GitHub Desktop.
Save birkin/57952fa4052167ddb8b5c98ec8beb920 to your computer and use it in GitHub Desktop.
explanation of rust shared-reference & move concepts.

Prompt

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?


Response

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:

  1. Shared References (&T): A shared reference in Rust allows read-only access to a value of type T, 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.

  2. Mutable References (&mut T): A mutable reference in Rust allows read-write access to a value of type T. The rule with mutable references is that you can only have one mutable reference to a particular piece of data in a particular scope.

  3. 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 of move is 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 the Copy trait). 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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment