0

I have a custom Node type and a BTreeSet of these nodes. I would like to remove a node from the BTreeSet, ideally without copying the data. I would like to search the set for the node, return a reference, and call remove on the set with the returned reference. I want to find a node by immutably lending a data structure and then after finding it, remove it by lending the data structure immutably:

use std::collections::BTreeSet;

#[derive(Clone, Debug, Ord, PartialOrd, PartialEq, Eq)]
pub struct Node {
    pub order: i32,
}

pub fn find_node<'a>(set: &'a BTreeSet<Node>, order: &i32) -> Option<&'a Node> {
    for el in set.iter() {
        if *order == el.order {
            return Some(el);
        }
    }
    None
}

fn main() {
    let mut set: BTreeSet<Node> = BTreeSet::new();
    let n1 = Node { order: 1 };
    let n2 = Node { order: 2 };
    let n3 = Node { order: 3 };
    set.insert(n1);
    set.insert(n2);
    set.insert(n3);

    let to_remove: Option<&Node> = match find_node(&set, &2) {
        Some(to_remove) => Some(to_remove),
        None => None,
    };
    match to_remove {
        Some(to_remove) => {
            set.remove(&to_remove);
        }
        None => {}
    }

    println!("Hello, world!");
}

(Rust Playground)

I get an error:

error[E0502]: cannot borrow `set` as mutable because it is also borrowed as immutable
  --> src/main.rs:32:13
   |
26 |     let to_remove: Option<&Node> = match find_node(&set, &2) {
   |                                                     --- immutable borrow occurs here
...
32 |             set.remove(&to_remove);
   |             ^^^ mutable borrow occurs here
...
38 | }
   | - immutable borrow ends here

What's the best way to do this?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Tony
  • 18,776
  • 31
  • 129
  • 193
  • 1
    [A shorter form of your code](https://play.rust-lang.org/?gist=3cd3e2619b70d5a8c6e9aad084a6d6ae&version=nightly&mode=debug&edition=2015) – Shepmaster Jul 11 '18 at 18:10
  • 3
    I believe your question is answered by the answers of [Removing items from BTreeMap found through iteration](https://stackoverflow.com/q/32913368/155423). If you disagree, please [edit] your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Jul 11 '18 at 18:26
  • It might be useful for someone who comes across this to know that `BTreeSet` and `BTreeMap` can use the same methodology. Also the method that worked for me which was implementing the `Borrow` trait is not explicitly noted as a non copying delete. Do you know if that's the case? – Tony Jul 12 '18 at 18:29
  • Using `Borrow` would copy as much data as if you had passed `&Node`, yes. – Shepmaster Jul 12 '18 at 19:23
  • Sorry what I mean is will the entire set be copied under the hood ...as in a new set created, or just the one node? If it behaves the same as if I could have a reference to node then this should be the cheapest way to do it. – Tony Jul 13 '18 at 02:03

0 Answers0