rust clone

rust - Derivar un rasgo produce un error inesperado del compilador, pero la implementación manual funciona



clone (2)

La respuesta está enterrada en el mensaje de error:

existe el método de clone pero no se cumplieron los siguientes límites de rasgos: T : std::clone::Clone

Cuando deriva Clone (y muchos otros tipos derivados automáticamente), agrega un Clone enlazado en todos los tipos genéricos. Usando rustc -Z unstable-options --pretty=expanded , podemos ver en qué se convierte:

impl <''a, T: ::std::clone::Clone + ''a> ::std::clone::Clone for Foo<''a, T> { #[inline] fn clone(&self) -> Foo<''a, T> { match *self { Foo { t: ref __self_0_0 } => Foo{t: ::std::clone::Clone::clone(&(*__self_0_0)),}, } } }

En este caso, el límite no es necesario porque el tipo genérico está detrás de una referencia.

Por ahora, deberá implementar Clone usted mismo. Hay un problema de Rust para esto , pero es un caso relativamente raro con una solución alternativa.

Este código ( playground ):

#[derive(Clone)] struct Foo<''a, T: ''a> { t: &''a T, } fn bar<''a, T>(foo: Foo<''a, T>) { foo.clone(); }

... no compila:

error: no method named `clone` found for type `Foo<''a, T>` in the current scope --> <anon>:7:9 |> 16 |> foo.clone(); |> ^^^^^ note: the method `clone` exists but the following trait bounds were not satisfied: `T : std::clone::Clone` help: items from traits can only be used if the trait is implemented and in scope; the following trait defines an item `clone`, perhaps you need to implement it: help: candidate #1: `std::clone::Clone`

Agregar use std::clone::Clone; no cambia nada, ya que de todos modos ya está en el preludio.

Cuando elimino el #[derive(Clone)] e implemento manualmente Clone para Foo , ¡se compila como se esperaba !

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

¿Que esta pasando aqui?

  • ¿Hay alguna diferencia entre #[derive()] -impls y manuales?
  • ¿Es esto un error del compilador?
  • ¿Algo más en lo que no pensé?

Su ejemplo derivará Clone sin ningún problema si marca explícitamente que T debe implementar Clone , así:

#[derive(Clone)] struct Foo<''a, T: ''a> { t: &''a T, } fn bar<''a, T: Clone>(foo: Foo<''a, T>) { foo.clone(); }

( Enlace del patio de juegos )

Parece inusual que pueda evitar especificar el límite explícitamente, pero la respuesta de Shepmaster parece sugerir que el compilador lo inserta implícitamente, por lo que mi sugerencia es funcionalmente idéntica.