Rust 借用检查器仅在 returns 分配了具有相同生命周期的引用的函数时抱怨多次借用为可变
Rust Borrow checker only complains about borrowing as mutable multiple times when a function that returns a reference with the same lifetime assigned
我在使用一些 Rust 代码时遇到问题,在某些情况下我被允许多次借用可变的东西(第一个令人困惑的部分),但在其他情况下则不行。
我写了下面的例子来说明:
(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_val
和 life_val
作为可变的。但是赋值了borrow_lifetime
的return值后,我就不能再借了
我的问题如下:
- 来自 'The Rules' 关于 Rust Book 中的借用,我应该在 'exactly one mutable reference' 范围内使用相同的值。但是,在上面的代码中,每次我调用
borrow_
函数时,我都将借用为可变的。
- 当我有一个return与参数具有相同生命周期的函数,并且我分配了那个参数时,为什么不允许相同类型的借用。
如有任何帮助,我们将不胜感激。我想这里发生的事情是我误解了 'borrowing as mutable' 的真正含义,以及何时确定某些东西被借用为可变的。
这是关于借用的范围,以及你是否保持借用。在上面的大部分调用中,some_val
是在函数调用时借用的,但是在函数returns.
之后被return借用了。
例外情况:
let num_again = borrow_lifetime(&mut life_val); //Borrow, assign lifetime result
您在调用 borrow_lifetime
期间借用 life_val
,但由于 return 值与参数 ('a
) 具有相同的生命周期,借用的范围被扩展到包括 num_again
的生命周期,即直到函数结束。再次借用 life_val
是不安全的,因为 num_again
仍然是对它的引用。
,但我认为值得进一步解释。
在 Rust 中有 2 种转移所有权的方法:
- 移动是永久转移
- 借用为临时转让,预计归还
Rust 与许多其他语言一样,使用一堆 词法作用域 对时间流逝进行建模。因此,暂时,借用从创建它的地方开始,并延伸到其范围的末尾。
因此,借用何时结束的问题类似于询问在什么范围内创建借用。
让我们用带编号的行回顾一下您的示例:
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
}
调用函数时,借用参数:
- 至少在函数调用期间
- 直到结果被丢弃的那一刻,如果结果与参数共享生命周期
所以,让我们看看这个:
在第 (2) 和 (3) 行你调用 borrow_mut_function
which returns a String
: 结果不与参数共享任何生命周期,因此参数仅在函数调用的生命周期内借用。
在第 (6) 和 (7) 行你调用 borrow_lifetime
which returns a &'a i32
: 结果与参数共享生命周期,所以参数被借用到结果范围的末尾......这是因为结果没有被使用。
在第 (8) 行你调用 borrow_lifetime
其中 returns 一个 &'a i32
然后你 分配 结果给num_again
:结果与参数共享一个生命周期,所以参数被借用到num_again
.
的范围结束
在第 (9) 行你调用了 borrow_lifetime
但是它的参数仍然被 num_again
借用所以这个调用是非法的。
就是这样,这就是今天 Rust 的工作方式。
以后有电话non-lexical borrows。也就是说,编译器会意识到:
num_again
从未使用过
num_again
没有特定的析构函数(没有 Drop
实现)
因此可以决定它的借用结束早于词法范围的结束。
我在使用一些 Rust 代码时遇到问题,在某些情况下我被允许多次借用可变的东西(第一个令人困惑的部分),但在其他情况下则不行。
我写了下面的例子来说明: (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_val
和 life_val
作为可变的。但是赋值了borrow_lifetime
的return值后,我就不能再借了
我的问题如下:
- 来自 'The Rules' 关于 Rust Book 中的借用,我应该在 'exactly one mutable reference' 范围内使用相同的值。但是,在上面的代码中,每次我调用
borrow_
函数时,我都将借用为可变的。 - 当我有一个return与参数具有相同生命周期的函数,并且我分配了那个参数时,为什么不允许相同类型的借用。
如有任何帮助,我们将不胜感激。我想这里发生的事情是我误解了 'borrowing as mutable' 的真正含义,以及何时确定某些东西被借用为可变的。
这是关于借用的范围,以及你是否保持借用。在上面的大部分调用中,some_val
是在函数调用时借用的,但是在函数returns.
例外情况:
let num_again = borrow_lifetime(&mut life_val); //Borrow, assign lifetime result
您在调用 borrow_lifetime
期间借用 life_val
,但由于 return 值与参数 ('a
) 具有相同的生命周期,借用的范围被扩展到包括 num_again
的生命周期,即直到函数结束。再次借用 life_val
是不安全的,因为 num_again
仍然是对它的引用。
在 Rust 中有 2 种转移所有权的方法:
- 移动是永久转移
- 借用为临时转让,预计归还
Rust 与许多其他语言一样,使用一堆 词法作用域 对时间流逝进行建模。因此,暂时,借用从创建它的地方开始,并延伸到其范围的末尾。
因此,借用何时结束的问题类似于询问在什么范围内创建借用。
让我们用带编号的行回顾一下您的示例:
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
}
调用函数时,借用参数:
- 至少在函数调用期间
- 直到结果被丢弃的那一刻,如果结果与参数共享生命周期
所以,让我们看看这个:
在第 (2) 和 (3) 行你调用
borrow_mut_function
which returns aString
: 结果不与参数共享任何生命周期,因此参数仅在函数调用的生命周期内借用。在第 (6) 和 (7) 行你调用
borrow_lifetime
which returns a&'a i32
: 结果与参数共享生命周期,所以参数被借用到结果范围的末尾......这是因为结果没有被使用。在第 (8) 行你调用
borrow_lifetime
其中 returns 一个&'a i32
然后你 分配 结果给num_again
:结果与参数共享一个生命周期,所以参数被借用到num_again
. 的范围结束
在第 (9) 行你调用了
borrow_lifetime
但是它的参数仍然被num_again
借用所以这个调用是非法的。
就是这样,这就是今天 Rust 的工作方式。
以后有电话non-lexical borrows。也就是说,编译器会意识到:
num_again
从未使用过num_again
没有特定的析构函数(没有Drop
实现)
因此可以决定它的借用结束早于词法范围的结束。