gpt4 book ai didi

rust - 预期绑定(bind)生命周期参数,找到具体生命周期 [E0271]

转载 作者:行者123 更新时间:2023-11-29 08:10:40 26 4
gpt4 key购买 nike

虽然下面的代码是一个早期的原型(prototype),关于我在这个阶段如何实现 Protocol Buffer 不要太认真,但我无法理解 rust 编译器祝福我的错误消息指的是什么。

src\main.rs:89:9: 89:36 error: type mismatch resolving for<'r> <[closure src\ma
in.rs:75:33: 88:10] as core::ops::FnOnce<(u32, gpb::definitions::WireType, &'r collections::vec::Vec<u8>, usize)>>::Output == usize
: expected bound lifetime parameter , found concrete lifetime [E0271] src\main.rs:89 gpb::decoding::read_message( source, field_handler );

即使在阅读了关于 lifetimes 等的 3 个文档章节之后。阿尔。我没有遇到“具体生命周期”这个词,因此很难弄清楚这个错误与什么代码有关。闭包本身,一个或多个参数,返回码?关闭传递给 read_message() ? ...

main.rs 片段

fn from_gpb( source : &Vec<u8>) -> TimeMessage {
fn init_vec_u64( count : usize, init_value : u64) -> Vec<u64> {
let mut result = Vec::<u64>::with_capacity(count);
for i in 0..count {
result.push(init_value);
}
result
}
let mut message_id : u32 = 0;
let mut times_sec = init_vec_u64(4,0u64);
let mut times_usec = init_vec_u64(4,0u64);
let mut max_time_index = 0;
let mut time_index = | index | { if max_time_index < index { max_time_index = index;}};
let mut field_handler = |tag,wire_type,source,position| -> usize {
match (tag,wire_type) {
(1u32,gpb::definitions::WireType::Varint) => {let (v,p) = gpb::decoding::read_varint32(source,position); message_id = v; p},
(2u32,gpb::definitions::WireType::Fixed64) => {let (sec,p) = gpb::decoding::read_fixed64(source,position); times_sec[0] = sec; time_index(0); p},
(3u32,gpb::definitions::WireType::Fixed64) => {let (usec,p) = gpb::decoding::read_fixed64(source,position); times_usec[0] = usec; time_index(0); p},
(4u32,gpb::definitions::WireType::Fixed64) => {let (sec,p) = gpb::decoding::read_fixed64(source,position); times_sec[1] = sec; time_index(1);p},
(5u32,gpb::definitions::WireType::Fixed64) => {let (usec,p) = gpb::decoding::read_fixed64(source,position); times_usec[1] = usec; time_index(1);p},
(6u32,gpb::definitions::WireType::Fixed64) => {let (sec,p) = gpb::decoding::read_fixed64(source,position); times_sec[2] = sec; time_index(2);p},
(7u32,gpb::definitions::WireType::Fixed64) => {let (usec,p) = gpb::decoding::read_fixed64(source,position); times_usec[2] = usec; time_index(2); p},
(8u32,gpb::definitions::WireType::Fixed64) => {let (sec,p) = gpb::decoding::read_fixed64(source,position); times_sec[3] = sec; time_index(3); p},
(9u32,gpb::definitions::WireType::Fixed64) => {let (usec,p) = gpb::decoding::read_fixed64(source,position); times_usec[3] = usec; time_index(3); p},
(_,_) => panic!("Invalid field tag/wire_type combination!") // TODO: change the panic to a gpb::decoding::skip(..) call.
}
};
gpb::decoding::read_message( source, field_handler );
let mut make_times = || -> Vec<prectime::PrecTime> {
let time_count = max_time_index+1;
let mut times = Vec::<prectime::PrecTime>::with_capacity(time_count);
times_sec.truncate(time_count);
times_usec.truncate(time_count);
for i in 0..time_count {
times.push(prectime::PrecTime { sec : times_sec[i], usec : times_usec[i]});
}
times
};
TimeMessage { id : message_id, times : make_times() }
}

gpb.rs 片段

pub fn read_message<F>( source : &Vec<u8>, field_handler : F) where F: Fn(u32,super::definitions::WireType, &Vec<u8>, usize) -> usize {
let mut cursor = 0;
while cursor < source.len() {
let (tag_and_wire_type, position) = read_varint32( source, cursor );
let wt = super::definitions::wire_type_from_value( tag_and_wire_type & 0x07u32 );
let tag = (tag_and_wire_type >> 3);
let new_pos = field_handler(tag,wt, source,position);
cursor = new_pos;
}
}

代码的作用总结:

  • 定义field_handler函数
  • read_message(data,field_handler) -> 调用 n 次:field_handler
  • 退出范围。

任何东西(闭包、调用、向量、field_handler 写入 from_gpb() 上下文,...)都是在 from_gpb() 中定义的功能,我根本不明白生命周期怎么会成为问题。所有关于生命周期的信息都应该提供给编译器。

最佳答案

首先,如果您想要一个快速的答案,您应该付出一些努力来编写一个最小的、可编译的示例,这样人们就不必猜测潜在的解决方案是否可行。像这样:

enum WireType {}

fn from_gpb(source: &Vec<u8>) {
let mut field_handler = |tag, wire_type, source, position| -> usize {
let tag: u32 = tag;
let wire_type: WireType = wire_type;
let source: &Vec<u8> = source;
let position: usize = position;
panic!();
};
read_message(source, field_handler);
}

fn read_message<F>(source: &Vec<u8>, field_handler: F)
where
F: Fn(u32, WireType, &Vec<u8>, usize) -> usize,
{
panic!();
}

此答案的其余部分基于以上出现以复制您的问题:

error[E0631]: type mismatch in closure arguments
--> src/lib.rs:11:5
|
4 | let mut field_handler = |tag, wire_type, source, position| -> usize {
| ------------------------------------------- found signature of `fn(u32, WireType, &std::vec::Vec<u8>, usize) -> _`
...
11 | read_message(source, field_handler);
| ^^^^^^^^^^^^ expected signature of `for<'r> fn(u32, WireType, &'r std::vec::Vec<u8>, usize) -> _`
|
note: required by `read_message`
--> src/lib.rs:14:1
|
14 | / fn read_message<F>(source: &Vec<u8>, field_handler: F)
15 | | where
16 | | F: Fn(u32, WireType, &Vec<u8>, usize) -> usize,
17 | | {
18 | | panic!();
19 | | }
| |_^

error[E0271]: type mismatch resolving `for<'r> <[closure@src/lib.rs:4:29: 10:6] as std::ops::FnOnce<(u32, WireType, &'r std::vec::Vec<u8>, usize)>>::Output == usize`
--> src/lib.rs:11:5
|
11 | read_message(source, field_handler);
| ^^^^^^^^^^^^ expected bound lifetime parameter, found concrete lifetime
|
note: required by `read_message`
--> src/lib.rs:14:1
|
14 | / fn read_message<F>(source: &Vec<u8>, field_handler: F)
15 | | where
16 | | F: Fn(u32, WireType, &Vec<u8>, usize) -> usize,
17 | | {
18 | | panic!();
19 | | }
| |_^

最简单的做法是让编译器正确推断闭包类型:

fn from_gpb_closure_inference(source: &Vec<u8>) {
read_message(source, |tag, wire_type, source, position| -> usize {
let tag: u32 = tag;
let wire_type: WireType = wire_type;
let source: &Vec<u8> = source;
let position: usize = position;
panic!();
});
}

只有当闭包直接作为函数的参数提供时,闭包推理才能真正正常工作。理论上,两者应该是等价的,但它们不是

您可以做的另一件事是欺骗编译器,使其在实际上不使用闭包的情况下进行推理:

fn constrain_handler<F>(f: F) -> F
where
F: Fn(u32, WireType, &Vec<u8>, usize) -> usize,
{
f
}

fn from_gpb_constrain(source: &Vec<u8>) {
let mut field_handler = constrain_handler(|tag, wire_type, source, position| -> usize {
let tag: u32 = tag;
let wire_type: WireType = wire_type;
let source: &Vec<u8> = source;
let position: usize = position;
panic!();
});
read_message(source, field_handler);
}

在这种情况下,constrain_handler 函数只是让编译器确定闭包的类型,以便稍后使用(或不使用)。

关于rust - 预期绑定(bind)生命周期参数,找到具体生命周期 [E0271],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31362206/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com