Vec is not Copy

Why is it that even if I clone the vec I still get the error?

fn get_content_clone(paths_from: &Vec<(String,String,usize)>) -> impl Fn(&mut Cursive) {
    let clone = paths_from.clone();
    move |s| {
        get_cpy_dialog_content(s, clone)
    }
}

I'm getting:

 ^^^^^ move occurs because `clone` has type `Vec<(std::string::String, std::string::String, usize)>`, which does not implement the `Copy` trait

impl Fn() can be called more than one time, but the value clone is consumed on the first call. Try this one instead:

fn get_content_clone(paths_from: &Vec<(String,String,usize)>) -> impl Fn(&mut Cursive) {
    let clone = paths_from.clone();
    move |s| {
        get_cpy_dialog_content(s, clone.clone())
    }
}

Hi and thank you.
Yes, indeed that works, but don't you think that the error message is very misleading?

Can you share the full error message here?

Probably something like

error[E0507]: cannot move out of `clone`, a captured variable in an `Fn` closure
 --> src/lib.rs:7:35
  |
5 |     let clone = paths_from.clone();
  |         ----- captured outer variable
6 |     move |s| {
7 |         get_cpy_dialog_content(s, clone)
  |                                   ^^^^^ move occurs because `clone` has type `Vec<(String, String, usize)>`, which does not implement the `Copy` trait

Yeah I agree so. It can definitely be improved more.

1 Like

E0507’s explanation does mention closure bodies, but there’s definitely room for improvement. The error message itself is pretty fine IMO. I don’t think that it’s necessarily the job of the error message to explain why one “cannot move out of a captured variable in an Fn closure”. That’s just a fact, the error code explanation should handle the rest. A separate error code for moving out of captured variables in non-FnOnce closures could help.

Well, actually ... the error message itself could be rephrased to be more clear about that it’s a fact that “it’s impossible to move out of a captured variable in an Fn closure”. I don’t know, maybe: cannot move out of `clone` because it’s a captured variable in an `Fn` closure.

Next to the options listed in the explanation

  • Try to avoid moving the variable. not possible when calling get_cpy_dialog_content
  • Somehow reclaim the ownership. e.g. with the extra .clone() call
  • Implement the Copy trait on the type. impossible for Vec

there’s also the option of downgrading from Fn to FnOnce, in case you don’t actually need an Fn when calling get_content_clone.

Hi and thanks, how would I need to do it (the downgrade)?

I meant changing the function signature to

fn get_content_clone(paths_from: &Vec<(String,String,usize)>) -> impl FnOnce(&mut Cursive)

maybe that’s not an option for you though; depends on how (and in particular how often) you want to call the function returned from a get_content_clone call.

1 Like

That's actually perfect fit for my scenario. Thanks a lot!

I actually still don't fully understand why it works.
The move keyword
specifies that we move from outside of the closure to the closure, so the closure becomes the owner of those things that were moved into.
If that's correct, the move happens during first call... So the next call don't have anything to move.
Why this works?

There are two categories of moves happening here:

  1. The move of clone into the closure, which happens at creation of the closure.
  2. The move of clone from the closure to the get_cpy_dialog_content function, which happens when calling the closure.

The move keyword is related to the first move.

1 Like

OK, got it, thanks