1

Consider the following code:

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

Playground

The error message says that:

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(), |_| {
  |                    ++++++++

And it's clear since I use owned Vec<i32> type here. But the problem is that it's pretty obvious that it cannot be used after move since Option cannot be Some and None at the same time. Is there a way to overcome the problem without clone or Rc?

0

2 Answers 2

6

Rust doesn't really have a way to say that only one argument of a function will be used, but it does know that only one branch of a control flow statement will run, so you can use match:

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

Similarly, you can use if let:

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

And in this case, you can just check if opt is Some since both branches end in the same thing:

if opt.is_some() {
    println!("{:?}", tail);
}
tail
Sign up to request clarification or add additional context in comments.

Comments

1

You can inline Option::map_or to help compiler understand that it should move tail to each branch conditionally.

fn print_or(opt: Option<()>, tail: Vec<i32>) -> Vec<i32> {
    match opt {
        Some(()) => {
            println!("{:?}", tail);
            tail
        }
        None => tail,
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.