The compiler suggests I add a 'static lifetime because the parameter type may not live long enough, but I don't think that's what I want
Check out the entire error:
error[E0310]: the parameter type `U` may not live long enough
--> src/main.rs:9:24
|
8 | fn add<U: Bar<T>>(&mut self, x: U) {
| -- help: consider adding an explicit lifetime bound `U: 'static`...
9 | self.data.push(Box::new(x));
| ^^^^^^^^^^^
|
note: ...so that the type `U` will meet its required lifetime bounds
--> src/main.rs:9:24
|
9 | self.data.push(Box::new(x));
| ^^^^^^^^^^^
Specifically, the compiler is letting you know that it's possible that some arbitrary type U
might contain a reference, and that reference could then become invalid:
impl<'a, T> Bar<T> for &'a str {}
fn main() {
let mut foo = Foo { data: vec![] };
{
let s = "oh no".to_string();
foo.add(s.as_ref());
}
}
That would be Bad News.
Whether you want a 'static
lifetime or a parameterized lifetime is up to your needs. The 'static
lifetime is easier to use, but has more restrictions. Because of this, it's the default when you declare a trait object in a struct or a type alias:
struct Foo<T> {
data: Vec<Box<dyn Bar<T>>>,
// same as
// data: Vec<Box<dyn Bar<T> + 'static>>,
}
However, when used as an argument, a trait object uses lifetime elision and gets a unique lifetime:
fn foo(&self, x: Box<dyn Bar<T>>)
// same as
// fn foo<'a, 'b>(&'a self, x: Box<dyn Bar<T> + 'b>)
These two things need to match up.
struct Foo<'a, T> {
data: Vec<Box<dyn Bar<T> + 'a>>,
}
impl<'a, T> Foo<'a, T> {
fn add<U>(&mut self, x: U)
where
U: Bar<T> + 'a,
{
self.data.push(Box::new(x));
}
}
or
struct Foo<T> {
data: Vec<Box<dyn Bar<T>>>,
}
impl<T> Foo<T> {
fn add<U>(&mut self, x: U)
where
U: Bar<T> + 'static,
{
self.data.push(Box::new(x));
}
}
asking me to consider adding a 'static lifetime qualifier (E0310). I am 99% sure that's not what I want, but I'm not exactly sure what I'm supposed to do.
Yes it is. The compiler does not want a &'static
reference, it wants U: 'static
.
Having U: 'static
means that U
contains no references with a lifetime less than 'static
. This is required because you want to put a U
instance in a structure without lifetimes.
trait Bar<T> {}
struct Foo<T> {
data: Vec<Box<dyn Bar<T>>>,
}
impl<T> Foo<T> {
fn add<U: Bar<T> + 'static>(&mut self, x: U) {
self.data.push(Box::new(x));
}
}