1

Here, the compiler complains that impl Foo may not live long enough:

struct VecWrapper(Vec<Box<dyn Foo>>);

impl VecWrapper {
    fn push(&mut self, item: impl Foo) {
        self.0.push(Box::new(item))
    }
}

trait Foo {}

This is not what I expect, because item should be moved into the Box. The compiler recommends adding a static lifetime:

  |
4 |     fn push(&mut self, item: impl Foo + 'static) {
  |                                       +++++++++

In my case, item and VecWrapper are created at runtime for error handling, so I would like to avoid using lifetimes here.

Krish
  • 1,044
  • 9
  • 20
  • 2
    I think you misunderstand what `'static` means here, it does **not** mean "for the entire lifetime of the program". It means that the variable `item` does not contain any references to other variables, but instead is its own independent object. And that is very much what you want, I guess. – Finomnis Dec 24 '22 at 20:49
  • 1
    THANK YOU!! I did not realize `'static` has [two](https://doc.rust-lang.org/rust-by-example/scope/lifetime/static_lifetime.html) subtly different meanings – Krish Dec 24 '22 at 21:06
  • 1
    Technically they are both identical, it's just that it's hard to create a static **reference** (e.g. `&'static`) that doesn't live for the entire duration of the program (because a reference always carries the lifetime of the object it references, so a reference that doesn't carry a lifetime is only possible if the referenced thing lives for the entire duration of the program). So that's why it is often simplified to mean "for the entire duration", but technically, that is always just half the truth. – Finomnis Dec 24 '22 at 21:34
  • 1
    Just to demonstrate: a static reference can also be generated via `Box::leak()`, which leaks a dynamic variable to a static reference. In that case it definitely doesn't live for the entire duration, but only for the leaking point onward. – Finomnis Dec 24 '22 at 21:41

1 Answers1

-1

Your trait can be implemented by something like struct Bar<'a, T>(&'a T);, if you pass a value of this type to your function, your struct would not sufficiently reflect the lifetime 'a imposed by &'a T.

You can add a lifetime to VecWrapper and put that lifetime on impl Foo if you don't want to restrict VecWrapper to owned types. Adding a 'static bound to impl Foo would limit VecWrapper to owned types.

struct VecWrapper<'a>(Vec<Box<dyn Foo + 'a>>);

impl<'a> VecWrapper<'a> {
    fn push(&mut self, item: impl Foo + 'a) {
        self.0.push(Box::new(item))
    }
}

trait Foo {}

struct Bar<'a, T>(&'a T);

impl<'a, T> Foo for Bar<'a, T> {
    
}

fn foo() {
    let s = String::new();
    VecWrapper(vec![]).push(Bar(&s));
}
sebpuetz
  • 2,430
  • 1
  • 7
  • 15