borrowed value does not live long enough

Case1 多个相同的生命周期

struct S<'a> {
    x: &'a i32,
    y: &'a i32
}

fn main() {
    let x = 10;
    let r;
    {
        let y = 20;
        {
            let s = S { x: &x, y: &y };
            r = s.x;
        }
    }
    println!("{} {}", x, r);

   |
12 |             let s = S { x: &x, y: &y };
   |                                   ^^ borrowed value does not live long enough
...
15 |     }
   |     - `y` dropped here while still borrowed
16 |     println!("{} {}", x, r);
   |

实际上,上面这段代码错误的原因是S<'a>中的两个字段的生命周期都是'a,这导致let s = S { x: &x, y: &y };r = s.x两个表达式存在歧义,前者要求x的生命周期和y一致,这个可以通过协变达成。但是后者要求s.x的生命周期要大于y。这就尴尬了,你是没办法找出这样的一个生命周期大于y并且等于y。所以上面报错了。

只需要将S的两个字段用不同的生命周期标注即可。这样就可以满足上面代码对于生命周期的要求。

struct S<'a, 'b> {
    x: &'a i32,
    y: &'b i32
}

Case 2 Lifetime不满足要求

use std::fmt::Display;

fn dynamic_thread_print(t: Box<dyn Display + Send>) {
    std::thread::spawn(move || {
        println!("{}", t);
    }).join();
}

fn static_thread_print<T: Display + Send>(t: T) {
    std::thread::spawn(move || {
        println!("{}", t);
    }).join();
}
error[E0310]: the parameter type `T` may not live long enough
  --> src/main.rs:10:5
   |
9  | fn static_thread_print<T: Display + Send>(t: T) {
   |                        -- help: consider adding an explicit lifetime bound...: `T: 'static +`
10 |     std::thread::spawn(move || {
   |     ^^^^^^^^^^^^^^^^^^ ...so that the type `[closure@src/main.rs:10:24: 12:6]` will meet its required lifetime bounds

这是因为std::thread::spawn要求其内部捕获的类型需要满足'static约束,因此会编译出错,要求给T添加'static约束,但是为什么dynamic_thread_print函数中没有要求t有'static的生命周期约束呢?这是因为编译器给我们默认添加了。对于所有的trait对象编译器有着一套规则来给其添加生命周期约束,下面是具体的规则。

use std::cell::Ref;

trait Trait {}

// 展开前
type T1 = Box<dyn Trait>;
// 展开后,Box<T> 没有对 T 的生命周期约束,所以推导为 'static
type T2 = Box<dyn Trait + 'static>;

// 展开前
impl dyn Trait {}
// 展开后
impl dyn Trait + 'static {}

// 展开前
type T3<'a> = &'a dyn Trait;
// 展开后,&'a T 要求 T: 'a, 所以推导为 'a
type T4<'a> = &'a (dyn Trait + 'a);

// 展开前
type T5<'a> = Ref<'a, dyn Trait>;
// 展开后,Ref<'a, T> 要求 T: 'a, 所以推导为 'a
type T6<'a> = Ref<'a, dyn Trait + 'a>;

trait GenericTrait<'a>: 'a {}

// 展开前
type T7<'a> = Box<dyn GenericTrait<'a>>;
// 展开后
type T8<'a> = Box<dyn GenericTrait<'a> + 'a>;

// 展开前
impl<'a> dyn GenericTrait<'a> {}
// 展开后
impl<'a> dyn GenericTrait<'a> + 'a {}

给予T ‘static这样的约束即可。