Rust 函数中奇怪的生命周期,发生第二次可变借用

问题描述 投票:0回答:1

我有两段关于寿命的 Rust 代码。第一个只有一个生命周期标记<'a>,无法通过编译。第二个有两个生命周期标记<'a, 'b>,可以通过编译。这是什么原因?

第一个:

fn deserialize1<'a, I: Iterator<Item = &'a u8>>(_iter: &'a mut I) {
}
fn deserialize2<'a, I: Iterator<Item = &'a u8>>(_iter: &'a mut I) {
}
fn deserialize3<'a, I: Iterator<Item = &'a u8>>(iter: &'a mut I) {
    deserialize1(iter);
    deserialize2(iter);
}

fn main() {
    let v : Vec<u8> = vec![1, 2, 3];
    let mut iter = v.iter();
    deserialize3(&mut iter);
}

第二个:

fn deserialize1<'a, 'b, I: Iterator<Item = &'a u8>>(_iter: &'b mut I) {
}
fn deserialize2<'a, 'b, I: Iterator<Item = &'a u8>>(_iter: &'b mut I) {
}
fn deserialize3<'a, 'b, I: Iterator<Item = &'a u8>>(iter: &'b mut I) {
    deserialize1(iter);
    deserialize2(iter);
}

fn main() {
    let v : Vec<u8> = vec![1, 2, 3];
    let mut iter = v.iter();
    deserialize3(&mut iter);
}

第一个编译失败:

error[E0499]: cannot borrow `*iter` as mutable more than once at a time
  --> src/main.rs:33:18
   |
31 | fn deserialize3<'a, I: Iterator<Item = &'a u8>>(iter: &'a mut I) {
   |                 -- lifetime `'a` defined here
32 |     deserialize1(iter);
   |     ------------------
   |     |            |
   |     |            first mutable borrow occurs here
   |     argument requires that `*iter` is borrowed for `'a`
33 |     deserialize2(iter);
   |                  ^^^^ second mutable borrow occurs here

我无法理解上面的编译信息。为什么生命周期会影响借用规则?

rust lifetime borrow-checker
1个回答
0
投票

当您像此处所做的那样使用一生时,您就过度限制了您的参考。为什么迭代器的生命周期have与其生成的引用的生命周期相匹配?它甚至受到更多限制,因为用于迭代器

'a
Item
invariant 在这种情况下意味着编译器根本无法调整生命周期。

好吧,这里使用单一生命周期有很多不灵活性,但为什么这是一个问题呢?由于

'a
是不变的,并且您将相同的内容传递给以相同方式定义的
deserialize1
deserialize2
,这意味着
iter: &'a mut I
意味着每个函数中的完全相同的内容。这两个函数都试图在
iter 的完全相同的生命周期内专门借用 'a
,而 Rust 借用检查器显然不允许这样做。

当您引入

iter

 使用不同的生命周期 
'b
 时,您允许编译器为每个可变借用选择不同的生命周期,因此不会发生冲突。

为什么生命周期会影响借用规则?

生命周期注释的存在只是为了告知借用检查器如何使用引用。显然,如果与您的使用情况相比,您对生命周期的注释不正确,借用检查器会捕获该情况并显示错误。


最后一点,您不需要明确提及

'b

。您可以保留 
iter
 不带注释,并且由于生命周期省略规则,它将与您的第二个变体相同:

fn deserialize1<'a, I: Iterator<Item = &'a u8>>(_iter: &mut I) {} fn deserialize2<'a, I: Iterator<Item = &'a u8>>(_iter: &mut I) {} fn deserialize3<'a, I: Iterator<Item = &'a u8>>(iter: &mut I) { deserialize1(iter); deserialize2(iter); }
    
© www.soinside.com 2019 - 2024. All rights reserved.