说我有以下内容,
type EpollEventCallback<'a> = FnMut(c_int) + Send + Sync + 'a;
struct EpollFdEventHandler<'a> {
on_readable: Option<Box<EpollEventCallback<'a>>>,
on_writable: Option<Box<EpollEventCallback<'a>>>,
}
// Map from c_int -> EpollFdEventHandler.
type EpollEventHandlerMap<'a> = collections::HashMap<c_int, EpollFdEventHandler<'a>>;
fn add_fd_handler
<'a, T: Fn(bool, &'a mut EpollFdEventHandler<'a>)>(
map: &'a mut EpollEventHandlerMap<'a>,
fd: c_int,
adder: T)
{
let mut hash_entry: hash_map::Entry<'a, _, _> = map.entry(fd);
match hash_entry {
hash_map::Entry::Occupied(ref mut occ_e) => {
let entry: &mut EpollFdEventHandler<'a> = occ_e.get_mut();
adder(false, entry);
},
hash_map::Entry::Vacant(vac_e) => {
/*
adder(
true,
vac_e.insert(EpollFdEventHandler {
on_readable: None,
on_writable: None,
}),
);
*/
}
};
}
add_fd_handler
应该是添加“FD处理程序”的辅助函数;在这里,它将传递一个闭包(adder
),它将设置on_readable
或on_writable
,具体取决于要添加的处理程序。 add_fd_handler
的工作就是简单地进行哈希表查找,并在需要时插入空条目。但是:
src/event_loop.rs:85:35: 85:48 error: `(hash_entry:std::collections::hash::map::Occupied).0` does not live long enough
src/event_loop.rs:85 hash_map::Entry::Occupied(ref mut occ_e) => {
^~~~~~~~~~~~~
src/event_loop.rs:82:1: 101:2 note: reference must be valid for the lifetime 'a as defined on the block at 82:0...
src/event_loop.rs:82 {
src/event_loop.rs:83 let mut hash_entry: hash_map::Entry<'a, _, _> = map.entry(fd);
src/event_loop.rs:84 match hash_entry {
src/event_loop.rs:85 hash_map::Entry::Occupied(ref mut occ_e) => {
src/event_loop.rs:86 let entry: &mut EpollFdEventHandler<'a> = occ_e.get_mut();
src/event_loop.rs:87 adder(false, entry);
...
src/event_loop.rs:83:67: 101:2 note: ...but borrowed value is only valid for the block suffix following statement 0 at 83:66
src/event_loop.rs:83 let mut hash_entry: hash_map::Entry<'a, _, _> = map.entry(fd);
src/event_loop.rs:84 match hash_entry {
src/event_loop.rs:85 hash_map::Entry::Occupied(ref mut occ_e) => {
src/event_loop.rs:86 let entry: &mut EpollFdEventHandler<'a> = occ_e.get_mut();
src/event_loop.rs:87 adder(false, entry);
src/event_loop.rs:88 },
如果我尝试将occ_e
用于adder(false, entry)
,则只显示occ_e
的错误! Rust声明match
“活得不够长”,但它只是在&'a mut
的那个分支中使用,那怎么可能呢?
我的最佳猜测是关闭的第二个arg,occ_e
就是这里的问题;我在'a
中的引用不是hash_entry
,它更短({{1}}上未指定的生命周期,我想,但我不知道如何记录这一点。)
答案 0 :(得分:1)
让编译器推断出正确的生命周期:
fn add_fd_handler
<T: Fn(bool, &mut EpollFdEventHandler)>(
map: &mut EpollEventHandlerMap,
fd: c_int,
adder: T)
{
let mut hash_entry = map.entry(fd);
match hash_entry {
hash_map::Entry::Occupied(ref mut occ_e) => {
let entry = occ_e.get_mut();
adder(false, entry);
},
hash_map::Entry::Vacant(vac_e) => {
/*
adder(
true,
vac_e.insert(EpollFdEventHandler {
on_readable: None,
on_writable: None,
}),
);
*/
}
};
}
问题在于您让调用者确定回调的生命周期,但是然后使用对局部变量的可变引用来调用回调。调用者不可能知道该局部变量的生命周期,因此编译器假定'a
必须比当前函数寿命更长。然而,entry
并不比这个功能更长,这就是你得到错误的原因。
声明T: Fn(bool, &mut EpollFdEventHandler)
相当于T: for<'a, 'b> Fn(bool, &'a mut EpollFdEventHandler<'b>)
。此上下文中的for
关键字允许您声明T
必须为指定生命周期参数的任何值实现Fn
。这仅适用于生命周期参数,因为不同的生命周期参数不会导致定义函数的多个版本,这与类型参数不同。