如何注释此 Rust/Calloop 回调代码的生命周期?

How can I annotate the lifetimes for this Rust/Calloop callback code?

我正在尝试编写一个向 Calloop's 事件循环添加回调函数的函数。如果将代码简单地粘贴到函数参数都在作用域和堆栈中的函数中,则代码可以正常工作。将其提取到函数中会导致生命周期问题。

这是我在进入 Calloop 的内部之前所能简化的代码(作为初学者,这有点超出我的能力范围):

use calloop::{Interest, Mode, generic::Generic, LoopHandle};
use std::os::unix::io::RawFd;

fn check_function<F, T>(
    handle: &mut LoopHandle<T>,
    fd: RawFd,
    callback: F,
)
where
    F: FnMut(calloop::Readiness, &mut calloop::generic::Fd, &mut T) -> Result<(), std::io::Error>
{
    let event_source = Generic::from_fd(fd, Interest::READ, Mode::Edge);

    handle.insert_source(
        event_source,
        callback,
    ).ok();
}

编译结果:

error[E0311]: the parameter type `F` may not live long enough
  --> src/test.rs:14:12
   |
4  | fn check_function<F, T>(
   |                   - help: consider adding an explicit lifetime bound...: `F: 'a`
...
14 |     handle.insert_source(
   |            ^^^^^^^^^^^^^
   |
note: the parameter type `F` must be valid for the anonymous lifetime #2 defined on the function body at 4:1...
  --> src/test.rs:4:1
   |
4  | / fn check_function<F, T>(
5  | |     handle: &mut LoopHandle<T>,
6  | |     fd: RawFd,
7  | |     callback: F,
8  | | )
9  | | where
10 | |     F: FnMut(calloop::Readiness, &mut calloop::generic::Fd, &mut T) -> Result<(), std::io::Error>
   | |_________________________________________________________________________________________________^
note: ...so that the type `F` will meet its required lifetime bounds
  --> src/test.rs:14:12
   |
14 |     handle.insert_source(
   |            ^^^^^^^^^^^^^

因为它在所有东西都在堆栈上时工作,我想我需要告诉它所有东西都有相同(或兼容)的生命周期:

fn check_function<'a, F, T>(
    handle: &mut LoopHandle<T>,
    fd: RawFd,
    callback: F,
)
where
    T: 'a,
    F: FnMut(calloop::Readiness, &mut calloop::generic::Fd, &mut T) -> Result<(), std::io::Error> + 'a

但是 rustc 告诉我添加 另一个 生命周期:

error[E0311]: the parameter type `F` may not live long enough
  --> src/test.rs:15:12
   |
4  | fn check_function<'a, F, T>(
   |                       - help: consider adding an explicit lifetime bound...: `F: 'b`
...
15 |     handle.insert_source(
   |            ^^^^^^^^^^^^^
   |
note: the parameter type `F` must be valid for the anonymous lifetime #2 defined on the function body at 4:1...
  --> src/test.rs:4:1
   |
4  | / fn check_function<'a, F, T>(
5  | |     handle: &mut LoopHandle<T>,
6  | |     fd: RawFd,
7  | |     callback: F,
...  |
10 | |     T: 'a,
11 | |     F: FnMut(calloop::Readiness, &mut calloop::generic::Fd, &mut T) -> Result<(), std::io::Error> + 'a
   | |______________________________________________________________________________________________________^
note: ...so that the type `F` will meet its required lifetime bounds
  --> src/test.rs:15:12
   |
15 |     handle.insert_source(
   |            ^^^^^^^^^^^^^

这似乎是一种相当缓慢的字母表学习方法。我真的很想了解 我如何告诉 rustc 这些生命周期都是兼容的 ,而不是仅仅在它工作之前抛出生命周期注释。其次是:

Rustc 对此没有多大帮助,但我发现 LoopHandle 是用生命周期参数化的,并且由于句柄拥有传入的 FnMut 的所有权,因此 FnMut 必须比 LoopHandle 长。一旦弄清楚了,注释正确的生命周期就很容易了:

use calloop::{
    generic::{Fd, Generic},
    Interest, LoopHandle, Mode,
};
use std::io::Result;
use std::os::unix::io::RawFd;
fn check_function<'a: 'b, 'b, F, T>(handle: &mut LoopHandle<'b, T>, fd: RawFd, callback: F)
where
    F: 'a + FnMut(calloop::Readiness, &mut Fd, &mut T) -> Result<()>,
{
    let event_source = Generic::from_fd(fd, Interest::READ, Mode::Edge);

    handle.insert_source(event_source, callback).ok();
}