编译器建议我添加一个 'static 生命周期,因为参数类型的寿命可能不够长,但我认为这不是我想要的
Posted
技术标签:
【中文标题】编译器建议我添加一个 \'static 生命周期,因为参数类型的寿命可能不够长,但我认为这不是我想要的【英文标题】: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编译器建议我添加一个 'static 生命周期,因为参数类型的寿命可能不够长,但我认为这不是我想要的 【发布时间】:2017-02-24 11:58:33 【问题描述】:我正在尝试实现类似于这个最小示例的东西:
trait Bar<T>
struct Foo<T>
data: Vec<Box<Bar<T>>>,
impl<T> Foo<T>
fn add<U: Bar<T>>(&mut self, x: U)
self.data.push(Box::new(x));
由于 Rust 默认(据我所知)所有权传递,我的心智模型认为这应该有效。 add
方法获取对象 x
的所有权,并且能够将该对象移动到 Box
中,因为它知道完整类型 U
(而不仅仅是 trait Bar<T>
)。一旦移入Box
,盒子内的项目的生命周期应该与盒子的实际生命周期相关联(例如,当pop()
ed 离开向量时,对象将被销毁)。
然而,很明显,编译器不同意(而且我肯定比我知道的更多...),要求我考虑添加一个 'static
生命周期限定符 (E0310)。我 99% 确定这不是我想要的,但我不确定我应该做什么。
为了澄清我的想法并帮助识别误解,我来自 C++ 背景的心智模型是:
Box<T>
本质上是 std::unique_ptr<T>
没有任何注释,如果Copy
,变量按值传递,否则按右值引用传递
使用参考注释,&
大致为const&
,&mut
大致为&
默认生命周期是词法范围
【问题讨论】:
【参考方案1】:要求我考虑添加一个“静态生命周期限定符”(E0310)。我 99% 确定这不是我想要的,但我不确定我应该做什么。
是的。编译器不需要&'static
引用,它需要U: 'static
。
拥有U: 'static
意味着U
不包含生命周期小于'static
的引用。这是必需的,因为您想将 U
实例放入没有生命周期的结构中。
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));
【讨论】:
【参考方案2】:检查整个错误:
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));
| ^^^^^^^^^^^
具体来说,编译器让您知道某些任意类型 U
可能包含引用,然后该引用可能会变得无效:
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());
那将是坏消息。
您是否需要 'static
生命周期或参数化生命周期取决于您的需要。 'static
生命周期更易于使用,但有更多限制。因此,当您在结构或类型别名中声明 trait 对象 时,这是默认设置:
struct Foo<T>
data: Vec<Box<dyn Bar<T>>>,
// same as
// data: Vec<Box<dyn Bar<T> + 'static>>,
但是,当用作参数时,特征对象使用 生命周期省略 并获得唯一的生命周期:
fn foo(&self, x: Box<dyn Bar<T>>)
// same as
// fn foo<'a, 'b>(&'a self, x: Box<dyn Bar<T> + 'b>)
这两件事需要匹配。
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));
或
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));
【讨论】:
我无法充分表达这种解释的价值。非常感谢!以上是关于编译器建议我添加一个 'static 生命周期,因为参数类型的寿命可能不够长,但我认为这不是我想要的的主要内容,如果未能解决你的问题,请参考以下文章