4

Why does this pass:

fn f(v: Vec<isize>) -> (Vec<isize>, isize) {
    match v.get(0) {
        Some(&a) => (v, a),
        _ => (v, 0)
    }
}

Playground

but this doesn't?:

fn f(v: Vec<isize>) -> (Vec<isize>, isize) {
    match v.get(0) {
        Some(a) => (v, *a),
        _ => (v, 0)
    }
}

Playground

error[E0505]: cannot move out of `v` because it is borrowed
 --> src/main.rs:7:21
  |
6 |     match v.get(0) {
  |           - borrow of `v` occurs here
7 |         Some(a) => (v, *a),
  |                     ^ move out of `v` occurs here
Tim Diekmann
  • 5,740
  • 9
  • 30
  • 53
Yuki Ito
  • 132
  • 7

2 Answers2

1

v.get(0) returns a reference to the element in the vector, so you are matching &isize. The Vec is now borrowed in the match arm.

In the first code snippet, you copy the isize, so the Vec isn't borrowed here. In the second snippet, the Vec is still borrowed, so you cannot move it out of scope.

However, you should consider to use if let or unwrap_or:

fn f(v: Vec<isize>) -> (Vec<isize>, isize) {
    let a = v.get(0).cloned();
    (v, a.unwrap_or(0))
}

Playground

fn f(v: Vec<isize>) -> (Vec<isize>, isize) {
    if let Some(&a) = v.get(0) {
        (v, a)
    } else {
        (v, 0)
    }
}

Playground


See also:

Tim Diekmann
  • 5,740
  • 9
  • 30
  • 53
0

In the first snippet, when you type Some(&a), you do not borrow v because a is copied.

In the second case, Some(a) is of type Option<&isize> so it holds a reference to v. When you try to move it, it triggers an error. If you copy it first, and then you return the pair, it works (you need the NLL feature however):

#![feature(nll)]

fn main() {
    println!("{:?}", f(vec![1]))
}

fn f(v: Vec<isize>) -> (Vec<isize>, isize) {
    match v.get(0) {
        Some(a) => {
            let a = *a; // v is no more borrowed
            (v, a)
        },
        _ => (v, 0)
    }
}

Playground

The borrow checker cannot be perfect, so you will often encounter some slightly inconsistent stuff.

Tim Diekmann
  • 5,740
  • 9
  • 30
  • 53
Boiethios
  • 25,767
  • 8
  • 91
  • 135