2015-10-19 34 views
0

說我有以下內容,如何解決這個與生命週期相關的錯誤?

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_readableon_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「活得不夠長」,但它只在match的分支中使用,那該怎麼做?

我的最好現在猜想是關閉的第二個參數,因爲&'a mut是什麼問題在這裏;我在occ_e中的參考不是'a,它是短一些的(我認爲在hash_entry上未指定的生命期,但我不知道如何註明)。

回答

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以指定生存期參數的任何值。這僅對於生命週期參數有效,因爲與類型參數不同,不同的生命週期參數不會導致定義多個版本的函數。