当前位置: 首页 > 知识库问答 >
问题:

预期约束寿命参数,发现混凝土寿命[E0271]

羊浩广
2023-03-14

虽然下面的代码是一个早期的原型,对于我在这个阶段如何实现协议缓冲区不必太认真,但我无法理解rust编译器给我带来的错误消息指的是什么。

src\main。rs:89:9:89:36错误:解决的类型不匹配

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

主要的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;
    }
}

代码的作用摘要:

  • 定义字段处理函数

任何东西(闭包、调用、向量、字段\u处理程序从\u gpb()写入上下文,…)是在函数中定义的,我不明白生命周期怎么会成为一个问题。编译器应该可以获得有关生命周期的所有信息。


共有1个答案

柴衡
2023-03-14

首先,如果你想要一个快速的答案,你应该努力写一个最小的,可编译的例子,这样人们就不必猜测一个潜在的解决方案是否有效。这样地:

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函数只是让编译器确定闭包的类型,允许稍后使用(或不使用)它。

 类似资料:
  • 我有一个问题与生命周期参数的结构。我不能100%确定如何描述这个问题,但是我创建了一个显示编译时错误的简单案例。 我得到的错误是 我尝试了很多变体,只是无法编译这个东西。我在这里找到了另一个帖子(如何修复:预期的具体寿命,但找到了绑定的寿命参数),但似乎绕过了问题,而不是解决它。我真的不明白为什么这个问题会出现。该 有什么想法吗?谢谢你的帮助。

  • 我无法计算出这段代码的生存期参数。我所尝试的一切通常都会导致编译器错误:“预期的绑定生存期参数,找到了具体的生存期”或者类似于“考虑使用所示的显式生存期参数”(所示的示例没有帮助)或“与trait不兼容的方法”。 、和都是简化版本,以尽量减少此示例。 铁锈游乐场

  • 我正在尝试在结构中存储函数: 编译器抱怨:

  • 问题内容: 我目前正在尝试诊断应用程序中的缓慢内存泄漏。到目前为止,我掌握的事实如下。 我有4天运行该应用程序的堆转储。 该堆转储包含约800个WeakReference对象,这些对象指向保留40mb内存的对象(所有对象都是同一类型,出于这个问题的目的,我将其称为Foo)。 Eclipse内存分析工具显示,这些WeakReferences引用的每个Foo对象均未被其他任何对象引用。我的期望是,这应

  • 问题内容: 我正在使用基于表单的身份验证。 我有一个注销链接,看起来像: 以及相应的注销方法: 点击注销链接后,我返回首页,但似乎没有CSS。当我按下按钮进行搜索时,出现以下错误: 但是CSS实际上位于/ resources下,因为我了解我的web.xml,所以不需要身份验证: 从这种状态来看,我似乎能够再次登录并看到偶尔无法恢复的错误之间的 一些 数据,但是没有CSS。真的有点破。任何建议,将不

  • 我们的系统由许多运行在“干净”机器上的python脚本组成,也就是说,它们需要尽可能少的额外软件。有没有一种方法可以使用OpenTelemetry而不必在这些机器上运行额外的服务器?是否有一种推送模式来发送数据而不是拉送?