1

I'm trying to build a HashMap with vectors as values and I have problems with borrowing / lifetimes.

The task is to find the funniest words in a given text as ranked by the funny_score method. I would like to store a list of words for each distinct score in a HashMap.

I have the following code

use std::collections::HashMap;

fn main() {
    let text = "";
    let mut scores: HashMap<usize, &mut Vec<&str>> = HashMap::new();
    for word in text.split(' ') {
        let funny_score = funny_score(word);
        match scores.get_mut(&funny_score) {
            Some(list) => list.push(word),
            None => {
                let mut list = vec![word];
                scores.insert(funny_score, &mut list);
            }
        }
    }
}

fn funny_score(_: &str) -> usize { 0 }

And the compiler says

error[E0597]: `list` does not live long enough
  --> src/main.rs:12:49
   |
12 |                 scores.insert(funny_score, &mut list);
   |                                                 ^^^^ borrowed value does not live long enough
13 |             }
   |             - `list` dropped here while still borrowed
...
16 | }
   | - borrowed value needs to live until here

error[E0499]: cannot borrow `scores` as mutable more than once at a time
  --> src/main.rs:12:17
   |
8  |         match scores.get_mut(&funny_score) {
   |               ------ first mutable borrow occurs here
...
12 |                 scores.insert(funny_score, &mut list);
   |                 ^^^^^^ second mutable borrow occurs here
13 |             }
14 |         }
   |         - first borrow ends here

How can I make this work?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Matilda Smeds
  • 1,384
  • 11
  • 18
  • Why did you decide to have a value that is a reference (`HashMap<_, &mut _>`)? – Shepmaster Mar 04 '18 at 17:57
  • 1
    [The duplicate applied to your problem](https://play.rust-lang.org/?gist=8b204b876d3cd495f075421fbc0ad985&version=stable). – Shepmaster Mar 04 '18 at 18:02
  • The second duplicate explains the first error, just substitute "return from a function" with "return from the block for my `None` case". – Shepmaster Mar 04 '18 at 18:03
  • Thanks Shepmaster, the example was really helpful. While I was looking at HashMap documentation, I didn't manage to read the relevant method documentation (https://doc.rust-lang.org/std/collections/struct.HashMap.html#method.entry, https://doc.rust-lang.org/std/collections/hash_map/enum.Entry.html#method.or_insert) with enough care. I'm glad HashMap and Entry APIs are actually convenient to use. – Matilda Smeds Mar 05 '18 at 07:22
  • As for why the strange HashMap signature... I made an assumption based on an earlier compiler error, that it was necessary somehow. Sounds silly, but it can happen to new Rustaceans sometimes. – Matilda Smeds Mar 05 '18 at 07:27

0 Answers0