2016-07-05 2 views
1

Мне нужно инициализировать элемент (fn init(&mut self) -> Option<&Error>) и использовать его, если ошибок нет.матч + 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 
    } 
} 

Fair. Необходимо использовать 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 loan conundrum] (http://stackoverflow.com/questions/30243606/if-let-borrow-conundrum) – malbarbo

+0

@malbarbo Я не думаю, что это точно так же, как тот. Это связано с возвратом ссылки с помощью метода '& mut self'. Это приводит к тому, что изменчивый долг сохраняется. [example] (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

btw, это может быть связано с https://github.com/rust-lang/rust/issues/21906 – snuk182

 Смежные вопросы

  • Нет связанных вопросов^_^