A compile error about lifetime

Following is my code:

pub trait Scalar: Sized {}
impl Scalar for i32 {}
impl Scalar for f32 {}
impl Scalar for u32 {}

pub trait RowIndex<T: Scalar> {
    type Slice<'a> where Self: 'a;
    fn slice_index(&self, start: usize, end: usize) -> Self::Slice<'_>;
}


fn ol<'a, T: RowIndex<K, Slice<'a> = Z> + 'a, K: Scalar, Z>(x: T) {
    let mut res = vec![];
    for i in 1..4 {
        let data = x.slice_index((i - 1) * 10, i * 10);
        res.push(data);
    }
}

The compile error:

error[E0597]: `x` does not live long enough
  --> src/lib.rs:15:20
   |
12 | fn ol<'a, T: RowIndex<K, Slice<'a> = Z> + 'a, K: Scalar, Z>(x: T) {
   |       -- lifetime `'a` defined here
...
15 |         let data = x.slice_index((i - 1) * 10, i * 10);
   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |                    |
   |                    borrowed value does not live long enough
   |                    argument requires that `x` is borrowed for `'a`
...
18 | }
   | - `x` dropped here while still borrowed

For more information about this error, try `rustc --explain E0597`.
error: could not compile `playground` due to previous error

In my understanding, for each iteration, a new data will be generated, and its lifetime is 'a. And x has a lifetime longer than 'a. Why this error happen?

Lifetime arguments to a function are chosen by the caller, so they could be arbitrarily long, and in any csee they are always talking about lifetimes outside of the function. The x variable is owned by the function and dropped when it exits, so it cannot be borrowed for the lifetime 'a.

You should presumably review the trait bounds involved to figure out why a longer borrow was required in the first place, and whether this rewuirement can be avoided. Or x could be passed in as a reference with the relevant lifetime.

1 Like

x doesn't have a lifetime at all, as it is taken by value, not by reference. That means x is dropped after the function is finished. I think you misinterpreted the lifetime in your trait bound T: RowIndex<K, Slice<'a> = Z> + 'a . The + 'a does not mean x will live as long as 'a, but that the concrete implementation of T will not contain any references that won't live at least as long as 'a. See here. Passing x by reference will work though:

pub trait Scalar: Sized {}
impl Scalar for i32 {}
impl Scalar for f32 {}
impl Scalar for u32 {}

pub trait RowIndex<T: Scalar> {
    type Slice<'a> where Self: 'a;
    fn slice_index(&self, start: usize, end: usize) -> Self::Slice<'_>;
}


fn ol<'a, T: RowIndex<K, Slice<'a> = Z> + 'a, K: Scalar, Z>(x: &'a T) {
    let mut res = vec![];
    for i in 1..4 {
        let data = x.slice_index((i - 1) * 10, i * 10);
        res.push(data);
    }
}

Playground.

2 Likes

Thanks very much, this is exactly what I am misunderstanding.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.