A problem about lifetime annotation

The following is the code and what the error said. I do not paste the all code, because I think the solution may be simple. If nessacery I could paste the whole code.

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

pub trait Ta {
    type A<'a>: where Self: 'a;
    type B;
    fn from_di<'c, 'a>(&'c self, di: &'a Di) -> Self::A<'a>;
    fn from_da<'e, 'a>(&'e self, da: Self::A<'a>) -> Self::B;
}

impl<'a, K> ForeCalc for K 
where
    K: Ta<A<'a> = Vec<f32>, B = Vec<f32>> + 'static,
{
    type A = i32;
    type B = Vec<f32>;
    fn calc(&self, di: &'_ Di, _data: Self::A) -> Self::B
    {
        self.from_di(di)
    }
}
Error: lifetime may not live long enough
    โ•ญโ”€[command_42:1:1]
    โ”‚
  9 โ”‚ impl<'a, K> ForeCalc for K
    ยท      โ”€โ”ฌ  
    ยท       โ•ฐโ”€โ”€ lifetime `'a` defined here
    ยท 
 15 โ”‚     fn calc(&self, di: &'_ Di, _data: Self::A) -> Self::B
    ยท                        โ”ฌ  
    ยท                        โ•ฐโ”€โ”€ let's call the lifetime of this reference `'1`
    ยท 
 17 โ”‚         self.from_di(di)
    ยท         โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€  
    ยท                 โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ argument requires that `'1` must outlive `'a`
โ”€โ”€โ”€โ”€โ•ฏ

To diagnose this, weโ€™ll need to see the definitions of trait Ta and fn from_di at least. If you can, post enough code so that we can recreate the problem on the playground.

1 Like

Yes, I append the trait Ta in it.

The problem is that your bound on K only specifies the associated type A for the specific lifetime 'a, which might be different than the lifetime of the reference &Di. You need to instead require that for every possible lifetime 'a, A<'a>=Vec<f32>:


impl<K> ForeCalc for K 
where
    K: for<'a> Ta<A<'a> = Vec<f32>, B = Vec<f32>> + 'static,
{
    type A = i32;
    type B = Vec<f32>;
    fn calc(&self, di: & Di, _data: Self::A) -> Self::B
    {
        self.from_di(di)
    }
}
1 Like

Thank you for your solution.
After I changed my code, there is one more problem:
This works fine:

pub struct Rank(usize, usize);
impl Rank {
    pub fn rank(&self, data: Vec<f32>) -> Vec<f32> { 
        vec![1.0f32, 2, 3]
    }
}


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

impl<K> ForeCalc for K 
where
    K: for<'a> Ta<A<'a> = Vec<f32>, B = Vec<f32>> + 'static,
{
    type A = i32;
    type B = Vec<f32>;
    fn calc(&self, di: & Di, _data: Self::A) -> Self::B
    {
        self.from_di(di)
    }
}

But when I move Rank to my crate, the code crash.

//my crate: Outer.rs
pub struct Rank(usize, usize);
impl Rank {
    pub fn rank(&self, data: Vec<f32>) -> Vec<f32> { 
        vec![1.0f32, 2, 3]
    }
}

Then in main.rs

use crate::Outer;

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

impl<K> ForeCalc for K 
where
    K: for<'a> Ta<A<'a> = Vec<f32>, B = Vec<f32>> + 'static,
{
    type A = i32;
    type B = Vec<f32>;
    fn calc(&self, di: & Di, _data: Self::A) -> Self::B
    {
        self.from_di(di)
    }
}

[E0119] Error: conflicting implementations of trait `ForeCalc` for type `bt::aa::Rank`
   โ•ญโ”€[command_56:1:1]
   โ”‚
 1 โ”‚ impl ForeCalc for Rank {
   ยท โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€  
   ยท            โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ first implementation here
   ยท 
 9 โ”‚ impl<K> ForeCalc for K
   ยท โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€  
   ยท            โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ conflicting implementation for `bt::aa::Rank`
โ”€โ”€โ”€โ•ฏ

I guess the reason is:

When Rank comes from other crate, the compilter can not know if the Rank is implemented the trait ForeCalc. So, if Rank has been implemented ForeCalc, then

impl<K> ForeCalc for K 
where
    K: for<'a> Ta<A<'a> = Vec<f32>, B = Vec<f32>> + 'static,

this where make a duplicate implementing on Rank.

But when Rank comes from local file, the compiler does know weather the Rank has been implemted ForeCalc.
If this guess is true, what can I do to avoid it?