Before you begin
Why this matters
Almost every Rust struct starts with a #[derive(…)] line, and most comparisons, copies, and printouts in a program run code that the line produced. If you know what each derived trait does, you can predict how values compare and sort, read the compiler errors that derive causes, and notice when the derived meaning is not the one your program needs.
What this helps you reason about
- Tell which impl block a method call runs, and read that answer from the stepper’s frame names.
- Predict what a derived ==, clone, or sort does from the order of a struct’s fields.
- Spot when a derived impl is wrong for your type, and write one by hand that agrees with the others.
In Java, a record writes equals, hashCode, and toString from its fields, and in other classes you or your IDE write them, together with compareTo. In Python, a dataclass writes them when the class is made. Rust has no parent classes. A type gets each behavior from an impl block, and #[derive] asks the compiler to write some of those blocks for you. Interfaces, traits, and type classes showed how impl Vehicle for EBike gives a type a trait. This lesson follows where each method on a type comes from, what each derived trait actually does, and when the derived version is wrong for your type. #[derive] is the Rust form of deriving in Haskell type classes, data, and newtype.
Already know this? The short version
- A method comes from an inherent impl (impl Kit), from a trait impl (impl Progress for Kit), or from a provided method in the trait itself; the stepper names them main::Kit::left, main::{impl#1}::percent, and main::Progress::label<main::Kit>.
- #[derive(…)] writes one impl per trait, field by field: Debug prints each field, Clone clones each, PartialEq compares each, Hash hashes each, Default gives each its default, and every field must have the trait (E0277). PartialOrd and Ord compare fields in declaration order and enum variants in declaration order; a struct with an f64 field cannot derive Eq or Ord.
- Copy needs Clone (trait Copy: Clone), and every field must be Copy (E0204 for a String field).
- Write an impl by hand when the derived meaning is wrong, and keep the traits in agreement: equal values hash the same, cmp is Equal exactly when == is true, and partial_cmp is Some(self.cmp(other)). The orphan rule (E0117) forbids a foreign trait on a foreign type; wrap the type in your own struct.
- The section “What goes wrong with traits and derive in real programs?” covers a derived order that changes with the fields, a hand-written == with a derived Hash, a derived PartialOrd next to a hand-written Ord, and Copy on a value with state.
Words in this lesson (8)
- method
- A function in an impl block whose first parameter is self, such as fn admit(&mut self). It is called on a value, as in north.admit().
- trait
- A named set of abilities that a type can have. A type that has a trait is said to implement it.
- inherent impl
- An impl block without a trait name, such as impl Kit { … }. Its methods belong to the type itself; no trait is involved.
- provided method
- A method written with a body inside a trait. Every type that implements the trait gets it, unless its impl block writes its own version.
- derive
- An attribute, written #[derive(…)] above a struct, that asks the compiler to write a trait’s code for the type, such as an == that compares every field.
- Copy
- A trait (a named set of abilities a type can have) for types whose bytes are a complete value, such as i32 or bool. Assigning a Copy value copies it, and the old binding stays usable.
- Ord
- The trait for types whose values can all be put in one order, with a cmp method that returns an Ordering. sort() needs it; f64 does not implement it, because of NaN.
- orphan rule
- The rule that impl Trait for Type compiles only when the trait or the type is defined in your own crate, the program or library being compiled.
Examples are focused snippets; imports, enclosing functions, or classes may be omitted. C examples use C11; Haskell examples use Haskell 2010. Expand the notes for language-specific depth.
01 / impl blocks
Where does a method on your type come from?
A Rust type gets methods from impl blocks, and from nowhere else. There are two kinds. An inherent impl, written impl Kit { … } with no trait name, adds methods that belong to Kit itself, as in Methods, receivers, and this. A trait impl, written impl Progress for Kit { … }, gives Kit the methods that the trait Progress lists. A type can have any number of both kinds.
A trait can also give a method a body, a provided method. Below, label is written once, in the trait, and calls percent, which each type must write. A Kit gets that label until impl Progress for Kit writes its own, as Interfaces, traits, and type classes showed.
When you call tugboat.left(), the compiler looks first at the inherent methods of Kit, then at the methods of the traits that Kit implements. The stepper shows which one ran. An inherent method’s frame is named after the type, main::Kit::left. A trait impl’s method is named after the position of its impl block, main::{impl#1}::percent. A provided method is named after the trait, with the type in angle brackets: main::Progress::label<main::Kit>.
impl Kit {
fn left(&self) -> u32 {
self.pieces - self.built
}
}
trait Progress {
fn percent(&self) -> u32;
fn label(&self) -> String {
format!("{}% built", self.percent())
}
}
impl Progress for Kit {
fn percent(&self) -> u32 {
self.built * 100 / self.pieces
}
} A method comes from the type’s own impl, from a trait impl, or from a provided method in the trait.
Coming from Java: A Java class lists its interfaces in its own declaration; a Rust trait impl is a separate block, and it can be written after the type, by someone who did not write the type.
Precisely: traits in scope and the full path
A trait method can be called with a dot only where the trait is in scope. In one file it always is; a trait from another module needs use, or the compiler reports E0599 and suggests the use line. Progress::label(&tugboat) names the trait directly, which also chooses between two traits that have methods with the same name.
Experiment
Find the impl block behind each method call
impl Kit adds methods that belong to Kit. impl Progress for Kit gives Kit the methods that Progress lists. label has a body in the trait, so Kit gets that body until its impl block writes its own label. Inside the provided label, self.percent() runs the percent of the type it was called for.
Why it matters To find which code a call runs, look for the impl block that defines the method: the type’s own impl, the trait impl, or the trait itself. The frame name in the stepper tells you which one ran.
Predict both lines, and which function the stepper enters for each call. Then add this method inside impl Progress for Kit, after percent: fn label(&self) -> String { format!("{} of {} pieces", self.built, self.pieces) }. Predict again.
struct Kit {
pieces: u32,
built: u32,
}
impl Kit {
fn left(&self) -> u32 {
self.pieces - self.built
}
}
trait Progress {
fn percent(&self) -> u32;
fn label(&self) -> String {
format!("{}% built", self.percent())
}
}
impl Progress for Kit {
fn percent(&self) -> u32 {
self.built * 100 / self.pieces
}
}
fn main() {
let tugboat = Kit { pieces: 200, built: 50 };
println!("{} left", tugboat.left());
println!("{}", tugboat.label());
}
What to look for
Step into tugboat.left(). The frame is main::Kit::left: a method from the inherent impl is named after its type. Back in main, step into tugboat.label(). The frame is main::Progress::label<main::Kit>: the provided method from the trait, run for a Kit. From there the stepper enters main::{impl#1}::percent, the percent written in impl Progress for Kit. The stepper names a method of a trait impl by the position of its impl block in the file, counted from 0: {impl#1} is the second impl block. The run prints 150 left, then 25% built. After the edit, tugboat.label() enters main::{impl#1}::label, Kit’s own version, percent is never called, and the second line is 50 of 200 pieces.
Expected output
150 left
25% built02 / derive
What does #[derive] write for you?
#[derive(Debug, Clone, PartialEq)] above a struct asks the compiler to write three impl blocks, one per trait, as if you had written impl Clone for Kit { … } yourself. Each derived impl works field by field. Debug prints the type’s name and each field with that field’s own Debug, so {:?} shows Kit { pieces: 120, paint: Paint { tins: 6 } }. Clone clones each field. PartialEq compares each field with its own ==, in the order the fields are declared, and is true only when every field is equal.
Because the derived code calls each field’s impl, every field must have the trait. If Paint has no derive line, the compiler reports error[E0277]: `Paint` doesn’t implement `Debug` at the line paint: Paint, with help: consider annotating `Paint` with `#[derive(Debug)]`. Clone and == give their own errors at the same field.
The standard library lets you derive nine traits: Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, and Default. Display, which prints text for people with {}, cannot be derived; you write it by hand, as a later section shows. The stepper never stops inside derived code, because that code has no lines in your file.
#[derive(Debug, Clone, PartialEq)]
struct Paint {
tins: u32,
}
#[derive(Debug, Clone, PartialEq)]
struct Kit {
pieces: u32,
paint: Paint,
} derive writes one impl per trait, and each impl uses the same trait on every field, so every field must have it.
Coming from Python: A dataclass writes __eq__ and __repr__ from its fields in the same way; #[derive] does it at compile time, and only for the traits you name.
Precisely: derive on a generic struct
For struct Pair<T> { left: T, right: T }, #[derive(Clone)] writes impl<T: Clone> Clone for Pair<T>. It adds a trait bound, as in Generics and type parameters, to every type parameter. So Pair<T> is Clone only when T is, and the bound is added even when no field holds a T directly. When that bound is too strict, write the impl by hand.
Experiment
Clone and print a struct with derived traits
Each derived impl handles the struct one field at a time, and for each field it calls that field’s own impl of the same trait. The derived Debug for Kit calls the Debug of Paint, and the derived == calls the == of Paint. Without a derive line, Paint has none of these, so the derived code for Kit cannot be written.
Why it matters Before you derive a trait on a struct, check that every field’s type has it. The compiler names the field that does not.
Predict both lines. Then delete the line #[derive(Debug, Clone, PartialEq)] above struct Paint, and predict what the compiler says.
#[derive(Debug, Clone, PartialEq)]
struct Paint {
tins: u32,
}
#[derive(Debug, Clone, PartialEq)]
struct Kit {
pieces: u32,
paint: Paint,
}
fn main() {
let windmill = Kit { pieces: 120, paint: Paint { tins: 4 } };
let mut spare = windmill.clone();
spare.paint.tins = 6;
println!("{:?}", spare);
println!("{}", windmill == spare);
}
What to look for
The stepper stays in main for every line. clone, {:?}, and == run code that the compiler wrote, and that code has no lines in your file to stop on. After spare.paint.tins = 6, spare shows {pieces: 120, paint: {tins: 6}}, while windmill still shows tins: 4: the derived clone cloned the inner Paint as well. The run prints Kit { pieces: 120, paint: Paint { tins: 6 } }, then false. After the edit, the build fails with four errors, and each one points at the line paint: Paint. The first is error[E0277]: `Paint` doesn’t implement `Debug`. The other three are for Clone, for ==, and for !=.
Expected output
Kit { pieces: 120, paint: Paint { tins: 6 } }
false03 / Copy
Why does Copy need Clone, and which structs can have it?
Variables showed that assigning a Copy value copies it, and the old binding stays usable. Copy has no method of its own. It is a marker: it tells the compiler that copying the bytes makes a complete second value. The copying itself is the job of Clone, and Copy is declared as trait Copy: Clone, which means every Copy type must also be Clone. #[derive(Debug, Copy)] alone reports error[E0277]: the trait bound `Glue: Clone` is not satisfied. Derive both: #[derive(Clone, Copy)].
Every field must be Copy as well. A String owns memory on the heap, and copying its bytes would give that memory two owners. A struct with brand: String and #[derive(Clone, Copy)] reports error[E0204]: the trait `Copy` may not be implemented for this type, with this field does not implement `Copy` under brand. Clone alone is still allowed: it clones the String.
Derive Copy for small values that behave like numbers, such as a size, an amount of glue, or a colour. A value that keeps state you change in place is a poor fit, as the production section shows.
#[derive(Debug, Clone, Copy)]
struct Glue {
ml: u32,
}
let tube = Glue { ml: 20 };
let mut other = tube; // a copy
other.ml -= 5;
// tube is still Glue { ml: 20 } Copy needs Clone, and every field must be Copy; derive Copy only for small, number-like values.
Precisely: Clone on a Copy type
For a Copy type, clone() must give the same result as the byte copy. The derived Clone does; a hand-written Clone that does something else compiles, but code that copies by assignment would skip it. A type with its own cleanup code, an impl of the Drop trait, cannot be Copy: error[E0184]: the trait `Copy` may not be implemented for this type; the type has a destructor.
Experiment
Copy a struct, then take away Clone
Copy is declared as trait Copy: Clone, so a type can be Copy only when it is also Clone. Copy itself adds no method. It tells the compiler that copying the bytes makes a complete second value, so an assignment copies and the old binding stays usable.
Why it matters Derive Clone and Copy together. When the compiler asks for Clone at a Copy, the fix is the missing Clone, not a change to Copy.
Predict the line. Then change #[derive(Debug, Clone, Copy)] to #[derive(Debug, Copy)] and predict what the compiler says.
#[derive(Debug, Clone, Copy)]
struct Glue {
ml: u32,
}
fn main() {
let tube = Glue { ml: 20 };
let mut other = tube;
other.ml -= 5;
println!("{:?} {:?}", tube, other);
}
What to look for
At let mut other = tube;, the panel shows tube and other, both {ml: 20}. After other.ml -= 5, other shows {ml: 15} and tube still shows {ml: 20}: the assignment copied the struct. The run prints Glue { ml: 20 } Glue { ml: 15 }. After the edit, the build fails with error[E0277]: the trait bound `Glue: Clone` is not satisfied. The error points at Copy in the derive line, and a note says required by a bound in `Copy`.
Expected output
Glue { ml: 20 } Glue { ml: 15 }04 / Derived order
In what order does a derived comparison read the fields?
A derived PartialOrd or Ord compares the first field declared in the struct. Only when the first fields are equal does it compare the second, and so on, the way a dictionary orders words letter by letter. The order of the fields in a struct literal makes no difference. The order of the lines in the struct declaration decides, so swapping two field lines changes what sort() does.
For an enum, the variants compare in the order they are declared: the first variant is the smallest. Variants with fields compare by variant first, then by their fields.
Eq and Ord promise more than PartialEq and PartialOrd: every value equals itself, and any two values can be put in order. An f64 cannot promise this, because NaN is not equal to itself. A struct with an f64 field can derive PartialEq and PartialOrd, but #[derive(PartialEq, Eq)] reports error[E0277]: the trait bound `f64: Eq` is not satisfied. Hash and Default also go field by field: Hash feeds each field into the hash in order, and Default gives each field its own default, as Constructors and creating values showed.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
struct Kit {
// compared first
pieces: u32,
// compared when pieces are equal
hours: u32,
}
let mut shelf = vec![
Kit { pieces: 300, hours: 6 },
Kit { pieces: 90, hours: 9 },
];
shelf.sort(); // the 90-piece kit comes first A derived order compares fields in declaration order, and enum variants in declaration order.
Coming from Python: @dataclass(order=True) compares fields in the same declaration order, like tuples.
Precisely: lexicographic order
This field-by-field order is called lexicographic order. Ord requires Eq and PartialOrd, so derive the four together: PartialEq, Eq, PartialOrd, Ord. Ordering, sorting, and comparators covers sort_by and sort_by_key, which order by a key without changing the type’s Ord.
Experiment
Sort with a derived order, then swap two fields
The derived cmp compares the first field declared in the struct. Only when the first fields are equal does it compare the second field. The order of the fields in a struct literal does not matter; the order in the declaration does.
Why it matters A derived order is the order of the struct’s fields. Moving a field line in the declaration changes every sort of that type.
Predict the order after sort. Then swap the two field lines in struct Kit, so that hours: u32 comes first, and predict again. The struct literals in main stay as they are.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
struct Kit {
pieces: u32,
hours: u32,
}
fn main() {
let mut shelf = vec![
Kit { pieces: 300, hours: 6 },
Kit { pieces: 90, hours: 9 },
Kit { pieces: 90, hours: 4 },
];
shelf.sort();
println!("{:?}", shelf);
}
What to look for
The stepper stops once on each line of the vec! list. Step past shelf.sort(): shelf changes from [{pieces: 300, hours: 6}, {pieces: 90, hours: 9}, {pieces: 90, hours: 4}] to [{pieces: 90, hours: 4}, {pieces: 90, hours: 9}, {pieces: 300, hours: 6}]. The stepper does not enter the sort or the derived cmp. The two kits with 90 pieces are equal on the first field, so hours decides between them. After the edit, the panel lists hours first in every kit, and the run prints [Kit { hours: 4, pieces: 90 }, Kit { hours: 6, pieces: 300 }, Kit { hours: 9, pieces: 90 }]: sorted by hours.
Expected output
[Kit { pieces: 90, hours: 4 }, Kit { pieces: 90, hours: 9 }, Kit { pieces: 300, hours: 6 }]05 / By hand
When should you write an impl yourself?
A derived impl uses every field, in declaration order. When that is not what equal or smaller means for your type, write the impl yourself. Two cases are common: equality that should ignore a field, and an order by a different field. Below, two kits with the same code are equal however much of each is built, and shorter builds sort first. impl Eq for Kit {} has no methods: it only promises that this == is a full equality.
The comparison traits must agree with each other. If a == b, then a and b must have the same hash, and a.cmp(&b) must be Equal; cmp must give Equal only when == is true. partial_cmp should be Some(self.cmp(other)). Derive them all, or write them all by hand from the same fields. Equality and comparison shows what a HashMap does when Hash and == disagree.
Display, the trait behind {}, is always written by hand. Its method fmt receives a fmt::Formatter, and write!(f, …) works like format! but writes into f.
One limit applies to every impl you write: the orphan rule. impl Trait for Type compiles only when the trait or the type is defined in your crate, the program or library being compiled. impl fmt::Display for Vec<Kit> reports error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate, because both Display and Vec come from the standard library. The fix is your own type around it: struct Shelf(Vec<Kit>), a struct with one unnamed field, read as shelf.0.
impl PartialEq for Kit {
fn eq(&self, other: &Self) -> bool {
self.code == other.code
}
}
impl Eq for Kit {}
impl Ord for Kit {
fn cmp(&self, other: &Self) -> Ordering {
self.hours.cmp(&other.hours)
}
}
struct Shelf(Vec<Kit>);
impl fmt::Display for Shelf {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} kits", self.0.len())
}
} Write an impl by hand when the derived meaning is wrong; keep ==, Hash, and cmp in agreement; wrap a foreign type to give it a foreign trait.
Coming from Java: equals, hashCode, and compareTo must agree in Java too; in Rust, rustc accepts a hand-written PartialEq next to a derived Hash without a warning, and only the Clippy linter reports it.
Precisely: why the orphan rule exists
If two libraries could both write impl Display for Vec<Kit>, a program that used both would have two answers for one call. The orphan rule makes sure each pair of trait and type has at most one impl. The wrapper struct is the newtype pattern, the same idea as newtype in Haskell.
Experiment
Compare two kits with a hand-written ==
mine == gift calls PartialEq::eq(&mine, &gift). With the hand-written impl, eq is the body you wrote, which looks at code only. The derived eq compares every field.
Why it matters When two values should count as equal although one field differs, write PartialEq yourself and leave that field out. Then make Hash and Ord follow the same fields.
mine and gift have the same code and a different number of pieces built. Predict the line. Then delete the whole impl PartialEq for Kit block, put #[derive(PartialEq)] above struct Kit, and predict again.
struct Kit {
code: u32,
built: u32,
}
impl PartialEq for Kit {
fn eq(&self, other: &Self) -> bool {
self.code == other.code
}
}
fn main() {
let mine = Kit { code: 4021, built: 80 };
let gift = Kit { code: 4021, built: 0 };
println!("{}", mine == gift);
}
What to look for
At mine == gift, the stepper enters main::{impl#0}::eq: this time the code is yours, so it has lines to stop on. self points to mine, {code: 4021, built: 80}, and other points to gift, {code: 4021, built: 0}. Only code is compared, and the run prints true. After the edit, == runs the derived eq, the stepper stays in main, built is compared as well, and the run prints false.
Expected output
true06 / In production
What goes wrong with traits and derive in real programs?
Programs that compile still go wrong where derived and hand-written impls meet. Four mistakes are common.
A derived order changes with the fields. Someone adds name as the first field of Kit, because it reads better, and every sort() of kits now sorts by name. When an order matters, write Ord by hand, or sort with sort_by_key at the place that needs it, and test the order.
A hand-written == next to a derived Hash. Two kits with the same code are equal, but the derived Hash also hashes built, so they get different hashes, and a HashSet keeps both. Write Hash by hand from the same fields that == uses.
A derived PartialOrd next to a hand-written Ord. cmp compares hours, but <, >, and the derived partial_cmp compare every field. In this build, the standard library’s sort also compared with <, so the hand-written order was never used. Write partial_cmp as Some(self.cmp(other)).
Copy on a value with state. let mut first = kits[0]; first.done = true; changes a copy, and kits[0] stays not done. Without Copy, the compiler stops at the first line with error[E0507]: cannot move out of index of `Vec<Kit>`. Use kits[0].done = true, or let first = &mut kits[0];.
impl Hash for Kit {
// the same field that == compares
fn hash<H: Hasher>(&self, state: &mut H) {
self.code.hash(state);
}
} Keep a derived order’s field order on purpose, write Hash and PartialOrd from the same rule as == and cmp, and derive Copy only for values you never change in place.
Precisely: Hash by hand
Hash and Hasher come from std::hash. hash is generic over the hasher H, which the HashMap chooses, and self.code.hash(state) feeds one field into it. Feed exactly the fields that eq compares, in a fixed order. sort is documented to need Ord, not to call cmp, so the order of a type whose PartialOrd and Ord disagree is not something to rely on in any version.
Experiment
Sort with a hand-written Ord next to a derived PartialOrd
Ord has cmp, and PartialOrd has partial_cmp, which <, >, <=, and >= call. Deriving PartialOrd writes a partial_cmp that compares every field in order, whatever your cmp says. In this build, the standard library’s sort compared elements with <, so the derived partial_cmp decided the order.
Why it matters When you write Ord by hand, write PartialOrd by hand too, as Some(self.cmp(other)). Then every comparison of the type uses one rule.
cmp compares hours only. Predict the first line, and the order after sort. Then delete PartialOrd from the derive line, add this block after impl Ord for Kit, and predict again: impl PartialOrd for Kit { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) } }
use std::cmp::Ordering;
#[derive(Debug, PartialEq, Eq, PartialOrd)]
struct Kit {
pieces: u32,
hours: u32,
}
// Shorter builds first.
impl Ord for Kit {
fn cmp(&self, other: &Self) -> Ordering {
self.hours.cmp(&other.hours)
}
}
fn main() {
let ship = Kit { pieces: 300, hours: 6 };
let crane = Kit { pieces: 90, hours: 9 };
println!("{:?} {}", ship.cmp(&crane), ship < crane);
let mut shelf = vec![crane, ship];
shelf.sort();
println!("{:?}", shelf);
}
What to look for
ship.cmp(&crane) enters main::{impl#0}::cmp, your method, and gives Less: 6 hours come before 9. ship < crane does not stop anywhere: < runs the derived partial_cmp, which compares pieces first, 300 against 90, so the answer is false. The first line is Less false. Step past shelf.sort(): the stepper never enters cmp, and shelf stays [{pieces: 90, hours: 9}, {pieces: 300, hours: 6}]. The sort compared with < as well. After the edit, ship < crane enters main::{impl#1}::partial_cmp and then cmp, and the first line is Less true. shelf.sort() enters the same two functions, and the order becomes ship first: [Kit { pieces: 300, hours: 6 }, Kit { pieces: 90, hours: 9 }].
Expected output
Less false
[Kit { pieces: 90, hours: 9 }, Kit { pieces: 300, hours: 6 }]07 / Try it
Can you predict what the derived traits do?
A kit has a skill level and a number of pieces, with derived traits. Predict each line. max returns the larger of two values, using cmp.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
enum Skill {
Beginner,
Expert,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
struct Kit {
skill: Skill,
pieces: u32,
}
fn main() {
let lighthouse = Kit { skill: Skill::Expert, pieces: 150 };
let windmill = Kit { skill: Skill::Beginner, pieces: 400 };
let mut copy = lighthouse;
copy.pieces = 90;
println!("{}", windmill < lighthouse);
println!("{}", copy == lighthouse);
println!("{:?}", copy.max(lighthouse));
}
What are the three output lines?
Reveal the reasoning
true, then false, then Kit { skill: Expert, pieces: 150 }. skill is the first field, and Beginner is declared before Expert, so the windmill is smaller although it has more pieces. Kit is Copy, so copy is a second Kit, and changing copy.pieces leaves lighthouse at 150; the derived == then finds 90 and 150 and gives false. Both kits have skill Expert, so max decides by pieces and returns lighthouse.
Practice tickets
- RUST-601 · The bonsai show list comes out in name order → Free
- RUST-602 · A new practice session’s metronome stands still → Sign in · Pro
- RUST-603 · A member with a tied time is missing from the board → Sign in · Pro
Keep exploring
Functions as values and higher-order operations →
Primary references
- The Rust Programming Language, Appendix C: Derivable Traits ↗
- The Rust Programming Language, 10.2: Traits: Defining Shared Behavior ↗
- The Rust Reference: Implementations ↗
- The Rust Reference: Trait implementation coherence ↗
- The Rust Reference: Derive ↗
- Rust standard library: std::cmp::Ord ↗
- Rust standard library: std::marker::Copy ↗
- Rust standard library: std::hash::Hash ↗