Why does the following code snippet does not compile?

I have scenario which I have distilled into a simplified code shown below.

enum A {
    A1,
    A2,
}

fn main() {
    println!("A1: {}", eval(A::A1));
    println!("A2: {}", eval(A::A2));
}

fn eval(a:A) -> String {
    let consumable = "x".to_string();
    let left = match a {
        A::A1 => {
            Some(consumable)
        },
        A::A2 => None,
    };
    let right = match left {
        Some(d) => d,
        None => {
            format!("Not {}", consumable)
        }
    };
    right
}

(Playground link - Rust Playground )

The above code fails to compile with error.

15 |             Some(consumable)
   |                  ---------- value moved here
...
22 |             format!("Not {}", consumable)
   |                               ^^^^^^^^^^ value borrowed here after move

To my eyes, for format!("Not {}", consumable) to run left needs to be None, and if it is None then consumable was never moved. What am I missing here?

Moves/borrowing don't look at any values, only scopes. The first match may have moved it, and that's all that counts.

You can put consumable in Option and use option.take(). Or you can try nesting the matches.

1 Like