I'm new to Rust and trying to understand how to properly handle the following borrow checker "problem":
I have a struct containing some fields, and I would like some of the fields to be constant over the lifetime of the object (const in C++). This way, I could borrow &mut self while also holding an immutable reference to the const field.
Here is a minimal example:
use std::collections::HashMap;
struct Process {
const_data: HashMap<String, i32>, // this is supposed to never be changed after construction!
mut_data: i32, // this is supposed to be mutated during object lifetime
}
impl Process {
fn do_more(&mut self, num: &i32) {
self.mut_data += num;
}
fn do_somethig(&mut self, name: &str) {
let num = self.const_data.get(name).unwrap(); // reference to part of self.const_data
self.do_more(num); // borrowing &mut self
}
}
fn main() {
let mut p = Process { const_data: HashMap::from([
("foo".to_string(), 1),
("bar".to_string(), 2),
("buzz".to_string(), 3),
]), mut_data: 0 };
p.do_somethig("foo");
}
It fails to compile with the error message
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
--> src/main.rs:16:9
|
15 | let num = self.const_data.get(name).unwrap();
| ------------------------- immutable borrow occurs here
16 | self.do_more(num);
| ^^^^^-------^^^^^
| | |
| | immutable borrow later used by call
| mutable borrow occurs here
Is there a way to mark Process::const_data as immutable, such that the borrow checker knows that its not contradicting the "one mutable reference" principle?
PS: In the example above we could make Process::do_more() take num by value and not by reference, however, in my actual project const_data would contain a complex struct which should not be copied or moved.