本文介绍了无法推断闭包的寿命,该闭包返回包含引用的盒装特征的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编译以下代码(游乐场 ):

I am trying to compile the following code (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]>>
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

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

I tried to add various lifetime hints, but I couldn't get this code to compile.

我以前在SO上与此相关的问题:

My previous related questions on SO about this:

  • Cannot infer a lifetime for a struct containing a reference to a closure: Solving the same problem, when the return value is a simple struct and not a trait.

如何将多个结构字段变成使用相同寿命的泛型?:关于尝试解决这一问题没有盒子的问题.答案表明,现在我将不得不使用Box>.

How can multiple struct fields be generics that use the same higher-kinded lifetime?: About trying to solve this problem without Boxes. The answer suggests that for now I will have to use Box>.

请注意,根据问题2的建议,我正在使用辅助功能constrain_handler.它使我能够克服另一个编译错误.

Note that I am using the helper function constrain_handler according to a suggestion I got in question 2; it allows me to overcome a different compilation error.

推荐答案

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

It appears that you've missed a key takeaway of your previous questions and their duplicates:

  • Lifetime annotation for closure argument
  • Cannot infer a lifetime for a struct containing a reference to a closure
  • How to declare a lifetime for a closure argument

通过在闭包参数上声明类型,您停止对参数进行类型推断.这将导致闭包生成新的隐式生存期,这与您的要求不符.只是根本不声明类型.

By declaring a type on the closure argument, you stop performing type inference for the arguments. This causes a new implicit lifetime to be generated by the closure, one which does not match your requirements. Just don't declare the type at all.

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

Next, you need to state that your closure is going to take a reference to some bytes and return a boxed trait object that will return some bytes of the same lifetime and contains a reference of that same lifetime:

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

请参见为什么Box< Iterator< Item =& Foo> +'a> 以获取有关+ 'a语法的更多详细信息.

See Why is Box<Iterator<Item = &Foo> + 'a> needed? for more details about the + 'a syntax.

然后更新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,
    };
}


如果您直接采用通用闭包,则整个过程可以变得更简单:


The whole thing can be made simpler if you just take a generic closure directly:

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 }),
    };
}

这篇关于无法推断闭包的寿命,该闭包返回包含引用的盒装特征的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-15 04:10