Search code examples
rustborrow-checker

How to correctly re-arrange the code to bypass Rust borrow checker?


The code:

use std::collections::HashMap;

fn do_something<'a>(map: &'a mut HashMap<u32, Box<u32>>, key: &u32) -> &'a mut u32 {
    if let Some(b) = map.get_mut(key) { return b.as_mut(); }

    let mut b = Box::new(123);
    map.insert(*key, b);

    b.as_mut()
}

I have 2 major compiler errors (3rd isn't the case):

  • The error with borrowing the map
  • The error with not implementing the Copy trait

I extracted this peace of code from my algorithm, means are the same. Some kind of "translated" code in other languages with GC would compile and run perfectly, but here I'm getting the errors. I understand why these errors occur, but I need my code to work that way: during the iteration I store the node in the map, and use it as the current value in the next iteration. I'm really wondering how to make this code working without some other stuff like Rc.


Solution

  • This is a known limitation in the current borrow checker. Polonius should accept this code, whenever it lands (estimates right now are sometime in 2024).

    However, the entry-based API is the correct approach anyway. It expresses the same operation much more succinctly, and is accepted by the current borrow checker:

    fn do_something<'a>(map: &'a mut HashMap<u32, Box<u32>>, key: &u32) -> &'a mut u32 {
        map.entry(*key).or_insert_with(|| Box::new(123)).as_mut()
    }
    

    (Playground)