Skip to content

Enums

One line: An enum names a closed set of alternatives and makes that set a type — and because a match on it has to account for every alternative, the compiler can tell you which code a new alternative breaks.

Rust's enum is not C's. A C enum is an integer with names attached; Rust's is a sum type — each variant may carry its own data, of its own shape — which is why Option, Result, and most well-designed Rust data models are enums and nothing about them is built into the language.

Two things follow, and the section is mostly about the second. An enum lets you model "exactly one of these" so that the impossible combinations cannot be written down. And match turns adding a variant into a build error everywhere the new case matters, which converts a discipline you have to remember into a list the compiler computes.

Lesson Level What it teaches
What an enum is 101 → 201 The declaration, the four shapes of variant, behaviour in an impl block, and the E0004 you get for free when a variant is added — plus why a fieldless enum casts to an integer and a payload-carrying one does not
Variants that carry data 201 Product versus sum, counted rather than asserted; what the payload costs, measured — the niche that makes Option<Box<T>> the same eight bytes as the pointer, and the rare 104-byte variant every 4-byte one pays for until it is boxed
An enum instead of a bool 201 Two bool parameters accept the backwards call and two enums do not — plus the newtype that also refuses it without naming either state, and the two clippy lints that stay quiet under four bools
A typo becomes a binding 201 Under use Enum::*, a mistyped arm is a catch-all variable, not an error — zero warnings, and the two lints that look like they should catch it do not
An enum as a state machine 201 match (state, event): the compiler enumerates the whole transition table, names the cells you left out, and stops the moment you write _

Enum pages that live elsewhere

Option and Result are ordinary enums, and they are met on the first day rather than in a section about enums — so their lessons stay where a beginner will find them. This section links them rather than moving them:

OPTION.md is the full reading order for Option itself.

Not yet written

The rest of the map, listed here rather than as empty pages so the gaps are visible: enums with a lifetime parameter (enum Token<'a>, which is the other thing those brackets hold), #[non_exhaustive] and what it does to a downstream crate's match, explicit discriminants and repr (enum Code { Ok = 200 }, repr(u8), and converting an integer back with TryFrom), custom error enums with Display, Error and From (the thiserror shape, by hand first), implementing Display for an enum — the match inside fmt, which is the usual first hand-written trait impl — and match guards and binding @.

Po polsku

Polska nazwa jest tu pierwszą pułapką. „Typ wyliczeniowy” zna każdy z C, Pascala albo Javy i znaczy tam dokładnie tyle, ile mówi: wyliczenie nazw, czyli garść stałych całkowitych z ładniejszymi etykietami. Rustowe wyliczenie (enum) to co innego — typ sumaryczny (sum type), czyli unia z etykietą, w której każdy wariant może nieść własne dane, własnego kształtu. Dlatego Option, Result i Cow nie są wbudowane w język, tylko są zwyczajnymi wyliczeniami z biblioteki standardowej, i dlatego pierwszy odruch przyniesiony z C — „to i tak w gruncie rzeczy liczba” — trzeba tutaj odłożyć na bok.

Druga rzecz, i o niej jest większość tego rozdziału: match na wyliczeniu musi obsłużyć każdy wariant, więc dorzucenie wariantu pół roku później zamienia się w błąd kompilacji (E0004) w każdym miejscu, które ma od tej chwili dziurę. To zamienia dyscyplinę, o której trzeba pamiętać, w listę, którą wylicza kompilator — odpowiednik grepa po całym projekcie, tyle że kompletny i nie do pominięcia. Cztery lekcje z poziomu 201 są w istocie czterema sposobami, na jakie tę gwarancję da się stracić: wygodnym _, literówką pod use Enum::*, dwoma argumentami typu bool zamiast dwóch wyliczeń i wreszcie _ w tablicy przejść automatu. Zdanie do zapamiętania brzmi więc: wyczerpujące dopasowanie nie jest tym, co daje wyliczenie, tylko tym, z czego match może zrezygnować.

Na koniec uwaga nawigacyjna, bo układ rozdziału bywa mylący: lekcji o Option i Result tu nie ma, choć to najzwyklejsze wyliczenia z dwoma wariantami — mieszkają w 17_Option_and_Result, bo spotyka się je pierwszego dnia, a nie przy okazji teorii typów. Polskie tłumaczenie Tour of Rust mówi o „Opcji” i „Rezultacie”, ale w kodzie, w komunikatach kompilatora i w wyszukiwarce zostają angielskie — tak samo jak enum, match i derive.

Szukaj po polsku: typ wyliczeniowy · typ sumaryczny · dopasowanie wyczerpujące · rust enum sum type · rust E0004 non-exhaustive patterns