无法推断包含对闭包的引用的结构的生存期 [英] Cannot infer a lifetime for a struct containing a reference to a closure

查看:101
本文介绍了无法推断包含对闭包的引用的结构的生存期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编译此简化且独立的代码版本:

I am trying to make this simplified and self-contained version of my code compile:

struct FragMsgReceiver<'a, 'b: 'a> {
    recv_dgram: &'a mut FnMut(&mut [u8]) -> Result<&'b mut [u8], ()>,
}

impl<'a, 'b> FragMsgReceiver<'a, 'b> {
    fn new(
        recv_dgram: &'a mut FnMut(&mut [u8])
            -> Result<&'b mut [u8], ()>
    ) -> Self {
        FragMsgReceiver { recv_dgram }
    }
}

fn main() {
    let recv_dgram = |buff: &mut [u8]| Ok(buff);
    let fmr = FragMsgReceiver::new(&mut recv_dgram);
}

这是错误:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/main.rs:15:43
   |
15 |     let recv_dgram = |buff: &mut [u8]| Ok(buff);
   |                                           ^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 15:22...
  --> src/main.rs:15:22
   |
15 |     let recv_dgram = |buff: &mut [u8]| Ok(buff);
   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that expression is assignable (expected &mut [u8], found &mut [u8])
  --> src/main.rs:15:43
   |
15 |     let recv_dgram = |buff: &mut [u8]| Ok(buff);
   |                                           ^^^^
note: but, the lifetime must be valid for the block suffix following statement 1 at 16:53...
  --> src/main.rs:16:53
   |
16 |       let fmr = FragMsgReceiver::new(&mut recv_dgram);
   |  _____________________________________________________^
17 | | }
   | |_^
note: ...so that variable is valid at time of its declaration
  --> src/main.rs:16:9
   |
16 |     let fmr = FragMsgReceiver::new(&mut recv_dgram);
   |         ^^^

根据我从错误消息中了解到的信息,编译器无法理解buff引用(recv_dgram的参数)实际上可以比recv_dgram的内部主体寿命更长.我可能是错的.

From what I understand from the error message, the compiler doesn't understand that the buff reference (argument of recv_dgram) can actually live longer than the inner body of recv_dgram. I could be wrong though.

为了提供一些背景信息,我正在尝试创建一个包装Rust Tokio UDP套接字的结构.为此,我引用了函数recv_dgram.在我的原始代码中,此函数将缓冲区作为参数,并返回Future. Future准备就绪时,缓冲区将被填充. Future的项还包含发送者的地址和写入缓冲区的字节数.

To give some context, I'm trying to create a struct that wraps a Rust Tokio UDP socket. To do this, I take a reference to a function recv_dgram. In my original code this function takes a buffer as argument, and returns a Future. When the Future is ready, the buffer will be filled. The Future's item also contains the address of sender and the amount of bytes that were written into the buffer.

推荐答案

让我们从恢复声明中的有效期开始吧

Let's start by restoring elided lifetime in your declaration

struct FragMsgReceiver<'a, 'b: 'a> {
    recv_dgram: &'a mut for<'c> FnMut(&'c mut [u8]) -> Result<&'b mut [u8], ()>,
}

此声明意味着FragMsgReceiver持有对FnMut特征对象的可变引用,该对象对具有 any 寿命'c的切片进行可变引用,并返回寿命为.

This declaration means that FragMsgReceiver holds a mutable reference to a FnMut trait object which takes a mutable reference to a slice having any lifetime 'c and returns a reference with lifetime 'b: 'a.

这不是您所需要的.您需要一个FnMut,它返回与输入参数的生存期相同的生存期的引用.可以这样写:

This is not what you need. You need an FnMut which returns a reference with the same lifetime as the lifetime of the input parameter. This can be written as:

type FnTraitObject = FnMut(&mut [u8]) -> Result<&mut [u8], ()>;

struct FragMsgReceiver<'a> {
    recv_dgram: &'a mut FnTraitObject,
}

impl<'a> FragMsgReceiver<'a> {
    fn new(recv_dgram: &'a mut FnTraitObject) -> Self {
        FragMsgReceiver { recv_dgram }
    }
}

生命周期省略在这里做正确的事情,但是编译器仍然抱怨:预期的绑定生命周期参数,找到了具体的生命周期",指向FragMsgReceiver::new(&mut recv_dgram).

Lifetime elision does the right thing here, but the compiler still complains: "expected bound lifetime parameter, found concrete lifetime", pointing at FragMsgReceiver::new(&mut recv_dgram).

此错误是由Rust类型推断的限制引起的.我们需要通过强制关闭 DK指出的关闭类型来协助推断.

This error is caused by a limitation of Rust's type inference. We need to assist the inference by coercing the type of the closure as it was pointed out by DK.

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

// ...

let mut recv_dgram = constrain_handler(|buff| Ok(buff));

在操场上完成代码

为明确起见,for<'c>表示'c可以是任何生存期,并且生存期是在呼叫站点确定的.例如,指向函数fn foo(_: &u32) -> &u32的指针的类型为for<'a> fn(&'a u32) -> &'a u32.

To clarify, for<'c> means that 'c can be any lifetime and the lifetime is determined at a call site. For example, the pointer to the function fn foo(_: &u32) -> &u32 has the type for<'a> fn(&'a u32) -> &'a u32.

这篇关于无法推断包含对闭包的引用的结构的生存期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆