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 values 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 value. 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

If the expected type is an enum union and more than one member enum has a matching case name, leading-dot shorthand is invalid:

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.is_enum() Type.Predicate
T.enum_cases() []const Type.EnumCase!Type.ReflectionError

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

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

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

is_enum_union() is true only for enum-union types. 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
  • discriminated unions
  • 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.