Skip to Content

Flags

flags declares a set of constants that combine bitwise. Members are physically int bits, but combinations within the same declaration keep the flags static surface, and the method surface is available directly.

Declaration and Combination

flags Perm { Read, Write, Execute = 16, } val p = Perm.Read | Perm.Write; print(p); print(p.Has(Perm.Read), p.Has(Perm.Execute));
3 True False

Valueless members auto-increment by powers of two (the first member is 1, each following member doubles), and implicit members after an explicit value start from “the previous explicit value doubled”. | combines members of the same declaration into the flags static surface; Has(member) tests containment.

Set, Clear, Toggle

All three methods return a new flags value; the original is untouched:

val full = p.Set(Perm.Execute); print(full.Has(Perm.Execute), p.Has(Perm.Execute)); val less = full.Clear(Perm.Write); print(less, less.Toggle(Perm.Read));
True False 17 16

Set adds a bit, Clear removes one, Toggle flips one. less is Read | Execute (1 + 16) and prints 17; toggling Read again leaves 16.

Converting to and from int

Flags are physically int bits, and conversion is implicit in both directions:

val n: int = p; print(n); val q: Perm = 3; print(q, q.Has(Perm.Read | Perm.Write));
3 3 True

Flags built from an int still carry the full method surface. Bitwise operations across different flags types are treated as int bitwise operations; the result no longer has the flags surface.

The Exact Rules for Implicit Increment

Valueless members increment by powers of two; after an explicit value, implicit members continue from “the previous explicit value doubled”:

flags Mode { A, B, C = 10, D, } print(Mode.A, Mode.B, Mode.C, Mode.D);
1 2 10 20

A and B get 1 and 2, C is explicitly 10, and D starts at 20. Member values must be compile-time integer constants; duplicate values are legal aliasing (two names on the same bit).

Aliasing and Cross-Type Operators

int converts implicitly to flags, and the result keeps the full method surface. Bitwise operations between two different flags types degrade to int, and the result no longer has the flags surface:

flags Other { X, } val aliasF: Mode = 1; print(aliasF.Has(Mode.A), aliasF.Has(Mode.B)); val cross = Mode.A | Other.X; print(cross);
True False 1

aliasF is built from int 1 and is equivalent to Mode.A: Has(Mode.A) holds and Has(Mode.B) does not. cross is already a plain int; to get the flags surface back, annotate the type as Mode explicitly.

Notes

  • Printing a flags value outputs the number directly; if you need names, decompose the bits yourself.
  • Has accepts combined bits (q.Has(Perm.Read | Perm.Write) tests that both bits are set).
  • All bitwise operators & | ^ ~ << >> work; their semantics are exactly int bitwise operations.
  • Set / Clear / Toggle all have value semantics: they return new flags values and are commonly chained for configuration.
Last updated on October 11, 2026