Strategies for solving 'cannot move out of' borrowing errors in Rust

 — 1 minute read


Sometimes you hold on a reference even though you’re sure the reference is not used anymore. Nevertheless, the borrow checker does not let you move the owned variable. Consider this example:

fn main() {
  let name = " Herman ".to_string();
  let trimmed_name = name.trim(); // == &[1..n-1]
  let len = trimmed_name.len();

  somefunction_move(name, len); // The compiler won't like this!
}

The reason behind this is that variables and thus lifetimes are lexically scoped. As long as the variable is in the lexical scope, it’s lifetime is still alive.

Herman J. Radtke III presents three strategies for how to deal with this:

1. Block

You can limit the scope of a variable by embedding it its own block:

fn main() {
  let name = " Herman ".to_string();
  let len = {
    let trimmed_name = name.trim(); // == &[1..n-1]
    trimmed_name.len()
  }

  somefunction_move(name, len); // The compiler will be happy.
}

2. Closure

You can limit the scope of a variable my embedding it in a closure:

fn main() {
  let name = " Herman ".to_string();

  let f = |name: &str| {
    let trimmed_name = name.trim(); // == &[1..n-1]
    trimmed_name.len()
  };

  let len = f(&name);

  somefunction_move(name, len); // The compiler will be happy.
}

3. Function

You can limit the scope of a variable my embedding it in a closure:

fn f(name: &str) -> {
  let trimmed_name = name.trim(); // == &[1..n-1]
  trimmed_name.len()
};

fn main() {
  let name = " Herman ".to_string();

  let len = f(&name);

  somefunction_move(name, len); // The compiler will be happy.
}

Herman has a real world example at the end of his article.