Anotating lifetime when impenting trait

Here is the code:

pub trait ForeCalc {
    type A;
    type B;
    fn calc(&self, di: &Di, data: Self::A) -> Self::B;
}

impl ForeCalc for Rank {
    type A = &[f32];
    type B = Vec<f32>;
    fn calc(&self, _di: &Di, data: Self::A) -> Self::B {
        self.rank(data)
    }
}

I need to annotate that the lifetime of associated type A = &[f32]' in trait ForeCalc is shorter than the lifetime of paramter _di: &Di from trait ForeCalc method calc.

The code may look like this:

impl<'a> ForeCalc for Rank {
    type A = &'a [f32];
    type B = Vec<f32>;
    fn calc(&self, _di: &'a Di, data: Self::A) -> Self::B {
        self.rank(data)
    }
}

But I do not know how to write it down. What should I do?

Use GAT (Generic Associated Types).

pub trait ForeCalc {
    type A<'la>;
    type B;
    fn calc<'a>(&self, di: &'a Di, data: Self::A<'a>) -> Self::B;
}

impl ForeCalc for Rank {
    type A<'la> = &'la [f32];
    type B = Vec<f32>;
    fn calc<'a>(&self, _di: &'a Di, data: Self::A<'a>) -> Self::B {
        self.rank(data)
    }
}
2 Likes

Thanks for your solution.
There is a one more asking:

#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
pub struct Rank(pub usize, pub usize);
impl Rank {
    pub fn rank(&self, data: &[f32]) -> Vec<f32> {
        data.into_iter().map(|x| x + 1.0f32).collect()
    } 
}

pub trait CalcId {
    fn id(&self) -> String;
}

pub trait ForeCalc {
    type A<'l>;
    type B;
    fn calc<'l>(&self, di: &Di, data: Self::A<'l>) -> Self::B;
}

impl ForeCalc for Rank {
    type A<'l> = &'l [f32];
    type B = Vec<f32>;
    fn calc<'l>(&self, _di: &'l Di, data: Self::A<'l>) -> Self::B {
        self.rank(data)
    }
}

The code above fine. Then I need to implement trait CalcId for Rank, I tried do this:

impl<T, A, B> CalcId for T
where
    T: for<'l> ForeCalc<A<'l> = A, B = B> + Debug,
{
    fn id(&self) -> String {
        format!("{:?}", self)
    }
}

This can compile, but type Rank has not been implemented CalcId. I thought this may be a matter of lifetime syntax. What should I do?

A couple things here.

  1. You don't need to specify associated type if you don't use it. This works just fine.
impl<T> CalcId for T
where
    T: ForeCalc + std::fmt::Debug,
{
    fn id(&self) -> String {
        format!("{:?}", self)
    }
}

fn main() {
    println!("{}", Rank(2, 2).id());
}
  1. &[f32] is not a single type, instead, for every different lifetime 'a, &'a [f32] is a different type. So there's no type A satisfy for<'l> ForeCalc<A<'l> = A>
1 Like

So, there is no regular way I can explicitly write the lifetime, am I right?