Unable to get immutable reference

I'm not able to get immutable reference to p on line 29. which is weird as I have no immutable reference before nor moved p

use serde::{Deserialize, Serialize};
use serde_json::Result;

#[derive(Serialize, Deserialize,Debug)]
struct Person {
    name: Option<String>,
    age: u8,
    phones: Option<Vec<String>>,
}

fn typed_example() -> Result<()> {
    // Some JSON input data as a &str. Maybe this comes from the user.
    let data = r#"
        {
            "name": "John Doe",
            "age": 43,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;

    // Parse the string of data into a Person object. This is exactly the
    // same function as the one that produced serde_json::Value above, but
    // now we are asking it for a Person as output.
    let p: Person = serde_json::from_str(data)?;

    // Do things just like with any other Rust data structure.
    println!("Please call {} at the number {}", &p.name.unwrap(), &(p.phones.unwrap()[0]));
    println!("{:?}", serde_json::to_string(&p)?);

    Ok(())
}

fn main() {
    typed_example().unwrap();
}

Error:

   Compiling playground v0.0.1 (/playground)
error[E0382]: borrow of partially moved value: `p`
   --> src/main.rs:30:44
    |
29  |     println!("Please call {} at the number {}", &p.name.unwrap(), &(p.phones.unwrap()[0]));
    |                                                                              -------- `p.phones` partially moved due to this method call
30  |     println!("{:?}", serde_json::to_string(&p)?);
    |                                            ^^ value borrowed here after partial move
    |
note: this function consumes the receiver `self` by taking ownership of it, which moves `p.phones`
    = note: partial move occurs because `p.phones` has type `std::option::Option<Vec<std::string::String>>`, which does not implement the `Copy` trait

error: aborting due to previous error

For more information about this error, try `rustc --explain E0382`.
error: could not compile `playground`

To learn more, run the command again with --verbose.

Please help

It's fixed.
new code:

use serde::{Deserialize, Serialize};
use serde_json::Result;

#[derive(Serialize, Deserialize,Debug)]
struct Person {
    name: Option<String>,
    age: u8,
    phones: Option<Vec<String>>,
}

fn typed_example() -> Result<()> {
    // Some JSON input data as a &str. Maybe this comes from the user.
    let data = r#"
        {
            "name": "John Doe",
            "age": 43,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;

    // Parse the string of data into a Person object. This is exactly the
    // same function as the one that produced serde_json::Value above, but
    // now we are asking it for a Person as output.
    let p: Person = serde_json::from_str(data)?;

    // Do things just like with any other Rust data structure.
    println!("Please call {} at the number {}", &p.name.as_ref().unwrap(), &(p.phones.as_ref().unwrap()[0]));
    println!("{}", serde_json::to_string(&p)?);

    Ok(())
}

fn main() {
    typed_example().unwrap();
}

The way to fix it is to insert as_ref()

println!("Please call {} at the number {}", p.name.as_ref().unwrap(), p.phones.as_ref().unwrap()[0]);

as for the explanation, the error message borrow of partially moved value means that you moved the value out of a field of p. Indeed, as the error message tells you, the field phones was moved, due to the call of unwrap(). Unwrap on an Option<T> moves this optional value, so the Option<Vec<String>> field gets moved out. The as_ref call fixes this since as_ref takes &Option<T> and turns it into Option<&T>. In particular, it only uses a reference to the p.phones field. The unwrap call then only moves/copies the Option<&T>, not the original Option<T>.

The same applies to the p.name.unwrap() call.

Edit: Seems you found the fix yourself.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.