rustlifetime-scoping

Cast requires that variable is borrowed for 'static


pub struct IterOverVecVec<'a> {
    m: &'a dyn IterTrait,
}

impl<'a> Iterator for IterOverVecVec<'a> {
    type Item = u16;
    fn next(&mut self) -> Option<Self::Item> {
        Some(1)
    }
}

impl<'a> IterOverVecVec<'a> {
    fn new(m: &'a dyn IterTrait) -> Self {
        Self { m }
    }
}

pub trait IterTrait {}

impl<'b> dyn IterTrait {
    pub fn get_iter<'a>(&'a self) -> IterOverVecVec<'a> {
        IterOverVecVec::new(self)
    }
}

pub struct HasAVec<'a> {
    m: &'a Vec<Vec<u16>>,
}

impl<'a> IterTrait for HasAVec<'a> {}

impl<'a> HasAVec<'a> {
    pub fn new(m: &'a Vec<Vec<u16>>) -> Self {
        Self { m }
    }
}

#[test]
fn fails() {
    let vecvec: Vec<Vec<u16>> = vec![vec![1, 2, 3], vec![4, 5, 6]];
    let struct_with_vecs = HasAVec::new(&vecvec);
    let ni = <dyn IterTrait>::get_iter(&struct_with_vecs);
}
error[E0597]: `vecvec` does not live long enough
  --> src/lib.rs:41:41
   |
41 |     let struct_with_vecs = HasAVec::new(&vecvec);
   |                                         ^^^^^^^ borrowed value does not live long enough
42 |     let ni = <dyn IterTrait>::get_iter(&struct_with_vecs);
   |                                        ----------------- cast requires that `vecvec` is borrowed for `'static`
43 | }
   | - `vecvec` dropped here while still borrowed

Link to playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=5d7b88a4a261821fabfd0228e8ef8b2c

My understanding of the root cause is: after struct_with_vecs is cast to the trait type on line 33, the compiler tries to infer it's (new?) lifetime and somehow arrives at 'static, and since I don't have the correct lifetime annotations, it errors out.

The closest thing to my issue that I found is a Rust forums thread ( https://users.rust-lang.org/t/argument-requires-that-is-borrowed-for-static/66503/2 ) which if I understand correctly, says that in a case like this one, Rust tries to apply the longest possible lifetime. However, I was not able to apply the solution from that question to my problem, since there is seems to me to be caused by closures which I am not using.

So my question goes, how do I make use of IterTrait::get_iter() without vecvec getting borrowed for 'static?


Solution

  • The reason rustc arrives at 'static is because dyn Trait is dyn Trait + 'static. To allow other lifetimes you should use dyn Trait + 'lifetime, or dyn Trait + '_ with the elided lifetime.

    If you replace

    impl dyn IterTrait {
    

    with

    impl dyn IterTrait + '_ {
    

    Then it works (playground).