fn find<'a>(acc: &str, parents: &'a HashMap<&str, &str>) -> &'a str {
let parent = parents.get(acc).unwrap();
if *parent == acc {
*parent
} else {
find(parent, parents)
}
}
main() {
let accts: Vec<Vec<String>> = vec![]; // some data
let mut parents = HashMap::<&str, &str>::new();
for ac_list in &accts {
for email in &ac_list[1..] {
let p = find(email, &parents);
let p2 = find(&ac_list[1], &parents);
parents.insert(p, p2); // cannot borrow `parents` as mutable because it is also borrowed as immutable
}
}
}
I thought the immutable borrowing &parents
are temporary references, so the mutable borrowing should pass. Is my understanding somehow wrong?
They are not temporary references, they live until they're dropped. And they can't be dropped before insert
takes place, since they're arguments to it.
I don't understand why &parents
references live until the .insert call. Shouldn't they be dropped when find
calls are finished?
&parents
is not the problem.
As stated in find
's signature the returned value borrows from parents
which means parents
is immuatble borrowed at least as long as the returned value is not droped.
Therefore, parents
is still borrowed by p
and p2
when you want to insert them. So mutable borrow of parents
is not allowed.
3 Likes
Change
fn find<'a>(acc: &str, parents: &'a HashMap<&str, &str>) -> &'a str {
(where the lifetime parameters are saying that your returned str
reference is borrowing from the HashMap
)
to
fn find<'a>(acc: &str, parents: &HashMap<&str, &'a str>) -> &'a str {
(where the lifetime parameters are saying that your returned str
reference is "equivalent" (in your code, a copy) to the values of your HashMap
, which may match your intuition).
5 Likes
This is extremely helpful !
1 Like