Rust生命周期 - 在Arc中的RWLock中从向量返回值

时间:2014-03-27 14:20:30

标签: rust lifetime

我在与Arcs和RWLocks相关的生命周期中遇到了很多麻烦。

struct ComponentContainer<T>{
    id_to_component: HashMap<uint, uint>,
    components: Arc<RWLock<~Vec<T>>>
}

id_to_component是组件ID的映射,是组件中Vec的索引。

我从直觉中尝试了一切:

impl<T: Component> ComponentContainer<T>{
    fn get<'a>(&'a self, id: uint) -> &'a T {
        let idx = self.id_to_component.get(&id);
        self.components.read().get(*idx)
    }
}

极其冗长(手动存储每个引用):

impl<T: Component> ComponentContainer<T> {
    fn get<'a>(&'a self, id: uint) -> &'a T {
        let idx = self.id_to_component.get(&id);
        let components: &'a RWLock<~Vec<T>> = &'a *self.components;
        let c: &'a RWLock<~Vec<T>> = &'a *components;
        let tmp: &'a RWLockReadGuard<'a, ~Vec<T>> = &'a c.read();
        let v: &'a ~Vec<T> = &'a **tmp;
        v.get(*idx)
    }
}

使用详细信息,我最终得到错误:

error: borrowed value does not live long enough
let tmp: &'a RWLockReadGuard<'a, ~Vec<T>> = &'a c.read();
                                            ^~~~~~~~~~~~

根据RWLock.read()的来源,返回的引用应该具有指定的生命周期,除非我没有错误地读取它。

编辑:短版本的完整生锈输出

test.rs:18:9: 18:31 error: borrowed value does not live long enough
test.rs:18         self.components.read().get(*idx)
                   ^~~~~~~~~~~~~~~~~~~~~~
test.rs:16:45: 19:6 note: reference must be valid for the lifetime &'a  as defined on the block at 16:44...
test.rs:16     fn get<'a>(&'a self, id: uint) -> &'a T {
test.rs:17         let idx = self.id_to_component.get(&id);
test.rs:18         self.components.read().get(*idx)
test.rs:19     }
test.rs:16:45: 19:6 note: ...but borrowed value is only valid for the block at 16:44
test.rs:16     fn get<'a>(&'a self, id: uint) -> &'a T {
test.rs:17         let idx = self.id_to_component.get(&id);
test.rs:18         self.components.read().get(*idx)
test.rs:19     }
error: aborting due to previous error

1 个答案:

答案 0 :(得分:1)

让我们看一下signature of read()

fn read<'a>(&'a self) -> RWLockReadGuard<'a>

返回RWLockReadGuard<'a>。这不是对RWLockReadGuard的引用,而是RWLockReadGuard包含}生活中的引用。

现在你的行:

'a

您正在参考let tmp: &'a RWLockReadGuard<'a, ~Vec<T>> = &'a c.read(); 。这意味着引用的对象必须至少与引用一样长。但情况并非如此:该值是RWLockReadGuard返回的值,它不存储在任何地方。因为它没有存储在任何地方,所以它在语句的末尾被丢弃,因此借用无效,因为所需的c.read()比语句长,因此无法满足。

你应该做的只是放弃'a部分,直接使用对象:

&'a

我不确定你的短版本乍一看有什么问题,而且我没有方便。请发布完整的rustc stderr。