Skip to content

Enums

Declare named closed alternatives with unit, tuple, struct, integer, generic, and recursive variants.

Updated View as Markdown

An enum is a named closed set of alternatives.

enum Direction {
    North
    East
    South
    West
}

Enum and variant names use PascalCase.

Unit variants

A unit variant carries no payload.

direction := North

The expected enum type resolves an unambiguous bare variant. Qualify a variant when context is insufficient or names collide.

direction := Direction.North

Construction and pattern resolution use the expected enum independently. A bare Ready can therefore be clear in an annotated binding yet ambiguous in an unconstrained expression. Qualification is a source-level disambiguator; it does not create a different variant.

Tuple variants

A tuple-style variant carries positional payloads.

enum Shape {
    Point
    Circle(float)
    Rectangle(float, float)
}

shape := Circle(10.0)

Destructure the payload in a pattern.

match shape {
    Point => 0.0
    Circle(radius) => 3.14159 * radius * radius
    Rectangle(width, height) => width * height
}

Struct variants

A struct-style variant names its payload fields.

enum Message {
    Quit
    Move { x: int, y: int }
    Write { text: string }
}

message := Move { x: 10, y: 20 }

Named payloads are appropriate when positions would be unclear or likely to change.

match message {
    Move { x, y } => move_to(x, y)
    Write { text } => println(text)
    Quit => stop()
}

One enum may mix unit, tuple, and struct-style variants. Each variant has its own constructor shape, and using the wrong arity or field set is a compile-time error.

Exhaustiveness

Because an enum is closed, match can prove whether all variants are handled.

fn opposite(direction: Direction): Direction {
    return match direction {
        North => South
        East => West
        South => North
        West => East
    }
}

Adding a variant can make existing matches non-exhaustive, which turns a domain expansion into a compile-time migration task.

Integer enums

Variants may have integer discriminants.

enum HttpStatus {
    Ok = 200
    NotFound = 404
}

Use explicit discriminants for external protocols or stable numeric representations. Do not mix data-carrying variants and integer discriminants in one enum.

Variants without an explicit discriminant use the compiler’s sequential enum rule. Do not expose an implicit number as a stable wire contract unless the ABI specification guarantees it.

An integer-valued enum remains an enum, not an int. Ordinary integer arithmetic and construction from an unchecked integer require an explicit API; the declaration does not make every integer a valid variant.

Generics

enum Tree[T] {
    Leaf(T)
    Branch([]Tree[T])
}

Payloads are checked after substituting the enum’s concrete type arguments.

Expected types can infer the generic argument during construction:

tree: Tree[string] = Leaf("root")

Without enough surrounding information, supply the type through an annotation or another constrained use.

Recursion

Recursive payloads need a finite representation. A managed collection can introduce the required indirection.

enum Expression {
    Literal(int)
    Add([]Expression)
}

A variant that embeds its own full enum directly without indirection is rejected.

The same finite-layout check follows mutually recursive structs and enums. A list, another managed container, or a supported indirect representation breaks the infinite inline cycle; merely moving the direct cycle through a second named type does not.

Methods

Enums can participate in inherent and trait implementations like other named types.

impl Direction {
    fn is_horizontal(self): bool {
        return match self {
            East | West => true
            _ => false
        }
    }
}

Use a named enum when alternatives need stable variant names, domain-specific payloads, methods, derives, or a public identity.

Payload values retain their ordinary ownership and cleanup behavior. Switching on a variant observes its tag; destructuring then binds that variant’s payload without changing the source type of the other alternatives.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close