我想在一个 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 但如果它的作用域是循环主体呢?
我重新发布一个被删除的答案,它是有效的。你可以把你的循环分成两个版本:突变和非突变,我把它放到两个独立的方法中。
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所有权的基本规则的一部分是,如果你有一个可突变的东西的引用,你不能有任何其他的引用(可突变或不可突变)--不允许突变数据的别名。不可变的别名是很好的,你可以拥有你想要的任何数量的不可变引用。
另一种解决方案是通过让所有的东西都可变,从而在所有地方重用可变的引用,但我觉得让不可变的东西可变是一种代码的味道,而且它还会像瘟疫一样在代码中传播限制,因为现在你可能在其他地方禁止了别名。