我正在尝试通过在我的项目中使用Rust来学习它。
然而,在某些代码中,我遇到了借用检查器的问题,其形式与以下代码非常相似:
use std::collections::HashMap;
use std::pin::Pin;
use std::vec::Vec;
struct MyStruct<'a> {
value: i32,
substructs: Option<Vec<Pin<&'a MyStruct<'a>>>>,
}
struct Toplevel<'a> {
my_structs: HashMap<String, Pin<Box<MyStruct<'a>>>>,
}
fn main() {
let mut toplevel = Toplevel {
my_structs: HashMap::new(),
};
// First pass: add the elements to the HashMap
toplevel.my_structs.insert(
"abc".into(),
Pin::new(Box::new(MyStruct {
value: 0,
substructs: None,
})),
);
toplevel.my_structs.insert(
"def".into(),
Pin::new(Box::new(MyStruct {
value: 5,
substructs: None,
})),
);
toplevel.my_structs.insert(
"ghi".into(),
Pin::new(Box::new(MyStruct {
value: -7,
substructs: None,
})),
);
// Second pass: for each MyStruct, add substructs
let subs = vec![
toplevel.my_structs.get("abc").unwrap().as_ref(),
toplevel.my_structs.get("def").unwrap().as_ref(),
toplevel.my_structs.get("ghi").unwrap().as_ref(),
];
toplevel.my_structs.get_mut("abc").unwrap().substructs = Some(subs);
}
编译时,我收到了以下消息:
error[E0502]: cannot borrow `toplevel.my_structs` as mutable because it is also borrowed as immutable
--> src/main.rs:48:5
|
44 | toplevel.my_structs.get("abc").unwrap().as_ref(),
| ------------------- immutable borrow occurs here
...
48 | toplevel.my_structs.get_mut("abc").unwrap().substructs = Some(subs);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------
| |
| mutable borrow occurs here
| immutable borrow later used here
我认为我理解了这种情况发生的原因:
toplevel.my_structs.get_mut(...)
将 toplevel.my_structs
借为可变状态。然而,在同一块中,toplevel.my_structs.get(...)
也借用了 toplevel.my_structs
(这次是不可变状态)。我也看到如果借用
&mut toplevel.my_structs
函数添加了一个新键,那么这确实会成为一个问题。然而,这里在
&mut toplevel.my_structs
的借用中所做的所有工作都只是修改与特定键对应的值,这不应该改变内存布局(由于 Pin
的保证可以得到)。 对吗?是否有一种方法可以将此信息传达给编译器,以便我可以编译此代码?这似乎与激励
hashmap::Entry
API 类似,但我需要能够访问其他键,而不仅仅是要修改的一个键。
Rc<RefCell<_>>
真的是解决这个问题并仍然使用“引用”的唯一方法吗?对于这个问题,使用引用计数似乎有点不必要。是否有一些参考页面可以查看可能的替代方案? - dccsillag