const declares a value evaluated at compile time. Constants can be top-level,
associated with a type, or local to a block.
const MAX_RETRIES = 5
const PORT: u16 = 8080
const MASK = 0xFFConstant names use SCREAMING_SNAKE_CASE.
Inference
An annotation is optional when the initializer determines a type.
const RETRIES = 5
const LABEL = "worker"
const ENABLED = trueThe evaluator preserves contextual numeric information. RETRIES can adapt
to a compatible numeric use, while PORT: u16 has the fixed declared type.
Constants are not mutable and cannot be targets of assignment.
Constant expressions
A constant expression may use literals, other constants, and supported pure operators. The compiler folds the expression and diagnoses cycles, division by zero, runtime dependencies, and invalid typed values.
const WIDTH = 80
const HEIGHT = 24
const AREA = WIDTH * HEIGHT
const LOW_NIBBLE = 0xFF & 0x0FShort-circuit boolean expressions and integer arithmetic, remainder, bitwise operations, shifts, comparisons, and unary operations are supported by the current evaluator.
String concatenation is folded when every input is constant.
const PRODUCT = "atoll"
const VERSION = "1"
const USER_AGENT = PRODUCT + "/" + VERSIONThe evaluator rejects:
- references to parameters or runtime bindings;
- calls without an explicitly supported compile-time meaning;
- dependency cycles;
- division or remainder by zero;
- values outside an annotated numeric type.
This is a deliberately bounded constant language, not arbitrary execution of the runtime in the compiler.
Typed and contextual constants
An annotation fixes a constant’s type and causes range checking at compile time.
const SMALL: u8 = 200
const TOO_LARGE: u8 = 999 // errorAn unsuffixed numeric constant remains usable where a compatible contextual numeric type is expected. This is compile-time literal adaptation, not an implicit runtime conversion.
Scope
Top-level constants participate in normal module visibility and imports.
const DEFAULT_TIMEOUT = 30
private const INTERNAL_TAG = 7Member constants can be declared inside a struct and are folded with the same rules as top-level constants.
struct Limits {
const MAX_ITEMS = 1024
}Traits can declare associated constants, and implementations can bind them. The member-lookup surface for ordinary application use is still being stabilized, so this guide does not rely on a particular associated-constant access spelling yet.
Local constants
Local constants are block-scoped and may reference other visible constants, but not parameters or runtime bindings.
fn packet_limit(): int {
const HEADER = 16
const PAYLOAD = 4096
return HEADER + PAYLOAD
}Use a normal binding when the value depends on runtime state.
Constants in patterns
A visible constant name in a pattern matches the constant’s value rather than introducing a new binding. Fresh names still bind normally; resolution decides which interpretation applies.
const QUIT = 0
match command {
QUIT => stop()
other => process(other)
}Use an enum variant when the cases form a closed semantic domain. A constant pattern is most appropriate for protocol numbers, limits, masks, or another value that already has a stable scalar representation.
Initialization
Constant evaluation happens before runtime bindings and function bodies are lowered. A constant therefore has no initialization order at runtime. Its folded value is substituted into uses, subject to the target type and layout.
Large runtime data structures are not created by const merely because their
source looks literal. Use a top-level function or an ordinary binding when
construction needs allocation, I/O, a host call, or another runtime effect.