A lifetime error

Following is my code( I made a playground for it), if can not compile.

struct DataSave {
    n: Vec<i32>,
    m: Vec<f32>,
}

trait PlusNumber {
    type A<'a>: where Self: 'a;
    type B;
    fn a_func_existed<'c, 'a>(&'c self, v: &'a DataSave) -> Self::A<'a>;
    fn plus_number<'c, 'a>(&'c self, v: Self::A<'a>) -> Self::B;
}

struct PlusOne;
struct PlusTwo;

impl PlusNumber for PlusOne {
    type A<'a> = &'a Vec<i32>;
    type B = Vec<i32>;

    fn a_func_existed<'c, 'a>(&'c self, v: &'a DataSave) -> Self::A<'a> {
        &v.n
    }

    fn plus_number<'c, 'a>(&'c self, v: Self::A<'a>) -> Self::B {
        v.iter().map(|x| x + 1).collect()
    }
}

struct DataFunc<'a, T, N> {
    data: &'a Vec<T>,
    func: N
}

trait SelectCalc {
    fn select_calc<'a, 'b, 'k, T, N, K>(&self, v: &DataFunc<'b, T, N>) -> Vec<K>
    where
        T: Clone + 'k,
        N: PlusNumber<A<'a> = &'k Vec<T>, B = Vec<K>> + 'static,
    ;
}


struct CalcHeader;

impl SelectCalc for CalcHeader {
    fn select_calc<'a, 'b, 'k, T, N, K>(&self, v: &DataFunc<'b, T, N>) -> Vec<K>
    where
        T: Clone + 'k,
        N: PlusNumber<A<'a> = &'k Vec<T>, B = Vec<K>> + 'static,
    {
        let mut res = Vec::new();
        let data_part = v.data[..10].to_vec();
        let res_part1 = &mut v.func.plus_number(&data_part);
        res.append(res_part1);
        res
    }
}

Here is the compile error:

[E0597] Error: `data_part` does not live long enough
    โ•ญโ”€[command_6:1:1]
    โ”‚
  4 โ”‚     fn select_calc<'a, 'b, 'k, T, N, K>(&self, v: &DataFunc<'b, T, N>) -> Vec<K>
    ยท                            โ”€โ”ฌ  
    ยท                             โ•ฐโ”€โ”€ lifetime `'k` defined here
    ยท 
 11 โ”‚         let res_part1 = &mut v.func.plus_number(&data_part);
    ยท                              โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€  
    ยท                                             โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ argument requires that `data_part` is borrowed for `'k`
    ยท                                                      โ”‚       
    ยท                                                      โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€ borrowed value does not live long enough
    ยท 
 14 โ”‚     }
    ยท     โ”ฌ  
    ยท     โ•ฐโ”€โ”€ `data_part` dropped here while still borrowed
โ”€โ”€โ”€โ”€โ•ฏ

How can I make it right?

You are using more than 2 explicit lifetimes; this is likely a sign of abuse, way too convoluted, and almost always unnecessary (on a single function at least).

By removing all the excessive lifetimes, one can see more clearly that the compiler complains about the local variable not satisfying some arbitrary lifetime parameter.

Your misunderstanding is that you think you can use a generic lifetime parameter here. You can't, because generic parameters are chosen by the caller. Here, there's no way a caller can specify a short enough lifetime that can be satisfied by a reference to a local variable inside the callee. That's impossible by definition. (The callee necessarily has a shorter lifetime/narrower scope than its caller.)

What you want instead is to tell the compiler that the given type must work for all lifetimes, which is a HRTB (since it's another level of universal quantification up from a simple generic parameter). Accordingly, the annotation for<'b> PlusNumber<A<'b> = &'b Vec<T>, โ€ฆ> compiles as expected.

5 Likes