Moving values in an and_modify/or_insert chain

I currently have the following code:

let mut create_new_heap_entry = || {
     //filtered version of the actual function to keep it simple

     //directed_edge_info is moved here
     let edge_info = create_edge_information(directed_edge_info);

    //not very relevant for this question
    let ret = Rc::new(HeapEntry::new(edge_info));
    data.heap.push(Rc::clone(&ret));

    ret
};

//data.distance is of type HashMap<i32, Rc<HeapEntry>>
data.distances.entry(adj_node).and_modify(|e| {
    if some_condition {
        *e = create_new_heap_entry();
    }
}).or_insert_with(create_new_heap_entry);

This gives the following error: closure cannot be moved more than once as it is not Copy due to moving the variable directed_edge_info out of its environment

But if you think about it and_modify will never run together with or_insert so this isn't actually a problem, but I understand that rust only cares about function signatures and doesn't worry about the actual implementations of those functions.

My question is if there is a function of HashMap tha solves this issue ? Or how would I rewrite the map update to solve this?

I think more info is needed about what directed_edge_info is, and how it's used in create_edge_information.

e.g. is it possible to simply .clone() the directed_edge_info and change the line to

let edge_info = create_edge_information(directed_edge_info.clone());

?

or can create_edge_information be changed to take a reference to directed_edge_info?

It might help if you make a minimal reproduction on the rust playground that shows a bit more about all the pieces to get better help (e.g. I threw together this quickly, using a String as the directed_edge_info, which is cloneable Rust Playground)

You might want to simply directly match on the Entry, like this:

match data.distances.entry(adj_node) {
    Entry::Vacant(mut entry) => {
        entry.insert(create_new_heap_entry());
    }
    Entry::Occupied(mut entry) => {
        if some_condition {
            entry.insert(create_new_heap_entry());
        }
    }
}
1 Like

this is a minimal reproding example: Rust Playground