# Part 0　はじめに：推論を土台にした型チェッカー
Source: https://rigor.typedduck.fail/ja/chibirigor/little/part0-introduction/

> 本編の入口です。コードを書く前に、chibirigorが何であり何でないかを掴みます。実装の前提（Prism、`check`/`annotate`）と、全編を貫く2つの約束ごとを先に共有します。

`chibirigor`は、**型を自分で推論する、最小限のRuby型チェッカー**です。本物の[Rigor](https://github.com/rigortype/rigor)（Ruby向けの漸進的型チェッカー）のアーキテクチャの「最小版」を、ステップバイステップで自分の手で作っていきます。[chibivue](https://github.com/chibivue-land/chibivue)がVueを小さく作り直して学ぶように、私たちはRigorを小さく作り直して学びます。本書もchibivueが`book/impls`に各回の到達点を残すのと同じ作りで、章末から`impls/dist/partN`の段階スナップショット（その章まで作った、動く最小版）に飛べます。

> **Note**
>
> **Rigorの来歴：なぜ作られ、なぜ「小さく」作り直すのか**
>
> Rigorの作者は、PHPをはじめとする動的言語の静的解析に十年ほど取り組んできました。Rubyの型まわりの道具には以前から使いにくさを感じていて、長らくそれをRubyという言語の宿命だと思っていました。ところがRubyKaigi 2026（函館）で、その思い込みを覆す発表にいくつも出会います。既存のRubyの型ツールの枠組みを離れて大きく踏み出す必要を感じ、TypeScriptやPythonの機能とPHPStanのプラグインアーキテクチャを、**RBSの型システムの上に統合し直して**生まれたのがRigorでした。
>
> ただ、Rigorは短期間で一気に出来上がったぶん、その全体像をつかんでいる人がほとんどいません。型推論という一見魔法のような仕組みも、chibivueがリアクティブシステムでやってみせたように、エッセンスだけ抜き出せば手を動かして作り直せるはずです。本書chibirigorは、その思いつきから始まっています。

本編で中心に作るのは、2つのコマンドだけ：

- **`check`**：Rubyのコードを読み、型の矛盾（診断）を報告する
- **`annotate`**：推論した型を表示する

このあと付録では、`check`に`--explain`／`--unreachable`のopt-inフラグを足す小さな発展も扱いますが、本編の軸はずっとこの2つです。

---

## 0.1推論を土台にした型チェッカー

最初に、chibirigorが何をする道具なのかを掴んでおきます。

世の中の**型チェッカー（type checker）**の多くは、プログラムに*書かれた型注釈*を前提に、それらが矛盾しないかを判定します。注釈が無いと仕事になりません。

- **型注釈**＝「この変数は`Integer`」のように*型をコードに書き添えること*。Rubyでは普段書きません。だから初めて自分で書くのはずっと先のPart 8（RBS）で、それまでは登場しません

ところがRubyのコードにはふつう型注釈がありません。そこでchibirigorは、注釈に頼る前に、まず式から型を自分で導出します。`1`を見れば整数、`"a".upcase`を見れば文字列、というふうに。そうして得た型を使って、矛盾を見つけたり（`check`）、型を見せたり（`annotate`）します。

一言で言えば、chibirigorは「推論を土台にした、注釈のいらない型チェッカー」です。推論はチェックと別物の前段ではなく、チェックを成り立たせている**土台**です。

ここで言う「推論」とは、式から型を上向きに組み立てる（合成）ことです。「`1`は整数」「`"a".upcase`は文字列」というふうに、書いてあるものから型を積み上げます。逆に、メソッドの引数の型を呼び出し元の使われ方から逆算することは、前編ではしません。引数は分からなければ`untyped`に倒します。不明はとりあえず`untyped`に逃がす、と覚えておけば十分です。`untyped`をはじめ特別な型のカタログは付録[a1](/ja/chibirigor/appendix/a1-special-types/)にあり、通読の必要はなく、Part 9まで読んだ後に引く参照用です。

> **Note**
>
> **Rubyのもう一つの推論ツールTypeProf**：
> 注釈なしのRubyから型を出すツールは、Rigorだけではありません。Ruby同梱の[TypeProf](https://github.com/ruby/typeprof)は、プログラム全体を「型レベルで実行」して、呼び出し元から引数の型まで逆算し、RBSを生成します。chibirigorが`untyped`に倒して諦める、まさにその仕事をします。
>
> chibirigor（とRigor）があえてそれをしないのは弱点ではなく設計の選択です：全体実行は大きなコードベースで爆発しがちなので、ローカルな推論に絞ってスケールと「沈黙（誤検知を出さない）」を取る。引数を逆算しないというこの一線は、前編ではPart 8で一度だけ具体に立ち返り、後編Part 5でていねいに扱います。

> **Tip**
>
> **参考書について（任意）**：
> 型理論をもう一段深く覗きたい方のために、各章の脇に参考書メモとして対応箇所を添えます。**どちらも必読ではありません**。無くても本書だけで完結します。必要な所だけ拾ってください。
>
> - 『**しくみ**』：遠藤侑介『[型システムのしくみ ― TypeScriptで実装しながら学ぶ型とプログラミング言語](https://www.lambdanote.com/products/type-systems)』（ラムダノート。以下『しくみ』）。『TAPL』のエッセンスを*やさしく蒸留*した入門書で、型注釈付きのミニ言語に対する*チェッカー*を作ります。chibirigorとちょうど裏表の関係です。
> - 『**TAPL**』：Benjamin C. Pierce『[型システム入門 ― プログラミング言語と型の理論](https://tatsu-zine.com/books/types-and-programming-languages-ja)』（オーム社。原著*Types and Programming Languages*, MIT Press）。本格的な教科書で、各話題に本式の証明があります。英語で読むなら原著がそのまま参照先になります（『しくみ』は日本語のみ）。
>
> このPart 0の話題（型安全性と未定義動作）は、『TAPL』第1章「はじめに」＋第8章 §8.3「安全性 = 進行 + 保存」／『しくみ』1章に対応します。

「まず推論し、その結果でチェックする」。推論が土台で、`check`と`annotate`はその出力を使います。この順序を、最初に頭に入れてください。

---

## 0.2入力を拒まないという約束

もう一つの約束ごとがあります。chibirigorは、Rubyが構文エラーにしないコードなら、**すべて受理します**。「型が付かないから解析しない」とは言いません。

- パーサにはRuby標準のPrismを使います。Prismは、多少壊れた構文すら部分的に解析するので、*受け付ける範囲はむしろRuby実行系より広い*くらいです
- ただし、「chibirigorが通した＝実行して動く」ことは保証しません。私たちが返すのは、あくまで推論した型と診断だけです

これは『しくみ』と決定的に違う姿勢です。同書のチェッカーは型エラーで*例外を投げて止まります*。chibirigorは、入力を常に受け取り、出力は診断と推論型です。止まらず、分からない所は黙って先に進みます。

---

## 0.3心臓となる2つの関数

これから作る型チェッカーの心臓は、たった2つの関数です。全編、この2つを育てていきます。

- **`type_of`**：式から型を求める（合成する）。`1 + 2` → `Integer`、`"a"` → `"a"`。分からなければ`untyped`を返すだけで、**失敗しません**
- **`accepts`**：ある型が期待される所に、別の型を渡して合うか確かめる

全体の流れはこうです。`type_of`が主役で、`check`/`annotate`はその出力を使うだけです。

```text
                              ┌─ 期待型がある所で accepts → 合わなければ ─→  check（診断）
ソース ─Prism→ AST ─type_of→ 型 ┤
                              └─ そのまま見せる ───────────────────────→  annotate（推論型）
```

![図0-1　chibirigorのデータの流れ](/ja/chibirigor/figures/svg/little-0-1.svg)
> ▼ 図0-1　chibirigorのデータの流れ

`type_of`が型を組み立て、`check`は「期待型と合うか」を確かめて診断を出し、`annotate`は組み立てた型をそのまま見せます。推論が土台で、`check`も`annotate`もその出力を使うのです。

そして、全編を貫く中核の原理を、いま言葉にしておきます。専門用語は要りません。

> **重要**
>
> 診断（型エラー）は「期待される型が決まっている所」でしか出ない。そして「分からない（`untyped`）」が絡んだら、決して怒らない。だから、型の分からない、けれど動いているコードが、咎められることはない。

Rigorのスローガンは「**動くコードを脅かさない**」です。

chibirigorも、健全さ（バグを一つ残らず捕まえること）より、誤検知を出さないこと（動くコードを赤くしないこと）をずっと大切にします。なぜそちらを選ぶのかは、各章でRubyの現実にぶつかりながら腑に落ちていきます。

---

## 0.4各章を貫く三つの視点

各章は、小さな三つの視点（パースペクティブ）から書かれています：

- **① 型理論**：その章で出会う概念を1つ（『しくみ』のどこに対応するか）。
- **② Ruby/RBSだと**：それがRubyだとどう見えるか、あるいは*どう見えないか*。
- **③ Rigor実装の問題**：素直な実装がRubyの現実でなぜ破綻し、どう折り合ったか。

「Rigorを理解する」とは、③の困りごとが②（Rubyの現実）から*必然的に*生まれ、それが①の概念で*やさしく*腑に落ちることです。難しい話（双方向型付けの形式化、変性、再帰型、本物の型推論…）は、すべて後編『The Seasoned chibirigor』に送ります。前編は、まず*動く*最小版を、気持ちよく作り切ることに集中します。

### これから9章で積むもの（全体像）

各章は前の章の上に積み上がります。1章で増えるのは「難しいこと1つ」だけ：

| 章 | 足すもの | キーワード |
|---|---|---|
| 1 | 型をデータで表し、式から型を求める | `Const`、`type_of`、`check`、`annotate` |
| 2 | メソッド送信を型付けする | ディスパッチ表、未知は`Dynamic` |
| 3 | 変数と文を扱う | 不変`Scope`、文を縫う |
| 4 | 型が枝分かれする（Union） | `Union` |
| 5 | 場合分けで型を絞る | ナローイング、2つの掟 |
| 6 | ハッシュと配列に型をつける | `HashShape`、`Tuple` |
| 7 | 「合うか」を三値で判定する | `accepts`、`:yes`/`:no`/`:maybe` |
| 8 | RBSから型を引き、戻り型を推論して見せる | `Rbs.load`、`def`のsig合成 |
| 9 | gradualの哲学で締める | `untyped`の伝播、baseline |

Part 9まで来ると、`check`と`annotate`が一通り動く型チェッカーが手元に残ります。

> **Tip**
>
> 『しくみ』／『TAPL』との対応早見表は付録[a4](/ja/chibirigor/appendix/a4-bibliography/)にまとめました（任意参考）。各章の冒頭にも対応する参考書の章を添えますが、まとめて俯瞰したいときは付録[a4](/ja/chibirigor/appendix/a4-bibliography/)を引いてください。『しくみ』でそのまま扱わなかった領域（Union型、三値、gradual、フロー感応スコープ）が、chibirigorが「先に進めた部分」です。

---

## 0.5準備

Ruby 3.4以降（Prism同梱）があれば動きます。テストフレームワークも使いません。

```console
$ ruby exe/chibirigor check  path/to/file.rb     # 型診断
$ ruby exe/chibirigor annotate path/to/file.rb   # 推論型の表示
```

> **Tip**
>
> **演習の答え合わせについて**：各章末に演習があります。「`annotate`／`check`で確かめよ」系は、上のコマンドを手元で走らせればその場で答え合わせできます。各章末の「この章の実装（演習の答え合わせにも）」リンク（`impls/dist/partN`）が*その章までの参照実装*なので、自分の写経と挙動がそろうか突き合わせられます。
>
> 一方「説明せよ／方針を述べよ」系には決まった一つの正解はなく、根拠はその章の本文にあります。手を動かして言葉にするのが目的です。

`parse`して構文木（AST）を覗くところから始めましょう。Prismがプログラムをどんな木にするか。それが分かれば、`type_of`が木をたどって型を組み立てる準備は整います。

**次章（Part 1）**：最初の`type_of`を書きます。リテラルと算術だけの、ほんの数十行の型チェッカーが、もう「型を付ける」仕事を始めます。

---

> **重要**
>
> **この章の位置づけ**：Part 0は概念の導入なので、対応する実装ファイルはありません。`lib/`のコードはPart 1からです。ここで約束した2つ、すなわち「推論を土台にすること（ただし引数の逆算はしない）」と「拒まない、脅かさないこと」が、以降のすべての設計判断の土台になります。
