# 通知設計書 105-hintConditionAlwaysTrue

## 概要

本ドキュメントは、Nimコンパイラの`hintConditionAlwaysTrue`ヒント通知に関する設計を定義する。このヒントは、条件式が常にtrueと評価される場合に通知するものである。

### 本通知の処理概要

`hintConditionAlwaysTrue`ヒントは、Nimコンパイラの意味解析フェーズで、`of`演算子（型チェック）による条件式がコンパイル時に常にtrueと判定された場合に出力される通知である。

**業務上の目的・背景**：Nimの`of`演算子はオブジェクト型の継承関係をチェックする。コンパイル時にこの条件が常にtrueと判定できる場合、それはコードの冗長性を示唆している可能性がある。この通知により、開発者は不必要な型チェックを発見し、コードの品質向上やパフォーマンス改善を行うことができる。また、型設計の問題を早期に発見するのにも役立つ。

**通知の送信タイミング**：セマンティック解析フェーズで`of`演算子が処理される際、継承関係の差分計算（inheritanceDiff）の結果が0以下の場合に送信される。これは、チェック対象の型が完全に一致するか、スーパークラスである場合に相当する。

**通知の受信者**：コンパイル実行者（開発者）がコンソール出力（stderr）を通じてこの通知を受信する。

**通知内容の概要**：「condition is always true: '$1'」という形式で、$1に条件式のレンダリング結果が代入される。

**期待されるアクション**：開発者はこの通知を確認し、当該条件式が本当に必要かどうかを検討する。不要であれば条件式を削除し、コードを簡潔にする。型設計に問題がある場合は、継承構造を見直す。

## 通知種別

コンソール出力（コンパイラヒント）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（コンパイルプロセス内で即時出力） |
| 優先度 | 低（ヒント情報） |
| リトライ | 無し |

### 送信先決定ロジック

標準エラー出力（stderr）に送信される。`--stdout`オプションが指定されている場合は標準出力（stdout）に送信される。`writelnHook`が設定されている場合は、そのフック関数に委譲される。

## 通知テンプレート

### コンソール出力の場合

| 項目 | 内容 |
|-----|------|
| メッセージ種別 | Hint |
| フォーマット | `Hint: condition is always true: '{条件式}' [CondTrue]` |
| 色 | 緑色（HintColor = fgGreen） |

### 本文テンプレート

```
Hint: condition is always true: 'x of ParentType' [CondTrue]
```

### 添付ファイル

なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| $1 | 条件式 | renderTree(n)の結果 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| セマンティック解析 | of演算子処理 | `inheritanceDiff <= 0` | 型が一致またはスーパークラスの場合 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| optHints not in conf.options | ヒント出力自体が無効化されている場合 |
| hintConditionAlwaysTrue not in conf.notes | 個別にヒントが無効化されている場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[semmagic: of演算子処理] --> B[引数の型解析]
    B --> C[skipTypes処理]
    C --> D{両方ともオブジェクト型?}
    D -->|No| E[localError出力]
    D -->|Yes| F[inheritanceDiff計算]
    F --> G{diff <= 0?}
    G -->|Yes| H[message hintConditionAlwaysTrue]
    H --> I[結果をtrue(1)に最適化]
    G -->|No| J{diff == high int?}
    J -->|Yes| K[commonSuperclass確認]
    K --> L{共通スーパークラスあり?}
    L -->|Yes| M[hintConditionAlwaysFalse]
    L -->|No| N[localError出力]
    J -->|No| O[通常のof演算子処理継続]
```

## データベース参照・更新仕様

該当なし（ファイルシステムやデータベースへのアクセスなし）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 該当なし | このヒントは情報出力のみ | - |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 制限なし | 条件が検出されるたびに出力 |

### 配信時間帯

制限なし（コンパイル実行時に即時出力）

## セキュリティ考慮事項

- 条件式の内容がログに出力されるが、通常は型名程度であり機密性は低い

## 備考

- この最適化により、ランタイムでの不要な型チェックが除去される
- 対応する`hintConditionAlwaysFalse`（No.106）と対をなす
- 継承関係の差分計算は`inheritanceDiff`関数で行われる
  - 0: 型が完全一致
  - 負の値: aがbのスーパークラス（n階層上）
  - 正の値: aがbのサブクラス（n階層下）
  - high(int): 互換性なし

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

通知種別の定義と継承関係チェックの仕組みを理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | lineinfos.nim | `compiler/lineinfos.nim` | TMsgKind列挙型でhintConditionAlwaysTrueの定義を確認（110行目） |
| 1-2 | lineinfos.nim | `compiler/lineinfos.nim` | MsgKindToStr配列でメッセージ文字列を確認（228行目） |

**読解のコツ**: hintConditionAlwaysTrueは"CondTrue"という短縮名を持ち、出力時には[CondTrue]として表示される。

#### Step 2: エントリーポイントを理解する

of演算子処理の起点を特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | semmagic.nim | `compiler/semmagic.nim` | of演算子のセマンティック処理（380-418行目）でhintConditionAlwaysTrue出力処理を確認 |

**主要処理フロー**:
1. **380行目**: `n.len == 3`で引数チェック
2. **381-382行目**: 両辺の式を型解析
3. **385-388行目**: `skipTypes`で型を抽出
4. **392-393行目**: オブジェクト型でない場合はエラー
5. **395行目**: `inheritanceDiff(a, b)`で継承関係を計算
6. **400-406行目**: `diff <= 0`の場合、hintConditionAlwaysTrueを出力し、結果を1（true）に最適化

#### Step 3: 継承関係計算を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | types.nim | `compiler/types.nim` | inheritanceDiff関数で継承階層の差分計算を理解 |

**主要処理フロー**:
- 戻り値の意味を理解することが重要（コメント参照: 396-399行目）

### プログラム呼び出し階層図

```
semExpr (意味解析エントリ)
    │
    └─ semOf / semMagic (semmagic.nim)
           │
           ├─ semExprWithType: 左辺の式を解析
           │
           ├─ semExprWithType: 右辺の式を解析
           │
           ├─ skipTypes: 型のポインタを除去
           │
           ├─ inheritanceDiff(a, b): 継承関係を計算
           │
           └─ diff <= 0 の場合
                  │
                  ├─ message(hintConditionAlwaysTrue) ← ここで出力
                  │      └─ liMessage → styledMsgWriteln
                  │
                  └─ newIntNode(nkIntLit, 1): trueに最適化
```

### データフロー図

```
[入力]               [処理]                    [出力]

of演算子式       ───▶ semExprWithType      ───▶ 型情報取得
(x of T)               │
                       ▼
                  skipTypes              ───▶ ポインタ除去後の型
                       │
                       ▼
                  inheritanceDiff        ───▶ 差分値 (int)
                       │
                       ▼
diff <= 0        ───▶ message            ───▶ stderr/stdout
                       │                      "Hint: condition is always true..."
                       ▼
                  newIntNode(1)          ───▶ 最適化されたAST (true)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| lineinfos.nim | `compiler/lineinfos.nim` | ソース | メッセージ種別定義（TMsgKind列挙型） |
| semmagic.nim | `compiler/semmagic.nim` | ソース | of演算子のセマンティック処理、hintConditionAlwaysTrue出力 |
| types.nim | `compiler/types.nim` | ソース | inheritanceDiff関数（継承関係計算） |
| msgs.nim | `compiler/msgs.nim` | ソース | メッセージ出力処理 |
| renderer.nim | `compiler/renderer.nim` | ソース | renderTree関数（条件式の文字列化） |
