当有一个涉及可变/不可变引用的函数作为具有(嵌套)生命周期的参数时,编译器如何处理借用?

时间:2018-06-14 07:26:47

标签: rust lifetime borrow-checker

fn func_vecmut<'a>(v: &'a mut Vec<&'a i32>, s: &'a String) {}

fn func_vecmut_fresh_lf<'a, 'b>(v: &'a mut Vec<&'a i32>, s: &'b String) {}

fn func_vec<'a>(v: &'a Vec<&'a i32>, s: &'a String) {}

fn main() {
    let mut v = vec![];
    {
        let s: String = String::from("abc");

        /* Note: Below, only one function call is active at a time, other two commented out */
        func_vecmut(&mut v, &s);          // Understandably, compiler fails this.
        func_vecmut_fresh_lf(&mut v, &s); // Understandably, compiler passes this i.e with fresh lifetime for String.
        func_vec(&v, &s);                 // Why does compiler pass this?
    }
}

func_vecmut中(据我所知),编译器发现String的生命周期与Vec的生命周期和它所拥有的元素(i32)相同。并且由于v的寿命更长(在块外定义),它会将借位扩展到s超出块的范围(即s的来世),因此会出现以下错误:

error[E0597]: `s` does not live long enough
  --> src/main.rs:13:30
   |
13 |         func_vecmut(&mut v, &s);          // Understandably, compiler fails this.
   |                              ^ borrowed value does not live long enough
...
16 |     }
   |     - `s` dropped here while still borrowed
17 | }
   | - borrowed value needs to live until here

可以通过为String参数赋予新的生命周期来解决问题(参见func_vecmut_fresh_lf)。

但是,为什么func_vec(&v, &s)的编译不会失败?唯一的区别是&mut Vec。这与不可变引用是Copy这一事实有关,而可变引用则不是这样吗?如果是的话,怎么样?函数体是空的,编译器在这里推断出什么?

0 个答案:

没有答案