Reputation: 9859
I'm learning Rust, and have implemented some simple code to experiment with closures - but am running up against an issue with the borrow-checker that I'm not sure how to resolve.
When compiling the following function
fn twice(x:int, f:|int| -> int) -> int {
f(f(x))
}
I get the following error
closure requires unique access to `f` but it is already borrowed
I'm working through the guide and have a moderate understanding of why the borrow-checker doesn't like this - but I'm unsure how to resolve it.
I can work around it by assigning the results of the first call to a temporary variable first, and then calling f(..)
again on this. However this feels inelegant.
Is there a cleaner/better way of writing f(f(x))
, or some way to convince the compiler that this is safe?
Upvotes: 1
Views: 551
Reputation: 430663
In modern Rust, the original code compiles as-is:
fn twice(x: i32, f: impl Fn(i32) -> i32) -> i32 {
f(f(x))
}
fn main() {
twice(42, |i| dbg!(i));
}
Upvotes: 0
Reputation: 102066
The full error message is:
<anon>:2:7: 2:8 error: closure requires unique access to `f` but it is already borrowed
<anon>:2 f(f(x))
^
<anon>:2:5: 2:6 note: previous borrow of `f` occurs here; the unique capture prevents subsequent moves or borrows of `f` until the borrow ends
<anon>:2 f(f(x))
^
<anon>:2:12: 2:12 note: previous borrow ends here
<anon>:2 f(f(x))
^
That is, the outer call is, in some sense, reserving f
and preventing it from being used first. This is very similar to issue #6268, which concerns methods instead of closures.
As you say, using a temporary is a fix, and is the most reasonable fix.
fn twice(x:int, f:|int| -> int) -> int {
let y = f(x);
f(y)
}
Upvotes: 3