# A problem about mutable borrow twice

I have the following codes(playground):

``````use std::collections::HashMap;

fn get_immut(immut_dict: &HashMap<i32, Vec<i32>>, i: i32) -> &Vec<i32> {
&immut_dict[&i]
}

fn get_mut(mut_dict: &mut HashMap<i32, Vec<i32>>, i: i32) -> &Vec<i32> {
mut_dict.insert(i + 1, vec![i + 1]);
get_immut(mut_dict, i)
}

fn get_immut_twice(mut_dict: &mut HashMap<i32, Vec<i32>>) -> Vec<i32> {
let data1 = get_mut(mut_dict, 1);
let data2 = get_mut(mut_dict, 2);
data1.iter().zip(data2.iter()).map(|(x, y)| x + y).collect()
}
``````

The complie error says that in `get_immut_twice` I mutable borrow the argument `mut_dict` twice.

I understand it in this way:
After I get `let data1 = get_mut(mut_dict, 1)`, as long as `data1` exits, `mut_dict` is being mutable borrowed. If I call `let data2 = get_mut(mut_dict, 2)`, the compile think I may change the existed `data1` by calling the function `get_mut`. So the error happened.

But I know that `data1` would not be changed, what should I do?

This happens when you coerce a `&mut T` to `&T`. The lifetime doesn't change, so it remains uniquely borrowed for the duration of the `&T`.

In this case you might be able to use `get_many_mut` . Or the equivalent method in `hashbrown` if you can't or don't want to use nightly.

1 Like

In general, this sort of thinking is flawed.

This isn't something the compiler can prove statically. It also depends on the internals of hashmap - it would not remain valid if the map had to reallocate, for example.

1 Like

With this particular exact code and API, since the `.insert` can actually invalidate the previously obtained reference to a `HashMap` item (e.g. in case the map is full and needs to re-allocate to grow), there’s really a bug here that needs to be addressed. The straightforward approach would be to decouple the mutation from the lookup, and do both mutations first, then both (immutable) lookups.

1 Like
{"extraction_info": {"found_math": false, "script_math_tex": 0, "script_math_asciimath": 0, "math_annotations": 0, "math_alttext": 0, "mathml": 0, "mathjax_tag": 0, "mathjax_inline_tex": 0, "mathjax_display_tex": 0, "mathjax_asciimath": 0, "img_math": 0, "codecogs_latex": 0, "wp_latex": 0, "mimetex.cgi": 0, "/images/math/codecogs": 0, "mathtex.cgi": 0, "katex": 0, "math-container": 0, "wp-katex-eq": 0, "align": 0, "equation": 0, "x-ck12": 0, "texerror": 0, "math_score": 0.8650864958763123, "perplexity": 4249.598414785175}, "config": {"markdown_headings": true, "markdown_code": true, "boilerplate_config": {"ratio_threshold": 0.18, "absolute_threshold": 10, "end_threshold": 15, "enable": true}, "remove_buttons": true, "remove_image_figures": true, "remove_link_clusters": true, "table_config": {"min_rows": 2, "min_cols": 3, "format": "plain"}, "remove_chinese": true, "remove_edit_buttons": true, "extract_latex": true}, "warc_path": "s3://commoncrawl/crawl-data/CC-MAIN-2023-14/segments/1679296949506.62/warc/CC-MAIN-20230330225648-20230331015648-00398.warc.gz"}