1

I can't figure out a way to hold elements inside a HashMap and edit them at the same time:

use std::collections::HashMap;

#[derive(Clone, Debug)]
pub struct Alliance {
    pub name: String,
    pub id: u32,
}

fn main() {
    let mut hashmap = HashMap::new();

    let mut alliance1 = Alliance {
        name: "alliance_1".to_string(),
        id: 1,
    };

    let mut alliance2 = Alliance {
        name: "alliance_2".to_string(),
        id: 2,
    };

    // Do I really need to clone the name strings here?
    let mut entry1 = hashmap.entry(alliance1.name.clone()).or_insert(alliance1);
    let mut entry2 = hashmap.entry(alliance2.name.clone()).or_insert(alliance2);

    swapNames(entry1, entry2);

    println!("{}", entry1.name);
    println!("{}", entry2.name);
}

fn swapNames(entry1: &mut Alliance, entry2: &mut Alliance) {
    let aux = entry1.name.clone();
    entry1.name = entry2.name.clone();
    entry2.name = aux;
}

playground

I get an error which I agree with:

error[E0499]: cannot borrow `hashmap` as mutable more than once at a time
  --> src/main.rs:24:22
   |
23 |     let mut entry1 = hashmap.entry(alliance1.name.clone()).or_insert(alliance1);
   |                      ------- first mutable borrow occurs here
24 |     let mut entry2 = hashmap.entry(alliance2.name.clone()).or_insert(alliance2);
   |                      ^^^^^^^ second mutable borrow occurs here
...
30 | }
   | - first borrow ends here

I just don't know how to code this in a way that compiles. I need to keep the Alliance structs mutable to further edit them down in the code (the swapNames function is just an example).

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Daniel Sorichetti
  • 1,921
  • 1
  • 20
  • 34
  • Idiomatic Rust uses `snake_case` for variables, methods, macros, and fields; `UpperCamelCase` for types; and `SCREAMING_SNAKE_CASE` for statics and constants. Use `swap_names` instead, please. – Shepmaster Nov 04 '18 at 23:13
  • I believe your question is answered by the answers of [Borrow two mutable values from the same HashMap](https://stackoverflow.com/q/47773849/155423). If you disagree, please [edit] your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Nov 04 '18 at 23:16
  • Thanks for the comments. I'll update my question as soon as I can. – Daniel Sorichetti Nov 04 '18 at 23:40
  • And to address the cloning-related comments: [How can I swap in a new value for a field in a mutable reference to a structure?](https://stackoverflow.com/q/27098694/155423); [How to use a struct members as its own 'key' when inserting the struct into a map without duplicating it?](https://stackoverflow.com/q/41035869/155423) – Shepmaster Nov 05 '18 at 01:03
  • 1
    [How can I mutate other elements of a HashMap when using the entry pattern?](https://stackoverflow.com/questions/52846885/how-can-i-mutate-other-elements-of-a-hashmap-when-using-the-entry-pattern) is at least as relevant. As in that question, you can't do this safely with the `entry` API because `or_insert` can cause the `HashMap` to be reallocated. You have to first insert both values, and then you can apply either of the answers to [Borrow two mutable values from the same HashMap](https://stackoverflow.com/questions/47773849/borrow-two-mutable-values-from-the-same-hashmap) – trent Nov 05 '18 at 14:27
  • 1
    I just had your issue a week ago and the answer in @Shepmaster’s link - RefCell - worked. Is there any reason why you don’t want to use it? – hpm Nov 06 '18 at 10:35
  • @AaronCruz I feel like using RefCell involves a huge change in a lot of lines of my codebase (adding borrow() or borrow_mut()). I'd rather use that as a last resort. – Daniel Sorichetti Nov 06 '18 at 18:21
  • You can always attempt to detangle the aspects of your code that need to mutate from those that don't. Often makes code cleaner and can make it easier to maintain. – Shepmaster Nov 07 '18 at 16:31

0 Answers0