# 型

Kagari は静的に型付けされます。すべての値はコンパイル時にわかる 1 つの型を持ちます。型はアイテムのシグネチャでは明記し、関数本体の中では推論されます。

## 型の式 {#type-expressions}

| 構文 | 型 |
| ---- | -- |
| `Path`、`Path<Args>` | 名前の付いた型。プリミティブ、構造体、列挙型、型エイリアス、ジェネリクスパラメータ |
| `()` | ユニット型。空のタプル |
| `(A,)`、`(A, B)`、… | タプル |
| `(A)` | `A`。括弧はグループ化だけです |
| `[T; N]` | 要素数 `N` の配列 |
| `&T`、`&mut T` | 共有参照または可変参照 |
| `fn(A) -> R`、`const fn(A) -> R`、`pushdown fn(A) -> R`、`scene fn(A) -> R` | 関数ポインタ |
| `Fn(A) -> R`、`const Fn(A) -> R`、`pushdown Fn(A) -> R` | クロージャ型 |
| `_` | プレースホルダ。「この型を推論する」 |
| `Self` | `impl` の中での対象の型 |

`-> R` のない関数ポインタ型やクロージャ型は `()` を返します。プレースホルダ `_` は本体の中の `let` の注釈やジェネリクス引数では使えますが、アイテムのシグネチャでは使えません（[`E2011`](../../diagnostics/types.md#e2011)）。スライス型 `[T]`、`str`、`!` 型の構文、`dyn` や `impl Trait` の型、生ポインタはありません。

## 概要 {#overview}

| 型 | 値 | 備考 |
| -- | -- | ---- |
| `bool` | `true`、`false` | |
| `()` | `()` | 結果を持たないブロックや関数の値 |
| `Int<lo, hi>` | `lo` から `hi` までの整数 | プリミティブ。[数値](./numbers.md#intlo-hi)を参照 |
| `u8` … `u128`、`i8` … `i128`、`usize`、`isize` | Rust と同じ | [Rust の整数](./numbers.md#rust-integers)を参照 |
| `Decimal`、`Rat` | 正確な十進数と分数 | [数値](./numbers.md)を参照 |
| `Text` | 定数テキスト | [Text と String](#text-and-string) を参照 |
| `String` | 実行時のテキスト | |
| タプル、配列 | `(bool, Route)`、`[Int<0, 3>; 4]` | |
| `Vec<T>` | 伸縮するリスト | |
| `Range<T>` | `0..4`、`3..=5` | [範囲](#ranges)を参照 |
| 構造体、列挙型 | ユーザーが宣言するもの。プレリュードの `Option<T>` と `Result<T, E>` | |
| 参照 | `&T`、`&mut T` | [値、参照、クロージャ](./values.md#references)を参照 |
| 関数ポインタ、クロージャ | `fn(u32) -> bool`、`Fn(u32) -> bool` | [クロージャ型とポインタ型](./values.md#closure-and-pointer-types)を参照 |
| ビルトイン型 | `Screen`、`Narrative`、`Element`、`Setting<T>`、`Meta<T>`、アセット型など | 不透明なハンドル。[ビルトイン型](../special/builtin-types.md)を参照 |

浮動小数点型はありません。物語が実行時に保持できる型は[有限型](#finite-types)に限られます。

## プリミティブ型 {#primitive-types}

`bool`、`Int`、12 個の Rust の整数型はプリミティブ型です。宣言を持たず、他のすべての名前の後に探されます（[パス](./modules.md#paths)を参照）。`Int` は常にちょうど 2 つの境界を取り、他のプリミティブはジェネリクス引数を取りません（[`E2005`](../../diagnostics/types.md#e2005)）。ユーザーのコードはプリミティブ型に `impl` を追加できません。

## Text と String {#text-and-string}

| 型 | 内容 |
| -- | ---- |
| `Text` | プログラムの定数テキスト。素の文字列リテラル（`"Mio"`）か、ルビやテキスト効果を含む `t![…]` のリッチテキストです。文字列リテラルの型はすべて `Text` です。`Text` は[有限型](#finite-types)です。その値はプログラムに書かれたテキストなので、物語が保持できます |
| `String` | `fn` のコードが実行時に組み立てる文字列。有限型ではありません |

どちらも `Eq` です。`Text` は `std::narrative::text` で、`String` は `std` で宣言されています。どちらもプレリュードにあります。

## タプル、配列、`Vec` {#tuples-arrays-and-vec}

- **タプル** `(A, B, …)` は型の異なる値をまとめます。フィールドは `.0`、`.1`、… です。要素 1 つのタプルは `(A,)` と書き、`()` はユニット型です。
- **配列** `[T; N]` は型 `T` の値をちょうど `N` 個持ちます。`N` は[型レベル定数](#type-level-constants)です。配列は `[a, b, c]` か `[value; N]` と書き、`a[i]` でインデックスします。範囲外のインデックスは、コンパイル時ならエラー、実行時なら VM パニックです。
- `Vec<T>` は実行時に長さが変わるリストです。`Vec::new()`、`push`、`len`、`is_empty`、`get`、`set` があります。有限型ではありません。[STD リファレンス](../../std/std.md)を参照してください。

## 構造体と列挙型 {#structs-and-enums}

構造体と列挙型は名前で区別されます。同じフィールドを持つ 2 つの宣言は別の型です。ジェネリックにできます。標準ライブラリは `Option<T>`（`None`、`Some(T)`）と `Result<T, E>`（`Ok(T)`、`Err(E)`）を宣言しており、そのバリアントはプレリュードにあります。宣言の形は[アイテム](./items.md#structs)にあります。

## 範囲 {#ranges}

`a..b` と `a..=b` は標準の構造体 `Range<T>` の値です。

```kis
pub struct Range<T> {
    pub start: T,
    pub end: T,
    pub inclusive: bool,
}
```

`a..b` は `b` を含まず、`a..=b` は含みます。値としての範囲は `a..b` と `a..=b` だけで、`a..` や `..b` などそれ以外の形は [`E2030`](../../diagnostics/types.md#e2030) です。パターンには独自の範囲の形 `a..`、`..=b`、`a..b`、`a..=b` があります（[範囲パターン](./patterns.md#range-patterns)を参照）。`..b` というパターンはなく、パターンの中の単独の `..` は残余パターンです。範囲は `for` で反復します（[制御フローとループ](./control-flow.md)を参照）。

## ジェネリクス {#generics}

関数、構造体、列挙型、型エイリアス、`impl` ブロックはジェネリクスパラメータを持てます。

```kis
struct Pair<T> { a: T, b: T }

fn first<T, const N: usize>(items: [T; N]) -> T {
    items[0]
}
```

- **型パラメータ** `T` には[境界](#trait-bounds)を付けられます。`T: Eq`、`T: Eq + Integer` のように書きます。
- **定数パラメータ** `const N: usize` は整数型の定数を表します。`Int<lo, hi>` 自体は、`i64` の定数パラメータを 2 つ持つプリミティブです。
- ジェネリクス引数は推論されるか、明示します。型の中では `Pair<u8>`、式の中ではターボフィッシュで `first::<u8, 3>(…)` と書きます。引数の数の誤りは [`E2005`](../../diagnostics/types.md#e2005) です。
- ジェネリックなコードは**単相化**されます。コンパイラは、プログラムが使う引数の組み合わせごとに複製を作ります。`pushdown fn` の中では型引数はすべて[有限型](#finite-types)でなければならず、物語は有限のプログラムのままです。
- ライフタイム、`where` 節、既定の引数、独自の関連型はありません。

### 型レベル定数 {#type-level-constants}

配列の長さ、`Int` の境界、定数ジェネリクス引数は**型レベル定数**です。ジェネリクス引数としては、整数リテラル（`Square<8>`）、負のリテラル（`Int<-5, 5>`）、定数パラメータや `const` アイテムの名前（`Int<0, MAX>`）、波括弧で囲んだ式（`Int<0, { MAX * 2 }>`）のいずれかで書きます。式に使えるのは、整数リテラル、単項 `-`、`+ - * / %`、最後の式だけからなるブロック、定数パラメータ、値がこうした式である `const` アイテムだけです（[`E2002`](../../diagnostics/types.md#e2002)）。定数が期待される所に型を書くと [`E2007`](../../diagnostics/types.md#e2007) です。

```kis
const MAX: i64 = 5;
static mut TRUST: Int<0, MAX> = 0;
static mut DOUBLE: Int<0, { MAX * 2 }> = 0;
```

## トレイト境界 {#trait-bounds}

境界には標準ライブラリのトレイトを指定します。コードはトレイトを宣言・実装できませんが、要求することはできます。

| トレイト | 実装する型 | 使えるもの |
| -------- | ---------- | ---------- |
| `Eq` | 構造的な等価性を持つすべての型。[等価性](#equality)を参照 | `==`、`!=` |
| `Integer` | `Int<lo, hi>` と Rust の整数 | `into`、`saturate`。[変換](./numbers.md#conversions)を参照 |
| `RandChoose` | フィールドなし列挙型と `Int<lo, hi>` | `rng_choose::<T>()` |
| `Asset` | アセット型 | `asset::<A>(…)` |
| `Step` | ステップ `Say` と `Choice` | `push_step`。関連型 `Output` |
| `ToText` | `Text`、`String`、`Int<lo, hi>`、Rust の整数、`Rat`、`Decimal` | `t![…]` の埋め込み `{expr}` |

境界を満たさないジェネリクス引数は [`E2026`](../../diagnostics/types.md#e2026) です。境界があると、そのトレイトのアイテムをパラメータに対して使えます。`S: Step` なら `S::Output`、`T: Integer` なら `value.into()` です。詳しくは[言語トレイト](../special/traits.md)を参照してください。

## 等価性 {#equality}

`derive` はありません。`==` と `!=` は両辺に `Eq` を必要とし（[`E2017`](../../diagnostics/types.md#e2017)）、`Eq` は自動で実装されます。

- `bool`、`Int<lo, hi>`、Rust の整数。
- フィールドや要素がすべて `Eq` である構造体、列挙型、タプル、配列。構造的に比較し、同じように組み立てられた 2 つの値が等しくなります。
- 関数ポインタと名前付き関数。同一性で比較します。
- `T` が `Eq` のときの `&T` と `&mut T`。指す先の値を比較します。
- 標準ライブラリが `Eq` と宣言しているビルトイン型。`String`、`Vec<T>`（`T` が `Eq` のとき）、`Rat`、`Decimal`、`Text`、`Screen`、アセット型です。

クロージャは決して `Eq` ではありません。それ以外のビルトイン型も `Eq` ではありません。

## 有限型 {#finite-types}

物語が実行時に保持するのは**有限型**だけです。有限型とは、値が有限個で、コンパイラが列挙できる型です。要点は次のとおりです。

| 有限 | 有限でない |
| ---- | ---------- |
| `bool`、`()`、`Int<lo, hi>` | Rust の整数、`Rat`、`Decimal` |
| 有限型からなる構造体、列挙型、タプル、配列 | `String`、`Vec<T>`、再帰的な型 |
| `Text` とアセット型 | `Screen` などのビルトインのハンドル |
| `pushdown fn`、`scene fn`、`const fn` のポインタ | `fn` のポインタ、クロージャ |
| 有限な `T` の `&T` と `&mut T`（パラメータとしてのみ） | |

任意の型の定数式は、値がコンパイル時に計算されるので、物語の中にも書けます。完全な規則は[関数種別](../concepts/kinds.md#finite-types)にあります。

## 関数ポインタ型とクロージャ型 {#function-pointer-and-closure-types}

関数ポインタ型とクロージャ型は呼び出すコードの[種別](../concepts/kinds.md)を持つので、呼び出し規則はそれらを通しても成り立ちます。

| 型 | 保持するもの |
| -- | ------------ |
| `fn(A) -> R`、`const fn(A) -> R` | その種別の名前付き関数 |
| `pushdown fn(A) -> R` | 名前付きの即時手続き |
| `scene fn(A) -> R` | 名前付きのシーン（構文は*暫定*） |
| `Fn(A) -> R`、`const Fn(A) -> R`、`pushdown Fn(A) -> R` | その種別のクロージャまたは関数（構文は*暫定*） |

型の変換を含めて[値、参照、クロージャ](./values.md#closure-and-pointer-types)で説明します。

## 型強制 {#coercions}

ある型の値が期待される所に別の型の値を与えると、次の暗黙の変換が適用されます。

| 変換元 | 変換先 |
| ------ | ------ |
| 整数リテラル | その値を範囲に含む任意の整数型 |
| `Int<l1, h1>` | `l2 <= l1` かつ `h1 <= h2` である `Int<l2, h2>`（拡大） |
| `&mut T` | `&T` |
| 名前付き関数またはタプルのコンストラクタ | 同じ種別とシグネチャの関数ポインタ |
| 名前付き関数、関数ポインタ、クロージャ | 同じ種別のクロージャ型（シーンを除く） |
| 何もキャプチャしないクロージャ | 同じ種別の関数ポインタ |
| `return`、`break`、`continue`、終わらない `loop` の型 | 任意の型 |

それ以外の型の変更は `x.into()` のように明示します。

## 型推論 {#type-inference}

本体の中では、Rust と同じく型は使われ方から推論されます。アイテムのシグネチャは決して推論されません。パラメータの型、戻り値型、定数と static の型は常に書きます。推論で型が決まらない場合は注釈が必要です（[`E2029`](../../diagnostics/types.md#e2029)）。

```kis
fn demo() {
    let names: Vec<Text> = Vec::new();
    let level: Int<0, 5> = 3;
}
```
