refactor(joinir): Phase 71-Pre - OwnershipPlanValidator Box (dev-only)

pattern3_with_if_phi.rs の check_ownership_plan_consistency() を独立した
OwnershipPlanValidator Box に抽出。P2/P4 での再利用を可能にする。

Key changes:
- plan_validator.rs: 新規作成 (~190行)
  - validate_relay_support(): Multi-hop relay Fail-Fast (Phase 70-A タグ)
  - validate_carrier_consistency(): Carrier set 整合性チェック (warn-only)
  - validate_condition_captures(): Condition captures チェック (warn-only)
  - validate_all(): All-in-one 検証

- pattern3_with_if_phi.rs: Validator box への委譲
  - check_ownership_plan_consistency() → OwnershipPlanValidator::validate_all()

Unit tests: 3 PASS
- test_validate_relay_support_single_hop_ok
- test_validate_relay_support_multihop_rejected
- test_validate_all_with_consistent_data

Tests: normalized_dev 50/50 PASS, lib 950/950 PASS

🤖 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-13 02:30:12 +09:00
parent 7b56a7c01d
commit 1424aac901
3 changed files with 201 additions and 53 deletions

View File

@ -311,63 +311,13 @@ impl MirBuilder {
/// 3. **Condition captures consistency**: plan captures vs condition bindings (warn-only)
///
/// Phase 70-A: Standardized error tag for runtime unsupported patterns.
/// Phase 71-Pre: Delegated to OwnershipPlanValidator box.
#[cfg(feature = "normalized_dev")]
fn check_ownership_plan_consistency(
plan: &crate::mir::join_ir::ownership::OwnershipPlan,
carrier_info: &crate::mir::join_ir::lowering::carrier_info::CarrierInfo,
condition_bindings: &std::collections::BTreeSet<String>,
) -> Result<(), String> {
use std::collections::BTreeSet;
// Check 1: Multi-hop relay is rejected (Fail-Fast)
// Tag: [ownership/relay:runtime_unsupported] - standardized for Phase 70-A
for relay in &plan.relay_writes {
if relay.relay_path.len() > 1 {
return Err(format!(
"[ownership/relay:runtime_unsupported] Multihop relay not executable yet: var='{}', owner={:?}, relay_path={:?}",
relay.name, relay.owner_scope, relay.relay_path
));
}
}
// Check 2: Carrier set consistency (warn-only, order SSOT deferred)
let plan_carriers: BTreeSet<String> = plan
.owned_vars
.iter()
.filter(|v| v.is_written)
.map(|v| v.name.clone())
.collect();
let existing_carriers: BTreeSet<String> = carrier_info
.carriers
.iter()
.map(|c| c.name.clone())
.collect();
if plan_carriers != existing_carriers {
eprintln!("[phase64/ownership] Carrier set mismatch (warn-only, order SSOT deferred):");
eprintln!(" OwnershipPlan carriers: {:?}", plan_carriers);
eprintln!(" Existing carriers: {:?}", existing_carriers);
// Don't fail - just warn (order SSOT not yet implemented)
}
// Check 3: Condition captures consistency (warn-only)
let plan_cond_captures: BTreeSet<String> = plan
.condition_captures
.iter()
.map(|c| c.name.clone())
.collect();
if !plan_cond_captures.is_subset(condition_bindings) {
let extra: Vec<_> = plan_cond_captures
.difference(condition_bindings)
.collect();
eprintln!(
"[phase64/ownership] Extra condition captures in plan (warn-only): {:?}",
extra
);
// Warn only - this might be expected in some cases
}
Ok(())
use crate::mir::join_ir::ownership::OwnershipPlanValidator;
OwnershipPlanValidator::validate_all(plan, carrier_info, condition_bindings)
}