I'm trying to make a node structure but I have no idea why this won't compile (Rust playground):
trait SomeTrait {}
struct SomeObject<'a> {
something: &'a dyn SomeTrait,
}
impl<'a> SomeTrait for SomeObject<'a> {}
struct OtherObject {}
impl SomeTrait for OtherObject {}
pub struct Node {
children: Vec<Box<dyn SomeTrait>>,
}
fn main() {
let a = vec![OtherObject {}];
let b: Vec<Box<dyn SomeTrait>> = a
.iter()
.map(|d| Box::new(SomeObject { something: d }) as Box<dyn SomeTrait>)
.collect();
//But if i comment this it's fine... why?
Box::new(Node { children: b });
}
error[E0597]: `a` does not live long enough
--> src/main.rs:17:38
|
17 | let b: Vec<Box<dyn SomeTrait>> = a
| ^ borrowed value does not live long enough
18 | .iter()
19 | .map(|d| Box::new(SomeObject { something: d }) as Box<dyn SomeTrait>)
| ----------------------------------------------------------- returning this value requires that `a` is borrowed for `'static`
...
24 | }
| - `a` dropped here while still borrowed
Why does it say that a
is still in use? Shouldn't the other variables be dropped before?
Fixed version:
trait SomeTrait {}
struct SomeObject<'a> {
something: &'a dyn SomeTrait,
}
impl<'a> SomeTrait for SomeObject<'a> {}
struct OtherObject {}
impl SomeTrait for OtherObject {}
pub struct Node<'a> {
children: Vec<Box<dyn SomeTrait + 'a>>,
}
fn main() {
let a = vec![OtherObject {}];
let b: Vec<Box<dyn SomeTrait>> = a
.iter()
.map(|d| Box::new(SomeObject { something: d }) as Box<dyn SomeTrait>)
.collect();
Box::new(Node { children: b });
}
So, what's the problem ?
pub struct Node {
children: Vec<Box<dyn SomeTrait>>,
}
is the same as
pub struct Node {
children: Vec<Box<dyn SomeTrait + 'static>>,
}
which means (1,2) that the SomeTriat
objects must not hold any references that are not 'static
. But you have:
.map(|d| Box::new(SomeObject { something: d }) as Box<dyn SomeTrait>)
where |d|
is actually a reference that does not live for as long as 'static
(it is valid for as long as the vector a
is in scope, which is less than 'static
), therefore the error message:
returning this value requires that `a` is borrowed for `'static`
By making your Node
object generic over the lifetime parameter 'a
, you can lift that restriction. After that change, your Node<'a>
objects will be bounded by the lifetime of .map(|d|...)
reference