Copy vs Clone
In the previous exercise, you learned that assignment moves ownership. But wait — this works fine:
let x = 42;
let y = x;
println!("{}", x); // still valid!
Why didn't x move? Because integers implement the Copy trait.
Copy types: stack-only data
Types that are small and live entirely on the stack can be copied instead of moved:
let a: i32 = 5;
let b = a; // a is copied, not moved
// both a and b are valid
Copy types include:
- All integer types (i32, u64, etc.)
- Floating point (f32, f64)
- Booleans (bool)
- Characters (char)
- Tuples of Copy types: (i32, bool)
Non-Copy types: heap data
Types that manage heap memory cannot be Copy — they must be moved or explicitly cloned:
let s1 = String::from("hello");
let s2 = s1; // s1 is MOVED
// println!("{}", s1); // ERROR
let s3 = String::from("hello");
let s4 = s3.clone(); // explicit deep copy
println!("{} {}", s3, s4); // both valid
Python comparison
In Python, everything is a reference. "Copying" is actually aliasing:
x = [1, 2, 3]
y = x # y points to same list
y.append(4)
print(x) # [1, 2, 3, 4] — oops!
import copy
z = copy.copy(x) # explicit shallow copy
Rust makes this explicit: small stack values copy automatically, heap values require .clone().
The Clone trait
.clone() creates a deep copy. It's explicit because it might be expensive:
let big_vec = vec![0; 1_000_000];
let copy = big_vec.clone(); // allocates another million integers
Login to see the full task and start coding.
This is a premium exercise
Log in to unlock the full exercise and start coding.
Login to access this exercise