如何注释此 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 这些生命周期都是兼容的 ,而不是仅仅在它工作之前抛出生命周期注释。其次是:
- 什么是“匿名生命周期 #2”?
-
check_function<'a, F: 'a, ...>
等于 check_function<'a, F, ...> where F: ... + 'a
吗?
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();
}
我正在尝试编写一个向 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 这些生命周期都是兼容的 ,而不是仅仅在它工作之前抛出生命周期注释。其次是:
- 什么是“匿名生命周期 #2”?
-
check_function<'a, F: 'a, ...>
等于check_function<'a, F, ...> where F: ... + 'a
吗?
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();
}