Rust loop on HashMap while borrowing self

北城以北 提交于 2019-12-12 05:26:11

问题


I have a Element struct that implements an update method which takes a tick duration. The struct contains a vector of components. These components are allowed to modify the element on an update. I'm getting a borrow error here and I'm not sure what to do. I tried fixing it with a block, but the block doesn't seems to satisfy the borrow checker.

use std::collections::HashMap;
use std::time::Duration;

pub struct Element {
    pub id: String,
    components: HashMap<String, Box<Component>>,
}

pub trait Component {
    fn name(&self) -> String;
    fn update(&mut self, &mut Element, Duration) {}
}

impl Element {
    pub fn update(&mut self, tick: Duration) {
        let keys = {
            (&mut self.components).keys().clone()
        };
        for key in keys {
            let mut component = self.components.remove(key).unwrap();
            component.update(self, Duration::from_millis(0));
        }
    }
}

fn main() {}

The Error

error[E0499]: cannot borrow `self.components` as mutable more than once at a time
  --> src/main.rs:20:33
   |
17 |             (&mut self.components).keys().clone()
   |                   --------------- first mutable borrow occurs here
...
20 |             let mut component = self.components.remove(key).unwrap();
   |                                 ^^^^^^^^^^^^^^^ second mutable borrow occurs here
...
23 |     }
   |     - first borrow ends here

error[E0499]: cannot borrow `*self` as mutable more than once at a time
  --> src/main.rs:21:30
   |
17 |             (&mut self.components).keys().clone()
   |                   --------------- first mutable borrow occurs here
...
21 |             component.update(self, Duration::from_millis(0));
   |                              ^^^^ second mutable borrow occurs here
22 |         }
23 |     }
   |     - first borrow ends here

回答1:


The keys() method returns an iterator over the keys in the hashmap. The clone() call only duplicates the iterator, but not the keys themselves. Your original approach with the map function looks promising. You probably need to collect the result in a Vec using the collect() method of the iterator:

let keys = self.components.keys().cloned().collect::<Vec<_>>();

And then:

for key in keys {
    self.components.remove(&key).unwrap();
}

This ensures that all the keys are copied before the removal operation starts.



来源:https://stackoverflow.com/questions/45311896/rust-loop-on-hashmap-while-borrowing-self

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!