HashMap的迭代和借值[关闭]。

问题描述 投票:-1回答:1

我想在一个 HashMap 然后对其调用一个不可变的方法。由于这些事情是连续发生的,所以似乎借款检查器应该允许这样做。然而,我得到了错误。

error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
  --> src/flow/mod.rs:50:27
   |
42 |         for (name, step) in self.steps.iter_mut() {
   |                             ---------------------
   |                             |
   |                             mutable borrow occurs here
   |                             mutable borrow later used here
...
50 |             step.validate(self, &mut reachable, errors)
   |                           ^^^^ immutable borrow occurs here

pub struct Flow {
    pub steps: HashMap<String, Box<Step>>,
}

impl Flow {
    pub fn validate(&mut self, errors: &mut ValidationErrors) {
        let mut reachable = HashSet::new();

        for (name, step) in self.steps.iter_mut() {
            step.name = name.clone(); // I'm done mutating here

            step.validate(self, &mut reachable, errors) // error here
        }
    }
}

impl Step {
    pub fn validate(&self, flow: &Flow, reachable: &mut HashSet<String>, errors: &mut ValidationErrors)
}

我想我需要告诉Rust我只在循环的第一行突变step 但如果它的作用域是循环主体呢?

rust borrow-checker
1个回答
0
投票

我重新发布一个被删除的答案,它是有效的。你可以把你的循环分成两个版本:突变和非突变,我把它放到两个独立的方法中。

pub fn clean(&mut self) {
    for (name, step) in self.steps.iter_mut() {
        step.name = name.clone();
    }
}

pub fn validate(&self) {
    for (_name, step) in self.steps.iter() {
        step.validate(self, &mut reachable, errors);
    }
}

rust所有权的基本规则的一部分是,如果你有一个可突变的东西的引用,你不能有任何其他的引用(可突变或不可突变)--不允许突变数据的别名。不可变的别名是很好的,你可以拥有你想要的任何数量的不可变引用。

另一种解决方案是通过让所有的东西都可变,从而在所有地方重用可变的引用,但我觉得让不可变的东西可变是一种代码的味道,而且它还会像瘟疫一样在代码中传播限制,因为现在你可能在其他地方禁止了别名。

© www.soinside.com 2019 - 2024. All rights reserved.