Selva
Selva

Reputation: 1151

I have a struct, a part of which is mutably borrowed. How can I avoid multiple borrow errors when trying to borrow it again?

I have a big function and it is seemingly difficult to implement in Rust. I am having trouble with Borrow checker and I searched StackOverflow and Google but not able to find an answer. This might be a duplicate but no solution worked for me

use std::collections::HashMap;

fn add(my: &mut MyStruct) {
    let count = my.count.entry("Test".to_string()).or_insert(1.0);
    let value = get_custom_val(my, 5.0);
    my.final_count = *count / value;
    *count = 5.0;
}

fn get_custom_val(my: &MyStruct, offset: f32) -> f32 {
    return my.val + offset;
}

struct MyStruct {
    count: HashMap<String,f32>,
    val: f32,
    final_count: f32
}

fn main() {
    let mut my = MyStruct {count: HashMap::new(), val: 1.0, final_count: 5.0};
    my.count.insert("Test".to_string(), 5.0);
    add(&mut my);
}

This is a very simple code here. But MyStruct in real has lot of HashMaps which has entry around 1000 elements. So I want to things more optimised.

With this error I get,

cannot borrow *my as immutable because it is also borrowed as mutable

It looks like a very basic manupulation and I am not able to achieve. I have been learning Rust for over a week and not able to quite understand this borrow :(

Can someone help me?

Some ideas were to add {} in let value... but that doesn't serve me because I need the value in next line.

Also, when I tried different thing (like changing get_custom_val to have &mut, I get below error

cannot borrow *my as mutable more than once at a time

Upvotes: 0

Views: 1257

Answers (1)

Aplet123
Aplet123

Reputation: 35560

Your add function should be (note how the first two lines are swapped):

fn add(my: &mut MyStruct) {
    let value = get_custom_val(my, 5.0);
    let count = my.count.entry("Test".to_string()).or_insert(1.0);
    my.final_count = *count / value;
    *count = 5.0;
}

Let's see why your old function errors:

fn add(my: &mut MyStruct) {
    // you get an Entry for the hashmap which requires a mutable reference to it
    let count = my.count.entry("Test".to_string()).or_insert(1.0);
    // the mutable reference is still there for the entry
    // but this function requires an immutable reference
    let value = get_custom_val(my, 5.0);
    // the error is thrown on this line because you try to use that mutable reference
    my.final_count = *count / value;
    *count = 5.0;
}

Upvotes: 3

Related Questions