【问题标题】:Borrow errors for multiple borrows多次借用的借用错误
【发布时间】:2016-10-20 22:43:21
【问题描述】:

我正在 rust 中实现一个就地递归解析器,但我遇到了一些借用错误。代码sn -p 重现了这个问题,虽然不是很有用

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

这给了我以下错误:

错误[E0499]:不能一次多次借用“my_vec”作为可变变量 --> test.rs:20:9 | 18 |让 mut last : &mut Box = my_vec.last_mut().unwrap(); | ------ 第一个可变借用发生在这里 19 |让 mut new_borrow = Box::new(MyBorrows::new(last.val)); 20 | my_vec.push(new_borrow); | ^^^^^^ 第二个可变借用发生在这里 21 | } 22 | } | - 第一次借到这里 错误:由于 3 个先前的错误而中止

在我的真实案例中,向量被用作堆栈来引用我正在解析的struct 越来越深的组件。这是我在 C++ 中用于通用解析的常见模式,我试图在 Rust 中复制它,但我遇到了问题。任何帮助将不胜感激。

【问题讨论】:

    标签: rust


    【解决方案1】:

    您正在尝试做的事情是不合理的。看起来您正在尝试创建多个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);
        }
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多