问题
I have a struct:
pub struct CommunityContents {
pub friends: RefCell<HashMap<FriendID, FriendData>>,
pub index: RefCell<HashMap<u64, BTreeMap<FriendID, FriendData>>>,
pub authenticated: bool,
pub age: u64,
pub height: u64,
}
Which is protected with a RwLock with a parent struct:
pub struct Community {
pub community_contents: RwLock<CommunityContents>,
}
pub struct FriendData {
pointer: Rc<Data>,
}
pub struct Data {
pub key: Key,
pub friend_ids: Vec<FriendID>,
}
I want to be able to modify the data inside index
. I have no problems inserting data into index doing write()
to CommunityContents
and a borrow_mut().insert(…)
for the BtreeMap
inside index
.
My problem is deleting elements from BtreeMap
, given FriendID
. My rough attempt is:
pub fn delete_family(community: &Self, friend_id: FriendID) {
//get community contents
let mut g = community.community_contents.write().expect("Lock is poisoned");
//get friend from inside friends name of community contents
let mut friend = g.friends.borrow_mut().get(&friend_id).unwrap().pointer.clone();
// get id attri
let mut friend_key = friend.key;
let mut a = g.index.borrow_mut().get(&friend_key);
let mut c = a.unwrap();
c.remove(&friend_id);
}
And I get the error cannot borrow as mutable. I've tried various things which has made my code above a bit messy.
Edit: sorry I missed out the FriendData
and Data
structs in my question.
回答1:
After making some guesses about the missing types from your example code, I see two errors:
error[E0716]: temporary value dropped while borrowed
--> src/lib.rs:37:21
|
37 | let mut a = g.index.borrow_mut().get(&friend_key);
| ^^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
38 | let mut c = a.unwrap();
| - borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
error[E0596]: cannot borrow `*c` as mutable, as it is behind a `&` reference
--> src/lib.rs:39:9
|
38 | let mut c = a.unwrap();
| ----- help: consider changing this to be a mutable reference: `&mut std::collections::BTreeMap<u64, FriendData>`
39 | c.remove(&friend_key);
| ^ `c` is a `&` reference, so the data it refers to cannot be borrowed as mutable
The first one can be fixed by following the suggestion - use a new variable to ensure that the temporary value (underlined in the error message) lives long enough:
let mut tmp = g.index.borrow_mut();
let mut a = tmp.get(&friend_key);
Now the borrowed value, tmp
lives right to the end of the function, outliving a
which needs to borrow from it.
The second error and suggestion might be harder to understand. a
is an Option<&BTreeMap>
but after unwrapping it you are trying to mutate it, so that reference needs to be mutable. The Option<&BTreeMap>
comes from the call to get
, so you need to find a way to get a mutable reference instead. you can do that with a different method, get_mut
, which will return the Option<&mut BTreeMap>
that you need:
let mut tmp = g.index.borrow_mut();
let mut a = tmp.get_mut(&friend_key);
来源:https://stackoverflow.com/questions/57350068/how-to-delete-item-from-hashmap-inside-a-refcell-within-an-rwlock-ed-struct