diff --git a/docs/development/current/main/10-Now.md b/docs/development/current/main/10-Now.md index 458681f6..34135028 100644 --- a/docs/development/current/main/10-Now.md +++ b/docs/development/current/main/10-Now.md @@ -1,9 +1,9 @@ # Self Current Task — Now (main) -## Current Focus: Phase 29aa P1(RcPlan 2-stage, meaning-preserving) +## Current Focus: Phase 29aa P2(No cleanup on Jump/Branch) -**2025-12-27: Phase 29aa P1 完了** ✅ -- 目的: rc_insertion を RcPlan に閉じ込め、Plan→Apply 2-stage 化(挙動不変) +**2025-12-27: Phase 29aa P2 完了** ✅ +- 目的: Jump/Branch 終端で cleanup を入れない契約を SSOT 化(Fail-Fast guard) - 入口: `docs/development/current/main/phases/phase-29aa/README.md` **2025-12-27: Phase 29z P2 closeout** ✅ diff --git a/docs/development/current/main/30-Backlog.md b/docs/development/current/main/30-Backlog.md index 1e909af6..5c9b3d9e 100644 --- a/docs/development/current/main/30-Backlog.md +++ b/docs/development/current/main/30-Backlog.md @@ -68,9 +68,8 @@ Related: - 入口: `docs/development/current/main/phases/phase-29z/README.md` - 指示書: `docs/development/current/main/phases/phase-29z/P0-RC_INSERTION_MINIMAL-INSTRUCTIONS.md` -- **Phase 29aa(P1 COMPLETE): RC insertion safety expansion(CFG-aware)** - - 進捗: P1 ✅ 完了(RcPlan 導入+Plan→Apply 2-stage化、挙動不変) - - 次(P2): CFG-aware の最小ターゲットを 1 個に絞る(例: edge cleanup を Return 以外でどう扱うか) +- **Phase 29aa(P2 COMPLETE): RC insertion safety expansion(CFG-aware)** + - 進捗: P2 ✅ 完了(Jump/Branch 終端で cleanup を入れない契約の SSOT 化) - 入口: `docs/development/current/main/phases/phase-29aa/README.md` - **Phase 29x(planned, post self-host): De-Rust runtime for LLVM execution** diff --git a/docs/development/current/main/phases/phase-29aa/README.md b/docs/development/current/main/phases/phase-29aa/README.md index 8e21e622..2eaa05ac 100644 --- a/docs/development/current/main/phases/phase-29aa/README.md +++ b/docs/development/current/main/phases/phase-29aa/README.md @@ -1,6 +1,6 @@ # Phase 29aa: RC insertion safety expansion(CFG-aware design) -Status: P1 Complete (RcPlan 2-stage) +Status: P2 Complete (No cleanup on Jump/Branch) Scope: Phase 29z の単一block限定実装から、誤releaseを起こさない形で CFG-aware に拡張するための設計を固める。 Entry: @@ -21,3 +21,4 @@ Deliverables (P0): Progress: - P0: CFG-aware 設計の固定(RcPlan/危険パターン/安全条件の契約) - P1: rc_insertion を RcPlan の Plan→Apply 2-stage へ分離(挙動不変) +- P2: Jump/Branch 終端では cleanup を入れない契約を SSOT 化(Fail-Fast guard) diff --git a/src/bin/rc_insertion_selfcheck.rs b/src/bin/rc_insertion_selfcheck.rs index a8cb7a7c..54ca78d7 100644 --- a/src/bin/rc_insertion_selfcheck.rs +++ b/src/bin/rc_insertion_selfcheck.rs @@ -131,7 +131,7 @@ fn main() { "return_cleanup", ); - // Case 4: Branch terminator should NOT inject block-end cleanup (unsafe cross-block) + // Case 4: Jump terminator should NOT inject block-end cleanup (unsafe cross-block) let ptr = ValueId::new(400); let v1 = ValueId::new(30); @@ -144,7 +144,33 @@ fn main() { }); block.terminator_span = Some(Span::unknown()); let entry = block.id; - let module = build_module_with_block(block, "selfcheck_branch_skip", "selfcheck_mod4"); + let module = build_module_with_block(block, "selfcheck_jump_skip", "selfcheck_mod4"); + assert_release_inserted( + module, + "selfcheck_jump_skip", + entry, + 0, + "jump_no_cleanup", + ); + + // Case 5: Branch terminator should NOT inject block-end cleanup (unsafe cross-block) + let ptr = ValueId::new(500); + let v1 = ValueId::new(40); + let cond = ValueId::new(41); + + let mut block = BasicBlock::new(BasicBlockId::new(0)); + block.instructions = vec![MirInstruction::Store { value: v1, ptr }]; + block.instruction_spans = vec![Span::unknown()]; + block.terminator = Some(MirInstruction::Branch { + condition: cond, + then_bb: BasicBlockId::new(1), + else_bb: BasicBlockId::new(2), + then_edge_args: None, + else_edge_args: None, + }); + block.terminator_span = Some(Span::unknown()); + let entry = block.id; + let module = build_module_with_block(block, "selfcheck_branch_skip", "selfcheck_mod5"); assert_release_inserted( module, "selfcheck_branch_skip", diff --git a/src/mir/passes/rc_insertion.rs b/src/mir/passes/rc_insertion.rs index a9bab751..b00ce7dc 100644 --- a/src/mir/passes/rc_insertion.rs +++ b/src/mir/passes/rc_insertion.rs @@ -267,16 +267,19 @@ fn apply_rc_plan( } if !drops_before_terminator.is_empty() { - if !drops_before_terminator.is_empty() { - let span = terminator_span.clone().unwrap_or_else(Span::unknown); - for drop_site in drops_before_terminator { - let _ = drop_site.reason; - new_insts.push(MirInstruction::ReleaseStrong { - values: drop_site.values, - }); - new_spans.push(span.clone()); - stats.release_inserted += 1; - } + debug_assert!( + matches!(terminator, Some(MirInstruction::Return { .. })), + "rc_insertion: ReturnCleanup planned for non-Return terminator" + ); + + let span = terminator_span.clone().unwrap_or_else(Span::unknown); + for drop_site in drops_before_terminator { + let _ = drop_site.reason; + new_insts.push(MirInstruction::ReleaseStrong { + values: drop_site.values, + }); + new_spans.push(span.clone()); + stats.release_inserted += 1; } }