从向量中获取特征对象引用

时间:2018-03-31 11:20:59

标签: rust

我正在努力从mylist中获取一个具有生命周期参考的元素。我把我的代码简化为:

Vec

playground

产生此错误:

pub trait Runnable {}

pub struct RunList<'a> {
    runnables: Vec<&'a mut Runnable>,
}

impl<'a> RunList<'a> {
    pub fn get(&self, id: usize) -> &'a mut Runnable {
        self.runnables[id]
    }
}

fn main() {}

1 个答案:

答案 0 :(得分:3)

首先,从'a的返回值类型中删除生命周期参数get

pub trait Runnable {}

pub struct RunList<'a> {
    runnables: Vec<&'a mut Runnable>,
}

impl<'a> RunList<'a> {
    pub fn get(&mut self, id: usize) -> &mut Runnable {
        self.runnables[id]
    }
}

fn main() {}

这可以解决潜在的问题:

error[E0389]: cannot borrow data mutably in a `&` reference
 --> src/main.rs:9:9
  |
9 |         self.runnables[id]
  |         ^^^^^^^^^^^^^^^^^^ assignment into an immutable reference

self.runnables[id]不可侵犯地借用&'a mut Runnable并隐含地取消引用它。你无法将&'a mut Runnable移出这个不可变借入。相反,你可以重新延长可运行的东西,这需要可变借用self

impl<'a> RunList<'a> {
    pub fn get(&mut self, id: usize) -> &mut Runnable {
        &mut *self.runnables[id]
    }
}

要了解这里究竟发生了什么,应该阅读:What is the return type of the indexing operation?

pub fn get(&mut self, id: usize) -> &mut Runnable {
    self.runnables[id]
}

相当于:

pub fn get(&mut self, id: usize) -> &mut Runnable {
    let r: &&mut (Runnable + 'a)  = self.runnables.index(id);
    *r
}

index返回&'a mut Runnable的不可变引用,其类型为&&mut (Runnable + 'a)。返回*r不起作用,因为您无法从借用内容中移动可变引用 1 ,并且不可变地借用不可变引用中的数据({{1} }不起作用)。因此,您需要&mut**r的版本,该版本授予对索引元素的可变访问权:index

index_mut

这很有效,因为pub fn get(&mut self, id: usize) -> &mut Runnable { let r: &mut &'a mut (Runnable + 'a) = self.runnables.index_mut(id); *r } 实际上可以在*r内部重新插入Runnable。与上面使用不可变引用&mut**r的情况相反,可变地引用可变引用r内的数据是完全正确的。执行r时,参数&mut**r会在解除引用过程中丢失。因此,返回'a而不是&'a mut Runnable在此处不起作用。

最后,&mut Runnable告诉编译器隐式解析为&mut *self.runnables[id]而不是*self.runnables.index_mut(id)*self.runnables.index(id)也可以。

1 可变引用不是*&mut self.runnables[id]。如果您将代码中的所有Copy更改为&'a mut Runnable,则会进行编译,因为不可变引用为&'a Runnable