【发布时间】: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);
}
UPD:正如建议的那样,这是一个像我一样的错误“家庭”,很好地解释了here。但是我的情况有更简单的解决方案。
【问题讨论】:
-
RefCell无法解决此问题。这是借用检查器的已知限制,对此有一些问题/答案。我指出了一个可能的重复项,但我认为我们应该找到一个明确的答案(如果可能的话)。 @Shepmaster 你知道更好的副本吗? -
@malbarbo 我不认为它与那个完全相同。它与从
&mut self方法返回的引用有关。这会导致可变借用持续存在。 example -
同时我找到了一个解决方案,但它对我来说看起来非常难看。 gist.github.com/7f108112b95e2550691095e34c7cf37f
-
最简单的方法是在处理错误后尽早使用
return。 @Shepmaster我觉得其实差不多,Option<Chars>也是借用&mut self,lifetime参数只是被省略了。
标签: rust borrow-checker