不能脱离`&`-pointer的解除引用

时间:2014-10-26 03:49:43

标签: rust

我有以下代码

pub struct PropertyDeclarationBlock {
    pub declarations: Arc<Vec<(PropertyDeclaration, PropertyDeclarationImportance)>>
}

impl PropertyDeclarationBlock {
    pub fn select_declarations(&self) -> Arc<Vec<PropertyDeclaration>> {
        Arc::new(self.declarations.clone().map_in_place(|p| {
                                                        let (declaration, _) = p;
                                                        declaration
                                                        }))
    }

}

我希望能够在PropertyDeclarationBlock上调用.select_declarations()并让它返回声明的克隆,但不是它是Arc Vec(PropertyDeclaration,PropertyDeclarationImportance)只是一个Arc Vec PropertyDeclaration,换句话说返回一个PropertyDeclaration的向量而不是前一个元组。

之前不会编译,因为我收到以下错误:

error: cannot move out of dereference of `&`-pointer
Arc::new(self.declarations.clone().map_in_place(|p| {
         ^~~~~~~~~~~~~~~~~~~~~~~~~

据我所知,由于该函数将self作为参数,因此它将拥有它的所有权。因为我宁愿使用burrow self函数,所以我使用&amp;。

修改

以下是实现新功能后的错误消息:

error: cannot move out of dereference of `&`-pointer
Arc::new(self.declarations.iter().map(|&(declaration, _)| declaration).collect())
                                       ^~~~~~~~~~~~~~~~~
note: attempting to move value to here (to prevent the move, use `ref declaration` or `ref mut declaration` to capture value by reference)
Arc::new(self.declarations.iter().map(|&(declaration, _)| declaration).collect())
                                         ^~~~~~~~~~~

我尝试在声明之前应用ref关键字,如错误消息所示,但它没有帮助。

1 个答案:

答案 0 :(得分:1)

self.declarations.clone()克隆Arc,而我相信您打算克隆Vec。要解析对map_in_place的调用,编译器会自动取消引用Arc以便能够调用Vec上定义的方法。编译器知道如何取消引用Arc,因为Arc实现了Derefderef返回一个借来的指针,这就是错误的来源。要克隆Vec,我们必须明确取消引用Arc(*self.declarations).clone()

但是,map_in_place在这种情况下不合适,因为(PropertyDeclaration, PropertyDeclarationImportance)的大小与PropertyDeclaration的大小不同(除非PropertyDeclarationImportance的大小为零,可能不是这种情况),这是每个文档所必需的。它失败并显示类似于此的消息:

task '<main>' failed at 'assertion failed: mem::size_of::<T>() == mem::size_of::<U>()', /build/rust-git/src/rust/src/libcollections/vec.rs:1805

这是一个正确的实施:

impl PropertyDeclarationBlock {
    pub fn select_declarations(&self) -> Arc<Vec<PropertyDeclaration>> {
        Arc::new(self.declarations.iter().map(|&(declaration, _)| declaration).collect())
    }
}

在这里,我们在Vec上使用iter来创建向量项目的迭代器。这将返回Items,它在不可变引用上实现Iterator

然后,我们使用map懒洋洋地将(PropertyDeclaration, PropertyDeclarationImportance)映射到PropertyDeclaration。注意我们如何解析闭包的参数列表中的元组引用(这也适用于fn)而不是使用let语句。

最后,我们使用collect为此序列创建一个新的集合容器。 collect的结果是通用的;它可以是任何实现FromIterator的类型。 Vec实现FromIterator,编译器从方法的签名中推断出Vec