为什么clone()不允许这样做?

时间:2020-10-01 02:47:54

标签: rust borrow-checker

我不明白为什么以下操作无效:

use std::collections::HashMap;

#[derive(Debug,Clone,PartialEq)]
struct Foo<'a> {
    contents: HashMap<&'a str, Foo<'a>>,
}

fn bar<'a>(val: Foo<'a>) -> Foo<'a> {
    *val.contents.get("bar").clone().unwrap()
}
error[E0507]: cannot move out of a shared reference
 --> src/lib.rs:9:5
  |
9 |     *val.contents.get("bar").clone().unwrap()
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `Foo<'_>`, which does not implement the `Copy` trait

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8ab3c7355903fc34751d5bd5360bb71a

我正在执行.clone(),我认为应该允许我返回结果值,该结果的所有权应与输入值分离,但事实并非如此。

另一不可思议的事情,它本身并不是一个阻止程序,但可能暗示了潜在的问题,是由于某种原因,.clone()返回了一个&Foo,这令人惊讶,因为在其他情况下我主要看到.clone()来自&T -> T。这就是*在这里的原因;没有它,这将无法通过类型检查。我知道Rust有一些“神奇的”引用/取消引用规则,但是我不太清楚这一点。

1 个答案:

答案 0 :(得分:1)

HashMap.get返回一个Option<&T>。克隆此选项将为您提供另一个Option<&T>,引用同一对象。

如果要将Option<&T>转换为Option<T>支持T的新Clone,则可以使用.cloned()。由于您拥有T而不是&T,因此也不再需要取消引用。

这意味着您的代码将类似于this

use std::collections::HashMap;

#[derive(Debug, Clone, PartialEq)]
struct Foo<'a> {
    contents: HashMap<&'a str, Foo<'a>>,
}

fn bar<'a>(val: Foo<'a>) -> Foo<'a> {
    val.contents.get("bar").cloned().unwrap()
}