Appendices
Compiler Rules for std Items
This appendix lists the rules the compiler enforces for std items beyond their signatures: which std types the story may hold, how literals and forms are typed, the special signatures, and which evaluation failures are compile errors. Each rule names the diagnostic you get when it is broken; the diagnostics are described in Diagnostics.
Kinds
- Every std function has the kind it is declared with: the
Kind:badge of its page. - The call rules of the language apply to std methods and builtins exactly as to your own
functions (
E3001). So a render (const fn) cannot callSetting::get, and a UI component (fn) cannot callpush_step. push_step(and sos!andchoice!) andrng_chooseare callable only from a scene (E3002,E3024).
Finite types
The story can hold only finite types at runtime
(E3008). Among std types, these are
finite:
Text;- the five file asset types (
ImageAsset,AudioAsset,VoiceAsset,VideoAsset,FontAsset); Render(aconst fnpointer);Option,Result,Rangeand other std structs and enums whose fields are all finite, for exampleVisibilityorPlayMode.
These are not finite:
String,Vec<T>,Rat,Decimal;Screen,Narrative,Meta,Settingand every other#[builtin]handle or state type, includingShaderAsset, the shader types such asColorShader<A>, andShaderArgs, so the effect values ofstd::screen::shaderare not finite either;- data that holds a Rust integer or a
Decimal:Duration,Color,EntityId,Part,Mark,Point,TextEffect,TextStyle, …
Story code can still name non-finite values in constant expressions, which are folded: ms(300)
or Mark(1) in a step is fine. A const fn call with runtime arguments is tabulated, and its
result must be finite.
Type rules
- A string literal has type
Text; a literal with a decimal point has typeDecimal. {expr}int![…]isto_text(expr), soexpr: TwithT: ToText(E2026).- In the story,
to_textof a finite runtime value is tabulated like anyconst fncall, so the line stays a finite function of the story state. - An
#[entry]scene’s parameter and return types must not containText, becausefncode can build runtime text withto_text(E3009). a..banda..=bhave typeRange<T>, whereTis a type bothaandbconvert to:0..7is aRange<Int<0, 7>>. A range expression needs both bounds:a..,..band..exist only in patterns (E2030).x.into()withx: Sand targetT, bothInteger, needs every value ofSto fit inT(E2018).x.saturate()has no such condition.
Forms
choice!ids are string literals, unique within their function (E3019).choice!arm values are fieldless enum variants, each at most once per choice (E3020).- A ruby base is a string literal; mono-ruby readings are an array literal with one reading per
base character (
E3021). - The effect of
is a constant expression (E3022).
Traits
- Only
stddeclares traits, and each one is#[builtin]. Atraititem or animpl Trait for Tin a game is an error (E1012,E1023). Eqholds for primitives,Int, function pointers, and structs, enums, tuples and arrays whose fields are allEq; for a#[builtin]type, only through animpl Eqinstd. Closures are neverEq.==on a non-Eqtype isE2017.- An unsatisfied bound (
A: Asset,T: RandChoose,T: ToText,A: ShaderArg, …) isE2026. ShaderArgholds for()and for structs marked#[shader_arg], and for nothing else.
#[shader_arg]
The argument type of a shader is () or a struct marked #[shader_arg]; see
Arguments.
#[shader_arg]on anything but a struct isE3018.- The struct needs named fields and no type parameters (const parameters are allowed)
(
E3025). - Each field is
bool,i32,u32,Decimal,Rat,Color,Point,Offset,Size,Anchor,Angle,Duration, an enum declared in Kagari with at least one variant and no fields, a#[shader_arg]struct, or an array[T; N]of one of these withN> 0 (E3026).
asset::<A>
- It needs
A: Asset(E2026). - Its argument must be a string literal
(
E2028), not empty (E1028), inside the asset directory (E1029) but outside its reserved top-level directoriessystem-fontsandstd(E1032), and the file must exist (E1027). system_fontfollows the same literal rule; its own errors areE1030andE1031.
nav::start(entry, args, on_exit)
The signature start<E, A, R>(entry: E, args: A, on_exit: Fn(R)) is special
(E2027):
entryis ascene fn(P1, …, Pn) -> Rpointer to an#[entry]scene;argsis the tuple(P1, …, Pn);on_exitisFn(R).
Settings and meta in const fn
- A
Setting<T>handle may appear in aconst fnonly as a value, that is, passed toEntity::gate.getandsetarefn. - Meta fields cannot be used in
constcode at all (E3013). SettingandMetahandles exist only as the initializer of an immutablestatic(E3011,E4007).
#[must_use]
It covers Change<T>, Swap and ChannelChange. A pending change that is discarded, or bound to
a local and never completed with apply_animation, is a warning
(W3023), and the change does not
happen.
for loops
foroverVec<T>, arrays andRange<T>of anIntegerTis allowed infnandconst fn. Anything else is not iterable (E2031).- In a
pushdown fn,forloops only over arrays and over ranges whose bounds are constant expressions (E3006).
Const-evaluation errors
When std code runs during const evaluation, these failures are compile errors:
| Failure | Diagnostic |
|---|---|
| Integer overflow | E4001 |
Division by zero (Rat::new(_, 0), Duration::div(0), …) | E4002 |
Vec::set out of range | E4005 |
A Setting or Meta handle outside a static initializer | E4007 |
The Motion rules: no keys, at not strictly increasing or equal to 0, a last key that is not identity, repeat = 0 | E4008 |
CubicBezier x outside 0–1, and Steps(0), in a tween or a transitional motion | E4009 |
| A duplicate text mark | E4010 |
begin_text while anchored on a mark | E4011 |
A Decimal fraction outside 0.0–1.0 where required: opacity, volume, anchor | E4012 |
Duration overflow or underflow | E4013 |
At runtime, the same failures in fn code are evaluation errors of the running game.
Last updated Oct 29, 2026