Code
// https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=5aa2ea5a3e0543f7cfe3585de30ca4d1
fn inner<F>(buf: &mut [u8], func: F) -> usize
where
F: FnOnce(&mut [u8]) -> Result<usize, isize>
{
match func(buf) {
Ok(n) => n,
Err(e) => e as usize,
}
}
fn outer<F>(buf: &mut [u8], func: F) -> usize
where
F: FnOnce(&mut [u8]) -> Result<usize, isize>
{
// As written, this doesn't work and will give the following error:
//
//
// --> src/main.rs:41:5
// |
// 29 | inner(buf, outer_closure)
// | ^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
// |
// = note: closure with signature `fn(&'2 mut [u8]) -> Result<usize, isize>` must implement `FnOnce<(&'1 mut [u8],)>`, for any lifetime `'1`...
// = note: ...but it actually implements `FnOnce<(&'2 mut [u8],)>`, for some specific lifetime `'2`
//
//
// But if we replace `|buf|` with `|buf: &mut [u8]|`, it's totally fine!
let outer_closure = |buf| {
match func(buf) {
Ok(n) => {
println!("OK: {n}");
Ok(n)
}
Err(e) => {
println!("ERR: {e}");
Err(e)
}
}
};
inner(buf, outer_closure)
}
fn main() {
let mut x = [0u8; 16];
let res = outer(&mut x, |buf| {
if buf.len() % 2 == 0 {
Ok(buf.len())
} else {
Err(buf.len() as isize)
}
});
println!("{res:?}");
}
Current output
Compiling playground v0.0.1 (/playground)
error: implementation of `FnOnce` is not general enough
--> src/main.rs:41:5
|
41 | inner(buf, outer_closure)
| ^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
|
= note: closure with signature `fn(&'2 mut [u8]) -> Result<usize, isize>` must implement `FnOnce<(&'1 mut [u8],)>`, for any lifetime `'1`...
= note: ...but it actually implements `FnOnce<(&'2 mut [u8],)>`, for some specific lifetime `'2`
error: could not compile `playground` (bin "playground") due to 1 previous error
Desired output
Some kind of output that either Just Works, or suggests:
- let outer_closure = |buf| {
+ let outer_closure = |buf: &mut [u8]| {
Rationale and extra context
This is a minimized version of some serialization code where I wanted to intercept a closure. I started looking into why HRTB was necessary here, but realized that the compilation error disappeared when giving the closure more explicit type annotations.
Other cases
Rust Version
Reproduces with the current stable 1.96.0 (linked on playground)
Anything else?
No response
Code
Current output
Desired output
Some kind of output that either Just Works, or suggests:
Rationale and extra context
This is a minimized version of some serialization code where I wanted to intercept a closure. I started looking into why HRTB was necessary here, but realized that the compilation error disappeared when giving the closure more explicit type annotations.
Other cases
Rust Version
Anything else?
No response