# 通知設計書 63-warnCycleCreated

## 概要

本ドキュメントは、Nimコンパイラの警告メッセージ `warnCycleCreated` の設計仕様を定義する。この警告は、参照型（ref）の値が自身への参照を持つ循環構造を作成しようとしている場合に出力される。

### 本通知の処理概要

この警告は、デストラクタ注入フェーズにおいて、参照型の代入が循環参照（サイクル）を作成する可能性を検出し、開発者に通知する機能を提供する。

**業務上の目的・背景**：NimのARC/ORC（参照カウント方式のメモリ管理）では、循環参照は特別な処理が必要となる。ARCのみでは循環参照を回収できず、メモリリークの原因となる。ORCでは循環参照コレクタが動作するが、パフォーマンスコストがかかる。この警告により、開発者は循環参照の発生箇所を認識し、`{.cursor.}`プラグマを使用して明示的に循環を防ぐか、意図的な循環参照であることを認識した上で適切なメモリ管理戦略を選択できる。

**通知の送信タイミング**：コンパイラのデストラクタ注入フェーズ（`injectdestructors.nim`）で、参照型への代入が検出され、代入元と代入先が構造的に等価（同一オブジェクトへの参照パス）である場合に警告が発生する。

**通知の受信者**：Nimコンパイラを使用してソースコードをコンパイルしている開発者。コンパイル時の警告メッセージとして標準エラー出力またはビルドログに表示される。

**通知内容の概要**：循環参照の作成を検出した旨と、該当するフィールドに`{.cursor.}`を付与することで循環を防げる旨のメッセージが出力される。メッセージ形式は動的に生成され、フィールド名が含まれる場合とそうでない場合がある。

**期待されるアクション**：開発者は該当するフィールドに`{.cursor.}`プラグマを付与して循環参照を防ぐか、ORCを使用して循環参照コレクタに処理を任せるか、データ構造を再設計して循環を避けることを検討する。

## 通知種別

コンパイラ警告メッセージ（stderr/ビルドログ出力）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（コンパイル処理中に即座に出力） |
| 優先度 | 中（Warning） |
| リトライ | 無（コンパイル時の一度きりの出力） |

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

警告は、コンパイラオプションで `warnCycleCreated`（短縮形: `CycleCreated`）が有効になっている場合に出力される。デフォルトで有効。

## 通知テンプレート

### コンパイラ警告出力の場合

| 項目 | 内容 |
|-----|------|
| 出力先 | stderr |
| メッセージ種別 | Warning |
| 形式 | テキスト |

### 本文テンプレート

フィールドが特定できる場合：
```
{ファイルパス}({行番号}, {カラム番号}) Warning: '{式}' creates an uncollectable ref cycle; annotate '{フィールド名}' with .cursor [CycleCreated]
```

フィールドが特定できない場合：
```
{ファイルパス}({行番号}, {カラム番号}) Warning: '{式}' creates an uncollectable ref cycle [CycleCreated]
```

### 添付ファイル

なし（コンパイラ出力のため）

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| $1 | 動的に生成されるメッセージ | injectdestructors.nim内で構築 | Yes |
| 式 | 循環参照を作成する代入式 | PNode | Yes |
| フィールド名 | cursorを付与すべきフィールド | field.sym | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| コンパイル処理 | 参照型への代入 | exprStructuralEquivalent(x, value) == true | 代入先と代入元が構造的に等価 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| --warning:CycleCreated:off | コマンドラインオプションで明示的に無効化 |
| {.warning[CycleCreated]:off.} | プラグマで無効化 |
| sfCursor in field.sym.flags | フィールドに{.cursor.}が付与されている |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[代入式の処理] --> B[cycleCheck関数呼び出し]
    B --> C[代入先の解析]
    C --> D{nkDotExpr?}
    D -->|Yes| E[フィールド取得]
    E --> F{sfCursor in flags?}
    F -->|Yes| G[処理終了]
    F -->|No| H[次の階層へ]
    D -->|No| H
    H --> I{exprStructuralEquivalent?}
    I -->|No| J[次の階層を解析]
    J --> D
    I -->|Yes| K[警告メッセージ生成]
    K --> L[message呼び出し]
    L --> M[処理終了]
```

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

本警告はコンパイラ内部処理であり、データベースは使用しない。

### 参照テーブル一覧

なし

### 更新テーブル一覧

なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 該当なし | 警告メッセージのため、エラーは発生しない | - |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

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

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

特になし。ソースコードの構造情報のみを扱い、機密情報は含まれない。

## 備考

- ARC（Automatic Reference Counting）では循環参照を自動回収できないため、メモリリークの原因となる
- ORC（ARC + Cycle Collector）では循環参照コレクタが動作するが、パフォーマンスコストがかかる
- `{.cursor.}`プラグマは参照カウントをインクリメントしない弱参照を作成する
- 循環参照が本当に必要な場合は、ORCを使用し、この警告を無視するか無効化する

---

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

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

### 推奨読解順序

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

まず、警告メッセージの種別と循環参照検出に関連するデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | lineinfos.nim | `compiler/lineinfos.nim` | TMsgKind列挙型でwarnCycleCreatedの定義（77行目）とメッセージテンプレート（185行目）を確認 |
| 1-2 | ast.nim | `compiler/ast.nim` | sfCursorフラグの定義を確認（シンボルフラグ） |

**読解のコツ**: sfCursorフラグは、フィールドが弱参照（カーソル）として宣言されていることを示す。

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

デストラクタ注入フェーズでの循環検出処理の起点を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | injectdestructors.nim | `compiler/injectdestructors.nim` | cycleCheck関数の実装（550-568行目付近）を確認 |

**主要処理フロー**:
1. **550行目付近**: `var x = n[0]` - 代入先の取得
2. **551行目付近**: `var field: PNode = nil` - フィールドノードの初期化
3. **552-560行目**: whileループで代入先を解析
4. **561行目**: `exprStructuralEquivalent(x, value, strictSymEquality = true)` - 構造的等価性のチェック
5. **567行目**: `message(c.graph.config, n.info, warnCycleCreated, msg)` - 警告出力

#### Step 3: 構造的等価性チェックを理解する

循環参照検出の核心部分を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | injectdestructors.nim | `compiler/injectdestructors.nim` | exprStructuralEquivalent関数の使用方法を確認 |

**主要処理フロー**:
- **553-555行目**: `nkDotExpr`の場合、フィールドを取得し、`sfCursor`フラグをチェック
- **564行目**: フィールドが特定できる場合のメッセージ生成
- **566行目**: フィールドが特定できない場合のメッセージ生成

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

```
injectdestructors.nim::process（デストラクタ注入メイン処理）
    │
    ├─ injectdestructors.nim::cycleCheck（循環参照チェック）
    │      │
    │      ├─ ast.nim::exprStructuralEquivalent（構造的等価性チェック）
    │      │
    │      └─ msgs.nim::message（警告出力 - warnCycleCreated）
    │
    └─ 他のデストラクタ注入処理
```

### データフロー図

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

代入AST ───▶ cycleCheck
                │
                ▼
        ┌─────────────────┐
        │ 代入先の解析     │
        │ (nkDotExpr等)    │
        └────────┬────────┘
                 │
                 ▼
        ┌─────────────────────────────┐
        │ exprStructuralEquivalent?   │
        │ (代入元と代入先が同一？)     │
        └────────────┬────────────────┘
                     │Yes
                     ▼
              メッセージ生成
                     │
                     ▼
               message ───▶ stderr（警告出力）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| lineinfos.nim | `compiler/lineinfos.nim` | ソース | TMsgKind定義とメッセージテンプレート |
| injectdestructors.nim | `compiler/injectdestructors.nim` | ソース | デストラクタ注入、cycleCheck関数 |
| msgs.nim | `compiler/msgs.nim` | ソース | メッセージ出力関数 |
| ast.nim | `compiler/ast.nim` | ソース | sfCursorフラグ定義、exprStructuralEquivalent関数 |
