A struct is a named product type.
struct Point {
x: float
y: float
}Struct names use PascalCase; field names use snake_case.
Construction
Construct a value by naming its fields.
origin := Point { x: 0.0, y: 0.0 }Named fields keep construction independent of declaration order. Shorthand uses a visible binding with the same name.
x := 10.0
y := 20.0
point := Point { x, y }Values supplied for known fields are checked against their declared types.
Current boundary
The parser accepts field defaults, but the current semantic constructor path does not apply them. It also does not yet diagnose every missing, duplicate, or unknown field in a struct literal. An omitted field can therefore reach lowering without an initialized source value.
Until construction checking is completed, initialize every declared field exactly once and do not rely on a declaration default:
struct Retry {
attempts: int = 3
enabled: bool
}
retry := Retry {
attempts: 3,
enabled: true,
}Treat an incomplete literal as unsupported even if the current compiler accepts it. Put reusable defaults and validation in a named constructor, and have that constructor explicitly initialize every field.
Access
Use . to read a field.
distance := point.x * point.x + point.y * point.yAssigning a field requires a mutable path to the value.
mut point := Point { x: 0.0, y: 0.0 }
point.x = 4.0The field declaration itself does not need a mut modifier. Mutability comes
from the binding and receiver path.
Nested assignment requires the complete path to be mutable. A mutable outer binding does not bypass a borrowed receiver’s contract, and assigning one field does not reconstruct unrelated fields.
Methods
Methods can be declared in the struct body.
struct Counter {
value: int
fn current(self): int => self.value
fn increment(mut self): void {
self.value += 1
}
}self is a read receiver; mut self permits mutation. A function without
self is static.
struct Point {
x: float
y: float
fn zero(): Point => Point { x: 0.0, y: 0.0 }
}Methods can also be supplied by an inherent impl block or a receiver-prefix
function. Trait implementations are covered in
Implementations.
Receiver form is part of the method contract:
| Receiver | Capability |
|---|---|
no self |
static function called through the type |
self |
read the value and call non-mutating behavior |
mut self |
update fields through the receiver |
Call syntax remains value.method() or Type.function() regardless of where
the implementation is written.
Generics
struct Page[T] {
items: []T
next_cursor: string?
}Every concrete Page[T] has fields checked with its substituted T. Generic
arguments use square brackets.
Generic inference can obtain T from constructor fields or an expected type.
An empty collection field may still need an annotation when no value constrains
its element type.
Decorators
Struct and field decorators can add compiler or subsystem metadata.
@derive(Equatable)
struct User {
id: int
@weak
manager: User?
}@derive, @externalizable, @weak, and model-specific decorators have
different target restrictions. See Decorators.
Recursion
A recursive value must include a representational break.
struct Node {
value: int
children: []Node
}Managed containers and supported optional/boxed layouts can provide indirection. A struct that embeds itself directly at full extent has no finite size and is rejected.
Mutually recursive declarations are checked by the same finite-layout rule.
Identity
Structs are nominal: two declarations with identical fields remain different types.
struct Width { value: int }
struct Height { value: int }The values do not interchange merely because both contain one int.
Storage representation is compiler-selected. Source equality follows
Equatable, not storage-handle identity.
Nominality is module-aware. Two modules can declare the same type name and field list without creating one shared type; imports retain the defining module’s identity.
Spelling
The current declaration is struct Name { ... }. Legacy type Name { ... }
and data Name { ... } forms are not current struct syntax. type declares
an alias.
Use an anonymous record for a short-lived structural shape, and a model only when the fields describe a persisted database row.