An item is a declaration that belongs to a module: a function, a type, a constant, a static,
an implementation, a module or an import. Items may appear at the top of a file, in an inline
module, in a block (see Items in blocks), and, for functions and constants, in
an impl.
Overview
| Item | Form | See |
|---|---|---|
| Function | fn f() {}, const fn f() {}, pushdown fn f() {} | Functions |
| Struct | struct Point { x: i32, y: i32 }, struct Id(u32);, struct Marker; | Structs |
| Enum | enum Route { None, Hanako, Azusa } | Enums |
| Constant | const HANAKO: EntityId = EntityId(216); | Constants |
| Story variable | static mut ROUTE: Route = Route::None; | Story variables |
| Handle | static MUSIC: Setting<Volume> = setting(volume(60)); | Handles |
| Type alias | type Pair<T> = (T, T); | Type aliases |
| Implementation | impl Point { … } | Implementations |
| Module | mod story;, mod ui { … } | Source Files and Modules |
| Import | use story::Day1; | use declarations |
The general shape of an item is:
Item = Attribute* "pub"? ItemBodyAttribute = "#" "[" Path "]"Items may be used before their declaration. The order of items in a file has no meaning.
Structs
struct Point { x: i32, y: i32 } // record structstruct Affection(Int<0, 5>); // tuple structstruct Marker; // unit structstruct Pair<T> { a: T, b: T } // generic struct- A record struct has named fields and is built with
Point { x: 1, y: 2 }. - A tuple struct has numbered fields, accessed as
.0,.1, …. Its name is also a constructor function:Affection(3). The constructor is aconst fnand can be used as a value of aconst fn(…) -> …pointer type. - A unit struct has no fields. Its name is its only value.
- A struct may be generic over types and constants; see Generics. There
are no
whereclauses and no default generic arguments. - Fields may be marked
puband may carry attributes. The compiler does not check field visibility yet; see Visibility. - There is no
derive. Equality is automatic; see Equality.
Enums
enum Route { None, Hanako, Azusa }
enum Ending { Normal, Good(Int<0, 3>), Bad { reason: Route },}- A variant is a unit variant, a tuple variant or a record variant, like the three struct forms.
- Variants are named through the enum,
Route::Hanako, unless imported:use Route::*;imports every variant.OptionandResulthave their variants in the prelude. - Tuple variant names are constructor functions, like tuple struct names:
Ending::Good(2). - Explicit discriminants (
A = 1) are a syntax error. Enums have no numeric value; convert with amatch. - An enum whose variants all carry no data is a fieldless enum. Fieldless enums implement
RandChooseand are the values ofchoice!arms.
Constants
const HANAKO: EntityId = EntityId(216);const MAX_AFFECTION: Int<0, 100> = 5 * 20;const ROOF: ImageAsset = asset("bg/roof.png");- The type is required.
- The initializer must be a constant expression
(
E3010): it is computed by the compiler. A constant without a value isE1011. - The type cannot contain a reference (
E3012). - A constant may be used anywhere, also in the story, whatever its type, because its value is known at compile time.
- A constant may also appear in an
impl(an associated constant, used asPoint::ORIGINorSelf::ORIGIN) and in a block. - A constant initializer is checked like
constcode: it may call onlyconst fn.
Statics
static declares a value with one place for the whole run of the game. There are exactly two
uses, and the compiler tells them apart by mut.
Story variables
static mut ROUTE: Route = Route::None;static mut AFFECTION_MIO: Int<0, 5> = 0;A static mut is a story variable: narrative state, saved and restored with the story.
- Its type must be finite
(
E3008) and cannot contain a reference (E3012). - Its initializer is a constant expression (
E3010). - Only
pushdown fncode may read or write it (E3007).
See Story variables for their meaning.
Handles
static MUSIC: Setting<Volume> = setting(volume(60));static CLEARED_AZUSA: Meta<bool> = meta(false);An immutable static is a handle: it holds a Setting<T> or a Meta<T>
(E3011). Its initializer is a call of setting(…) or
meta(…) with a constant argument. These calls are allowed only in the initializer of a static
(E4007). Use const for an ordinary constant. Settings and meta
are described in The Game System.
Type aliases
type Pair<T> = (T, T);type Board = Square<8>;A type alias gives a type another name; it does not create a new type. It may be generic. An alias
without a type is E1011, and an alias that expands to itself
is E2010. An alias of a struct or enum can name its associated
items and can be the target of an impl: Board::new().
Implementations
struct Square<const N: u64> { side: u64,}
impl<const N: u64> Square<N> { const CELLS: u64 = N * N;
pub const fn new() -> Self { Self { side: N } }
pub const fn cells(&self) -> u64 { self.side * Self::CELLS }}An inherent implementation impl Type { … } adds associated functions and constants to a
struct or enum. Functions with a self parameter are methods; see
Methods and associated functions.
- The target is a struct or enum, written with its generic arguments; the
impldeclares the generic parameters it uses:impl<T> Pair<T> { … }. The target may also be a struct or enum of the standard library. Primitive types cannot be extended (E1022). - Inside the
impl,Selfis the target type. - Associated items are private unless marked
pub. Two associated items of one type with the same name areE1014, even in differentimplblocks. - A type may have several
implblocks, in any module of the game. impl Trait for Typeis reserved for the standard library (E1023).
Traits
User code does not declare traits (E1012) and does not
implement them (E1023). The standard library declares a fixed
set of traits, which code uses as bounds on generic parameters (see
Trait bounds). They are described in
Language Traits.
Modules and imports
mod declares a module and use imports names. Both are described in
Source Files and Modules.
Items in blocks
A block may contain items next to its statements. The items are visible in the whole block, including before their declaration, and in nested blocks; they are not visible outside the block.
fn uses() -> u64 { const STEP: u64 = 2; fn helper(x: u64) -> u64 { x + STEP } use crate::widen as w; helper(1) + w(3u8)}
fn widen<T: Integer>(value: T) -> u64 { Integer::into(value)}An item in a block is an ordinary item: a nested function does not capture the locals of the
enclosing function, and a nested const is computed at compile time. A file module (mod name;)
cannot be declared in a block (E1005); an inline module can.
Attributes
An attribute is written #[name] before an item, before pub. The compiler knows four
attributes:
| Attribute | On |
|---|---|
#[scene] | a pushdown fn |
#[entry] | a #[scene] function |
#[must_use] | a struct or an enum |
#[builtin] | a function, struct or trait of the standard library |
Any other attribute is E1006, an attribute with arguments
(#[scene(x)]) is E1007, and an attribute on the wrong item
is E3018. Inner attributes #![…] are a syntax error. The
meaning of each attribute is in Attributes.
Last updated Oct 29, 2026