HashMap issue when trying to implement search or insert

I tried to implement my own analogue of the method find_or_insert, which looks like this:

use std::collections::HashMap;

pub struct SomeManager {
    next: i32,
    types: HashMap<i32, i32>,
}

impl SomeManager {
    pub fn get_type<'a>(&'a mut self, k: i32) -> &'a i32 {
        match self.types.get(&k) {
            Some(ref x) => return *x,
            None => {
                self.types.insert(k, self.next);
                self.next += 1;
                return self.types.get(&k).unwrap();
            }
        }
    }
}

fn main() {}

Error:

error[E0502]: cannot borrow `self.types` as mutable because it is also borrowed as immutable
  --> src/main.rs:13:17
   |
10 |         match self.types.get(&k) {
   |               ---------- immutable borrow occurs here
...
13 |                 self.types.insert(k, self.next);
   |                 ^^^^^^^^^^ mutable borrow occurs here
...
18 |     }
   |     - immutable borrow ends here

I know that there are some standard methods that implement this functionality, but I want this method to be as easy as possible - it will be called very often and almost always when the values ​​already exist.

As I understand it, when we call self.types.get, we borrow it into the scope of the match , so we cannot call self.types.inserthere. I tried to move methods from the None branch from the match statement , but also does not work.

The only working solution I found requires twice get:

pub fn get_type<'a>(&'a mut self, k: i32) -> &'a i32 {
    let is_none = match self.types.get(&k) {
        Some(ref x) => false,
        None => true,
    };
    if is_none {
        self.types.insert(k, self.next);
        self.next += 1;
    }
    self.types.get(&k).unwrap()
}

How can I get around such situations?

+2
2

HashMap . , HashMap::entry Entry::or_insert_with:

pub fn get_type<'a>(&'a mut self, k: i32) -> &'a i32 {
    self.types.entry(k).or_insert_with(|| {
        let value = self.next;
        self.next += 1;
        value
    })
}

, , theres self , .

, self.next , self.types. , .

pub fn get_type<'a>(&'a mut self, k: i32) -> &'a i32 {
    let next = &mut self.next;

    self.types.entry(k).or_insert_with(|| {
        let value = *next;
        *next += 1;
        value
    })
}
+5

, , , , . . :

pub fn get_type<'a>(&'a mut self, k: i32) -> &'a i32 {
    let contains = self.types.contains_key(&k);
    if !contains {
        self.types.insert(k, self.next);
        self.next += 1;
    }
    self.types.get(&k).unwrap()
}

, - - .

(, ) .

+1

Source: https://habr.com/ru/post/1658637/