无法移出借用的上下文

时间:2018-09-21 00:38:25

标签: rust

我有一段非常简单的代码,我无法编译:

struct X;

struct A {
    field: Option<Box<X>>,
}

impl A {
    pub fn get_field(&self) -> Option<&X> {
        return self.field.map(|value| &*value);
    }
}
error[E0507]: cannot move out of borrowed content
 --> src/lib.rs:9:16
  |
9 |         return self.field.map(|value| &*value);
  |                ^^^^ cannot move out of borrowed content

error[E0597]: `*value` does not live long enough
 --> src/lib.rs:9:40
  |
9 |         return self.field.map(|value| &*value);
  |                                        ^^^^^-
  |                                        |    |
  |                                        |    borrowed value only lives until here
  |                                        borrowed value does not live long enough
  |
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 8:5...
 --> src/lib.rs:8:5
  |
8 | /     pub fn get_field(&self) -> Option<&X> {
9 | |         return self.field.map(|value| &*value);
10| |     }
  | |_____^

我真的不明白为什么这行不通。

1 个答案:

答案 0 :(得分:5)

  

我真的不明白为什么这行不通。

您的代码定义了一个结构A,该结构可能会或可能不会在堆(而不是堆栈)中保存X

在方法get_field中,您获得了对该结构的引用,但是,如果可能,您希望获得对内部X的引用。

仅通过查看A的函数签名和结构定义来得出以上结论。

查看函数体,self.field的类型为Option<_>map是其方法。查看the documentation for Option::map

pub fn map<U, F>(self, f: F) -> Option<U> 
where
  F: FnOnce(T) -> U,
     

通过将函数应用于包含的值,将Option<T>映射到Option<U>

它接受只能运行一次的闭包,在您的情况下接受Box<X>,然后根据您的函数返回类型应返回&X。乍看之下,这似乎是完美的匹配,因为如果value: Box<X>然后*value: X&*value: &X,但它不会编译!怎么了?

如果您仔细查看map的签名,您会发现它有2个参数,而不是1个。第一个参数是“方法接收器” self,其类型为Self

在Rust中,这意味着此调用将需要使用方法接收方;调用后,用于调用该方法的对象将不再有效。

但是,不允许您的get_field方法删除方法接收者self.fieldself仅是对A的引用,因此self.field也是仅供参考。然后,您将无法调用map来消耗self.field

解决方案是使用as_ref

pub fn as_ref(&self) -> Option<&T>
     

Option<T>转换为Option<&T>

尽管它说从Option<T>进行转换,但是从签名中您可以看到它接受&Option<T>,因此它只是将外部&移入了内部。现在您可以使用map

 pub fn get_field(&self) -> Option<&X> {
    return self.field.as_ref().map(|value| &*value);
 }

现在可以了。