Не может привязываться путем перемещения в защитный шаблон

Как исправить проблему cannot bind by-move into a pattern guard [E0008] на s?

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

Есть ли способ изменить его, не помещая условие в руку?

Ответ 1

В этом случае вы можете привязывать по ссылке:

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

Общая проблема здесь заключается в том, что привязка с помощью move должна запрещать дальнейшее использование исходной переменной, поскольку перемещение приводит к недействительности данных. Если защита false, тогда исходная переменная должна использоваться для сопоставления с более поздними шаблонами, что является незаконным из-за перемещения.

Например:

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

Если x - Some, внутренний String выведен и освобожден при принятии решения о том, следует ли брать a, но тот же самый String снова используется снова для руки b рычаг a отклоняется.