为什么派生的clone()方法返回引用?

时间:2017-10-24 08:59:52

标签: rust

为包含对泛型类型对象的引用的结构派生Clone特征(除非它已绑定Clone。在这种情况下,克隆按预期工作)将生成clone()方法返回对象的引用,但不返回新对象。

我有代码:

#[derive(Clone)]
struct A<'a, T: 'a>{
    ref_generic: &'a T
}

fn test_call<'a, T: 'a>(a: &A<'a, T>)->A<'a, T>{
    a.clone()
}

哪会导致错误:

error[E0308]: mismatched types
  --> src/lib.rs:15:5
   |
14 | fn test_call<'a, T: 'a>(a: &A<'a, T>)->A<'a, T>{
   |                                        -------- expected `A<'a, T>` because of return type
15 |     a.clone()
   |     ^^^^^^^^^ expected struct `A`, found &A<'_, T>
   |
   = note: expected type `A<'a, T>`
              found type `&A<'_, T>`

为什么派生表现得这样?

遵循手动实施可以避免这种障碍,但令人不快。

impl<'a, T: 'a> Clone for A<'a, T>{
    fn clone(&self)->Self{
        A{ref_generic: self.ref_generic}
    }
}

1 个答案:

答案 0 :(得分:7)

您没有致电A::clone()。您正在调用&A::clone(),即您正在克隆引用,而不是对象。

编译器实际上更愿意调用A::clone(),因为参数匹配更精确(Clone::clone需要&self,所以单个ref完全匹配,而不需要自动引用对参考克隆的调用),但它不能。 (您可以通过查看尝试执行(*a).clone()时收到的错误消息来查看。)这是因为自动派生的Clone天真地将其实现为:

impl <'a, T: Clone + 'a> Clone for A<'a, T> {
  fn clone(&self) -> Self { Self { ref_generic: self.ref_generic } }
}

请注意Clone上绑定的T。这种约束不是必需的,但自动推导仍然需要它。这是bug #26925

您的test_call函数在T上没有绑定,这意味着Clone的派生A impl不可用,因此编译器会回退到只有Clone impl它可以调用,这是&A