Ошибка: использование перемещенного значения, хотя его нельзя использовать

Рассмотрим следующий код:

fn print_or(opt: Option<()>, tail: Vec<i32>) -> Vec<i32> {
    opt.map_or(tail, |_| {
        println!("{:?}", tail);
        tail
    })
}

Детская площадка

В сообщении об ошибке говорится, что:

error[E0382]: use of moved value: `tail`
 --> src/lib.rs:2:22
  |
1 | fn print_or(opt: Option<()>, tail: Vec<i32>) -> Vec<i32> {
  |                              ---- move occurs because `tail` has type `Vec<i32>`, which does not implement the `Copy` trait
2 |     opt.map_or(tail, |_| {
  |                ----  ^^^ value used here after move
  |                |
  |                value moved here
3 |         println!("{:?}", tail);
4 |         tail
  |         ---- use occurs due to use in closure
  |
help: consider cloning the value if the performance cost is acceptable
  |
2 |     opt.map_or(tail.clone(), |_| {
  |                    ++++++++

И это понятно, поскольку я использую здесь собственный шрифт Vec<i32>. Но проблема в том, что совершенно очевидно, что его нельзя использовать после перемещения, поскольку Option не может быть Some и None одновременно. Есть ли способ решить проблему без clone или Rc?

Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
1
0
68
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете встроить Option::map_or, чтобы помочь компилятору понять, что он должен перемещаться tail в каждую ветку условно.

fn print_or(opt: Option<()>, tail: Vec<i32>) -> Vec<i32> {
    match opt {
        Some(()) => {
            println!("{:?}", tail);
            tail
        }
        None => tail,
    }
}
Ответ принят как подходящий

В Rust на самом деле нет способа сказать, что будет использоваться только один аргумент функции, но он знает, что будет выполняться только одна ветвь оператора потока управления, поэтому вы можете использовать match:

match opt {
    None => tail,
    Some(()) => {
        println!("{:?}", tail);
        tail
    }
}

Аналогично вы можете использовать if let:

if let Some(()) = opt {
    println!("{:?}", tail);
    tail
} else {
    tail
}

И в этом случае вы можете просто проверить, является ли optSome, поскольку обе ветви заканчиваются одним и тем же:

if opt.is_some() {
    println!("{:?}", tail);
}
tail

Другие вопросы по теме