我有以下代码。
trait T<GT> {
type AT;
fn foo(&self);
}
struct AbstractT<GT, AT> {
t: Box<dyn T<GT, AT = AT>>,
}
impl<GT, AT> T<GT> for AbstractT<GT, AT> {
type AT = AT;
fn foo(&self) {
self.t.foo();
}
}
fn boxed_abstract<GT, TT: T<GT> + 'static>(tt: TT) -> Box<dyn T<GT, AT = TT::AT>> {
Box::new(AbstractT { t: Box::new(tt) })
}
这引发了这些错误。
error[E0310]: the associated type `<TT as T<GT>>::AT` may not live long enough
--> src/lib.rs:20:5
|
20 | Box::new(AbstractT { t: Box::new(tt) })
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<TT as T<GT>>::AT: 'static`...
note: ...so that the type `AbstractT<GT, <TT as T<GT>>::AT>` will meet its required lifetime bounds
--> src/lib.rs:20:5
|
20 | Box::new(AbstractT { t: Box::new(tt) })
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0310]: the parameter type `GT` may not live long enough
--> src/lib.rs:20:5
|
19 | fn boxed_abstract<GT, TT: T<GT> + 'static>(tt: TT) -> Box<dyn T<GT, AT = TT::AT>> {
| -- help: consider adding an explicit lifetime bound...: `GT: 'static`
20 | Box::new(AbstractT { t: Box::new(tt) })
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...so that the type `AbstractT<GT, <TT as T<GT>>::AT>` will meet its required lifetime bounds
--> src/lib.rs:20:5
|
20 | Box::new(AbstractT { t: Box::new(tt) })
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
如果我删除 GT
从任何地方来的,它都能很好地编译,但如果有了 GT
它以一堆寿命错误失败。看来,存在 GT
不应影响任何一方的寿命。dyn T
或 T::AT
(因为在它们中没有使用),但显然是这样的。同样的,一生的 dyn T
不应依赖寿命 GT
或 AT
但显然是这样的。
是我遗漏了什么,还是这是个终身推理的问题?
你可能遗漏了什么。Rust会自动推断特质对象的寿命边界,在盒状特质对象的情况下,自动推断的寿命边界是指 'static
. 例如,当Rust编译器查看你的代码时,它看到的就是这个。
trait T<GT> {
type AT;
fn foo(&self);
}
struct AbstractT<GT, AT> {
// notice the added "+ 'static" below
t: Box<dyn T<GT, AT = AT> + 'static>,
}
impl<GT, AT> T<GT> for AbstractT<GT, AT> {
type AT = AT;
fn foo(&self) {
self.t.foo();
}
}
// notice the added "+ 'static" in the return type
fn boxed_abstract<GT, TT: T<GT> + 'static>(tt: TT) -> Box<dyn T<GT, AT = TT::AT> + 'static> {
Box::new(AbstractT { t: Box::new(tt) })
}
为了使它能被编译,我们只需要添加更多的显式的 'static
你所有的通用类型的界限,像这样。
trait T<GT> {
type AT;
fn foo(&self);
}
struct AbstractT<GT, AT> {
t: Box<dyn T<GT, AT = AT>>,
}
impl<GT, AT> T<GT> for AbstractT<GT, AT> {
type AT = AT;
fn foo(&self) {
self.t.foo();
}
}
fn boxed_abstract<GT, TT>(tt: TT) -> Box<dyn T<GT, AT = TT::AT>>
where TT: T<GT> + 'static, GT: 'static
{
Box::new(AbstractT { t: Box::new(tt) })
}
我们之所以需要这些 'static
bounds很简单:一个容器类型只能由 'static
如果它里面的所有类型都被称为 'static
以此类推递归。
进一步的阅读。
更新
如果你不喜欢 'static
你可以提出 AbstractT
通过给它的类型添加一个显式的寿命注解来实现对寿命的通用,就像这样。
trait T<GT> {
type AT;
fn foo(&self);
}
struct AbstractT<'a, GT, AT> {
t: Box<dyn T<GT, AT = AT> + 'a>,
}
impl<'a, GT, AT> T<GT> for AbstractT<'a, GT, AT> {
type AT = AT;
fn foo(&self) {
self.t.foo();
}
}
fn boxed_abstract<'a, GT, TT>(tt: TT) -> Box<dyn T<GT, AT = TT::AT> + 'a>
where TT: T<GT> + 'a, GT: 'a
{
Box::new(AbstractT { t: Box::new(tt) })
}