Help to fix build error "use of moved value"

I have a build error and no idea how to fix it:

error[E0382]: use of moved value: `commits`
  --> src/main.rs:13:9
   |
13 |         commits.push(n as u8);
   |         ^^^^^^^ value used here after move
...
17 |             verify_proofs(commits, proofs);
   |                           ------- value moved here
   |
   = note: move occurs because `commits` has type `std::vec::Vec<u8>`, which does not implement the `Copy` trait

Please refer to Rust Playground Code here, or the pasted code as following:

fn verify_proofs(commits:Vec<u8>, proofs:Vec<u8>) {
    println!("commits={:02x?}, proofs={:02x?}",
        commits, proofs
    );
}

fn main() {
    let mut commits:Vec<u8> = vec![];
    let mut proofs:Vec<u8> = vec![];
    
    for n in 0..64 {
        commits.push(n as u8);
        proofs.push(n as u8);
        
        if n % 32 == 0 {
            verify_proofs(commits, proofs);
            commits.clear();
            proofs.clear();
        }
    }
}

Could somebody help? Thanks.

1 Like

First things first, the hint it gives you is that you’re missing the ability to copy:

   = note: move occurs because `commits` has type `std::vec::Vec<u8>`, which does not implement the `Copy` trait

The hint in itself is pretty simple, but kind of subtle if you’re coming from languages where it would happen anyway (usually without your express consent). As you’re likely new to Rust, it’s worth mentioning that the Rust compiler is very good at telling you when you’ve made a mistake, and at least partially guiding you. It’s only when you do something unsafe, or uncommon (which includes strange things), that you’ll likely need to dig into it.

What’s happening is that the main function has to copy because you are passing by value. If it implemented Copy, it would automatically copy it into the function (any changes you make in the function are lost). If you step through the changes below you’ll see the issues arise bit by bit.

The solution here is to replace the prototype with a reference (this is a partial update):

fn verify_proofs(commits: &Vec<u8> ...

However, you’ll hit the same problem with the proofs vector (as it’s the same type), so you update again:

fn verify_proofs(commits: &Vec<u8>, proofs: &Vec<u8>)

From there you’ll hit a new issue: you’re not passing by reference, you’re still trying to pass by copy. That’s fine, you need to change your syntax to let it know. Unlike C++, it doesn’t automatically detect it and do it–you have to make this choice explicitly.

verify_proofs(&commits, &proofs);

The full playground code of the updated version is here: https://play.rust-lang.org/?gist=e6c4475885637569ba3de262977803f1&version=stable&mode=debug&edition=2015

The full explanation of what’s happening is in the References and Borrowing section of the Rust book.

To help propel your testing forward, since the values need to be mutable in the other function for changes, you would need to make them &mut Vec<u8> in the prototype, and pass them with &mut commits (or proofs). Things get a bit more interesting down the road, so I’d recommend reading through the book chapter on references and borrowing.

3 Likes

Thanks @aws for your help~ It works :bouquet:

1 Like