Nested iteration combined with side-effects don't seem to work very well with Rust iterators. Here is an example:
fn main(){
let v1=vec![1];
let v2=vec![3];
let mut v3=vec![];
v1.iter().map(|x|{
v2.iter().map(|y|{
v3.push(*y);
})
});
}
This results in the following error:
error: captured variable cannot escape `FnMut` closure body
--> src/main.rs:6:5
|
4 | let mut v3=vec![];
| ------ variable defined here
5 | v1.iter().map(|x|{
| - inferred to be a `FnMut` closure
6 | / v2.iter().map(|y|{
7 | | v3.push(*y);
| | -- variable captured here
8 | | })
| |______^ returns a reference to a captured variable which escapes the closure body
I assume the problem has something to do with the laziness of iterators and a conflict between the two closures. What is causing the error? And how do I fix it?
Related
This question already has answers here:
Accessing a method of self inside a thread in Rust
(1 answer)
How can I pass a reference to a stack variable to a thread?
(1 answer)
Closed 6 months ago.
I have a program that has an object oriented struct which has functions in it that use threading (std::thread). In the threads I want to access "self". Unfortunately when I do that, I get this unhelpful error:
error[E0521]: borrowed data escapes outside of associated function
--> src\screens\map\map.rs:170:34
|
67 | &mut self,
| ---------
| |
| `self` is a reference that is only valid in the associated function body
| let's call the lifetime of this reference `'1`
...
170 | let handle = thread::spawn(move || {
| __________________________________^
171 | | let renderbytes = self.cloudslayer.render(
172 | | runtimechunksize as u32,
173 | | runtimechunksize as u32,
... |
179 | | renderbytes
180 | | });
| | ^
| | |
| |______________________`self` escapes the associated function body here
| argument requires that `'1` must outlive `'static`
error[E0382]: borrow of moved value: `self`
--> src\screens\map\map.rs:340:9
|
67 | &mut self,
| --------- move occurs because `self` has type `&mut screens::map::map::Map`, which does not implement the `Copy` trait
...
170 | let handle = thread::spawn(move || {
| ------- value moved into closure here, in previous iteration of loop
...
340 | / self.cachedrenderedchunks
341 | | .retain(|key, _| chunksonscreen.contains(key))
| |__________________________________________________________^ value borrowed here after move
Here is the thread:
let handle = thread::spawn(move || {
let renderbytes = self.cloudslayer.render(
runtimechunksize as u32,
runtimechunksize as u32,
x,
y,
lod,
);
renderbytes
});
I have only been programming in rust for about 3 weeks now, and so I am sure there is some dumb reason why this doesn't work, but any help would be greatly appreciated.
today I tried to write this MusicGuesser with GTK for fun and got this error:
error[E0507]: cannot move out of `guess`, a captured variable in an `Fn` closure
--> src/main.rs:63:32
|
15 | let mut guess = Arc::new(get_guess());
| --------- captured outer variable
16 |
17 | app.connect_activate(move |app| {
| ---------- captured by this `Fn` closure
...
63 | button.connect_clicked(move |_| {
| ^^^^^^^^ move out of `guess` occurs here
64 | let mut guess = Arc::clone(&guess);
| -----
| |
| variable moved due to use in closure
| move occurs because `guess` has type `Arc<Vec<std::string::String>>`, which does not implement the `Copy` trait
I found some same questions about this error, but I didn't understand them. There is source code: https://pastebin.com/1pNxEiB5
let guess = Arc::new(get_guess());
let cloned_guess = Arc::clone(&guess);
// ...
app.connect_activate(move |app| {
// ...
button.connect_clicked(move |_| {
let guess = cloned_guess;
// ...
If you use something in a move || closure, you move it into that closure. That means in your case you move the entire outer guess object in.
So you need to clone first, and then only move the cloned object in.
You will hit the next problem soon, though, because the content of Arc is always immutable. In Rust, you can never have multiple mutable references to the same thing. So in order to modify your guess, you will have to create interior mutability via Mutex or similar.
This Rust code works:
let a = self.stack.pop_or_err()?;
let b = self.stack.pop_or_err()?;
self.stack.push(a * b);
(The ?s are unimportant, just an application detail.)
If i turn it into:
self.stack.push(self.stack.pop_or_err()? * self.stack.pop_or_err()?);
the I see:
error[E0499]: cannot borrow `self.stack` as mutable more than once at a time
--> src/question2.rs:121:33
|
121 | self.stack.push(self.stack.pop_or_err()? + self.stack.pop_or_err()?);
| ----------------^^^^^^^^^^^^^^^^^^^^^^^-----------------------------
| | | |
| | | second mutable borrow occurs here
| | first borrow later used by call
| first mutable borrow occurs here
error[E0499]: cannot borrow `self.stack` as mutable more than once at a time
--> src/question2.rs:121:60
|
121 | self.stack.push(self.stack.pop_or_err()? + self.stack.pop_or_err()?);
| -------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^--
| | | |
| | | second mutable borrow occurs here
| | first borrow later used by call
| first mutable borrow occurs here
Is there a one-line form of calling a method on a mut reference which uses the reference in arguments in the method call?
As #Netwave mentioned, I don't think there's a clean way to do this, but I have the following gibberish which does the trick:
(|x: i32, v: &mut Vec<i32>| v.push(x))(v.pop()? * v.pop()?, &mut v);
Each call to pop takes a mutable reference, but then drops it, so we can do the product in one expression. However, passing the mutable reference to v will hold on to it, so we must pass that to the closure second. This is also why we have to pass &mut v to the closure explicitly rather than capturing it. I believe the reason for using the push method directly not working is that it takes &mut self as the first argument.
I by no means recommend this! But it is possible.
Rust has a method on an enum called .map_or_else() it takes two closures one of which triggers on None, the other triggers on Some(inner) passing inner.
This is great, but what I want to do is move a value into both branches of it. This generates an error,
error[E0382]: borrow of moved value: `result`
--> src/sequence/renderer.rs:124:5
|
104 | let result = match self.display {
| ------ move occurs because `result` has type `String`, which does not implement the `Copy` trait
...
123 | || Ok(result),
| -- ------ variable moved due to use in closure
| |
| value moved into closure here
124 | |v| Ok(format!("{:0>width$}", result.clone(), width=v as usize ))
| ^^^ ------ borrow occurs due to use in closure
| |
| value borrowed here after move)
This error can be be solved by replacing the first closure to .map_or_else with,
Ok(result.clone())
But is this a good idea? Then I have to clone() a string for no benefit? What is the idiomatic way to use .map_or_else() when both sides need access to the same variable?
Unfortunately there is no way for this to work, since Rust has no way of annotating the two closures as "only one will get invoked".
So your best bet is to not use the higher-level function and instead write a simple match expression.
This question already has answers here:
What's the correct way to implement the equivalent of multiple mutable (statically allocated, statically dispatched, etc.) callbacks in Rust?
(1 answer)
How can callbacks with captured mutable variables be treated like normal mutable borrows?
(1 answer)
When I can use either Cell or RefCell, which should I choose?
(3 answers)
Closed 5 years ago.
I'm very new to learning Rust. Here's a condensed and silly code sample which I'm trying to compile:
fn do_something(read: &Fn() -> i32, write: &mut FnMut(i32)) {
if read() == 10 {
write(11);
}
}
fn print_11() {
let mut val = 10;
do_something(&|| val, &mut |n| val = n);
println!("Got {}", val);
}
The write closure borrows val mutably, and the read closure borrows it immutably. The compiler blocks this for this reason:
error[E0502]: cannot borrow `val` as mutable because it is also borrowed as immutable
--> src/main.rs:9:32
|
9 | do_something(&|| val, &mut |n| val = n);
| -- --- ^^^ --- - immutable borrow ends here
| | | | |
| | | | borrow occurs due to use of `val` in closure
| | | mutable borrow occurs here
| | previous borrow occurs due to use of `val` in closure
| immutable borrow occurs here
error[E0502]: cannot borrow `val` as mutable because it is also borrowed as immutable
--> src/main.rs:9:32
|
9 | do_something(&|| val, &mut |n| val = n);
| -- --- ^^^ --- - immutable borrow ends here
| | | | |
| | | | borrow occurs due to use of `val` in closure
| | | mutable borrow occurs here
| | previous borrow occurs due to use of `val` in closure
| immutable borrow occurs here
Is there an idiomatic way to create two closures which can read/write to the same variable? Is this a case for using something like Rc?