Why this impl type lifetime may not live long enough

I am trying play around the trait object and I met this issue:

use std::collections::HashMap;

trait A {}

struct App {
    table: HashMap<String, Box<dyn A>>,
}

// this commented snippet of code is fine
// impl App {
//     fn register(&mut self, app: impl A + 'static) {
//         self.table.insert(String::from("a"), Box::new(app));
//     }
// }

// this one gives me: the parameter type `impl A + 'a` may not live long enough
impl App {
    fn register<'s, 'a: 's>(&'s mut self, app: impl A + 'a) {
        self.table.insert(String::from("a"), Box::new(app));
    }
}

As I remember, 'a:'s means 'a cover the lifetime of 's. Doesn't app: impl A + 'a live longer than 's self? So the why the app may not live long enough?

Thanks!

The problem you have here is that the Box<dyn A> in App is a Box<dyn A + 'static> -- App doesn't have any lifetime parameters, so it's allowed to be moved out of any scope, which means that you can't have put anything into it that's tied to a smaller scope.

If you want to put non-'static things into an App, you'll need something like this:

struct App<'a> {
    table: HashMap<String, Box<dyn A + 'a>>,
}

impl<'a> App<'a> {
    fn register(&mut self, app: impl A + 'a) {
        self.table.insert(String::from("a"), Box::new(app));
    }
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=78b9a748201c84a8b839a7cabc8a32a2

2 Likes