5

req.url.fragment is an optional String. If it has a value, I want to copy that value into fragment, otherwise I want to assign an empty string. I keep getting the error that I cannot move out of borrowed content.

How do I resolve this?

fn fb_token(req: &mut Request) -> IronResult<Response> {
    let fragment = match req.url.fragment {
        Some(fragment) => fragment,
        None => "".to_string(),
    };

    Ok(Response::with((status::Ok, fragment)))
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
W.K.S
  • 9,787
  • 15
  • 75
  • 122

2 Answers2

13

It depends on what you want to do with the existing string in the structure.

let fragment = match req.url.fragment {
    Some(fragment) => fragment,
    None => "".to_string(),
};

In this code, you are moving the String out of req.url.fragment, but that would leave it in an undefined state. That's a bad thing, and Rust prevents you from doing that!

As the error message states:

to prevent the move, use ref fragment or ref mut fragment to capture value by reference

If you want to leave the string where it is and return a copy, then you can take a reference and then clone it:

let fragment = match req.url {
    Some(ref fragment) => fragment.clone(),
    None => "".to_string()
};

If you want to leave the existing string as a None, then you can use take:

let fragment = match req.url.take() {
    Some(fragment) => fragment,
    None => "".to_string()
};

Even shorter, you can use unwrap_or_else:

let fragment = req.url.take().unwrap_or_else(String::new);
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • I did understand the thing about how borrowing freezes the referred object, meaning moving is not allowed in this case but I just couldn't figure out how to avoid the moving. Clearly I need to revise some concepts and go through the docs more carefully. Thanks for your help :) – W.K.S Apr 29 '15 at 03:42
2

The problem here is that one cannot invalidate a &mut reference, and moving ownership out is one way to invalidate. (There's a few links to similar questions/answers in the sidebar on the right.)

A fix is to instead use references, which should work quite well in this case:

fn fb_token(req: &mut Request) -> IronResult<Response> {
    let fragment: &str = match req.url.fragment {
        Some(ref fragment) => &**fragment,
        None => "",
    };

    Ok(Response::with((status::Ok, fragment)))
}

(The &str annotation isn't necessary, just to make it clearer what's happening.)

This works because iron implements Modifier<Response> for &str, so that type can be used with with instead of the owned String.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
huon
  • 94,605
  • 21
  • 231
  • 225