diff --git a/src/trait/clone.md b/src/trait/clone.md index 8e04f5a2ae..093ffa33a3 100644 --- a/src/trait/clone.md +++ b/src/trait/clone.md @@ -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 @@ -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 is not Copy #[derive(Clone, Debug)] struct Pair(Box, Box); 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 @@ -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); @@ -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); @@ -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