Expected bound lifetime parameter, found concrete lifetime [E0271]

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.

Leave a Comment