我正在 Rust 中实现一个就地递归解析器,但遇到了一些借用错误。代码片段重现了问题,尽管它不是很有用
use std::vec::Vec;
struct MyBorrows<'a> {
val : &'a mut i32
}
impl <'a> MyBorrows<'a> {
fn new(v : &'a mut i32) -> MyBorrows<'a> {
MyBorrows { val : v }
}
}
fn main() {
let mut my_val = 23;
let mut my_vec : Vec<Box<MyBorrows>> = Vec::new();
my_vec.push(Box::new(MyBorrows::new(&mut my_val)));
for i in [1..4].iter() {
let mut last : &mut Box<MyBorrows> = my_vec.last_mut().unwrap();
let mut new_borrow = Box::new(MyBorrows::new(last.val));
my_vec.push(new_borrow);
}
}
这给了我以下错误:
error[E0499]: cannot borrow `my_vec` as mutable more than once at a time
--> test.rs:20:9
|
18 | let mut last : &mut; Box = my_vec.last_mut().unwrap();
| ------ first mutable borrow occurs here
19 | let mut new_borrow = Box::new(MyBorrows::new(last.val));
20 | my_vec.push(new_borrow);
| ^^^^^^ second mutable borrow occurs here
21 | }
22 | }
| - first borrow ends here
error: aborting due to 3 previous errors
在我的实际情况中,向量用作堆栈来引用越来越深的组件struct
我正在解析成.这是我在 C++ 中用于通用解析的常见模式,我试图在 Rust 中复制它,但我遇到了问题。任何帮助将不胜感激。
你试图做的事情是不合理的。您似乎正在尝试创建多个MyBorrows
它们都可变地借用相同的值,并让它们同时存活(在向量中)。这样的设置正是 Rust 旨在防止的,因为这就是数据竞争的发生方式。
你可能想做的是im可变地借用一堆值,这是合法的。因此,在清理了不必要的可变借用之后,我将问题简化为:
struct MyBorrows<'a> {
val : &'a i32
}
impl <'a> MyBorrows<'a> {
fn new(v : &'a i32) -> MyBorrows<'a> {
MyBorrows { val : v }
}
}
fn main() {
let my_val = 23;
let mut my_vec = vec![];
my_vec.push(Box::new(MyBorrows::new(&my_val)));
for _ in 1..4 {
let last = my_vec.last().unwrap();
let new_borrow = Box::new(MyBorrows::new(last.val));
my_vec.push(new_borrow);
}
}
现在你会得到一个稍微不同的错误:
error[E0502]: cannot borrow `my_vec` as mutable because it is also borrowed as immutable
--> test.rs:18:9
|
16 | let last = my_vec.last().unwrap();
| ------ immutable borrow occurs here
17 | let new_borrow = Box::new(MyBorrows::new(last.val));
18 | my_vec.push(new_borrow);
| ^^^^^^ mutable borrow occurs here
19 | }
| - immutable borrow ends here
error: aborting due to previous error
这个比较棘手,当你打电话时你必须意识到发生了什么my_vec.last()
——它返回对 Vec 中现有内存的引用,阻止任何其他内容接触 Vec。目前在 Rust 中,该引用一直存在到当前块的末尾。为了解决这个问题,请将可变借用包含在其自己的块作用域中:
fn main() {
let my_val = 23;
let mut my_vec = vec![];
my_vec.push(Box::new(MyBorrows::new(&my_val)));
for _ in 1..4 {
let new_borrow;
{
let last = my_vec.last().unwrap();
new_borrow = Box::new(MyBorrows::new(last.val));
}
my_vec.push(new_borrow);
}
}
现在,可变借用在推送发生之前结束,并且生命周期有效。希望在未来,我们将得到非词汇生命周期 https://github.com/rust-lang/rfcs/issues/811添加到语言中,这样编译器就可以发现我的第一个示例实际上是安全的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)