盒装结构包含引用时的降序
Drop order for when boxed struct contains reference
我正在尝试制作一个节点结构,但我不知道为什么它无法编译 (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
为什么说a
还在用呢?之前不应该去掉其他变量吗?
Node
的类型:
pub struct Node {
children: Vec<Box<dyn SomeTrait>>,
}
不捕获任何生命周期信息,即使 SomeTrait
的具体实现,即 SomeObject
带有引用。然后借用检查器必须推断此生命周期为 'static
,就好像你写了:
pub struct Node {
children: Vec<Box<dyn SomeTrait + 'static>>,
}
您可以通过表达 Node
可能 包含非静态引用来解决此问题:
pub struct Node<'a> {
children: Vec<Box<dyn SomeTrait + 'a>>,
}
这允许借用检查器正确跟踪借用。
固定版本:
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 });
}
那么,问题是什么?
pub struct Node {
children: Vec<Box<dyn SomeTrait>>,
}
与
相同
pub struct Node {
children: Vec<Box<dyn SomeTrait + 'static>>,
}
这意味着 (1,2) SomeTriat
对象不得包含任何非 'static
的引用。但是你有:
.map(|d| Box::new(SomeObject { something: d }) as Box<dyn SomeTrait>)
其中 |d|
实际上是一个引用,它的寿命不会像 'static
一样长(只要向量 a
在范围内,它就有效,这是更少的比 'static
),因此错误消息:
returning this value requires that `a` is borrowed for `'static`
通过使您的 Node
对象在生命周期参数 'a
上通用,您可以解除该限制。更改后,您的 Node<'a>
对象将受 .map(|d|...)
引用
的生命周期限制
资源:
我正在尝试制作一个节点结构,但我不知道为什么它无法编译 (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
为什么说a
还在用呢?之前不应该去掉其他变量吗?
Node
的类型:
pub struct Node {
children: Vec<Box<dyn SomeTrait>>,
}
不捕获任何生命周期信息,即使 SomeTrait
的具体实现,即 SomeObject
带有引用。然后借用检查器必须推断此生命周期为 'static
,就好像你写了:
pub struct Node {
children: Vec<Box<dyn SomeTrait + 'static>>,
}
您可以通过表达 Node
可能 包含非静态引用来解决此问题:
pub struct Node<'a> {
children: Vec<Box<dyn SomeTrait + 'a>>,
}
这允许借用检查器正确跟踪借用。
固定版本:
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 });
}
那么,问题是什么?
pub struct Node {
children: Vec<Box<dyn SomeTrait>>,
}
与
相同pub struct Node {
children: Vec<Box<dyn SomeTrait + 'static>>,
}
这意味着 (1,2) SomeTriat
对象不得包含任何非 'static
的引用。但是你有:
.map(|d| Box::new(SomeObject { something: d }) as Box<dyn SomeTrait>)
其中 |d|
实际上是一个引用,它的寿命不会像 'static
一样长(只要向量 a
在范围内,它就有效,这是更少的比 'static
),因此错误消息:
returning this value requires that `a` is borrowed for `'static`
通过使您的 Node
对象在生命周期参数 'a
上通用,您可以解除该限制。更改后,您的 Node<'a>
对象将受 .map(|d|...)
引用