Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions src/trait/clone.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Clone
# Clone and Copy

When dealing with resources, the default behavior is to transfer them during
assignments or function calls. However, sometimes we need to make a
Expand All @@ -7,19 +7,37 @@ copy of the resource as well.
The [`Clone`][clone] trait helps us do exactly this. Most commonly, we can
use the `.clone()` method defined by the `Clone` trait.

## Copy: Implicit Cloning

The [`Copy`][copy] trait allows a type to be duplicated simply by copying bits,
with no additional logic required. When a type implements `Copy`, assignments
and function calls will implicitly copy the value instead of moving it.

**Important:** `Copy` requires `Clone` - any type that implements `Copy` must
also implement `Clone`. This is because `Copy` is defined as a subtrait:
`trait Copy: Clone {}`. The `Clone` implementation for `Copy` types simply
copies the bits.

Not all types can implement `Copy`. A type can only be `Copy` if:
- All of its components are `Copy`
- It doesn't manage external resources (like heap memory, file handles, etc.)

```rust,editable
// A unit struct without resources
// Note: Copy requires Clone, so we must derive both
#[derive(Debug, Clone, Copy)]
struct Unit;

// A tuple struct with resources that implements the `Clone` trait
// This CANNOT be Copy because Box<T> is not Copy
#[derive(Clone, Debug)]
struct Pair(Box<i32>, Box<i32>);

fn main() {
// Instantiate `Unit`
let unit = Unit;
// Copy `Unit`, there are no resources to move
// Copy `Unit` - this is an implicit copy, not a move!
// Because Unit implements Copy, the value is duplicated automatically
let copied_unit = unit;

// Both `Unit`s can be used independently
Expand All @@ -31,6 +49,7 @@ fn main() {
println!("original: {:?}", pair);

// Move `pair` into `moved_pair`, moves resources
// Pair does not implement Copy, so this is a move
let moved_pair = pair;
println!("moved: {:?}", moved_pair);

Expand All @@ -39,6 +58,7 @@ fn main() {
// TODO ^ Try uncommenting this line

// Clone `moved_pair` into `cloned_pair` (resources are included)
// Unlike Copy, Clone is explicit - we must call .clone()
let cloned_pair = moved_pair.clone();
// Drop the moved original pair using std::mem::drop
drop(moved_pair);
Expand All @@ -53,3 +73,4 @@ fn main() {
```

[clone]: https://doc.rust-lang.org/std/clone/trait.Clone.html
[copy]: https://doc.rust-lang.org/std/marker/trait.Copy.html