Enums
Enums define sum types (tagged unions): a value is exactly one of the declared variants.
Definitions
A comma separates two variants. A line break after the comma is optional. A line break alone does not separate two variants: an enum with one variant on each line needs a comma at the end of each line but the last.
// Simple enum
pub enum Status {
pending,
active,
completed
}
// With associated data (named parameters)
pub enum Message {
text(content: String),
image(url: String, size: I32),
video(url: String, duration: I32)
}
// Generic enum
pub enum Result<T, E> {
ok(value: T),
error(err: E)
}
pub enum Option<T> {
some(value: T),
none
}
Instantiation
Enum values use the leading-dot shorthand .variant. The type that
the context gives, here the type of the let, tells which enum the
variant belongs to:
pub enum Status {
pending,
active
}
pub enum Message {
text(content: String),
image(url: String, size: I32)
}
pub enum Result<T, E> {
ok(value: T),
error(err: E)
}
// Simple variant
let status1: Status = .pending
let status2: Status = .active
// With named parameters
let msg1: Message = .text(content: "Hello")
let msg2: Message = .image(url: "/pic.jpg", size: 1024)
// Generic enum
let result1: Result<String, I32> = .ok(value: "success")
let result2: Result<String, I32> = .error(err: 404)
The full form names the enum: Status.pending. A generic enum takes
its type arguments on the path, the same way a struct literal does:
Result<String, I32>.ok(value: "done"). The full form needs no
context:
pub enum Status {
pending,
active
}
pub enum Maybe<T> {
some(value: T),
none
}
pub let first = Status.pending
pub let empty = Maybe<I32>.none
pub let held = Maybe<I32>.some(value: 3)
pub fn run_checks() {
assert(condition: first == Status.pending)
assert(condition: empty != held)
}
The compiler checks the dot form against the enum that the context expects:
- A dot form with no expected enum, such as
let v = .pending, is the errorCannotInferEnumType. Write the annotation or the full form. - A variant that the expected enum does not have is the error
UnknownEnumVariant, also when another enum has the variant. - Each payload field is checked against its declared type. A missing
payload field is the error
MissingField, an unknown one is the errorUnknownField, and a value of the wrong type is aTypeMismatch. - A variant with data needs its data:
.imagealone is the errorEnumVariantRequiresData. A variant without data takes none:.pending(x: 1)is the errorEnumVariantWithoutData.
pub enum Status { pending, active }
pub enum Level { low, high }
pub let s: Status = .low // error: 'low' is a variant of Level
Pattern Matching
To consume enum values, use a match expression: see
Control Flow & Pattern Matching. A
destructuring pattern cannot take an enum value: see
Expressions / Destructuring.