I am trying to write a function that adds a callback function to Calloop's event loop. The code works fine if it is simply pasted into a function where the function parameters are all in scope and on the stack. Pulling it out into a function results in lifetime problems.
This is as much as I could simplify the code before having to get into Calloop's internals (which are a bit beyond me as a beginner):
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();
}
Compiling this results in:
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(
| ^^^^^^^^^^^^^
Since it works when everything is on the stack, I figure I need to tell it that everything has the same (or compatible) lifetimes:
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
But rustc tells me to add another lifetime:
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(
| ^^^^^^^^^^^^^
This seems like a rather slow way to learn the alphabet. Rather than just throw lifetime annotations around until it works, I'd really like to understand how I can tell rustc that these lifetimes are all compatible. Secondary to that:
- what is "anonymous lifetime #2"?
- is
check_function<'a, F: 'a, ...>equivalent tocheck_function<'a, F, ...> where F: ... + 'a?