Enums in Rust are fundamentally different from enums in C/C++: they can store associated data and are perfect for modeling state and errors. They are used to build type-safe finite-state machines, various forms of Option/Result, and implement the "sum types" pattern. Historically, similar constructs have been used in functional languages to describe the variations of an entity with strictly delineated options.
Problem: To achieve expressiveness (to express all state options), where each case handling is required, and it's impossible to accidentally skip a branch. Project-wide errors can be difficult to type without such an expressive structure.
Solution: Enums with associated data and pattern matching provide control — each branch is checked by the compiler, ensuring exhaustiveness. Additionally, a plethora of utility methods have already been implemented for Result and Option.
Code example:
enum NetworkState { Disconnected, Connecting(u32), // attempt number Connected(String), Error(String), } fn print_state(state: NetworkState) { match state { NetworkState::Disconnected => println!("Net: disconnected"), NetworkState::Connecting(count) => println!("Net: connecting (attempt {})", count), NetworkState::Connected(addr) => println!("Net: connected to {}", addr), NetworkState::Error(msg) => println!("Net error: {}", msg), } }
Key features:
Can enum branches be partially handled without _?
The compiler prohibits unclosed cases for non-exhaustive enums, but if _ is used, unhandled branches will be "absorbed". One should avoid _ in clinically important branches to ensure future changes are not overlooked.
In what cases are associated values referenced, and in which are they copied during pattern matching?
During pattern matching, associated data is moved by default. If only viewing is needed, use references:
match &state { NetworkState::Connected(addr) => println!("by ref: {}", addr), _ => {} }
Can two enums with overlapping variant names be used in one structure?
Yes, but the variant names are used with the enum prefix. This avoids collisions and makes the code self-documenting (e.g., Status::Ok vs NetworkState::Ok).
_ to hide newer options when extending enums_ =>) in critical error handlersIn the code, processing Result<T, E> consistently has a catch-all via _ =>, and new errors (when extending enums) go unnoticed — leading to silent loss of errors.
Pros:
Cons:
Exhaustiveness matching is used, each Enum variant is explicitly handled, or a panic occurs in a branch for which there is no stable behavior.
Pros:
Cons: