【问题标题】:Cannot infer a lifetime for a closure returning a boxed trait that contains a reference无法推断返回包含引用的盒装特征的闭包的生命周期
【发布时间】:2017-09-16 11:18:12
【问题描述】:

我正在尝试编译以下代码 (playground):

trait MockFutureTrait {
    type Item;
}

struct MockFuture<T> {
    item: T,
}

impl<T> MockFutureTrait for MockFuture<T> {
    type Item = T;
}

struct FragMsgReceiver<'a, 'c: 'a> {
    recv_dgram: &'a FnMut(&mut [u8])
        -> Box<MockFutureTrait<Item = &mut [u8]> + 'c>,
}

fn constrain_handler<F>(f: F) -> F
where
    F: FnMut(&mut [u8]) -> Box<MockFutureTrait<Item = &mut [u8]>>,
{
    f
}


fn main() {
    let mut recv_dgram = constrain_handler(|buf: &mut [u8]| {
        Box::new(MockFuture { item: buf }) as Box<MockFutureTrait<Item = &mut [u8]>>
    });

    let ref_recv_dgram = &mut recv_dgram;
    let fmr = FragMsgReceiver {
        recv_dgram: ref_recv_dgram,
    };
}

我得到了编译错误:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/main.rs:28:37
   |
28 |         Box::new(MockFuture { item: buf }) as Box<MockFutureTrait<Item = &mut [u8]>>
   |                                     ^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 27:44...
  --> src/main.rs:27:44
   |
27 |       let mut recv_dgram = constrain_handler(|buf: &mut [u8]| {
   |  ____________________________________________^
28 | |         Box::new(MockFuture { item: buf }) as Box<MockFutureTrait<Item = &mut [u8]>>
29 | |     });
   | |_____^
note: ...so that expression is assignable (expected &mut [u8], found &mut [u8])
  --> src/main.rs:28:37
   |
28 |         Box::new(MockFuture { item: buf }) as Box<MockFutureTrait<Item = &mut [u8]>>
   |                                     ^^^
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that expression is assignable (expected std::boxed::Box<MockFutureTrait<Item=&mut [u8]> + 'static>, found std::boxed::Box<MockFutureTrait<Item=&mut [u8]>>)
  --> src/main.rs:28:9
   |
28 |         Box::new(MockFuture { item: buf }) as Box<MockFutureTrait<Item = &mut [u8]>>
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

我尝试添加各种生命周期提示,但无法编译此代码。

我之前关于 SO 的相关问题:

请注意,根据我在问题 2 中得到的建议,我正在使用辅助函数 constrain_handler;它允许我克服不同的编译错误。

【问题讨论】:

  • 我从来没有看到过my comment on your original question 的回答,说明你为什么希望它成为对闭包的引用。
  • @shepmaster:还有其他方法吗?我想要做的是采用基于数据报的套接字,并将其包装在一种新类型中,该类型将允许我发送和接收抽象数据报(这些数据报与底层数据报之间没有 1-1 对应关系)。因此,我参考了recv_dgram 函数。

标签: rust lifetime


【解决方案1】:

您似乎错过了以前问题及其重复问题的关键要点:

通过在闭包参数上声明类型,您停止对参数执行类型推断。这会导致闭包生成一个新的隐式生命周期,它与您的要求不匹配。根本不声明类型。

接下来,您需要声明您的闭包将引用一些字节并返回一个装箱的 trait 对象,该对象将返回相同生命周期的一些字节并包含相同生命周期的引用:

struct FragMsgReceiver<'a> {
    recv_dgram: &'a for<'b> FnMut(&'b mut [u8])
        -> Box<MockFutureTrait<Item = &'b mut [u8]> + 'b>,
}

有关+ 'a 语法的更多详细信息,请参阅Why is Box<Iterator<Item = &Foo> + 'a> needed?

然后更新constrain_handler 以匹配:

struct FragMsgReceiver<'a> {
    recv_dgram: &'a for<'b> FnMut(&'b mut [u8])
        -> Box<MockFutureTrait<Item = &'b mut [u8]> + 'b>,
}

fn constrain_handler<F>(f: F) -> F
where
    F: for<'b> FnMut(&'b mut [u8])
        -> Box<MockFutureTrait<Item = &'b mut [u8]> + 'b>,
{
    f
}

fn main() {
    let mut recv_dgram = constrain_handler(|buf| Box::new(MockFuture { item: buf }));

    let fmr = FragMsgReceiver {
        recv_dgram: &mut recv_dgram,
    };
}

如果你直接采用通用闭包,整个事情可以变得更简单:

struct FragMsgReceiver<R>
where
    R: for<'b> FnMut(&'b mut [u8])
        -> Box<MockFutureTrait<Item = &'b mut [u8]> + 'b>,
{
    recv_dgram: R,
}

fn main() {
    let fmr = FragMsgReceiver {
        recv_dgram: |buf| Box::new(MockFuture { item: buf }),
    };
}

【讨论】:

  • 您对FragMsgReceiver 的第一个定义和第二个定义(在where 子句中使用R 的地方)有区别吗?
  • @real 是的——它不再是对 trait 对象的引用(注意缺少 &amp;'a),而是将被单态化的泛型类型。
  • 我不知道这是可能的。那么现在 FragMsgReceiver 的大小取决于闭包的大小?整个闭包是否存储在 FragMsgReceiver 中?
  • @real FragMsgReceiver&lt;R&gt; 的大小取决于闭包的大小 — 是的,would be zero in this case存储在 FragMsgReceiver 中的整个闭包 — 是的,FragMsgReceiver 拥有该闭包。
  • @real 如果我可以问一下,学习泛型之前,您通过什么学习途径了解 trait 对象的引用?
猜你喜欢
  • 2019-06-12
  • 1970-01-01
  • 1970-01-01
  • 2020-08-27
  • 2015-02-22
  • 1970-01-01
  • 1970-01-01
  • 2016-04-08
相关资源
最近更新 更多