1

我有以下代码:

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它会因一堆生命周期错误而失败。似乎 of 的存在不GT应该影响dyn TorT::AT的生命周期(因为它没有在其中使用),但显然确实如此。同样,生命周期不dyn T应该依赖于生命周期,GTAT它显然确实如此。

我错过了什么还是终身推理问题?

4

1 回答 1

1

你可能会遗漏一些东西。Rust 自动推断 trait 对象的生命周期,在盒装 trait 对象的情况下,自动推断的生命周期是'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边界的原因很简单:一个容器类型只有在'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) })
}

操场

于 2020-05-19T12:51:50.677 回答