Why would a Type need a lifetime?

The code below gives me the following error:

   Compiling playground v0.0.1 (/playground)
error[E0310]: the parameter type `T` may not live long enough
  --> src/lib.rs:21:25
   |
21 |         self.queue.push(Box::new(Watcher{obj}));
   |                         ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
   |
help: consider adding an explicit lifetime bound...
   |
20 |     fn register<T: 'static>(&mut self, obj: T) {
   |                  +++++++++

obj is moved, so I assume that it doesn't need a lifetime since it's now owned by the Watcher object in the Box. So why do I need a lifetime for the type parameter T. What would a lifetime mean for a type parameter?

If, as the compiler suggest, I add a static lifetime, it works. But what does this mean? Does it mean that T cannot take references as types?

Playground Link

struct Watcher<T> {
    obj: T,
}

trait Dispatchable {
    fn dispatch(&mut self);
}

impl<T> Dispatchable for Watcher<T> {
    fn dispatch(&mut self) {
    }
}

struct Loop {
    queue: Vec<Box<dyn Dispatchable>>,
}

impl Loop {
    fn register<T>(&mut self, obj: T) {
        self.queue.push(Box::new(Watcher{obj}));
    }
}

Essentially that, yes. Remember that &'a T is a type of its own, and it's not 'static by definition.

1 Like

I see, thanks. I didn't want to just use the solution the compiler was suggesting without understanding why. Thanks!

1 Like
  • T: 'static should be read as "T is bounded by a 'static lifetime"
  • if T: 'static then T can be a borrowed type with a 'static lifetime or an owned type

src: Common Rust Lifetime Misconceptions

Another solution is to tell the compiler T is able to live long enough than something:

struct Loop<'l> {
    queue: Vec<Box<dyn Dispatchable + 'l>>,
}

impl<'l> Loop<'l> {
    fn register<T: 'l>(&mut self, obj: T) {
        self.queue.push(Box::new(Watcher{obj}));
    }
}

But it's rarely what you really want.

2 Likes