我正在努力使这个简化且自包含的代码版本编译:
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
的内部主体更长寿。我可能错了。
为了给出一些上下文,我正在尝试创建一个包装Rust Tokio UDP套接字的结构。为此,我引用了一个函数recv_dgram
。在我的原始代码中,此函数将缓冲区作为参数,并返回Future
。当Future
准备就绪时,缓冲区将被填充。 Future
项还包含发送方的地址和写入缓冲区的字节数。
答案 0 :(得分:1)
让我们首先在声明中恢复elided lifetime
struct FragMsgReceiver<'a, 'b: 'a> {
recv_dgram: &'a mut for<'c> FnMut(&'c mut [u8]) -> Result<&'b mut [u8], ()>,
}
此声明表示FragMsgReceiver
拥有对FnMut
特征对象的可变引用,该对象对具有任何生命期'c
的切片进行可变引用并返回生命周期为'b: 'a
的参考。
这不是你需要的。您需要一个FnMut
,它返回一个与输入参数的生命周期相同的生命周期的引用。这可以写成:
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 }
}
}
Lifetime elision在这里做了正确的事情,但是编译器仍然抱怨:&#34;期望的绑定生命周期参数,找到具体的生命周期&#34;,指向FragMsgReceiver::new(&mut recv_dgram)
。
此错误是由Rust类型推断的限制引起的。我们需要通过强制关闭类型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));
Complete code on the playground
为了澄清,for<'c>
表示'c
可以是任何生命周期,生命周期是在呼叫站点确定的。例如,指向函数fn foo(_: &u32) -> &u32
的指针的类型为for<'a> fn(&'a u32) -> &'a u32
。