2016-07-05 62 views
1

我需要初始化一個項目(fn init(&mut self) -> Option<&Error>),並在沒有錯誤的情況下使用它。match + RefCell = X活不夠長

pub fn add(&mut self, mut m: Box<Item>) { 
    if let None = m.init() { 
     self.items.push(m); 
    } 
} 

這工作,除非我需要檢查錯誤,如果有任何:

pub fn add(&mut self, mut m: Box<Item>) { 
    if let Some(e) = m.init() { 
     //process error 
    } else { 
     self.items.push(m); //won't compile, m is borrowed 
    } 
} 

博覽會。需要使用RefCell。然而,這

pub fn add(&mut self, mut m: Box<Item>) { 
    let rc = RefCell::new(m); 

    if let Some(e) = rc.borrow_mut().init() {   
     //process error   
    } else { 
     self.items.push(rc.borrow_mut()) 
    } 
} 

怪異

error: `rc` does not live long enough 
     if let Some(e) = rc.borrow_mut().init() { 
        ^~ 
note: reference must be valid for the destruction scope surrounding block at 75:60... 
    pub fn add_module(&mut self, mut m: Box<RuntimeModule>) { 
                 ^
note: ...but borrowed value is only valid for the block suffix following statement 0 at 76:30 
     let rc = RefCell::new(m); 

結束我試過幾乎所有:普通的盒子,Rc '編輯框,RefCell' 編輯框,Rc「編RefCell。試圖去適應this answer我的情況。沒用。

完整的示例:

use std::cell::RefCell; 
use std::error::Error; 

trait Item { 
    fn init(&mut self) -> Option<&Error>; 
} 

struct ItemImpl {} 

impl Item for ItemImpl { 
    fn init(&mut self) -> Option<&Error> { 
     None 
    } 
} 

//=========================================== 

struct Storage { 
    items: Vec<Box<Item>>, 
} 

impl Storage { 
    fn new() -> Storage { 
     Storage{ 
      items: Vec::new(), 
     } 
    } 

    fn add(&mut self, mut m: Box<Item>) { 
     let rc = RefCell::new(m); 

     if let Some(e) = rc.borrow_mut().init() {   
      //process error   
     } else { 
      self.items.push(*rc.borrow_mut()) 
     } 
    } 
} 

fn main() { 
    let mut s = Storage::new(); 
    let mut i = Box::new(ItemImpl{}); 
    s.add(i); 
} 

Playground

UPD:作爲建議,這是像我做了一個 「家庭」 的錯誤,這是很好的解釋here。但是我的情況有更簡單的解

+0

的'RefCell'不會解決這個問題。這是借用檢查器的知識侷限性,並且有關於此的一些問題/答案。我指出了一個可能的重複,但我認爲我們應該找到一個明確的答案(如果可能的話)。 @Shepmaster你知道更好的重複嗎? – malbarbo

+0

[If let borrow conundrum]可能的重複(http://stackoverflow.com/questions/30243606/if-let-borrow-conundrum) – malbarbo

+0

@malbarbo我不認爲它和那個完全一樣。它與從'&mut self'方法返回引用有關。這會導致可變借款持續下去。 [示例](https://play.rust-lang.org/?gist=5a6c22cd3d19b5b5eb9f3a759ecb84aa) – Shepmaster

回答

3

由於krdln建議,要解決這個最簡單的方法是在if塊返回,因此範圍貸:

fn add(&mut self, mut m: Box<Item>) { 
    if let Some(e) = m.init() { 
     //process error 
     return; 
    } 
    self.items.push(m); 
} 
+0

對我的情況有意義,謝謝。 – snuk182

+0

順便說一句,這可能是相關的https://github.com/rust-lang/rust/issues/21906 – snuk182