Skip to content
Pre-Release: Fe is under active development. This documentation covers the upcoming release. Follow progress on GitHub

Enums

Enums (enumerations) define a type that can be one of several distinct variants. Each variant can optionally hold data.

Define an enum with the enum keyword:

enum Direction {
North,
South,
East,
West,
}

Use pub for public visibility:

pub enum Status {
Active,
Inactive,
Pending,
}

Fe supports three kinds of enum variants:

Variants with no associated data:

enum Color {
Red,
Green,
Blue,
}
let color = Color::Red

Variants with unnamed fields:

enum Message {
Quit,
Move(i32, i32),
Write(String<20>),
}
let message = Message::Move(10, 20)
let text = Message::Write("hello")

Access tuple variant data through pattern matching.

Variants with named fields:

enum Event {
Click { x: i32, y: i32 },
KeyPress { code: u32, shift: bool },
Resize { width: u32, height: u32 },
}
let event = Event::Click { x: 100, y: 200 }

Use the EnumName::VariantName syntax:

enum Option<T> {
Some(T),
None,
}
let present: Option<u256> = Option::Some(42)
let absent: Option<u256> = Option::None

Match expressions extract data from enum variants:

enum Result<T, E> {
Ok(T),
Err(E),
}
fn handle_result(result: Result<u256, String<20>>) {
match result {
Result::Ok(value) => {
// Use value
}
Result::Err(error) => {
// Handle error
}
}
}

Match expressions must handle all variants. The compiler enforces this:

enum Status {
Active
Inactive
Pending
}
match status {
Status::Active => "running"
Status::Inactive => "stopped"
// Error: missing Status::Pending
}

Use the wildcard _ to match remaining variants:

let description = match status {
Status::Active => "running"
_ => "not running" // Matches Inactive and Pending
}

Bind variant data to variables:

enum Message {
Text(String<20>),
Number(u256),
}
match message {
Message::Text(s) => {
// s is the String
}
Message::Number(n) => {
// n is the u256
}
}

Match on struct variant fields:

enum Event {
Click { x: i32, y: i32 },
}
match event {
Event::Click { x, y } => {
// x and y are available
}
}

Use .. to ignore some fields:

match event {
Event::Click { x, .. } => {
// Only use x, ignore y
}
}

Match nested structures:

enum Outer {
Inner(Option<u256>),
}
match outer {
Outer::Inner(Option::Some(value)) => {
// Matched nested Some
}
Outer::Inner(Option::None) => {
// Matched nested None
}
}

Enums can have type parameters:

enum Option<T> {
Some(T),
None,
}
enum Result<T, E> {
Ok(T),
Err(E),
}
fn find_user(id: u256) -> Option<User> {
if id == 0 {
return Option::None
}
Option::Some(load_user(id))
}
fn divide(a: u256, b: u256) -> Result<u256, String<20>> {
if b == 0 {
return Result::Err("division by zero")
}
Result::Ok(a / b)
}

Constrain generic types:

enum Container<T: Clone> {
Single(T)
Pair(T, T)
}

Match is an expression that returns a value:

let description = match status {
Status::Active => "System is running"
Status::Inactive => "System is stopped"
Status::Pending => "System is starting"
}

All match arms must return the same type.

Represent optional values:

enum Option<T> {
Some(T),
None,
}
fn get_balance(account_id: u256) -> Option<u256> {
if account_exists(account_id) {
Option::Some(load_balance(account_id))
} else {
Option::None
}
}

Represent success or failure:

enum Result<T, E> {
Ok(T)
Err(E)
}
fn parse_amount(input: String) -> Result<u256, String> {
// Returns Ok(amount) or Err(message)
}
SyntaxDescription
enum Name { }Define an enum
VariantUnit variant (no data)
Variant(T1, T2)Tuple variant
Variant { field: T }Struct variant
Enum::VariantConstruct a variant
match val { }Pattern match on enum
Variant(x)Bind tuple variant data
Variant { field }Bind struct variant data
Variant { .. }Ignore struct variant fields
_Wildcard pattern