Search code examples
rusttrait-objects

How to apply a lifetime to VecDeque<Box<dyn Trait>>?


I'm trying to create a VecDeque of structs that all implement an Animal trait. This code works, but I don't understand why adding ' static fixes it and how to make it use 'a instead.

pub trait Animal {
    fn says(self) -> Option<String>;
}

use std::collections::VecDeque;

pub struct Zoo {
    list: VecDeque<Box<dyn Animal>>,
}

impl Zoo {
    pub fn new() -> Zoo {
        Zoo {
            list: VecDeque::new(),
        }
    }

    pub fn add<T>(&mut self, animal: T)
    where
        T: Animal + 'static,
    {
        self.list.push_back(Box::new(animal));
    }
}

Two questions:

  1. Could someone please explain how to use 'a properly and how this would work / what it would mean? And also I guess why I even need a lifetime here (is it because I'm using Box)?
  2. I'm also confused why I have to use #[path="..."] since without it, it asks me to move the file to src/lib/animal.rs but when I move it, that still doesn't work.

Solution

  • As already pointed out, Box<dyn Animal> is equivalent to Box<dyn Animal + 'static>, which means a pointer to something which is valid through the whole program (like string literals). This is probably not what you want.

    You want it such that your Zoo cannot live longer than your Animals. (This is what the compiler will enforce). So you annotate Zoo with a lifetime 'a and you require that every Animal which is stored in the Zoo lives at least as long as 'a:

    pub struct Zoo<'a> {
        animals: VecDeque<Box<dyn Animal + 'a>>,
    }   
    

    The compiler will check whether your lifetime annotations will make sense and enforce that a reference cannot outlive an object.