# 通知設計書 28-TransitiveAnalysisFailure

## 概要

本ドキュメントは、Zigコンパイラにおける推移的解析失敗通知「TransitiveAnalysisFailure」の設計を記述する。

### 本通知の処理概要

本通知は、あるAnalUnitの解析が失敗した際に、その失敗が依存元に伝播することを示す内部状態変更である。直接エラーを起こしたユニットではなく、そのユニットに依存するユニットが「推移的な解析失敗」として記録される。

**業務上の目的・背景**：コンパイルエラーが発生した場合、そのエラーの直接的な原因だけでなく、依存関係を通じて影響を受けるすべてのコードを把握する必要がある。推移的解析失敗の追跡により、(1) エラーの根本原因を特定しやすくなり、(2) 依存元で冗長なエラーメッセージの出力を避けることができる。

**通知の送信タイミング**：`error.AnalysisFail`が発生し、そのAnalUnitが`failed_analysis`マップにエントリを持たない場合（つまり、直接のエラー原因ではない場合）に、`transitive_failed_analysis`マップに追加される。

**通知の受信者**：これは内部状態変更であり、外部への通知ではない。エラー報告時に、推移的失敗かどうかを判定し、適切なエラーメッセージを生成するために使用される。

**通知内容の概要**：推移的に失敗したAnalUnitが`transitive_failed_analysis`マップに記録される。

**期待されるアクション**：コンパイラは推移的失敗を認識し、根本原因のエラーのみを報告する。開発者は根本原因を修正することで、推移的失敗も解消される。

## 通知種別

内部状態変更（マップ更新）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（内部状態更新） |
| 優先度 | - |
| リトライ | なし |

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

`error.AnalysisFail`がキャッチされた際に、`failed_analysis.contains(unit)`がfalseであれば、`transitive_failed_analysis`に追加する。

## 通知テンプレート

該当なし（内部状態変更）

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| unit | 推移的に失敗したAnalUnit | AnalUnit | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 解析失敗 | error.AnalysisFail | failed_analysisに含まれない場合 | 依存先のエラーによる失敗 |
| 型解析失敗 | resolveStructLayout等 | 依存型の解析失敗 | 型の解析が依存先で失敗 |
| メモ化状態失敗 | analyzeMemoizedState | 組み込み型解析の失敗 | std.builtinの解析失敗 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| failed_analysisに含まれる | 直接のエラー原因の場合 |
| 既にtransitive_failed_analysisに含まれる | 重複防止 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[解析実行] --> B{エラー発生?}
    B -->|No| C[成功]
    B -->|error.AnalysisFail| D{failed_analysisに含まれる?}
    D -->|Yes| E[直接エラー - 処理済み]
    D -->|No| F[transitive_failed_analysisに追加]
    F --> G[log.debug: mark transitive failure]
    G --> H[error.AnalysisFailを返す]
    E --> H
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| failed_analysis | 直接エラーかどうかの判定 | エントリがなければ推移的 |
| transitive_failed_analysis | 既存の推移的失敗確認 | 重複防止 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| transitive_failed_analysis | PUT | AnalUnitを推移的失敗としてマーク |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| OutOfMemory | マップ拡張時にメモリ不足 | エラーを伝播 |

### リトライ仕様

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

## 配信設定

該当なし（内部処理）

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

- 内部状態のみを変更し、外部への情報漏洩はない

## 備考

- エラー報告時に`transitive_failed_analysis`を確認することで、冗長なエラーを避ける
- インクリメンタルコンパイルでは、根本原因が修正されると推移的失敗もクリアされる
- デバッグログで`"mark transitive analysis failure for {f}"`が出力される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Zcu.zig | `src/Zcu.zig` | 180-182行目: failed_analysisとtransitive_failed_analysisの定義 |

**読解のコツ**: `failed_analysis`は`*ErrorMsg`を値として持ち、直接のエラー情報を保持する。`transitive_failed_analysis`は`void`を値とし、マーカーとしてのみ機能する。

#### Step 2: 推移的失敗のマーク処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Zcu/PerThread.zig | `src/Zcu/PerThread.zig` | 674-681行目: ensureMemoizedStateUpToDateでの処理 |
| 2-2 | Type.zig | `src/Type.zig` | 3848-3853行目: resolveStructLayoutでの処理 |

**主要処理フロー（PerThread.zig）**:
- **674行目**: `error.AnalysisFail`をキャッチ
- **675-678行目**: `failed_analysis.contains(unit)`がfalseなら推移的失敗
- **678行目**: `transitive_failed_analysis.put`で追加
- **679行目**: `log.debug`でマーク情報を出力

#### Step 3: エラー報告での使用を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | IncrementalDebugServer.zig | `src/IncrementalDebugServer.zig` | 288-290行目: unit_infoでの表示 |

**主要処理フロー**:
- **288行目**: `failed_analysis.contains(unit)`で直接失敗を確認
- **289行目**: `transitive_failed_analysis.contains(unit)`で推移的失敗を確認
- **290行目**: 推移的失敗は`"true (transitive)"`と表示

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

```
[解析処理]
    │
    ├─ ensureMemoizedStateUpToDate()
    │      └─ analyzeMemoizedState() catch |err| switch (err)
    │              │
    │              └─ error.AnalysisFail
    │                      │
    │                      ├─ failed_analysis.contains() → true → 直接エラー
    │                      │
    │                      └─ false → transitive_failed_analysis.put() ← 本通知
    │
    ├─ resolveStructLayout()
    │      └─ catch |err| switch (err)
    │              └─ error.AnalysisFail
    │                      └─ transitive_failed_analysis.put() ← 本通知
    │
    └─ resolveUnionLayout()
           └─ 同様のパターン
```

### データフロー図

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

error.AnalysisFail  ───▶ failed_analysisチェック    ───▶ 分岐
        │                       │                           │
        ▼                       ▼                           ▼
  依存先のエラー         [含まれる] 直接エラー       処理済み
        │               [含まれない] 推移的エラー          │
        ▼                       │                           ▼
  catchでキャッチ        transitive_failed_analysis.put()
                               │
                               ▼
                        log.debug出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Zcu.zig | `src/Zcu.zig` | ソース | failed_analysis/transitive_failed_analysisマップ定義 |
| Zcu/PerThread.zig | `src/Zcu/PerThread.zig` | ソース | 解析処理とエラーハンドリング |
| Type.zig | `src/Type.zig` | ソース | 型解析でのエラーハンドリング |
| IncrementalDebugServer.zig | `src/IncrementalDebugServer.zig` | ソース | デバッグ表示での使用 |
