0
votes

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
Please provide the exact error. Also consider removing fields and types that are not relevant to the problem, to create a minimal reproducible example.Peter Hall

1 Answers

1
votes

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);