泛型生命周期具体化为引用的生命周期还是引用值的生命周期?

Does a generic lifetime materialize as the reference's lifetime or the referenced value's lifetime?

考虑以下程序:

fn main() {
    let c;                                      |<-'a
    let mut a = "Hello, world!".to_string();    |
    {                                           |
        let b = &mut a;           |<-'b         |
        c = foo(b);               |             |
    }                                           |
    println!("{}", c)                           |
}

fn foo<'z>(a: &'z mut str) -> &'z str {
    a
}

b的生命周期是'b,但是c的生命周期是'a,比'b长。 foo 的生命周期约束表示 foo 的 return 值(在本例中为 c)应该与其参数具有相同的生命周期(在本例中为 b ). foo 的生命周期约束是如何满足的?

但是,这个程序可以编译,所以我猜foo的生命周期参数'z具体化为b的引用值(a)的生命周期所以foo 的生命周期限制是否满足?

值有自己的生命周期,但引用也会跟踪它所引用的事物的生命周期。不幸的是,这里没有可用的官方术语。我(和其他一些人)开始使用的术语是具体的生命周期。 main 中有三个变量,因此有三个具体的生命周期:

fn main() {
    let c;                     //       'c
    let mut a = String::new(); // 'a     ¦
    {                          //  |     ¦
        let b = &mut a;        //  | 'b  ¦
        c = foo(b);            //  |  |  |
    }                          //  |     |
    println!("{}", c)          //  |     |
}

aStringb&mut Stringc&str。这三个变量都是值,但是 bc 也是 引用。在这种情况下,b 指的是 a 中的值,即 &'a mut String。由于 c 源自 b,它具有相同的 "inner lifetime":&'a str.

值得注意的是,b 本身的生命周期 永远不会 发挥作用。它非常罕见,因为你需要有可变借用和 "extra" 借用:

fn main() {
    let c;
    let mut a = String::new();
    {
        let mut b = &mut a;
        c = foo(&mut b);    // Mutably borrowing `b` here
    }
    println!("{}", c)
}
error[E0597]: `b` does not live long enough
 --> src/main.rs:6:17
  |
6 |         c = foo(&mut b);
  |                 ^^^^^^ borrowed value does not live long enough
7 |     }
  |     - `b` dropped here while still borrowed
8 |     println!("{}", c)
  |                    - borrow later used here

在这种情况下,传递给 foo 的值是 &'b mut &'a mut String 类型,它被强制转换为 &'b mut str。值 b 的寿命不够长,您收到错误。

I don't think this model can account for more complicated borrowing relationships. If a is used again after the println!, for example, the mutable borrow can't be for the entire lifetime of a

a 的可变借用由 c 持有,但 借用的持续时间 不需要对应于 c。由于 non-lexical lifetimes(在这种情况下更好地称为 "non-lexical borrows"),c 持有的 a 的借用可以在 println! 之后但在范围结束之前终止.

增强上面的图表以显示 value 的生命周期与 referred-to value 的生命周期结合在括号中:

fn main() {
    let c;                     //           'c
    let mut a = String::new(); // 'a         ¦
    {                          //  |         ¦
        let b = &mut a;        //  | 'b('a)  ¦
        c = foo(b);            //  |  |('a)  |('a)
    }                          //  |         |('a)
    println!("{}", c);         //  |         |('a)
                               //  |         |
    println!("{}", a);         //  |         |
}

另请参阅:

  • Reference does not live long enough in nested structure