英文:
Lifetimes in Rust: mut data borrowed
问题
以下代码报告了一个错误:借用的值寿命不够长
fn main() {
    let e = 100;
    let mut a = (1,);
    let mut b = (&e,);
    {
        let mut c = (&mut a, &mut b);
        let f = &mut c;
        f.1 .0 = &(f.0 .0);
    }
    println!("{:?}", b);
}
但以下代码是正确的:
fn main() {
    let e = 100;
    let a = (1,);
    let mut b = (&e,);
    {
        let mut c = (&a, &mut b);
        let f = &mut c;
        f.1 .0 = &(f.0 .0);
    }
    println!("{:?}", b);
}
为什么?!!
第一个代码的完整错误消息:
error[E0597]: `c` does not live long enough
  --> src/main.rs:7:17
   |
6  |         let mut c = (&mut a, &mut b);
   |             ----- binding `c` declared here
7  |         let f = &mut c;
   |                 ^^^^^^ borrowed value does not live enough
8  |         f.1 .0 = &f.0 .0;
9  |     }
   |     - `c` dropped here while still borrowed
10 |     println!("{:?}", b);
   |                      - borrow later used here
For more information about this error, try `rustc --explain E0597`.
英文:
The following code reports an error:
borrowed value does not live long enough
fn main() {
    let e = 100;
    let mut a = (1,);
    let mut b = (&e,);
    {
        let mut c = (&mut a, &mut b);
        let f = &mut c;
        f.1 .0 = &(f.0 .0);
    }
    println!("{:?}", b);
}
But the following code is correct:
fn main() {
    let e = 100;
    let a = (1,);
    let mut b = (&e,);
    {
        let mut c = (&a, &mut b);
        let f = &mut c;
        f.1 .0 = &(f.0 .0);
    }
    println!("{:?}", b);
}
Why?!!
Full error message for the first code:
error[E0597]: `c` does not live long enough
  --> src/main.rs:7:17
   |
6  |         let mut c = (&mut a, &mut b);
   |             ----- binding `c` declared here
7  |         let f = &mut c;
   |                 ^^^^^^ borrowed value does not live long enough
8  |         f.1 .0 = &f.0 .0;
9  |     }
   |     - `c` dropped here while still borrowed
10 |     println!("{:?}", b);
   |                      - borrow later used here
For more information about this error, try `rustc --explain E0597`.
答案1
得分: 2
这是因为共享引用是Copy的,而可变引用不是。
以下是您的代码的简化版本,更容易讨论:
fn main() {
    let mut a = 1;
    let b;
    {
        let mut c = &mut a;
        // 或者:
        let mut c = &a;
        let f = &mut c;
        b = &**f;
    }
    println!("{b}");
}
让我们将a和c的生命周期分别称为'a和'c。因此,f的类型是&'c mut &'a [mut] i32。当我们执行b = &**f时,在可变和不可变版本之间存在差异。
在不可变版本中,我们对f进行解引用,得到&'a i32。然后,我们复制这个引用(这是可以的,因为共享引用是Copy),并得到一个类型为&'a i32的独立引用。我们可以将这个引用(或它的重新借用版本&*r)分配给b,因为a的生命周期与b相同。
在可变情况下,我们也对f进行解引用。但是,我们得到的引用是可变引用:&'a mut i32。由于可变引用不是Copy,我们不能将它复制到一个独立的引用中。它必须留在原地,在f的&'c mut后面。
然而,我们可以重新借用此引用以创建一个从中派生的引用。但是,当您重新借用类型为&'a mut &'b mut T的引用时,您无法获得类型为&'b mut T的引用,只能获得&'a mut T。否则,您获得的引用可能会超出原始引用的生命周期,并且在您没有权限的情况下存在。
因此,我们得到了**&'c mut i32**,而不是&'a mut i32。b的生命周期超出了c,因此我们不能将&'c mut i32(或从中创建的共享&'c i32)分配给b。
英文:
This is because shared references are Copy, while mutable references are not.
Here's a trimmed down version of your code, which is easier to discuss:
fn main() {
    let mut a = 1;
    let b;
    {
        let mut c = &mut a;
        // Or:
        let mut c = &a;
        let f = &mut c;
        b = &**f;
    }
    println!("{b}");
}
Let's call the lifetimes of a and c 'a and 'c respectively. Therefore, f has type &'c mut &'a [mut] i32. When we do b = &**f, there is a difference between the mutable and immutable version.
In the immutable version, we dereference f to get &'a i32. We then copy this reference (which is fine because shared references are Copy), and get a freestanding reference of type &'a i32. We can assign this reference (or the reborrowed version of it, &*r) to b, because a has the same scope b has.
In the mutable case, we also dereference f. However, the reference we get is a mutable reference: &'a mut i32. Since mutable references are not Copy, we cannot copy it to a freestanding reference. It has to stay where it is, behind the &'c mut of f.
What we can do, however, is to reborrow this reference to create a reference descended from it. However, when you reborrow a reference of type &'a mut &'b mut T, you cannot get a reference of type &'b mut T, only &'a mut T. Otherwise, the reference you got could outlive the original reference, and exist while you have no permission for such reference.
Therefore, we get &'c mut i32, and not &'a mut i32. b outlives c, so we cannot assign a &'c mut i32 (or a shared &'c i32 created from it) to b.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论