Kagari
Type to search documentation.

Special Types, Traits and Attributes

Attributes

An attribute is written #[name] directly before an item. Kagari has exactly five attributes and none of them takes arguments. Games use four of them; #[builtin] is reserved for the standard library.

AttributeAllowed onMeaningMisuse
#[scene]pushdown fnA scene: may run steps, call scenes and draw random valuesE3018
#[entry]a #[scene] functionAn entry scene: the system can start the story hereE3018, E3008, E3009
#[must_use]struct, enumA value of the type must be completed, not droppedE3018; warning W3023 at the use
#[shader_arg]structThe type can be a shader’s argumentsE3018, E3025, E3026
#[builtin]standard library only: functions, structs, traitsImplemented by the compiler and the engineE1008, E1009, E1013

Syntax

kix
/// The first scene of the game.
#[scene]
#[entry]
pub pushdown fn Main() {
s!(t!["It was the last day of summer."]);
}
  • An attribute stands before an item: a function (including an associated function in an impl), struct, enum, const, static, type, mod, use, impl or trait. It comes after the item’s doc comments and before pub.
  • Several attributes may be stacked, on one line or on separate lines, in any order.
  • /// doc comments are comments, not attributes.
  • Inner attributes (#![…]) do not exist, and an attribute must be followed by an item: both are syntax errors (E0001). Attributes cannot be put on statements or expressions.
  • A name other than the five is E1006, and the attribute is ignored.
  • An attribute written with arguments, such as #[must_use("reason")], is E1007; the attribute still applies.

Tentative. The parser also accepts attributes on struct fields, tuple fields and enum variants, but the compiler currently ignores them there, including unknown names. Do not rely on it.

#[scene]

#[scene] makes a pushdown fn a scene. Only a scene may:

  • run a step: s!(…), choice!{…} or a call of push_step (E3002 elsewhere);
  • call another scene, including itself (E3003 elsewhere);
  • draw a random value with rng_choose (E3024 elsewhere).

A pushdown fn without #[scene] is an instant procedure. Every loop and every cycle of calls in a scene must pass through a step (E5001, E5002). A pointer to a scene has the type scene fn(…) -> R.

kix
#[scene]
pushdown fn Greeting() {
s!(who = "Mio", t!["Hello."]);
}

#[scene] on anything but a pushdown fn is E3018, for example on a fn or a const fn.

See Scenes and Instant Procedures.

#[entry]

#[entry] marks a scene as an entry scene: a place where the game system can start the story. It needs #[scene] on the same function; without it, #[entry] is E3018. The order of the two attributes does not matter.

  • The system starts an entry scene with nav::start(Scene, args, on_exit). The first argument must be the path of an #[entry] scene, not any other expression (E2027); args is the tuple of its parameters, and on_exit receives its return value.
  • Like every scene, its parameter and return types must be finite (E3008). In addition, they must not contain Text (E3009), because fn code can build text at runtime.
  • When the entry scene returns, the story is over. Its return value is the ending.
  • The compiler analyzes the story starting from each entry scene. Write entry scenes without generic parameters: a generic #[entry] scene is not used as a starting point.
kix
pub enum Ending { NormalEnd, AzusaEnd }
#[scene]
#[entry]
pub pushdown fn Main(cleared_azusa: bool) -> Ending {
s!(t!["Morning."]);
if cleared_azusa { Ending::AzusaEnd } else { Ending::NormalEnd }
}

See Entry Scenes and Endings.

#[must_use]

#[must_use] on a struct or an enum says that a value of the type is an unfinished operation. On any other item it is E3018. The compiler warns (W3023) when:

  • an expression statement produces a value of the type, or a reference to one; or
  • a let binds such a value to a local, and the function never calls a method of the type on that local.

The standard library marks its pending changes Change<T>, Swap and ChannelChange: a change of the screen happens only through apply_animation, so a forgotten apply_animation is caught at compile time.

kis
const fn roof(mut screen: Screen) -> Screen {
screen.background().clear(); // W3023: nothing happens
screen.background().clear().apply_animation(fade(ms(500))); // completed
screen
}

A game may mark its own types too. The warning then lists the type’s methods as the ways to complete the value.

#[shader_arg]

#[shader_arg] on a struct makes it a shader argument type: the type implements ShaderArg, so a shader asset such as ColorShader<Memory> can take it, and the engine passes its value to the shader. On any other item it is E3018.

kis
use std::screen::shader::ColorShader;
#[shader_arg]
struct Memory {
strength: Decimal,
}
const MEMORY: ColorShader<Memory> = asset("memory.wgsl");
  • The struct has named fields, at least one, and no type parameters; const parameters are allowed (E3025 otherwise).
  • Every field has a type a shader can read: bool, i32, u32, Decimal, Rat, the std types Color, Point, Offset, Size, Anchor, Angle and Duration, an enum without fields, a #[shader_arg] struct, or an array [T; N] of one of these with N > 0. Any other field type, or an array of length 0, is E3026 at the field.

How each field reaches the shader is described in Writing Shaders in the STD Reference.

#[builtin]

#[builtin] marks an item that the compiler and the engine implement. It is allowed only in the standard library (E1008); you meet it when reading std declarations:

kis
#[builtin] pub struct Screen;
#[builtin] pub const fn asset<A: Asset>(path: narrative::Text) -> A;
#[builtin] pub trait Eq {}
OnRule
a functionIt has no body (E1009). It is called like any function, and the kind rules apply to it as to any other function
a structIt has no fields (E1009). The type is opaque; see Opaque builtin types
a traitEvery std trait must be #[builtin] (E1013); see Language Traits

A function without a body that is not #[builtin] is E1010.

Diagnostics

CodeWhen
E0001An inner attribute #![…], or attributes not followed by an item
E1006An unknown attribute
E1007An attribute with arguments
E1008#[builtin] outside the standard library
E1009A #[builtin] function with a body, or a #[builtin] struct with fields
E1013A standard library trait without #[builtin]
E3018#[scene] not on a pushdown fn, #[entry] without #[scene], #[must_use] not on a struct or enum, #[shader_arg] not on a struct
E3008, E3009An entry scene’s parameter or return type is not finite, or contains Text
E2027nav::start of something that is not an #[entry] scene
W3023A #[must_use] value dropped or never completed
E3025A #[shader_arg] struct without named fields, or with type parameters
E3026A #[shader_arg] field of a type a shader cannot read, or an array of length 0

Last updated Oct 29, 2026