I have seen this error in other examples and it being solved by setting a local variable or referencing it. In this case I am inside a for each loop and neither worked.
I am using the mustache library and thought I would try the Map Builder. All of the examples seem to be hardcoded values and all setup in a single line.
variable moved due to use in closure
cannot move out of `data`, a captured variable in an `FnMut` closure
move occurs because `data` has type `MapBuilder`, which does not implement the `Copy` trait
You should ask your IDE, or cargo on the terminal, to give you the complete error message, and then share that instead of those snippets.
Also make sure to mention all relevant dependencies used here (as long as they are public), to spare us some detective work if someone wanted to reproduce the issue.
MapBuilder::insert_str takes the builder (self) by value.
So calling this method from the closure passed to foreach requires that this closure to capture data by value.
I see… insert_str is a sort of Self -> Self method. In order to call that in an FnMut context, you can wrap the value in an Option and use Option::take.
pub fn wrapper(template: String, params: RHash) -> Result<String, Error> {
- let data = MapBuilder::new();
+ let mut data = Some(MapBuilder::new());
params.foreach(|key: Symbol, value: Value| {
- data.insert_str(key.to_string(), value.to_string());
+ data = Some(data.take().unwrap().insert_str(key.to_string(), value.to_string()));
return Ok(ForEach::Continue);
})?;
- return renderer::render(template, data.build())
+ return renderer::render(template, data.unwrap().build())
.map_err(|e| Error::new(runtime_error(), e.to_string()));
}
There are a lot of suggestions on this. This worked. Thank you for this as I wouldn't have worked out to wrap with "some". I tried the mut but that didn't work on it's own. All of it together allows the Map Builder to be used.
No, that won’t work in an FnMut; you cannot move out of the variable data there, which is captured by mutable reference; this does not work even if you’re intending to move back in a new value later. (This restriction exists for sound handling of panics.) The only thing you can do is put back a new value immediately, e.g. with std::mem::replace.
I confirmed that since I wasn't sure myself. I also looked for a way to get an iterator from RHash, but there is no way. If there were, fold could be used or a regular for loop.
Although you can get a HashMap or a Vec as @drewtato suggested.
I just look at the source for RHash and the iteration is done though FFI so a normal Rust iterator is impossible. A fold is possible but would just be sugar on @steffahnOption version or an unsafe version of it. Also it's using an extern "C" to wrap the closure so panics inside are either UB or an abort depending on the version of the compiler.