Skip to content

実装ファイルの tree-shaking 誤削除を修正 + tags.json スキーマ自動移行#36

Merged
TwoSquirrels merged 18 commits into
mainfrom
keep-impl-files
Jul 9, 2026
Merged

実装ファイルの tree-shaking 誤削除を修正 + tags.json スキーマ自動移行#36
TwoSquirrels merged 18 commits into
mainfrom
keep-impl-files

Conversation

@TwoSquirrels

@TwoSquirrels TwoSquirrels commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Fixes #21

概要

宣言と実装が別ファイルに分かれたライブラリで、演算子オーバーロード等が tree-shaking で誤って消えるバグ (#21) を修正します。あわせて必要になった tags.json のスキーマ更新 (v1 → v2) を、ユーザー操作なしで吸収する仕組みを入れます。

背景 (#21)

現行の依存検出は「ユーザーコードに現れる識別子」を手がかりに逆引きします。しかし f * g のような演算子の使用は識別子として現れないため、operator*= の実装だけを置いたファイルが「未使用」と誤判定されて消え、バンドル後に undefined reference になります (Nyaan's Library の FPS で発生)。この症状は宣言がクラス本体側に残るためコンパイルは通り、リンク時にしか顕在化しません

変更内容

#21: 実装ファイルの保持

  • 登録時: クラス外の修飾付き定義 (X<...>::method) の型名や明示的特殊化の主テンプレート名を「実装先の型名」として tags.json に記録する (implements フィールド、schema v2)。
  • バンドル時: 「必要と判定されたファイルが定義する型を実装先に持つファイルも必要」という逆引きを 1 種追加し、増えなくなるまで反復する。識別子に現れない依存を、実装ファイルが自ら書く型名から辿れるようにする。
  • Nyaan's Library 実測: リンクエラーが解消し、全ヘッダー同時 include のワーストケースでも残存率の増加は +5pt 未満。

スキーマ更新の自動吸収

tags.json はライブラリ実体から再生成できるキャッシュなので、スキーマ不一致は risundle 側の都合と捉え、ユーザー操作を要求しません。

  • bundle: 不一致の登録をライブラリ実体から自動で作り直してから続行。
  • update / add-std: スキーマ非依存の中核 (Registration) だけを読み、旧スキーマからでも回復。
  • list / show: 読み取りに徹し、エラーにも移行にもせず読める情報だけ表示。

原則は「ユーザーの内容変更 (ハッシュ不一致) は確認させ、risundle の形式変更 (スキーマ不一致) は黙って直す」という非対称です。

設計・ドキュメント

  • 設計判断は docs/architecture.md に、挙動は docs/spec.md (ja/en) に追記。
  • スキーマ耐性の土台として Registration 型を導入し、種別判定を一元化。Inventory の逆引きを FileTags レコードに整理。

テスト

  • 実装ファイル保持の結合テストは、症状がリンク時にしか出ないためリンク・実行まで通して検証 (修正前のコードで落ちることを確認済み)。
  • スキーマ移行 (bundle 自動移行 / update・add-std の回復 / list・show の寛容 / 破損エラーの伝播) を単体テストで網羅。

補足

Summary by CodeRabbit

  • New Features

    • Library details now include implementation-target type names in verbose output.
    • Bundle analysis better preserves implementation files tied to separate declarations.
  • Bug Fixes

    • Tree-shaking now keeps needed operator and other out-of-class implementation files.
    • Cache schema changes are handled automatically during bundle/update flows instead of requiring manual recovery.
  • Documentation

    • Updated architecture and specification docs to reflect the new library metadata and cache behavior.

TwoSquirrels and others added 6 commits July 8, 2026 02:36
ファイルごとの「実装先の型名」一覧を tags.json に持てるようにする
(#21 の器)。旧 v1 は library update を促すエラーで弾く。
この時点では登録側は常に空を書き込む。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TwiopnwyFnRbSUyNoFLWAZ
クラス外の修飾付き定義 (X<...>::method) の修飾側と、明示的特殊化
(template <> struct T<...>) の主テンプレート名を「実装先の型名」として
登録時に記録し、tags.json の implements に保存する (#21)。
演算子オーバーロードだけの実装ファイルでも実装先が残るのが要点。
show -v に Implements 表示を追加。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TwiopnwyFnRbSUyNoFLWAZ
必要ファイルが定義する型を実装先に持つファイル (演算子オーバーロード等、
識別子に現れない依存) を implements の逆引きで必要集合へ加え、
増えなくなるまで -M の必要集合と交互に更新する (#21)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TwiopnwyFnRbSUyNoFLWAZ
Issue 番号や時系列 (「従来通り」等) に依存するコメントを、コードだけで
理解できる現在形の記述へ書き換える。inventory のモジュールコメントに
実装ファイル逆引きの問い合わせを追記。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TwiopnwyFnRbSUyNoFLWAZ
宣言と演算子実装が分かれたライブラリの縮小再現。実装消失は
undefined reference としてリンクで顕在化するため、リンク・実行まで
通して検証する。修正前のコードで FAILED になることを確認済み。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TwiopnwyFnRbSUyNoFLWAZ
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds implementation-target type-name tracking (implements) to identifier enumeration, uses it in inventory reverse-lookup and bundle tree-shaking to retain out-of-class implementation files, migrates tags.json to schema_version 2 with automatic silent schema recovery, updates library CLI commands accordingly, and revises docs/specs and tests.

Changes

Implements tracking, tree-shaking, and schema migration

Layer / File(s) Summary
Identifier enumeration: extract implementation targets
src/library/identifiers.rs
Adds Enumeration struct (definitions/implements), threads an implements accumulator through AST traversal, and adds collect_implement_target for qualified/template targets, with new tests.
tags.json schema v2
src/library/tags.rs
Bumps schema_version to 2, adds SchemaMismatch error type, extends TagsKind::Library with implements, adds Registration struct/loader, updates JSON conversion, and tests.
Inventory reverse-lookup
src/bundle/inventory.rs
Adds FileTags struct, replaces defines-only lookup with file_tags, updates dependency_headers, and implements implementation_files with new tests.
Bundle tree-shaking and E2E test
src/commands/bundle.rs, tests/cli.rs
Calls auto_migrate before bundling; iteratively expands needed headers via implementation-derived headers until stable; adds a CLI test verifying operator implementation retention.
library command schema-tolerant read/update paths
src/commands/library.rs
Reworks existing_std_compilers, register_library, update_one/reregister, list, show to use Registration; adds exported auto_migrate, show_outdated, Implements display, and tests.
Docs and spec updates
docs/architecture.md, docs/spec.md, docs/spec.ja.md
Documents implementation-target-based tree-shaking, the schema_version 2 implements format, and automatic silent schema migration policy.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
    participant Bundle as commands::bundle::run
    participant Migrate as cmd_library::auto_migrate
    participant Inventory as bundle::inventory
    participant Tags as library::tags::Tags

    Bundle->>Migrate: auto_migrate(&store)
    Migrate->>Tags: Tags::load(each library)
    Tags-->>Migrate: Ok or SchemaMismatch
    Migrate->>Migrate: reregister mismatched libraries
    Bundle->>Inventory: dependency_headers(used)
    Inventory-->>Bundle: dependency_headers set
    loop until stable
        Bundle->>Inventory: implementation_files(needed, present)
        Inventory->>Inventory: compute needed type names from defines
        Inventory->>Inventory: filter present files by implements
        Inventory-->>Bundle: implementation headers
        Bundle->>Bundle: expand dependency_headers
    end
    Bundle->>Bundle: render bundle with needed headers
Loading

Possibly related PRs

  • TwoSquirrels/risundle#25: Both PRs modify tree-shaking/needed-header computation in src/commands/bundle.rs's unused_origins logic.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the two main changes: fixing implementation-file tree-shaking and adding automatic tags.json schema migration.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch keep-impl-files

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

TwoSquirrels and others added 11 commits July 8, 2026 22:29
update は登録内容を丸ごと作り直すため、tags.json からは登録パス
(std ならコンパイラ集合) しか使わない。これらは全スキーマバージョンに
存在するので、スキーマ検証をせずに読み出す MigrationSource を導入し、
「スキーマ不一致は update で再生成」というエラー案内が実際に機能する
ようにする。旧実装では update 自体が同じエラーで倒れ、案内が詰みに
なっていた。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TwiopnwyFnRbSUyNoFLWAZ
add-std は登録を作り直すため、既存 std の tags.json からは認識コンパイラ
集合しか使わない。update と同様に MigrationSource で検証せずに読み、
スキーマの合わない登録があっても集合を引き継いで再登録できるようにする。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TwiopnwyFnRbSUyNoFLWAZ
schema_version 不一致を anyhow の文字列エラーから SchemaMismatch 型へ
変更し、呼び出し側が downcast で判別できるようにする。tags.json は
ライブラリ実体から再生成できるキャッシュなので、この判別を足がかりに
各コマンドが自動移行や寛容表示で回復できるようにするための土台。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TwiopnwyFnRbSUyNoFLWAZ
tags.json はライブラリ実体から再生成できるキャッシュであり、スキーマ
形式の変化は risundle 側の都合なので、バンドル前に schema_version が
現行と合わない登録をライブラリ実体から黙って作り直す (std の初回自動
登録と同じ発想)。ユーザーに update を要求せず、アップグレード後の初回
バンドルだけ数秒伸びる形にする。

update_one から再登録の中核を reregister として切り出し、auto_migrate と
共有する。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TwiopnwyFnRbSUyNoFLWAZ
list と show は読み取りコマンドなので、スキーマ不一致でもエラーにせず、
状態も書き換えない (バンドル時の自動移行に任せる)。list は全バージョン
共通の ID・種別・パスだけを MigrationSource から読む。show は詳細を
読める場合はそのまま出し、読めない場合は基本情報と update 案内を出す。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TwiopnwyFnRbSUyNoFLWAZ
schema_version 不一致時の各コマンドの挙動 (バンドル時の自動移行、
update/add-std の回復、list/show の寛容読み) を tags.json 節に追記。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TwiopnwyFnRbSUyNoFLWAZ
- MigrationSource の doc を実際の利用箇所 (update/add-std/自動移行/list/show)
  に合わせて更新 (旧: library update のみと記載)
- auto_migrate の分岐を「現行/旧スキーマ/破損」の 3 分岐へ整理しコメント付与
- auto_migrate が schema 不一致以外のエラーを伝播することのテストを追加

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TwiopnwyFnRbSUyNoFLWAZ
スキーマ耐性の方針 (移行/救出再登録/寛容読み) が各コマンドに散っていた
問題に対し、共通の土台概念を明確にする。MigrationSource を
「スキーマ非依存の登録の中核」を表す Registration へ改名し、種別判定
(compilers の有無) を Registration::kind_label に一元化。commands 側で
重複していた kind_label 自由関数を廃止する。動作は不変。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TwiopnwyFnRbSUyNoFLWAZ
tags_entry が (files, implements, key) の 3-tuple を返し
#[allow(clippy::type_complexity)] を要していた点を、per-file の
FileTags { defines, implements } を返す file_tags に置き換える。
定義/実装先を持たないファイルは空スライスになり (従来の None と同義)、
defined_identifiers/implement_targets の 2 ヘルパを畳んで呼び出しを直截にする。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TwiopnwyFnRbSUyNoFLWAZ
…tion

コードから読み取りにくい設計判断 (なぜ) を 2 節追記:
- 実装ファイルを「実装先の型名」で引く理由と、素朴な代替案を退けた経緯
- tags.json のスキーマ変化を黙って吸収する非対称の原則
  (ユーザーの内容変更は確認、risundle の形式変更は自動移行)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TwiopnwyFnRbSUyNoFLWAZ
テスト名やモジュール doc・直後の assert から自明な説明コメントを削除する
(実装コードの rationale コメントは維持)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TwiopnwyFnRbSUyNoFLWAZ
@TwoSquirrels TwoSquirrels changed the title Keep impl files 実装ファイルの tree-shaking 誤削除を修正 + tags.json スキーマ自動移行 Jul 9, 2026
@TwoSquirrels TwoSquirrels marked this pull request as ready for review July 9, 2026 10:35
実在しない AC Library もどきのファイル構成 (atcoder/modint_impl.hpp 等。
ACL はヘッダーオンリーで implements が生じない) を、宣言と実装が分かれた
架空の行列ライブラリに差し替え、implements が発生する構造を正しく示す。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TwiopnwyFnRbSUyNoFLWAZ
@TwoSquirrels TwoSquirrels merged commit d778231 into main Jul 9, 2026
9 checks passed
@TwoSquirrels TwoSquirrels deleted the keep-impl-files branch July 9, 2026 11:42
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