use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::HashMap;
struct S {}
struct Foo {
counter: u64,
h: HashMap<u64, S>,
g: HashMap<String, u64>,
}
impl Foo {
fn add_h(&mut self) -> u64 {
self.counter += 1;
let s = S {};
self.h.insert(self.counter, s);
self.counter
}
fn add_g(&mut self, s: String) -> u64 {
match self.g.entry(s) {
Occupied(s) => *s.get(),
Vacant(v) => {
let h = self.add_h();
*v.insert(h)
}
}
}
fn add_g2(&mut self, s: String) -> u64 {
match self.g.entry(s) {
Occupied(s) => *s.get(),
Vacant(v) => {
let h = {
self.counter += 1;
let s = S {};
self.h.insert(self.counter, s);
self.counter
};
*v.insert(h)
}
}
}
}
The method add_g
does not pass the borrow checker. It actually make sense, since I got self
borrowed as mutable (by add_g
) and then I try to borrow it again with add_h
.
I can fix the problem with the method add_g2
, that basically replace the call to add_h
with the body of add_h
itself (I made it explicit with a false scope). I don't like this approach since I am replicating logic that should not be replicated, IMHO.
Are there any pattern to avoid this problem?