1

I am modifiying a crate (rust-argon2) to some custom needs. That crate uses multithreading with scoped threads using crossbeam. I want to have a mutable state between threads, that may depend on each other.

The following snippet showcases the situation: fill_memory_blocks_mt gets some mutable state reference state, that will be mutated in fill_segment across multiple threads using crossbeam_utils::thread::scope. They are synced via common::SYNC_POINTS.

fn fill_memory_blocks_mt(context: &Context, memory: &mut Memory, state: &mut Argon2Result) {
    for p in 0..context.config.time_cost {
        for s in 0..common::SYNC_POINTS {
            let _ = scope(|scoped| {
                for (l, mem) in (0..context.config.lanes).zip(memory.as_lanes_mut()) {
                    let position = Position {
                        pass: p,
                        lane: l,
                        slice: s,
                        index: 0,
                    };
                    scoped.spawn(move |_| {
                        fill_segment(context, &position, mem, state);
                    });
                }
            });
        }
    }
}

The compiler outputs following message:

error[E0382]: use of moved value: `state`
   --> src/core.rs:223:34
    |
223 |                     scoped.spawn(move |_| {
    |                                  ^^^^^^^^ value moved into closure here, in previous iteration of loop
224 |                         fill_segment(context, &position, mem, state);
    |                                                               ----- use occurs due to use in closure
    |
    = note: move occurs because `state` has type `&mut Argon2Result`, which does not implement the `Copy` trait
help: consider creating a fresh reborrow of `state` here
    |
223 |                     scoped.spawn(&mut *move |_| {
    |                                  ++++++

error[E0382]: use of moved value: `state`
   --> src/core.rs:215:27
    |
212 | fn fill_memory_blocks_mt(context: &Context, memory: &mut Memory, state: &mut Argon2Result) {
    |                                                                  ----- move occurs because `state` has type `&mut Argon2Result`, which does not implement the `Copy` trait
...
215 |             let _ = scope(|scoped| {
    |                           ^^^^^^^^ value moved into closure here, in previous iteration of loop
...
224 |                         fill_segment(context, &position, mem, state);
    |                                                               ----- use occurs due to use in closure
    |
help: consider creating a fresh reborrow of `state` here
    |
215 |             let _ = scope(&mut *|scoped| {
    |                           ++++++

For more information about this error, try `rustc --explain E0382`.
error: could not compile `rust-argon2-wasm` due to 2 previous errors

Of course I don't want to copy state but use one instance for all threads. They don't overwrite fields between each other, but may depend on each other.

prohit
  • 609
  • 1
  • 6
  • 18
  • 1
    Please post the full error message from `cargo check`, not your IDE. – Chayim Friedman Aug 28 '22 at 08:57
  • There's no `async` in the code you posted. Also, the compiler's suggestion looks like a bug, you can file a bug report. – Chayim Friedman Aug 28 '22 at 09:19
  • If I change spawn to be `async`, I'm getting the following output. `scoped.spawn(|_| async move { fill_segment(context, &position, mem, state); }); ` – prohit Aug 28 '22 at 09:34
  • `error[E0631]: type mismatch in closure arguments | 217 | let _ = scope(|scoped: Scope| { | ^^^^^ --------------- found signature of `for<'r> fn(crossbeam_utils::thread::Scope<'r>) -> _` | | | expected signature of `for<'r> fn(&'r crossbeam_utils::thread::Scope<'_>) -> _` | note: required by a bound in `crossbeam_utils::thread::scope` | 151 | F: FnOnce(&Scope<'env>) -> R, | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `scope` ` – prohit Aug 28 '22 at 09:37
  • But in the compiler error there is `async`, I don't understand. – Chayim Friedman Aug 28 '22 at 20:28
  • Sorry for the confusions, some attempts got mixed up there on my end. I corrected the compiler output in the question now. – prohit Aug 29 '22 at 16:40

0 Answers0