How to work around self borrowing with map .or_insert_with? Rust (1.11)
dictionary, rust
Solution
The problem is that the closure captures `self`, whereas it only needs to capture a mutable reference to the `last_id` field.
Rust allows us to take independent mutable borrows on distinct fields, so we can use that to our advantage and pass a mutable reference to the `last_id` field to the closure.
use std::collections::HashMap;
struct Foo {
local_ids: HashMap<i32, i32>,
last_id: i32,
}
impl Foo {
fn foo(&mut self, external_id: i32) {
let last_id = &mut self.last_id;
let id = self.local_ids
.entry(external_id)
.or_insert_with(|| { *last_id += 1; *last_id });
}
}
When we use the expression `self.last_id` in the closure, the closure captures `self` directly, but Rust doesn't realize that the borrows are independent, so we need to be more explicit.
Problem
This snippet ``` use std::collections::HashMap; struct Foo { local_ids: HashMap<i32, i32>, last_id: i32, } impl Foo { fn foo(&mut self, external_id: i32) { let id = self.local_ids .entry(external_id) .or_insert_with(||{self.last_id += 1; self.last_id}); } } ``` Doesn't work because we can't borrow self twice ``` error: closure requires unique access to `self` but `self.local_ids` is already borrowed [E0500] ``` Is this possible to fix without a second key lookup? This is very similar to Rust: HashMap borrow issue when trying to implement find or insert, but the API has changed substantially. The find_with_or_insert_with answer from above doesn't appear to map to the current api.