Skip to content
CryoCryo home
LanguageControl and data

9Enums

Cryo enums are algebraic data types. Variants may be unit or carry a payload. The compiler enforces exhaustive matching.

9.1 Unit Enums

type enum Color {
    Red;
    Green;
    Blue;
}

const c: Color = Color::Red;

Variants are accessed through the enum name with ::, so Color::Red and TrafficLight::Red are unambiguous.

Variants may have explicit integer values for FFI or protocol encoding:

type enum ErrorCode {
    Ok       = 0;
    NotFound = 404;
    Internal = 500;
}

9.2 Variants with Payloads

A variant can carry one or more values:

type enum Shape {
    Circle(f64);
    Rectangle(f64, f64);
    Point;
}

const s: Shape = Shape::Circle(5.0);

A Shape value is always exactly one variant; the compiler tracks which one and enforces exhaustive matching.

9.3 Generic Enums

Enums can be parameterised over types. The standard library's Option and Result are the canonical examples:

type enum Option<T> {
    Some(T);
    None;
}

type enum Result<T, E> {
    Ok(T);
    Err(E);
}

const v: Option<int>          = Option::Some(42);
const r: Result<string, int>  = Result::Ok("success");

Each instantiation is an independent type at the machine level; Option<int> and Option<string> share no runtime representation.

A variant constructs one instantiation, and something must say which: type arguments written on the path (Option::<i32>::None, Result::Ok::<i32, i32>(4)), the expected type (an annotation, a parameter, a return type), or the variant's own arguments (Option::Some(42) is an Option<i32>). A variant nothing instantiates - const n = Option::None;, or Result::Ok(1) with E unbound - is refused (E0307). Type arguments written on the path also type the payload: Result::<i32, i32>::Ok("x") is refused (E0214), and in Option::<u8>::Some(200) the literal is a u8.

9.4 Methods on Enums

Enums cannot declare methods inline. Methods are added via an implement block, which is also how the standard library gives Option and Result their rich API:

implement enum Option<T> {
    is_some(&this) -> boolean {
        match (this) {
            Option::Some(_) => { return true; }
            Option::None    => { return false; }
        }
    }

    unwrap(&this) -> T {
        match (this) {
            Option::Some(value) => { return value; }
            Option::None        => {
                panic("unwrap on None", intrinsics::location());
            }
        }
    }
}

See section 12 for the full implement-block grammar.