Bilal Syed Hussain
Bilal Syed Hussain

Reputation: 9214

cannot bind by-move into a pattern guard

How do I fix the problem of cannot bind by-move into a pattern guard [E0008] on s?

let res = match Some("hi".to_string()) {
    Some(s) if s.len() == 0 => 1,
    _ => 3
};

Is there anyway of changing it without putting the condition in the arm?

Upvotes: 22

Views: 5689

Answers (1)

huon
huon

Reputation: 102096

In this case, you can bind by reference:

let res = match Some("hi".to_string()) {
    Some(ref s) if s.len() == 0 => 1,
    _ => 3
};

The general problem here is that binding by move must disallow further uses of the original variable, as moving out invalidates the data. If the guard is false, then the original variable needs to be used to match against the later patterns, which is illegal due to the move.

For example:

fn f(x: Option<String>) {
    match x {
        Some(a) if { drop(a); false } => println!("impossible"),
        Some(b) => println!("whoops, {}", b),
        None => println!("none"),
    }
}

If x is Some, the internal String is moved out and deallocated when deciding if a arm should be taken, but that same String is immediately used again for the b arm once the a arm is rejected.

Upvotes: 34

Related Questions