In Rust, the Clone and Copy traits control how values are duplicated. Understanding these traits is essential because they directly impact ownership and how your code behaves when you assign or pass values around.
The Copy trait marks types that can be duplicated simply by copying their bits in memory. When a type implements Copy, assignment creates a copy rather than a move, meaning you can continue using the original value. Primitive types like integers, floats, and booleans are Copy by default. The Clone trait, on the other hand, provides explicit cloning via the .clone() method and can involve arbitrary code, including heap allocations.
The key relationship: Copy is a subtrait of Clone, meaning every Copy type must also be Clone. However, not every Clone type is Copy. Types like String and Vec<T> are Clone but not Copy because copying them would require duplicating heap-allocated data.
pub trait Clone {
fn clone(&self) -> Self;
}
pub trait Copy: Clone { } // Marker trait - no methods// Simple struct with all Copy fields - can derive both
#[derive(Clone, Copy)]
struct Point {
x: i32,
y: i32,
}
// Struct with non-Copy field - can only derive Clone
#[derive(Clone)]
struct Person {
name: String, // String is not Copy
age: u32,
}Implement the following types demonstrating Clone and Copy:
Create a Color struct with r, g, b fields (all u8). This type should be Copy since it only contains primitive fields.
Clone and CopyDebug and PartialEq for testingCreate a Dimensions struct with width and height fields (both f64). This should also be Copy.
Clone and CopyDebug and PartialEq for testingCreate a Label struct with a text field (String). Since String is not Copy, this type can only be Clone.
Clone (but NOT Copy)Debug and PartialEq for testingCreate a Document struct with:
title: Stringpages: Vec<String>This type contains heap-allocated data, so it should only be Clone.
Clone (but NOT Copy)Debug and PartialEq for testingTaggedValue<T> (Generic Clone)Create a generic TaggedValue<T> struct with:
tag: Stringvalue: TImplement Clone for TaggedValue<T> where T: Clone. Since it contains a String, it cannot be Copy.
Clone with appropriate boundsDebug and PartialEq with appropriate boundsImplement these functions to demonstrate the difference between Clone and Copy:
duplicate_copy<T: Copy>(value: T) -> (T, T) - Returns a tuple with two copies of the valueduplicate_clone<T: Clone>(value: &T) -> T - Returns a clone of the referenced valueclone_vec<T: Clone>(items: &[T]) -> Vec<T> - Clones all items in a slice into a new Vec// Copy types - original still usable after assignment
let color1 = Color { r: 255, g: 128, b: 0 };
let color2 = color1; // Copy happens here
assert_eq!(color1.r, 255); // color1 still valid!
let dims = Dimensions { width: 10.0, height: 20.0 };
let (d1, d2) = duplicate_copy(dims);
assert_eq!(d1.width, d2.width);
// Clone types - must explicitly clone
let label1 = Label { text: String::from("Hello") };
let label2 = label1.clone(); // Explicit clone needed
// label1 is still valid because we cloned, not moved
let doc = Document {
title: String::from("My Doc"),
pages: vec![String::from("Page 1")],
};
let doc_copy = duplicate_clone(&doc);
assert_eq!(doc.title, doc_copy.title);
// Generic clone
let tagged = TaggedValue {
tag: String::from("number"),
value: 42,
};
let tagged_clone = tagged.clone();
assert_eq!(tagged.value, tagged_clone.value);
// Clone a slice
let numbers = vec![1, 2, 3];
let cloned = clone_vec(&numbers);
assert_eq!(cloned, vec![1, 2, 3]);#[derive(Clone, Copy)] for types where all fields implement Copy#[derive(Clone)] (without Copy) for types containing String, Vec, or other heap-allocated types#[derive(Clone)] with T: Cloneduplicate_copy function takes ownership but can return two copies since T: Copyduplicate_clone function takes a reference and returns a clone.iter().cloned().collect() or .to_vec() to clone a slice into a Vec