Skip to content

Enums

Accepted

Accepted for V1 tag-only enum and enum-union semantics; pattern matching, payload variants, and representation control are deferred.

Enums are closed, tag-only value types. They are ordinary type handles produced by an enum type expression and usually bound to a type-like const:

const Ordering = enum {
  less,
  equal,
  greater,
}

Ordering is a constant whose value has type type. enum { ... } constructs a closed enum type handle. Enum values are runtime values whose type is that enum.

Enum Cases

Enum case names use lower_snake_case:

const result: Ordering = Ordering.less

Cases are scoped by their enum type. A.ready and B.ready are distinct case identities even when their case names match.

Leading-dot shorthand is allowed only when an expected enum or enum-union type supplies a unique matching case:

const result: Ordering = .less

Free unqualified case names are not valid.

Declaration order is preserved for reflection, diagnostics, documentation, and deterministic snapshots. It does not imply numeric discriminants, ordering operators, or a public memory layout.

Enum Unions

Enum types compose with |:

const Status = FileStatus | NetworkStatus

An enum union is a concrete closed value type, not a constraint type and not a discriminated union with payloads. It may appear anywhere an ordinary concrete value type may appear: locals, fields, parameters, returns, arrays, and optionals.

Enum-union operands may be plain enum types or enum-union types. Nested enum unions flatten, duplicate member enum types collapse, and member order normalizes deterministically:

const AorB = A | B
const All = AorB | C

A | B and B | A denote the same semantic enum-union type. Source spelling may still be preserved in declaration metadata for diagnostics and documentation.

Enum-union case identity preserves the source enum:

A.ready != B.ready

An enum-union type namespace exposes a case name only when exactly one member enum contributes that name:

const status: Status = Status.ready // ok only when exactly one member has `ready`

If more than one member enum has a matching case name, union-qualified lookup and leading-dot shorthand are both invalid. Write the declaring enum owner:

const status: A | B = .ready // error if both A.ready and B.ready exist

Enum-Union Compatibility

A plain enum value coerces to an enum union that contains its enum type:

const status: A | B = A.ready

A broader enum union does not implicitly coerce to a narrower enum type or narrower enum union. V1 does not provide enum-union narrowing operations.

Equality is available through compiler-owned PartialEq(T) conformances for plain enum types and enum-union types. Comparison is valid when both operands can be viewed through a common enum or enum-union type.

Enum Reflection

Enum reflection exposes separate APIs for plain tag-only enums and enum-union types:

T.type.is_enum() TypeDef.Predicate
T.type.enum_cases() []const TypeDef.EnumCase!TypeDef.ReflectionError

T.type.is_enum_union() TypeDef.Predicate
T.type.enum_union_members() []const type!TypeDef.ReflectionError

T.type.is_enum() is true only for plain tag-only enum types. T.type.enum_cases() returns cases in declaration order:

const EnumCase = struct {
  name: []const u8
  source: ?SourceLocation
  docs: ?[]const u8
}

T.type.is_enum_union() is true only for enum-union types. T.type.enum_union_members() returns member enum types in normalized deterministic order.

Reflection may preserve source spelling where declaration metadata records an alias or inline union expression, but semantic enum-union member order remains normalized.

Enum reflection is separate from error-set reflection because enum and error-set reflection expose different type families, even though both use scoped case identities.

Boundaries

Deferred:

  • payload-bearing variants and discriminated unions, tracked by CEP-0072: Algebraic Data Types
  • exhaustive switch or pattern matching
  • enum-union narrowing
  • explicit integer discriminants
  • enum @repr and C ABI representation
  • public memory layout guarantees

Plain enums and enum unions are copyable, non-resource values by default. They do not implement Disposable.