The following code can compile:
use std::collections::HashMap;
struct MutAndImmut(HashMap<&'static str, Vec<i32>>, HashMap<&'static str, Vec<i32>>);
fn compute_inner_index(data: &mut MutAndImmut) -> &Vec<i32> {
if !data.1.contains_key("c") {
data.1.insert("c", vec![]);
};
let a_value = &data.0["a"];
let b_value = &data.0["b"];
let c_value = data.1.get_mut("c").unwrap();
if c_value.len() < a_value.len() {
for i in c_value.len() .. a_value.len() {
c_value.push(a_value[i] + b_value[i]);
}
};
c_value
}
The computing logic is to comput data.1["c"]
with using data.0["a"], data.0["b"]
. So it is using immutable reference &data.0["a"], &data.0["b"]
and mutable reference data.1["c"]
at the same time. But somehow the compiler allow this to pass in this situation.
But the following code can not compile:
fn compute_outer_index(data: &mut MutAndImmut) -> &Vec<i32> {
if !data.1.contains_key("c") {
data.1.insert("c", vec![]);
};
let a_value = get_data_imm(data, "a");
let b_value = get_data_imm(data, "b");
let c_value = get_data_mut(data);
if c_value.len() < a_value.len() {
for i in c_value.len() .. a_value.len() {
c_value.push(a_value[i] + b_value[i]);
}
};
c_value
}
fn get_data_mut(data: &mut MutAndImmut) -> &mut Vec<i32> {
data.1.get_mut("c").unwrap()
}
fn get_data_imm<'a>(data: &'a MutAndImmut, s: &'static str) -> &'a Vec<i32> {
&data.0[s]
}
It seems because that the indexing comes from out function get_data_imm
rather than &data.0["a"]
, although the accual operation is the same.
So, if I need the style of the second functon compute_outer_index
, how can I do it in a better way? Do I need to using unsafe
block? If I am assure that get_data_mut(data)
won't influence the immutablly borrowed data a_value
and b_value
, is it the best way to get that to using unsafe
block?