Right, let’s talk about Clone. This is your “I need a full, independent copy of this thing” button. It’s explicit, which is Rust’s way of saying, “Copying can be expensive, so I’m not going to do it behind your back. You have to ask for it by name.”

Think of it as the opposite of Copy. With Copy, the compiler does the work silently. With Clone, you have to call .clone() explicitly. This is a crucial distinction. It’s a signal, both to the compiler and to anyone reading your code, that an operation with potential cost is happening. If you see .clone(), you should at least briefly think, “Okay, we’re duplicating data here.”

The core of the trait is dead simple:

pub trait Clone {
    fn clone(&self) -> Self;

    // provided default methods, like clone_from
}

Your job, when implementing it for your own types, is to write the clone method so it constructs a new, independent value that’s semantically equal to self.

The Default Derive (And When To Use It)

For many types, implementing Clone is brain-dead easy. If all the fields in your struct or enum also implement Clone (which most standard types do), you can just #[derive(Clone)] and be done with it. The compiler will generate a clone method that just calls clone on each field.

#[derive(Clone, Debug)]
struct Config {
    hostname: String, // String implements Clone
    port: u16,        // u16 implements Clone
    timeout: Duration, // Duration implements Clone
}

let config_one = Config {
    hostname: "localhost".to_string(),
    port: 8080,
    timeout: Duration::from_secs(30),
};

// This is our explicit, deep copy.
let config_two = config_one.clone();

Here, config_two gets its own entirely new String on the heap, its own u16, and its own Duration. Modifying config_one.hostname will have no effect on config_two.hostname. This is what we mean by a deep copy.

Manual Implementation: When The Derive Isn’t Enough

The derive macro is brilliant until it isn’t. The moment your type manages its own resources or contains a non-Clone type (which is rare), you have to roll up your sleeves and implement it yourself.

The most classic example is when you have a struct containing a raw pointer. The derive would just copy the pointer value, resulting in two structs both pointing to the same memory—a classic “shallow copy” that leads to double frees and utter chaos. This is precisely what Clone is designed to prevent.

Let’s look at a less dangerous but more common scenario: a simple struct that holds a heap-allocated array. We can’t derive because we’re using a raw pointer to be deliberately difficult, but the logic applies to any custom allocation.

struct MyVec {
    data: *mut i32,
    length: usize,
}

impl MyVec {
    fn new() -> Self {
        // In real life, you'd use Box<[i32]> or Vec<i32>. This is for illustration.
        let mut v = Vec::with_capacity(10);
        v.extend([1, 2, 3, 4]);
        let length = v.len();
        let data = Box::into_raw(v.into_boxed_slice()) as *mut i32;
        Self { data, length }
    }
}

impl Clone for MyVec {
    fn clone(&self) -> Self {
        // This is the crucial part: we allocate new memory.
        let new_vec = unsafe {
            let slice = std::slice::from_raw_parts(self.data, self.length);
            slice.to_vec() // Creates a brand new Vec<i32>
        };

        // Now we have to manage that new memory, just like in `new`.
        let data = Box::into_raw(new_vec.into_boxed_slice()) as *mut i32;
        Self {
            data,
            length: self.length,
        }
    }
}

// Don't forget Drop! This is critical and often the reason you're
// implementing Clone manually in the first place.
impl Drop for MyVec {
    fn drop(&mut self) {
        unsafe {
            let _ = Box::from_raw(std::slice::from_raw_parts_mut(self.data, self.length));
        }
    }
}

The key insight in the clone method is slice.to_vec(). It’s not copying the pointer; it’s creating a whole new collection on the heap by iterating over and cloning each element. This is the heart of a proper deep copy: duplicating the structure and all the data it owns.

Cloning Enums and The Matchery

Cloning enums is where you might have to drop the derive and get manual, especially if some variants contain non-Clone data or need special handling. The generated code from #[derive(Clone)] is essentially a big match self block that calls clone on the inner data for each variant. If you need to do it yourself, that’s exactly what you write.

enum NetworkEvent {
    Ping,
    Message(String),
    // Suppose we have a variant that can't be derived...
    // Connection(SomeNonCloneableHandle),
}

// The derived impl would look like this:
impl Clone for NetworkEvent {
    fn clone(&self) -> Self {
        match self {
            NetworkEvent::Ping => NetworkEvent::Ping,
            NetworkEvent::Message(s) => NetworkEvent::Message(s.clone()),
            // NetworkEvent::Connection(h) => NetworkEvent::Connection(h.clone()), // Wouldn't work if h isn't Clone
        }
    }
}

The clone_from Method: An Optional Optimization

Look at the trait definition again. There’s a provided method clone_from:

fn clone_from(&mut self, source: &Self) {
    *self = source.clone()
}

This is a potential optimization hook. The default implementation just does *self = source.clone(), which means it drops the old value in self and replaces it with a brand new clone. But if you’re cloning into a Vec, for example, you might be able to reuse the already-allocated buffer. You can override this method to provide a more efficient implementation.

In practice, you almost never need to implement this yourself unless you’re writing extremely performance-sensitive code. The standard library uses it for types like String and Vec to avoid unnecessary allocations. For your own types, starting with the default is perfectly fine.