Issue
Here's the example
fn call_with_f<F>(f:F) where F: FnOnce(){
f();
}
struct Vec2{
x:i32,
y:i32
}
impl Vec2{
fn new(x:i32, y:i32) -> Self{
Self{
x,
y
}
}
fn x(&self) -> &i32{
&self.x
}
}
fn main() {
let v = Vec2::new(1,2);
let rx = v.x();
call_with_f(move||{
println!("{}", v.x());
println!("{}", rx);
});
}
The compiler gives
error[E0505]: cannot move out of `v` because it is borrowed
--> src\main.rs:88:14
|
87 | let rx = v.x();
| - borrow of `v` occurs here
88 | call_with_f(move||{
| ^^^^^^ move out of `v` occurs here
89 | println!("{}", v.x());
| - move occurs due to use in closure
90 | println!("{}", rx);
| -- borrow later captured here by closure
I know the complaint of compiler, but this case is necessary sometime. In a very complicated
circumstance, a bunch of work need to be done before given into the closure, a reference as an intermediate varible could simplify the preparation. v
and rv
have same lifetime at the beginning, they also remain the same lifetime after moved according to the semantics of the move closure. Why?
Solution
You cannot move a borrowed value. Period.
Moreover, such closure cannot exist (safely): it needs to store both the owned value and a reference to (part of) it, i.e. it is self-referential. See Lifetime of references in closures.
Depending on your use case, there may be various solutions, ordered from the best to the worst:
- Create the reference inside the closure.
- Don't move the owned value. One of the common reasons people have your question is because they need a
'static
closure for threads. If this is the case, you may find scoped threads helpful. - Use a crate such as
owning_ref
(unsound!) orourboros
(no known sound holes IIRC) to create the self-referential closure. You may need to desugar the closure manually (partially, at least). - Use
unsafe
code for creating the self referential closure. WARNING: Do Not Do That Unless You Really Know What You're Doing.
Answered By - Chayim Friedman Answer Checked By - Mary Flores (PHPFixing Volunteer)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.