Creates a temporary value which is freed while still in use in HashMap

Hi!

I'm trying to read the content of a file and count the occurrence of each words.

When I do

    let reader = BufReader::new(my_file);

    // Go through every word and create a HashMap with the number of occurrence for each words
    for line in reader.lines() {
        println!("Line: {:?}", line);
        for word in line.unwrap().split_whitespace() {
            println!("Word: {:?}", &word);
        } 
    }

I get :

Line: Ok("one one one two three two")
Word: "one"
Word: "one"
Word: "one"
Word: "two"
Word: "three"
Word: "two"
Line: Ok("one one one two three two")
Word: "one"
Word: "one"
Word: "one"
Word: "two"
Word: "three"
Word: "two"

Which is correct, my test file has 2 lines are are identical.

When I try to use word as the key for my HashMap as such :

    let reader = BufReader::new(my_file);

    // Go through every word and create a HashMap with the number of occurence for each words
    for line in reader.lines() {
        //println!("Line: {:?}", line);
        for word in line.unwrap().split_whitespace() {
            let item: &mut i128 = all_words.entry(&word).or_insert(0);
            *item += 1;
        } 
    }

I get the following error :

   |
42 |         for word in line.unwrap().split_whitespace() {
   |                     ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
...
45 |             let item: &mut i128 = all_words.entry(&word).or_insert(0);
   |                                   --------- borrow later used here
...
48 |         } 
   |         - temporary value is freed at the end of this statement
   |
   = note: consider using a `let` binding to create a longer lived value

I tried cloning word to key and using that instead but I get the same error.

For more reference:

cat a.txt 
one one one two three two
one one one two three two

So I'm expecting my HashMap to be
"one", 6
"two", 4
"three", 2

Everything is in the main function for now to make it even easier.

I'm pretty new to Rust (and programming in general) so sorry if this is obvious. I tried to look at other posts here with the same error but none gave an answer that worked for my code.

Thank you.

The variable line is scoped to the body of the outer loop (ie., an individual iteration) and word borrows from it. Even if that weren't the case, you would still be trying to store a reference to word in the map which has a larger scope, which is (also) obviously wrong.

Why are you doing all this dance with references? It seems completely unnecessary; you should be working with (owned) values most of the time. Just copy the part of the string that you need as a hash map key.

This compiles.

2 Likes

Thanks for your reply.

To answer your question about the dance: Because I though/that's how I understood HashMap worked.

Using your code I saw that the way I created my HashMap was also wrong/using the wrong type.

Now the code works!

Thank you!

I'm curious why?

From the (online) class I took.

But there was no example of using HashMap with variables, just a few example where the teacher "hard coded" the value and changed the value.

As stated in my original message, I'm very very new to Rust and programming in general :slight_smile:

This is actually part of the program I'm trying to built as the last stage of that class. There's no grade/diploma, I'm doing it purely for fun and to try to learn something new that could be useful in my future day job.

If you are not sure how a given type/trait/function works, you should first and foremost look at its documentation in the reference, and/or find examples in the Book.

Unfortunately, a lot of unofficial material you can find online is garbage. I'm pretty sure the typical use case for hash maps is not hard-coded keys, so any non-toy example should at least show something where the content is actually dynamic.