1

I'd like to mutably borrow a hash map on every iteration of a loop.

I have the following hash map, function, and loop:

use std::collections::HashMap;

fn func<'a>(hash_map: &'a mut HashMap<&'a str, String>) {
    unimplimented!();
}

fn loop() {
    let mut hash_map = HashMap::new();

    let mut i = 0;
    while i < 10 {
        func(&mut hash_map);
        i += 1;
    }
}

This will produce the following error on the func(&mut hash_map); line:

cannot borrow `hash_map` as mutable more than once at a time

`hash_map` was mutably borrowed here in the previous iteration of the looprustc(E0499)

main.rs(62, 25): `hash_map` was mutably borrowed here in the previous iteration of the loop

How can I refactor this to be able to mutably borrow the hash map on every iteration of the loop?

I believe I understand Rust's ownership rules enough to understand why this error is happening, just not well enough to fix it.

Note: I know there are better ways to write a loop in Rust, just wanted a very simple loop for this example.

Cerberus
  • 8,879
  • 1
  • 25
  • 40
Nick
  • 5,108
  • 2
  • 25
  • 58
  • 1
    Please show the signature of `func`, there's nothing inherently wrong with what you're doing here. Provide a minimal reproducible example. – kmdreko Jun 13 '22 at 17:19
  • Updated. Thanks for pointing out to look at the function definition. Realized I was using an unneeded lifetime and that was causing the issue. – Nick Jun 13 '22 at 17:28
  • 2
    In general, `&'a mut T<'a>` is a red flag, since it almost always unusable. Maybe someone will make this into proper answer (or I'll do it myself tomorrow), since the error is quite common and deserves good description. – Cerberus Jun 13 '22 at 17:50

1 Answers1

1

Looks like I was using an unneeded lifetime in the function argument type definition. Instead of hash_map: &'a mut HashMap<&'a str, String>, I could just use hash_map: &mut HashMap<&'a str, String>.

The following code works for me.

use std::collections::HashMap;
use external::func;

fn func<'a>(hash_map: &mut HashMap<&'a str, String>) {
    unimplimented!();
}

fn loop() {
    let mut hash_map = HashMap::new();

    let mut i = 0;
    while i < 10 {
        func(&mut hash_map);
        i += 1;
    }
}
Nick
  • 5,108
  • 2
  • 25
  • 58
  • `&'a str` is an unusual key type for a `HashMap`; Usually it's either `&'static str` or `String`. But if that's needed in your case, sure :) Just wanted to point out that this might be a mistake. – Finomnis Jun 13 '22 at 18:18
  • Oh yeah, it was completely a mistake in this case. But good to know that it's unusual typing for a `HashMap` in general! – Nick Jun 13 '22 at 18:36
  • @Finomnis I think the best replacement for `&'a str` would be `Rc`, since it combines being a reference while still not being `'static`. – jthulhu Jun 13 '22 at 19:54