【问题标题】:match + RefCell = X does not live long enoughmatch + RefCell = X 寿命不够长
【发布时间】:2016-07-06 17:27:38
【问题描述】:

我需要初始化一个项目(fn init(&mut self) -> Option<&Error>),如果没有错误就使用它。

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'ed 盒子、RefCell'ed 盒子、Rc'ed 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。但是我的情况有更简单的解决方案。

【问题讨论】:

  • RefCell 无法解决此问题。这是借用检查器的已知限制,对此有一些问题/答案。我指出了一个可能的重复项,但我认为我们应该找到一个明确的答案(如果可能的话)。 @Shepmaster 你知道更好的副本吗?
  • If let borrow conundrum的可能重复
  • @malbarbo 我不认为它与那个完全相同。它与从 &amp;mut self 方法返回的引用有关。这会导致可变借用持续存在。 example
  • 同时我找到了一个解决方案,但它对我来说看起来非常难看。 gist.github.com/7f108112b95e2550691095e34c7cf37f
  • 最简单的方法是在处理错误后尽早使用return。 @Shepmaster我觉得其实差不多,Option&lt;Chars&gt;也是借用&amp;mut self,lifetime参数只是被省略了。

标签: rust borrow-checker


【解决方案1】:

正如 krdln 所建议的,解决此问题的最简单方法是在 if 块中返回,从而确定借用范围:

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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-17
  • 2015-05-26
  • 1970-01-01
  • 1970-01-01
  • 2015-02-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多