A question about the lifetime

TL;DR I passed some parameter by value to a function, and return some other value (rather than reference), but the compiler complained about a lifetime problem.

The minimum reproduction sample code is placed at
https://github.com/astrojhgu/lifetime_test

I’m implementing a kmeans algorithm.

In order to do that, I need to first create an Inner Product space trait, which represents a type that can calculate inner product between any two vars of this type, based on which distance can be defined.

The definition of the trait is

//an inner product space is firstly linear space, 
//so that Add, Sub operators between two elements in the space should be defined. 
//Besides, the mul operator to a scalar should be defined. 

//So that Add, Sub and Mul traits should be implemented beforehand.

pub trait InnerProdSpace<'a, Scalar>
    where
        Scalar: Float,
        Self: 'a + Sized,
 //I don't want the op consume the input values 
//so I require &Self, rather Self to impl the Add trait. Same for Sub and Mul.
//As a result, lifetime parameter 'a appeared in the trait's definition.

        &'a Self: Add<Output = Self>,
        &'a Self: Sub<Output = Self>,
        &'a Self: Mul<Scalar, Output = Self>,
{
    fn dot(&self, rhs: &Self) -> Scalar;//inner product should be implemented by user

    fn distance_to(&'a self, rhs: &'a Self) -> Scalar
    {
        let d=self-rhs;
        d.dot(&d).sqrt()
    }
}

Then I write the kmeans function as follows

pub fn kmeans<'a, Scalar, T>(points: Vec<T>, mut seeds: Vec<T>) -> Vec<Vec<T>>
where
    T: InnerProdSpace<'a, Scalar>,
    &'a T: Add<Output = T>,
    &'a T: Sub<Output = T>,
    &'a T: Mul<Scalar, Output = T>,
    Scalar: Float,
{
    let k = seeds.len();

    for p in &points {
//               ^^^^^^^ borrowed value does not live long enough
        let aa:Vec<_> = seeds
            .iter().map(|a|{
            a.distance_to(p)
        }).collect();
    }

    //place an empty result here to make the compiler happy
    vec![vec![]]
}

You are having lifetime issues because of your trait definition. Instead of using concrete lifetimes there, use HRTB (Higher Rank Trait Bounds) for the trait bounds on the operators.

for<'a> &'a Self: Add<Output=Self>

This means, “for all lifetimes this constraint is satified.”

1 Like

Thanks, it works.