mirror of
https://github.com/leonardomso/rust-skills.git
synced 2026-09-14 19:33:21 +08:00
5f0b2079f8
Add unsafe, concurrency, conversions, and pattern-matching categories plus rules across existing ones, and correct advice that was outdated for Rust 1.96.
3.0 KiB
3.0 KiB
own-copy-small
Implement
Copyfor small, simple types
Why It Matters
Types that implement Copy are implicitly duplicated on assignment instead of moved. This eliminates the need for explicit .clone() calls and makes the code more ergonomic. For small types (generally ≤16 bytes), copying is as fast or faster than moving a pointer.
Bad
// Small type without Copy - requires explicit clone
#[derive(Clone, Debug)]
struct Point {
x: f64,
y: f64,
}
fn distance(p1: Point, p2: Point) -> f64 {
((p2.x - p1.x).powi(2) + (p2.y - p1.y).powi(2)).sqrt()
}
let origin = Point { x: 0.0, y: 0.0 };
let target = Point { x: 3.0, y: 4.0 };
let d1 = distance(origin.clone(), target.clone()); // Tedious
let d2 = distance(origin.clone(), target.clone()); // Every use needs clone
// origin and target still usable but verbose
Good
// Small type with Copy - implicit duplication
#[derive(Clone, Copy, Debug)]
struct Point {
x: f64,
y: f64,
}
fn distance(p1: Point, p2: Point) -> f64 {
((p2.x - p1.x).powi(2) + (p2.y - p1.y).powi(2)).sqrt()
}
let origin = Point { x: 0.0, y: 0.0 };
let target = Point { x: 3.0, y: 4.0 };
let d1 = distance(origin, target); // Implicitly copied
let d2 = distance(origin, target); // Still works!
// origin and target remain valid
Copy Requirements
A type can implement Copy only if:
- All fields implement
Copy - No custom
Dropimplementation - No heap-allocated data (
String,Vec,Box, etc.)
// ✅ Can be Copy
#[derive(Clone, Copy)]
struct Color {
r: u8,
g: u8,
b: u8,
a: u8,
}
// ❌ Cannot be Copy - contains String
#[derive(Clone)]
struct Person {
name: String, // String is not Copy
age: u32,
}
// ❌ Cannot be Copy - has Drop
struct FileHandle {
fd: i32,
}
impl Drop for FileHandle {
fn drop(&mut self) { /* close file */ }
}
Size Guidelines
| Size | Recommendation |
|---|---|
| ≤ 16 bytes | Implement Copy |
| 17-64 bytes | Consider Copy, benchmark if critical |
| > 64 bytes | Probably don't, prefer references |
use std::mem::size_of;
#[derive(Clone, Copy)]
struct SmallId(u64); // 8 bytes ✅
#[derive(Clone, Copy)]
struct Rect { x: f32, y: f32, w: f32, h: f32 } // 16 bytes ✅
#[derive(Clone)] // No Copy - 72 bytes
struct Transform {
matrix: [[f64; 3]; 3], // 72 bytes, too large
}
Common Copy Types
Standard library types that are Copy:
- All primitives:
i32,f64,bool,char, etc. - Shared references:
&T(note:&mut Tis NOTCopy— copying a mutable reference would alias it, so it is reborrowed instead) - Raw pointers:
*const T,*mut T - Function pointers:
fn(T) -> U - Tuples of
Copytypes:(i32, f64) - Arrays of
Copytypes:[u8; 32] Option<T>whereT: CopyPhantomData<T>
See Also
- own-clone-explicit - When Clone without Copy is appropriate
- type-newtype-ids - Newtype pattern often uses Copy