I don't understand: consider adding an explicit lifetime bound ..... +'static

I have this problem in one of my developments. I looked in other posts for similar problems, but each time I didn't understand the cause and the possible solutions.

I have reduced my code to this example:

trait T1{}

struct A<G: T1> {
    a: G,
}

trait T2{
    fn create(self) -> Box<dyn T3>;
} 

trait T3 {}

struct B<G: T1>{
    a: G
}

impl<G: T1> T3 for B<G> {}

impl<G: T1> T2 for A<G> {
    fn create(self) -> Box<dyn T3>{
        let b: Box<dyn T3>  = Box::new(B{a: self.a});
        b
    }
}

playground

I've got this error:
error[E0310]: the parameter type G may not live long enough

a: self.a a is moved so why it doesn't live long enough ? ( and self will be deleted)
How to create Box<dyn T3> in the function create ?

Thank you very much for your help.

When you coerce G to dyn T3, you're actually coercing it to dyn T3 + 'some_lifetime, where G has to be valid for 'some_lifetime.

That is, you can only coerce G to dyn T3 + 'g if G: T3 + 'g.[1]

Outside of function bodies, Box<dyn Trait> is short for Box<dyn Trait + 'static>.[2] So the signature you have with less lifetime elision is

impl<G: T1> T2 for A<G> {
    fn create(self) -> Box<dyn T3 + 'static> {

and the coercion is only possible if G: 'static:

//         vvvvvvvvv
impl<G: T1 + 'static> T2 for A<G> {
    fn create(self) -> Box<dyn T3> {

Or if you control the trait, you could make it more general.

trait T2 {
    fn create<'this>(self) -> Box<dyn T3 + 'this> where Self: Sized + 'this;
} 

impl<G: T1> T2 for A<G> {
    fn create<'this>(self) -> Box<dyn T3 + 'this> where Self: 'this {

(This works because A<G>: 'some_lifetime if G: 'some_lifetime, and vice-versa. See below.)

Rust lifetimes (those '_ things) are typically about the duration of borrows, or (as in this case) the validity of a type. They are not for example about how long an place or value exists before its destructor is called.[3] That these are both called "lifetimes" casually is an unfortunate overlap of terminology.

G: 'static is asserting a property of the type G itself, not of any particular value.[4] And the property is "G's fully resolved type mentions no lifetimes (except perhaps 'static)". More generally, for G: 'g the property is "all mentioned lifetimes satisfy 'lifetime: 'g".


  1. more about that ↩︎

  2. more about dyn lifetime elision ↩︎

  3. one might call that its liveness scope ↩︎

  4. In particular it doesn't mean the values never drop. String: 'static for example; that doesn't mean Strings never get deallocated. They do. ↩︎

4 Likes

Thanks for this complete answer, I understand the situation better. I haven't read the full link to "Learn Rust" yet, I'll read it now.

I had a bad interpretation of the concept of 'static. I thought 'static meant "valid for the entire duration of the program". If I understand better, this means either

  • valid for the entire duration of the program
  • the type does not contain temporary references,

Thanks again

T: 'static means[1] that the type T is "valid everywhere" because it "does not contain temporary references", or any other mention of a temporary lifetime.[2] Values of the type have the ability to "last forever" (but don't have to last forever and typically don't last forever, unless they're statics or leaked).

If you mean, "valid for the entire runtime of the program", then that's true of a value that has a type like &'static str or &'static mut SomeLeakedThing.


  1. well what I wrote before, but also effectively ↩︎

  2. "any other mention" is too niche to worry much about now probably; as a short example, dyn Trait<'a> + 'static does not meet a 'static bound ↩︎

Thanks. I think I need to know more about the rust type system.

And you were 100% correct! It's something that most Rust newbies pass through even if nobody may adequately explain why (after they “get it” they become initiated and could no longer explain what confused them).

What does it for a type to be “valid for the entire duration of the program”?
Well… that means… that means…
:bangbang::exclamation:that means that we could create a variable of that type then said variable could be 'static, that is: valid for the entire dutation of the program​:exclamation::bangbang:
And that's… correct answer!

Thus yes, 'static does mean that something should be “valid for the entire duration of the program”… only the fact that you have long-living type doesn't mean that every value of that type that you have is long-living, too!

If every variable of type i32 (most obviously a 'static type, that is: i32: 'static) would have to live till the end of program… that would be some kinda BASIC-wannabe, not Rust!

For some reason when newcomers see T: 'static they immediately jump to the conclusion that every variable of type T should be 'static… but that never implied and never hinted in any description of Rust that I know of!

I recommend every rust programmer to read Common Rust Lifetime Misconceptions at least once since it addresses this specific example and a bunch of others as well :slight_smile:

1 Like

Sorry for the delay, I'm a bit busy at the moment.
@khimru: Thanks for the clarification on 'static, it's actually a confusion I had between the type and the instance of the type.
@JustusFluegel: Thanks for the link, it's an amazing resource