Rust Borrow 检查器仅在函数返回具有相同生命周期的引用时抱怨多次借用为可变的

2023-12-26

我对一些 Rust 代码遇到了问题,在某些条件下(第一个令人困惑的部分),我被允许多次借用可变的东西,但在其他条件下则不允许。

我写了下面的例子来说明: ()

struct NoLifetime {}
struct WithLifetime <'a> {
    pub field: &'a i32
}

fn main() {
    let mut some_val = NoLifetime {};
    borrow_mut_function(&mut some_val);
    borrow_mut_function(&mut some_val); // Borrowing as mutable for the second time.

    let num = 5;
    let mut life_val = WithLifetime { field: &num };
    borrow_lifetime(&mut life_val);
    borrow_lifetime(&mut life_val); // Borrowing as mutable for the second time.

    let num_again = borrow_lifetime(&mut life_val); // Borrow, assign lifetime result
    borrow_lifetime(&mut life_val); // Compiler: cannot borrow `life_val` as mutable more than once
}

fn borrow_mut_function(val_in: &mut NoLifetime) -> String {
    "abc".to_string()
}
fn borrow_lifetime<'a>(val_in: &'a mut WithLifetime) -> &'a i32 {
    val_in.field
}

如果你看到了,我可以借两个some_val, and life_val不止一次是可变的。但是,在分配返回值之后borrow_lifetime,我不能再借了。

我的问题如下:

  1. 摘自《关于借款的规则》锈书 https://doc.rust-lang.org/book/references-and-borrowing.html,我应该在相同值的范围内有“恰好一个可变引用”。然而,在上面的代码中,每次调用时我都会借用可变的borrow_功能。
  2. 当我有一个函数返回与参数具有相同生命周期的内容并分配该参数时,为什么不允许相同类型的借用。

任何帮助,将不胜感激。我想这里发生的事情是我误解了“可变借用”的真正含义,以及何时确定某些东西被借用为可变的。


Rust 现在接受此代码,因为非词汇借用 https://stackoverflow.com/q/50251487/155423.

对于非词法借用,借用在变量的最后一次使用(本质上)结束,并注意析构函数是一种使用,析构函数在作用域的末尾运行。

因此,编译器意识到:

  • num_again从未使用过
  • num_again没有特定的析构函数(没有Drop执行)

它决定它的借用在它开始的那一行结束,而不是在词法范围的末尾,因此life_val可以免费再次使用。


克里斯已经给出了要点 https://stackoverflow.com/a/38006912/155423,但我认为值得进一步解释。

2Rust 转移所有权的方法:

  • moving is a 永恒的转移
  • 借用 is a 暂时的转让,所有权有望归还

Rust 与许多其他语言一样,使用堆栈来模拟时间流逝词汇范围。因此,for now,借用从创建的地方开始,并延伸到其范围的末尾。


非词汇借用之前的历史行为:

因此,借用何时结束的问题过去类似于询问借用是在什么范围内创建的。

让我们用编号行回顾一下您的示例:

fn main() {
    let mut some_val = NoLifetime {};                // 1
    borrow_mut_function(&mut some_val);              // 2
    borrow_mut_function(&mut some_val);              // 3
                                                     // 
    let num = 5;                                     // 4
    let mut life_val = WithLifetime { field: &num }; // 5
    borrow_lifetime(&mut life_val);                  // 6
    borrow_lifetime(&mut life_val);                  // 7
                                                     //
    let num_again = borrow_lifetime(&mut life_val);  // 8
    borrow_lifetime(&mut life_val);                  // 9
}

当调用函数时,参数被借用:

  • 至少在函数调用期间。
  • 直到结果被放弃的那一刻,if结果与论证共享一生。

那么,让我们看看这个:

  • 在第 (2) 行和第 (3) 行中,您调用borrow_mut_function它返回一个String:结果不与参数共享任何生命周期,因此参数仅在函数调用的生命周期内借用。

  • 在第 (6) 行和第 (7) 行中,您调用borrow_lifetime它返回一个&'a i32:结果与参数共享生命周期,因此参数被借用直到结果范围的末尾...这是立即的,因为结果没有被使用。

  • 您拨打第 (8) 行borrow_lifetime它返回一个&'a i32你呢assign结果为num_again:结果与参数共享生命周期,因此参数被借用直到范围结束num_again.

  • 您拨打第 (9) 行borrow_lifetime然而它的论点仍然借用num_again所以这个调用是非法的。

就是这样,Rust 当时就是这样工作的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Rust Borrow 检查器仅在函数返回具有相同生命周期的引用时抱怨多次借用为可变的 的相关文章

随机推荐