Lifetime error with trait object

I am using following pattern of code in my program.

use std::fmt::Debug;

pub type Input<D> = Box<dyn Pipeline<D,Item=D>>;

pub trait Pipeline<D,Item=D>: Iterator<Item=D> + Repeater<D>
    where D: Debug + Clone
{
}

pub trait Repeater<D> where D: Debug + Clone {
    fn repeat(&self) -> Input<D>;
}


pub struct Identity<D> where D: Debug + Clone {
    items: Vec<D>,
    offset: usize,
}

impl<D> Repeater<D> for Identity<D> where D: Debug + Clone {
    fn repeat(&self) -> Input<D> {
        Box::new(Identity{items: self.items.clone(), offset:0})
    }
}

impl<D> Iterator for Identity<D> where D: Debug + Clone {
    type Item=D;

    fn next(&mut self) -> Option<D> {
        if self.offset >= self.items.len() { return None }
        let n = self.offset;
        self.offset += 1;
        Some(self.items[n].clone())
    }
}

impl<D> Pipeline<D> for Identity<D> where D: Debug + Clone {
}

fn main() {
    let mut a = Identity{items: vec![1,2,3,4], offset: 0};
    println!("first {:?}", a.next());
}

And I am getting the following error:

error[E0310]: the parameter type `D` may not live long enough        
  --> trait_object.rs:22:9                                           
   |                                                                 
20 | impl<D> Repeater<D> for Identity<D> where D: Debug + Clone {    
   |      - help: consider adding an explicit lifetime bound `D: 'sta
21 |     fn repeat(&self) -> Input<D> {                              
22 |         Box::new(Identity{items: self.items.clone(), offset:0}) 
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
   |                                                                 
note: ...so that the type `Identity<D>` will meet its required lifeti
  --> trait_object.rs:22:9                                           
   |                                                                 
22 |         Box::new(Identity{items: self.items.clone(), offset:0}) 

Here Box::new(Identity{}) is allocated in heap, and D is got as owned value from the iterator. Not able to understand where the lifetime issue come from. How to fix this error ? Any help much appreciated.

Thanks,

By default, boxes are static. Even though you’re using D as values, that type might contain non-static references within. You could try specifying D: 'static, or you could make your boxed type use generic lifetimes like:

pub type Input<'a, D: 'a> = Box<dyn Pipeline<D,Item=D> + 'a>;

(I’m on mobile, so I didn’t actually try this yet…)

1 Like

Vow, it does work. Thank you so much. Now I have to stare at this solution until I get enlightenment. :slight_smile:
Thanks again,

So we are essentially doing is - to tied down the lifetime of D to lifetime of the trait object. Right ? And it does make sense, because I can always have implementation that returns a different type implementing Pipeline but has its field refer to Identity::Item, instead of cloning it.

Thanks,