Amusingly, the functional approach with Iterator::fold
seems more amicable for the borrow checker:
fn add_string(&mut self, string: String, val: i32) {
let mut last_node = string.chars().fold(&mut self.root, |current_node, c| {
current_node.chars.entry(c).or_insert(Node {
chars: HashMap::new(),
val: -1,
})
});
last_node.val = val;
}