编者注:在RFC 599实施后,此代码不再产生相同的错误,但答案中讨论的概念仍然有效。
我正在尝试编译此代码:
trait A {
fn f(&self);
}
struct S {
a: Box<A>,
}
我收到此错误:
a.rs:6:13: 6:14 error: explicit lifetime bound required
a.rs:6 a: Box<A>,
我希望S.a
拥有A
的实例,并且不知道这个生命周期是如何合适的。我需要做些什么才能使编译器满意?
My Rust版本:
rustc --version
rustc 0.12.0-pre-nightly (79a5448f4 2014-09-13 20:36:02 +0000)
答案 0 :(得分:21)
(稍微迂腐一点:A
是一个特质,因此S
不拥有 A
的实例,它拥有一个盒装实例<实现A
的某种类型的em>。)
特征对象表示具有某种未知类型的数据,也就是说,唯一知道的数据是它实现了特征A
。由于类型未知,编译器无法直接推断所包含数据的生命周期,因此要求在trait对象类型中明确说明此信息。
这是通过Trait+'lifetime
完成的。最简单的方法是使用'static
,即完全禁止存储因范围而变得无效的数据:
a: Box<A + 'static>
以前,(在引入有生命限制的特征对象和此explicit lifetime bound required
错误消息的可能性之前),所有盒装特征对象都是隐式'static
,也就是说,这种限制形式是唯一的选择。
最灵活的形式是在外部暴露生命周期:
struct S<'x> {
a: Box<A + 'x>
}
这允许S
存储实现A
的任何类型的特征对象,可能对S
有效的范围有一些限制(即'x
的类型{ {1}}小于'static
S
对象将被困在某个堆栈框架内。)
答案 1 :(得分:18)
这里的问题是也可以为引用实现特征,所以如果你没有为Box指定所需的生命周期,那么任何东西都可以存储在那里。
您可以在此rfc中查看有关生命周期的要求。
所以一种可能的解决方案是绑定生命周期Send
(我把我放在S中):
trait A {
fn f(&self);
}
struct I;
impl A for I {
fn f(&self) {
println!("A for I")
}
}
struct S {
a: Box<A + Send>
}
fn main() {
let s = S {
a: box I
};
s.a.f();
}
另一个是将生命周期设置为'a
(我们可以将参考&amp; I或I设置为S):
trait A {
fn f(&self);
}
struct I;
impl A for I {
fn f(&self) {
println!("A for I")
}
}
impl <'a> A for &'a I {
fn f(&self) {
println!("A for &I")
}
}
struct S<'a> {
a: Box<A + 'a>
}
fn main() {
let s = S {
a: box &I
};
s.a.f();
}
请注意,这是更通用的,我们可以存储引用和拥有数据(Send
类,其生命周期为'static
),但是在使用类型的任何地方都需要一个生命周期参数。