feat(joinir): Phase 228-8 - ConditionOnly carrier latch incoming support

- ExitMetaCollector includes ConditionOnly carriers in exit_bindings (for latch)
- ExitLineReconnector skips ConditionOnly in variable_map updates
- Pattern 2/3/4 pass carrier_info to ExitMetaCollector
- Resolves "has no latch incoming set" error

Role separation:
- Header PHI: entry + latch for both LoopState and ConditionOnly
- Exit PHI: LoopState only (ConditionOnly excluded)
- variable_map: LoopState only (ConditionOnly skipped)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-10 21:30:03 +09:00
parent 192620f842
commit 717a50ceeb
5 changed files with 86 additions and 10 deletions

View File

@ -546,8 +546,9 @@ impl MirBuilder {
let exit_meta = &fragment_meta.exit_meta;
// Phase 33-10: Collect exit bindings from ExitMeta using Box
// Phase 228-8: Pass carrier_info to include ConditionOnly carriers
use crate::mir::builder::control_flow::joinir::merge::exit_line::ExitMetaCollector;
let exit_bindings = ExitMetaCollector::collect(self, &exit_meta, debug);
let exit_bindings = ExitMetaCollector::collect(self, &exit_meta, Some(&carrier_info), debug);
// Phase 176-3: Build input mappings for all carriers
// JoinIR main() params: [ValueId(0), ValueId(1), ValueId(2), ...] for (i, carrier1, carrier2, ...)

View File

@ -154,7 +154,8 @@ impl MirBuilder {
}
// Build exit bindings using ExitMetaCollector
let exit_bindings = ExitMetaCollector::collect(self, exit_meta, debug);
// Phase 228-8: Pass carrier_info to include ConditionOnly carriers
let exit_bindings = ExitMetaCollector::collect(self, exit_meta, Some(&ctx.carrier_info), debug);
// Build boundary with carrier inputs
use crate::mir::join_ir::lowering::JoinInlineBoundaryBuilder;
@ -297,9 +298,11 @@ impl MirBuilder {
// Phase 213: Use ExitMetaCollector for dynamic exit binding generation
// Note: ExitMetaCollector internally validates that all exit carriers in ExitMeta
// have corresponding variable_map entries. No additional validation needed here.
// Phase 228-8: Pass None for carrier_info (legacy path doesn't have ConditionOnly carriers)
let exit_bindings = ExitMetaCollector::collect(
self,
exit_meta,
None, // Phase 228-8: No carrier_info in legacy path
debug,
);

View File

@ -330,10 +330,12 @@ impl MirBuilder {
// Phase 179 Task 2: Use ExitMetaCollector for unified exit binding generation
// Replaces manual loop (Phase 196 implementation) with modular Box approach
// Phase 228-8: Pass carrier_info to include ConditionOnly carriers
use super::super::merge::exit_line::meta_collector::ExitMetaCollector;
let exit_bindings = ExitMetaCollector::collect(
self,
&exit_meta,
Some(&carrier_info), // Phase 228-8: Include ConditionOnly carriers
debug,
);