Skip to content

docs: harden RT semantics and purity boundaries (#9) - #22

Closed
mao2009 wants to merge 1 commit into
feature/issue-8-regression-coveragefrom
feature/issue-9-rt-semantics
Closed

docs: harden RT semantics and purity boundaries (#9)#22
mao2009 wants to merge 1 commit into
feature/issue-8-regression-coveragefrom
feature/issue-9-rt-semantics

Conversation

@mao2009

@mao2009 mao2009 commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Issue #9: Harden RT semantics and purity boundaries

Refs #9

[PureMethod] による Referential Transparency 検証について「何を pure とみなすか」を明確にします。テスト数 101 → 128

⚠️ Base branch: この PR は feature/issue-8-regression-coverage をベースにしています(merge order: #20#21 → this)。

判定原則

参照透過性を (1) 観測可能な状態変化がないこと / (2) 決定性があること の 2 性質として定義しました。単純な禁止 API 一覧を採らない理由も明記しています — blocklist は「なぜ非純粋なのか」を表現できず、列挙し忘れた非純粋 API を黙って許可してしまうためです。

v1.0 で保証しない範囲(false negative)を明示

この PR の中核成果です。 実測により、以下が検出されないことを確認・記録しました。

# ギャップ
1 instance state の変更(最大) _f = 1; P = 1; — RT0001 は static のみ対象
2 既知純粋型の非決定的メンバ DateTime.Now / DateTime.UtcNow / Guid.NewGuid()
3 参照経由の変更 a[0] = 5;
4 delegate / lambda 呼び出し Func<int> f = ...; f();
5 制御境界 throw / try-catch / オブジェクト生成
6 assembly 跨ぎ・呼び出し先への到達 Issue #10
7 ローカル関数 本体は RT0001、呼び出しは RT0002 の二重報告

#2 の原因: 既知純粋型リストが型粒度である一方、純粋性は本来メンバの性質であるため、決定的メンバと非決定的メンバを併せ持つ型が誤って近似されます。

false positive 候補

現時点で確認済みの false positive は なし。構造的リスクとして、ローカル関数呼び出し / 既知純粋型リストの取りこぼし / I/O 判定が型表示名の前方一致であることによる名前空間衝突を記載しました。

Diagnostic message の整合

RT0001・RT0002 は条件を正確に述べています。RT0003 は「どの操作か」を示しておらず改善余地がありますが、message 文言は DIAGNOSTICS.md の契約対象外のため非破壊的に変更可能である旨を記載しました。

Changes

  • docs/PURITY-SEMANTICS.md(新規)— 判定原則、保証する範囲、保証しない範囲、FP 候補、message 整合、Open decisions
  • PuritySemanticsTests.cs(27 tests)— 上記を実測で固定。false negative は FALSE_NEGATIVE_* テストで「検出されないこと」を明示的に assert し、ギャップをテストスイート上で可視化
  • docs/DIAGNOSTICS.md — RT セクションから相互参照を追加

⚠️ 挙動は変更していません

文書中の全挙動は analyzer を実際に実行して観測した結果であり、ソース読解からの推測ではありません。

検出範囲の拡大は DIAGNOSTICS.md の互換性ルール上 major リリースの破壊的変更に該当し、かつ製品判断を要します。そのため実装は行わず、Open decisions として 4 件記載するに留めました。

  1. instance state 変更に RT0001 相当を追加するか(最大のギャップ)
  2. 既知純粋型リストをメンバ粒度に変更するか(DateTime.Now は拒否、new DateTime(...) は許可)
  3. ローカル関数は外側の [PureMethod] 契約を継承すべきか(Issue [Analyzer] Define pure method contract and interprocedural analysis #10
  4. I/O 判定を前方一致からより厳密な方式へ変更するか

Verification

  • Build: PASS (0 error) / Tests: 128/128 PASS(baseline 56 から +72)/ git diff --check: PASS

Issue #9 完了条件

  • pure/non-pure の判定原則が文書化されている
  • 主要な境界ケースに Analyzer Tests がある
  • false positive / false negative 候補を整理している
  • Diagnostic message がルールの意味と一致している
  • v1.0 で保証する範囲と保証しない範囲が明示されている

Merge boundary

技術検証を通過しても MERGE CANDIDATE にとどまります。merge には Merge Skill による検証と、この PR / HEAD に対する新しい明示的 human approval が必要です。

🤖 Generated with Claude Code

Issue #9 に対応し、[PureMethod] による Referential Transparency 検証に
ついて「何を pure とみなすか」を明確にする。テスト数 101 -> 128。

追加: docs/PURITY-SEMANTICS.md

判定原則を定義した。参照透過性を
(1) 観測可能な状態変化がないこと
(2) 決定性があること
の 2 性質として定め、単純な禁止 API 一覧を採らない理由を明記した。
blocklist は「なぜ非純粋なのか」を表現できず、列挙し忘れた非純粋 API を
黙って許可してしまう。

v1.0 で保証する範囲を表として確定した。
static mutable field の読み書き (RT0001)、I/O 型のメソッド呼び出しと
プロパティ参照 (RT0003)、[PureMethod] でないメソッド・interface メソッド・
out パラメータメソッドの呼び出し (RT0002)。
正しく報告しないケース (static readonly / const / [PureMethod] 同士の
呼び出し / 再帰 / generic / 既知純粋型 / 決定的なコンストラクタ) も明記した。

v1.0 で保証しない範囲を false negative として 7 分類で明記した。
1. instance state の変更 (最大のギャップ。RT0001 は static のみを対象)
2. 既知純粋型の非決定的メンバ (DateTime.Now / DateTime.UtcNow /
   Guid.NewGuid。既知純粋型リストが型粒度であり、純粋性は本来メンバの
   性質であるため)
3. 参照経由の変更 (配列要素書き込み等。ローカルを追跡していない)
4. delegate / lambda の呼び出し (Func/Action が既知純粋型のため
   実体によらず常に許可される)
5. 制御境界 (throw / try-catch / オブジェクト生成)
6. assembly 跨ぎと呼び出し先への到達 (Issue #10)
7. ローカル関数 (本体は外側として解析され RT0001 が出るが、
   ローカル関数自身は [PureMethod] を持たないため呼び出しが RT0002)

false positive 候補を整理した。現時点で確認済みの false positive はない。
構造的リスクとしてローカル関数呼び出し、既知純粋型リストの取りこぼし、
I/O 判定が型表示名の前方一致であることによる名前空間衝突を挙げた。

Diagnostic message とルール意味の一致を検証した。RT0001/RT0002 は
条件を正確に述べている。RT0003 は「どの操作か」を示していないため
改善余地があるが、message 文言は DIAGNOSTICS.md の契約対象外であり
非破壊的に変更可能である旨を記載した。

追加: PuritySemanticsTests.cs (27 tests)
上記の各挙動を実測で固定した。false negative については
FALSE_NEGATIVE_ プレフィックスのテストで「検出されないこと」を明示的に
assert している。これは検出されないのが正しいという主張ではなく、
v1.0 で保証していない範囲をテストスイート上で可視化するためである。

本 PR は Analyzer の挙動を変更していない。
文書中の全挙動は analyzer を実際に実行して観測した結果であり、
ソース読解からの推測ではない。検出範囲の拡大は DIAGNOSTICS.md の
互換性ルール上 major リリースの破壊的変更に該当するため、
製品判断を要する項目を Open decisions として 4 件記載するに留めた。

更新: docs/DIAGNOSTICS.md
RT セクションから PURITY-SEMANTICS.md への参照を追加。

検証結果:
- dotnet build: PASS (0 error)
- dotnet test --no-build: PASS (128/128、baseline 56 から +72)
- git diff --check: PASS

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XB2mDSE67ZDQS9mk5KfAdZ
@coderabbitai

coderabbitai Bot commented Sep 3, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: 353edcca-4cbd-445a-a74f-a37bc8bd08fb

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

mao2009 added a commit that referenced this pull request Sep 3, 2026
PR #20 (Issue #7) が main にマージされたため、PR #21 のスタック元
feature/issue-7-diagnostic-ssot は不要になった。PR #21 を main 直接の
PR に付け替えるにあたり、ブランチ内容を現在の main 基準に更新する。

方式として rebase ではなく merge を選択した理由:
- merge-skill SKILL.md の固定安全ポリシーが force push を禁じており、
  rebase は履歴書き換えのため force push が必須になる
- PR #22 が本ブランチを base にスタックしているため、force push は
  #22 の merge-base を破壊し diff ノイズを生む
- merge であれば fast-forward push で済み、#22 の diff は #9 変更のみの
  ままクリーンに保たれる
- 履歴とトレーサビリティが完全に保存される

取り込んだ main の変更:
- 285f852 Merge pull request #20 (Issue #7 diagnostic SSOT)
- 44bc400 docs: READMEのDiagnostic titleを実装の値に一致させる

Issue #8 の変更範囲 (test-only) には影響しない。main...HEAD の
三点diff は Issue #8 のテスト3ファイルのみである。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HbycDX129cVZTorjE2s4W9
@mao2009
mao2009 deleted the branch feature/issue-8-regression-coverage September 8, 2026 01:18
@mao2009 mao2009 closed this Sep 8, 2026
@mao2009
mao2009 deleted the feature/issue-9-rt-semantics branch September 8, 2026 01:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant