预期的绑定生命周期参数,找到了具体的生命周期 [E0271] [英] Expected bound lifetime parameter, found concrete lifetime [E0271]

查看:48
本文介绍了预期的绑定生命周期参数,找到了具体的生命周期 [E0271]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

虽然下面的代码是一个早期的原型,在这个阶段我不会太认真地考虑我如何实现协议缓冲区,但我无法理解 rust 编译器祝福我的错误消息指的是什么.

<块引用>

src\main.rs:89:9: 89:36 错误:类型不匹配解析 for<'r><[关闭src\main.rs:75:33: 88:10] 作为 core::ops::FnOnce<(u32, gpb::definitions::WireType, &'r collections::vec::Vec<u8>, usize)>;>::Output == usize:预期边界寿命参数,发现混凝土寿命 [E0271]src\main.rs:89 gpb::decoding::read_message( source, field_handler );

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

main.rs 片段

fn from_gpb( source : &Vec) ->时间消息{fn init_vec_u64(count : usize, init_value : u64) ->Vec u64 ;{让 mut 结果 = Vec::<u64>::with_capacity(count);因为我在 0..count {结果.push(init_value);}结果}让 mut message_id : u32 = 0;让 mut times_sec = init_vec_u64(4,0u64);让 mut times_usec = init_vec_u64(4,0u64);让 mut max_time_index = 0;让 mut time_index = |索引 |{ 如果 max_time_index <索引 { max_time_index = 索引;}};让 mut field_handler = |tag,wire_type,source,position|->使用{匹配(标签,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);时间秒 [0] = 秒;时间索引(0);p},(3u32,gpb::definitions::WireType::Fixed64) =>{let (usec,p) = gpb::decoding::read_fixed64(source,position);times_usec[0] = usec;时间索引(0);p},(4u32,gpb::definitions::WireType::Fixed64) =>{let (sec,p) = gpb::decoding::read_fixed64(source,position);时间秒 [1] = 秒;时间索引(1);p},(5u32,gpb::definitions::WireType::Fixed64) =>{let (usec,p) = gpb::decoding::read_fixed64(source,position);times_usec[1] = usec;时间索引(1);p},(6u32,gpb::definitions::WireType::Fixed64) =>{let (sec,p) = gpb::decoding::read_fixed64(source,position);时间秒 [2] = 秒;time_index(2);p},(7u32,gpb::definitions::WireType::Fixed64) =>{let (usec,p) = gpb::decoding::read_fixed64(source,position);times_usec[2] = usec;时间索引(2);p},(8u32,gpb::definitions::WireType::Fixed64) =>{let (sec,p) = gpb::decoding::read_fixed64(source,position);时间秒 [3] = 秒;时间索引(3);p},(9u32,gpb::definitions::WireType::Fixed64) =>{let (usec,p) = gpb::decoding::read_fixed64(source,position);times_usec[3] = usec;时间索引(3);p},(_,_) =>panic!("Invalid field tag/wire_type组合!")//TODO:将恐慌更改为 gpb::decoding::skip(..) 调用.}};gpb::decoding::read_message( source, field_handler );让 mut make_times = ||->Vec

{让 time_count = max_time_index+1;让 mut 时间 = Vec::<prectime::PrecTime>::with_capacity(time_count);times_sec.truncate(time_count);times_usec.truncate(time_count);对于我在 0..time_count {times.push(prectime::PrecTime { sec : times_sec[i], usec : times_usec[i]});}次};TimeMessage { id : message_id, 时间 : make_times() }}

gpb.rs 片段

pub fn read_message( source : &Vec, field_handler : F) where Fn(u32,super::definitions::WireType, &Vec, usize)->使用{让 mut 游标 = 0;而光标 <源.len() {让 (tag_and_wire_type, position) = read_varint32( source, cursor );让 wt = super::definitions::wire_type_from_value( tag_and_wire_type & 0x07u32 );让标签 = (tag_and_wire_type >> 3);让 new_pos = field_handler(tag,wt, source,position);游标 = new_pos;}}

代码功能总结:

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

任何东西(闭包、调用、向量、from_gpb() 上下文中写入的 field_handler,...)都是在 from_gpb() 函数中定义的,我只是不明白生命如何会成为一个问题.所有关于生命周期的信息都应该对编译器可用.

解决方案

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

enum WireType {}fn from_gpb(来源:&Vec<u8>){让 mut field_handler = |标签、线型、来源、位置|->使用{让标签:u32 = 标签;让wire_type: WireType = wire_type;让来源:&Vec<u8>= 来源;让位置:使用=位置;恐慌!();};读消息(来源,field_handler);}fn read_message(来源:&Vec,field_handler:F)在哪里F:Fn(u32, WireType, &Vec<u8>, usize) ->使用,{恐慌!();}

这个答案的其余部分基于上述内容,似乎复制了您的问题:

error[E0631]: 闭包参数中的类型不匹配-->src/lib.rs:11:5|4 |让 mut field_handler = |标签、线型、来源、位置|->使用{|------------------------------------- 找到`fn(u32, WireType, &std::vec::Vec, usize) ->_`...11 |读消息(来源,field_handler);|^^^^^^^^^^^^`for<'r>的预期签名fn(u32, WireType, &'r std::vec::Vec<u8>, usize) ->_`|注意:`read_message` 需要-->src/lib.rs:14:1|14 |/fn read_message(来源:&Vec,field_handler:F)15 ||在哪里16 ||F:Fn(u32, WireType, &Vec<u8>, usize) ->使用,17 ||{18 ||恐慌!();19 ||}||_^错误[E0271]:类型不匹配解析`for<'r><[closure@src/lib.rs:4:29: 10:6] 作为 std::ops::FnOnce<(u32, WireType, &'r std::vec::Vec<u8>, usize)>>::Output == usize`-->src/lib.rs:11:5|11 |读消息(来源,field_handler);|^^^^^^^^^^^^ 预期绑定生命周期参数,找到具体生命周期|注意:`read_message` 需要-->src/lib.rs:14:1|14 |/fn read_message(来源:&Vec,field_handler:F)15 ||在哪里16 ||F:Fn(u32, WireType, &Vec<u8>, usize) ->使用,17 ||{18 ||恐慌!();19 ||}||_^

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

fn from_gpb_closure_inference(来源:&Vec<u8>){read_message(source, |tag, wire_type, source, position| -> usize {让标签:u32 = 标签;让wire_type: WireType = wire_type;让来源:&Vec<u8>= 来源;让位置:使用=位置;恐慌!();});}

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

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

fn constrain_handler(f: F) ->F在哪里F:Fn(u32, WireType, &Vec<u8>, usize) ->使用,{F}fn from_gpb_constrain(来源:&Vec<u8>){让 mut field_handler = constrain_handler(|tag, wire_type, source, position| -> usize {让标签:u32 = 标签;让wire_type: WireType = wire_type;让来源:&Vec<u8>= 来源;让位置:使用=位置;恐慌!();});读消息(来源,field_handler);}

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

While the code below is an early prototype and not to be taken too seriously concerning how I implement protocol buffers at this stage, I fail to understand what the error message rust compilers blesses me with refers to.

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

Even after reading the 3 documentation chapters on lifetimes et. al. I did not come across the term "concrete lifetime" and thus have trouble figuring out what code this error relates to. The closure itself, one or multiple arguments, the return code? The passing of the closure to read_message()? ...

main.rs snippet

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 snippet

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

Summary of what the code does:

  • define field_handler function
  • read_message(data,field_handler) -> calls n times: field_handler
  • exit scope.

As anything (the closure, the calls, the vectors, the field_handler writes in from_gpb() context,...) is defined inside from_gpb() function, I simply do not understand how the lifetime could become an issue. All information about lifetimes should be available to the compiler.

解决方案

First thing's first, if you want a quick answer, you should put some effort into writing a minimal, compilable example so that people don't have to guess whether or not a potential solution is going to work or not. Like this:

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!();
}

The rest of this answer is based on the above which appears to replicate your problem:

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 | | }
   | |_^

The simplest thing to do is to allow the compiler to properly infer the closure type:

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!();
    });
}

Closure inference only really works properly when the closure is provided directly as an argument to a function. In theory, the two should be equivalent, but they aren't.

The other thing you can do is kind-of trick the compiler into doing the inference without actually using the closure:

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

In this case, the constrain_handler function is just getting the compiler to nail down the type of the closure, allowing it to be used (or not) later on.

这篇关于预期的绑定生命周期参数,找到了具体的生命周期 [E0271]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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