A decorator begins with @ and precedes the declaration, field, parameter, or
binding it modifies.
@inline
fn small(value: int): int {
return value + 1
}
@sealed
trait InternalProtocol {
fn execute(self): void
}The parser preserves arbitrary decorator syntax. A decorator has behavior only when a compiler pass, tool, runtime adapter, or domain subsystem recognizes it.
Syntax
A decorator name is lowercase and can be dotted for a subsystem namespace.
@sql.name("booking_records")
model Booking {
@id
id: int
}Arguments are parsed as expressions, but every recognized decorator defines a narrower compile-time argument contract. A decorator written without parentheses has no arguments.
Multiple decorators can apply to one target. Their source order normally does not change their meaning.
@host("clock", "monotonic")
@suspend
fn monotonic_time(): intCompilation
These decorators affect ordinary program compilation:
| Decorator | Target | Meaning |
|---|---|---|
@allow(naming) |
Supported declaration | Suppress its naming diagnostic |
@derive(Trait, ...) |
Struct or enum | Synthesize supported trait implementations |
@sealed |
Trait | Restrict implementations to the declaring file |
@inline |
Function | Request inlining |
@inline(always) |
Function | Require inlining where valid |
@noinline |
Function | Prevent inlining |
@linear |
Local binding | Require linear-use checking |
@externalizable |
Struct or enum | Opt into serialization code generation |
@extern |
Struct or enum | Alias of @externalizable |
@weak |
Field | Store a supported optional reference weakly |
@derive requires one or more bare trait names.
@derive(Equatable, Hashable)
struct Coordinate {
x: int
y: int
}Only compiler-supported derivations can be synthesized. @derive is not a
general macro system and does not execute arbitrary user code.
The naming lint is currently opt-in. Its suppression is retained on functions, structs, enums, error types, traits, error unions, and implementation blocks. Enum-level suppression also covers variants. Aliases and constants do not currently retain declaration decorators for this lint. See Naming conventions for exact coverage.
@weak has layout and type restrictions. It applies to supported nullable
reference-shaped fields, not scalars, strings, tuples, or non-optional values.
See References.
Tooling
The CLI recognizes entry-point decorators:
| Decorator | Meaning |
|---|---|
@test |
Discover a function as a test |
@bench |
Discover a function as a benchmark |
@ignore |
Skip a discovered test unless ignored tests are requested |
They take no arguments. @test is diagnosed on non-function declarations.
@test
fn addition_works(): void {
assert(20 + 22 == 42)
}Runtime
The prelude and runtime adapter use low-level decorators:
| Decorator | Meaning |
|---|---|
@host("namespace", "name") |
Bind a function to a typed host import |
@pure |
Mark a host binding synchronous and non-suspending |
@suspend |
Mark a function as a suspension source |
@builtin |
Mark a declaration supplied by compiler lowering |
@intrinsic |
Bind a function to its same-named intrinsic |
@intrinsic("name") |
Bind an explicit intrinsic name |
@niche |
Select a compiler-known niche representation |
@cycle_free |
Assert that an internal type cannot form RC cycles |
These are part of the compiler/runtime ABI. Application code should normally call safe standard-library functions rather than declare new host imports or intrinsics.
@host requires exactly two string arguments. @builtin, @pure,
@suspend, @niche, and @cycle_free take no arguments. @builtin and
@host conflict. @pure requires @host and conflicts with @suspend.
The removed @kind routing decorator produces a migration diagnostic. Use a
two-argument @host binding instead.
Data
The data layer recognizes decorators such as @id, @unique,
@sql.name, @sql.function, full-text metadata, vector dimensions, and
selected index options.
@sql.name("people")
model Person {
@id
id: int
@unique
email: string
}Their valid targets, arguments, and engine restrictions are documented in Models and Schemas.
Unknown names
Core parsing retains an unknown decorator so domain-specific tools can inspect it. Core sema may otherwise ignore the name.
@acme.reviewed("2026-07")
fn calculate(): int => 42Preservation does not mean that the decorator executes, validates its arguments, changes code generation, or exists at runtime. A subsystem must document and implement those semantics.
The legacy docs/decorators/ catalog proposes actor, job, UI, auth, AI, MCP,
HTTP-routing, and event decorators. Those application systems are not current
core-language features and remain classified under
Feature Status.