Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the derived clone() method return a reference? [duplicate]

Tags:

rust

Deriving the Clone trait for a struct containing a reference to object of generic type (Unless it has Clone bound. In that case cloning work as expected) will generate clone() method which returns a reference to object but not a new object.

I have the code:

#[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()
}

Which will cause an error:

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>`

Why does derive behave this way?

Following manual implementation allow to avoid this obstacle but unpleasant.

impl<'a, T: 'a> Clone for A<'a, T>{
    fn clone(&self)->Self{
        A{ref_generic: self.ref_generic}
    }
}
like image 672
Pavel Arnold Avatar asked Oct 24 '17 08:10

Pavel Arnold


People also ask

What is clone () in Java?

Object cloning refers to the creation of an exact copy of an object. It creates a new instance of the class of the current object and initializes all its fields with exactly the contents of the corresponding fields of this object. Using Assignment Operator to create a copy of the reference variable.

What does clone do rust?

Trait std::clone::Clone1.0. A common trait for the ability to explicitly duplicate an object. Differs from Copy in that Copy is implicit and extremely inexpensive, while Clone is always explicit and may or may not be expensive.

Why clone method is not visible?

Object class is in java. lang package and MyClass is in GoodQuestions package. So clone() method becomes a private member of MyClass class. That explains why you are unable to access clone() method from TestSingleTon class.


1 Answers

You are not calling A::clone(). You are calling &A::clone(), i.e. you are cloning the reference, not the object.

The compiler would actually prefer to call A::clone(), because the argument matches more precisely (Clone::clone takes a &self, so the single ref matches exactly, instead of requiring auto-ref for the call to the reference clone), but it can't. (You can see that by looking at the error message you get when you try to do (*a).clone() instead.) This is because the auto-derived Clone naively implements it as:

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

Note the Clone bound on T. That bound is not necessary, but the auto-derivation still requires it. This is bug #26925.

Your test_call function does not have a bound on T, which means that the derived Clone impl for A is not available, so the compiler falls back to the only Clone impl it can call, which is the one for &A.

like image 83
Sebastian Redl Avatar answered Oct 12 '22 03:10

Sebastian Redl