首页 文章

借用多次借用的错误

提问于
浏览
2

我正在实现一个就地递归解析器生锈,我得到一些借用错误 . 代码片段再现了问题,尽管它不是很有用

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中复制但我遇到了问题 . 任何帮助将不胜感激 .

1 回答

  • 3

    你想要做的是不健全 . 看起来你正在尝试创建多个 MyBorrows ,它们都可以相互借用相同的值,并让它们一次存活(在向量中) . 这样的设置正是Rust旨在防止的,因为这就是数据竞争的发生方式 .

    你可能想要做的就是不可避免地借用一堆 Value ,这是合法的 . 因此,在清理了不必要的可变借词之后,我将问题简化为:

    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);
        }
    }
    

    现在,可变借用在推送发生之前结束,并且生命周期起作用 . 希望在将来,we will get non-lexical lifetimes添加到语言中,因此编译器可以确定我的第一个示例实际上是安全的 .

相关问题