Common traits
The standard library has traits that almost every type wants. Rust can write many of them for you.
derive
#[derive(...)] above a struct or enum writes trait impls for you.
#[derive(Debug, Clone, PartialEq)]struct Point { x: i32, y: i32,}It works only if every field also has that trait. The attribute can also sit on the same line as the struct: #[derive(Debug)] struct Id(u32);.
PartialEq
PartialEq makes == and != work. A derived PartialEq compares every field. Without it, a == b fails with E0369. You can also write it by hand: implement fn eq(&self, other: &Self) -> bool.
let a = Point { x: 1, y: 2 };let b = Point { x: 1, y: 2 };println!("{}", a == b); // trueDisplay
Display controls how {} prints a value. It can't be derived; you write it yourself.
use std::fmt;impl fmt::Display for Point { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "({}, {})", self.x, self.y) }}use std::fmt; lets you write the short names fmt::Display and fmt::Formatter. write! works like println!, but writes into f. Once you have Display, to_string() works too.
Default
Default gives a starting value with Type::default(). A derived Default uses each field's default: 0 for numbers, false for bool, and an empty String.
#[derive(Default)]struct Config { level: u8, name: String }let c = Config::default(); // level 0, name ""Clone vs Copy
Clonegives you.clone(), which you call yourself.Copymakes plain assignment copy the value instead of moving it.CopyneedsClonetoo, and every field must beCopy.- A struct with a
Stringcan beClonebut neverCopy(E0204).
Remember
- derive writes standard impls when every field supports them.
==needsPartialEq;{}needsDisplay.Defaultgives zero-like starting values.- Clone is explicit; Copy happens on every assignment.