Search code examples
rustborrowing

Rust borrowing with some object types and not others?


I am having a very difficult time understanding how borrowing works, and I can't for the life of me work out why these two cases are so different. The part that does work was inspired from https://users.rust-lang.org/t/rust-mutability-moving-and-borrowing-the-straight-dope/22166, the part that doesn't is what I am trying to achieve with a Response object from reqwest.

struct Player { name: String, age: u8, description: String }
impl Player {
    fn namefn(&self) -> &String {
        &self.name
    }
}

fn immutable_borrow_nok(borrowed: &reqwest::blocking::Response) -> Result<()> {
    // println!("I am some json, I don't work {:#?}", borrowed.text()); <-- if I get uncommented I won't compile
    Ok(())
}
fn immutable_borrow(borrowed: &Player) -> Result<()> {
    println!("I am {}, I've been immutably borrowed", borrowed.namefn());
    Ok(())
}

fn main() -> Result<()>{
    let our_player = Player { name: "Jones".to_string(), age: 25, description: "Just a happy guy.".to_string() };
    immutable_borrow(&our_player);
    println!("My name is {}, and I am being used after an immutable borrow", our_player.namefn());

    let res = reqwest::blocking::Client::new().post("http://httpbin.org/anything").send()?.error_for_status()?;
    immutable_borrow_nok(&res);
    println!("I am also some json but I *do* work... {:#?}", res.text());

    Ok(())
}

Solution

  • If you look at the definition of the text method here you can see that it consumes (moves) self after calling. So after calling text method you cannot use Response because it simply doesn't exist anymore.

    But inside your immutable_borrow_nok function you have a reference to Response. immutable_borrow_nok does not own it. Values passed by the reference cannot be consumed. So Response can't be consumed (moved) inside immutable_borrow_nok.

    If you really want to use text method inside immutable_borrow_nok you should define it like this:

    // Response now owned by this function
    fn immutable_owned_nok(owned: reqwest::blocking::Response) -> Result<()> {
        println!("I am some json, I don't work {:#?}", borrowed.text());
        Ok(())
    }
    

    But you should understand that after calling immutable_owned_nok you cannot use your Response anymore in your code.