struct TestStruct<F> {
param: F,
}
trait TestTrait {}
impl<F> TestTrait for TestStruct<F> {}
fn t<F>(input: F) -> Box<dyn TestTrait> {
Box::new(TestStruct { param: input }) // error here
}
error[E0310]: the parameter type `F` may not live long enough
--> src/main.rs:22:5
|
22 | Box::new(TestStruct { param: input }) //
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| the parameter type `F` must be valid for the static lifetime...
| ...so that the type `F` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound
|
21 | fn t<F: 'static>(input: F) -> Box<dyn TestTrait> {
| +++++++++
For more information about this error, try `rustc --explain E0310`.
This seems to happens only for generics, i tried input: Box<dyn trait>
/input: Struct
and some other types, maybe i'm wrong about only for generics
.
Add 'static
to fn t<F: 'static>
works.
And '_
works inside traits:
struct TestStruct<F> {
param: F,
}
trait TestTrait {}
impl<F> TestTrait for TestStruct<F> {}
impl<F> TestStruct<F> {
fn t(&self, input: F) -> Box<dyn TestTrait + '_> { // add `'_` here will compile, but not for the example above
// is it the same as adding `'static` at `impl<F: 'static>`?
Box::new(TestStruct { param: input })
}
}
I don't understand why it's needed and why 'static
.
Consider what would happen if your t
function is invoked with an input
that contains a borrow of shorter lifetime than 'static
:
let s = String::from("foo");
let boxed_trait_object = t(s.as_str());
drop(s);
When s
is dropped, boxed_trait_object
contains a reference to freed memory: undefined behaviour. The compiler sees that the returned trait object is not constrained by any lifetime and therefore requires F: 'static
to prevent situations like the above.
However, we can instead add a lifetime parameter to the function signature:
fn t<'a, F: 'a>(input: F) -> Box<dyn 'a + TestTrait> {
Box::new(TestStruct { param: input })
}
Here we are saying that the returned trait object is constrained to the lifetime of the borrows in input
(if any).