本文介绍了当一个函数返回分配了相同生命周期的引用时,Rust Borrow Checker仅抱怨多次借用是可变的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一些Rust代码上遇到了问题,在某些条件下(我首先混淆的部分),我被允许多次借用一些可变的东西,而在其他情况下却没有.

I'm having problem with some Rust code where I'm being allowed to borrow something as mutable more than once on certain conditions (first confusing part), but not others.

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

I've written the following example to illustrate:(Playground)

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_vallife_val这两个变量.但是,在分配了borrow_lifetime的返回值之后,我将无法再借用.

If you see, I can borrow both some_val, and life_val as mutable more than once. However, after assigning the return value of borrow_lifetime, I can no longer borrow.

我的问题如下:

  1. 摘录自锈皮书中有关借书的规则" >,我应该在范围上具有完全可变的引用",以达到相同的值.但是,在上面的代码中,每次调用borrow_函数时,我都是以可变的方式借用的.
  2. 为什么当我有一个函数返回与参数具有相同生存期的东西并分配该参数时,为什么不允许相同类型的借用.
  1. From 'The Rules' about Borrowing in the Rust Book, I'm supposed to have 'exactly one mutable reference' in scope to the same value. However, in the code above I'm borrowing as mutable every time I call a borrow_ function.
  2. Why is the same type of borrowing not allowed when I have a function that returns something with the same lifetime as the parameter, and I assign that parameter.

任何帮助将不胜感激.我想这里发生的事情是我误解了借贷易变"的真正含义,以及何时确定借来的东西是易变的.

Any help would be appreciated. I imagine what is happening here is that I am misunderstanding what 'borrowing as mutable' really means, and when to determine that something is being borrowed as mutable.

推荐答案

Chris已经给出了要点,但是我认为值得进一步解释.

Chris already gave the gist of it, but I think it is worth explaining further.

2 种方式可以在Rust中转移所有权:

There are 2 ways to transfer ownership in Rust:

  • 移动永久转移
  • 借用临时转移,预计将归还所有权
  • moving is a permanent transfer
  • borrowing is a temporary transfer, ownership is expected to be returned

Rust使用一堆词法范围对时间流逝进行建模.结果,现在,借用从创建它的地方开始,一直扩展到作用域的结尾.

Rust, like many other languages, models time passing using a stack of lexical scopes. As a result, for now, a borrow starts where it is created and extend until the end of its scope.

因此,借贷何时终止的问题类似于询问借贷创建的范围.

Thus, the questions of when a borrow ends is akin to asking what scope is the borrow created in.

让我们用带编号的行查看您的示例:

Let's review your example with numbered lines:

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
}

调用函数时,将借用参数:

When a function is called, the argument is borrowed:

  • 至少在函数调用期间
  • 直到删除结果为止,如果结果与参数共享一个生命期
  • at least for the duration of the function call
  • up to the moment the result is dropped, if the result shares a lifetime with the argument

所以,让我们来看一下:

So, let's look at this:

    在第(2)和(3)行上的
  • 调用borrow_mut_function,它返回一个String:结果与参数不共享任何生存期,因此该参数仅在函数的生存期内被借用呼叫.

  • on line (2) and (3) you call borrow_mut_function which returns a String: the result does not share any lifetime with the argument, so the argument is only borrowed for the lifetime of the function call.

调用borrow_lifetime,它返回一个&'a i32:结果与参数共享一个生存期,因此该参数将被借用直到结果范围的结尾...这是因为未使用结果而立即生效.

on line (6) and (7) you call borrow_lifetime which returns a &'a i32: the result shares a lifetime with the argument, so the argument is borrowed until the end of the scope of the result... which is immediately since the result is not used.

上调用borrow_lifetime返回一个&'a i32,然后将结果分配num_again:结果与该参数共享一个生存期,因此参数被借用到num_again范围的末尾.

on line (8) you call borrow_lifetime which returns a &'a i32 and you assign the result to num_again: the result shares a lifetime with the argument, so the argument is borrowed until the end of the scope of num_again.

调用borrow_lifetime,但是它的参数仍然是num_again借用的,因此该调用是非法的.

on line (9) you call borrow_lifetime however its argument is still borrow by num_again so the call is illegal.

就是这样,Rust就是今天的工作方式.

That's it, this is how Rust works today.

将来会呼吁 非词汇借用 .也就是说,编译器将意识到:

In the future, there is a call for non-lexical borrows. That is, the compiler would realize that:

  • num_again从未使用
  • num_again没有特定的析构函数(没有Drop实现)
  • num_again is never used
  • num_again does not have a specific destructor (no Drop implementation)

,因此可以决定其借用的终止早于词汇范围的终止.

and could therefore decide that its borrow ends sooner than the end of the lexical scope.

这篇关于当一个函数返回分配了相同生命周期的引用时,Rust Borrow Checker仅抱怨多次借用是可变的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 06:19