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.